00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "global.h"
00026 #ifdef HAVE_HDRSTOP
00027 #pragma hdrstop
00028 #endif
00029
00030 #include <cstring>
00031 #include "x86istr.h"
00032 #include "x86instr.h"
00033
00034 #define REG_INFO(reg) (*RegistryInfo::GetInfo(reg))
00035 #define COMPLETE(reg) (REG_INFO(reg).completeReg)
00036 #define INTERSECT(reg_a,reg_b) ( REG_INFO(reg_a).completeReg == REG_INFO(reg_b).completeReg && (REG_INFO(reg_a).partialMask®_INFO(reg_b).partialMask)!=0 )
00037 #define USE_TYPE(u) static_cast<enum Instruction::UseType>(u)
00038
00039 enum Instruction::UseType Instruction::GetUseType(reg_t reg,Param* param) const
00040 {
00041 unsigned res = useNone;
00042 unsigned overwriteMask = useReadWrite;
00043
00044
00045
00046
00047
00048 if (numArg>0)
00049 {
00050 int i = 0;
00051 if (Args[0].type == Param::t_registry)
00052 {
00053 if ( INTERSECT(reg,Args[0].mem_reg1) )
00054 {
00055 if ( (REG_INFO(reg).partialMask®_INFO(Args[0].mem_reg1).partialMask) != REG_INFO(reg).partialMask)
00056 overwriteMask = useReadModify;
00057 res |= (useModify|useOverwrite);
00058 }
00059 i = 1;
00060 }
00061 for(;i<numArg;++i)
00062 {
00063 switch(Args[i].type)
00064 {
00065 case Param::t_memory:
00066 if ( Args[i].mem_reg2 != null_reg && INTERSECT(reg,Args[i].mem_reg2) )
00067 res |= useRead;
00068 case Param::t_registry:
00069 if ( Args[i].mem_reg1 != null_reg && INTERSECT(reg,Args[i].mem_reg1) )
00070 res |= useRead;
00071 break;
00072 }
00073 }
00074 }
00075
00076
00077
00078 switch(instruction)
00079 {
00080 case istr_jb:
00081 case istr_jbe:
00082 case istr_jc:
00083 case istr_jg:
00084 case istr_jl:
00085 case istr_jle:
00086 case istr_jnbe:
00087 case istr_jnb:
00088 case istr_jnc:
00089 case istr_jng:
00090 case istr_jnl:
00091 case istr_jnle:
00092 case istr_jno:
00093 case istr_jnp:
00094 case istr_jns:
00095 case istr_jnz:
00096 case istr_jo:
00097 case istr_jp:
00098 case istr_js:
00099 case istr_jz:
00100 case istr_cld:
00101 break;
00102 case istr_call:
00103 _PRG_ASSERT(numArg==1);
00104 if (res != useNone)
00105 return useRead;
00106 break;
00107 case istr_setb:
00108 case istr_setbe:
00109 case istr_setl:
00110 case istr_setle:
00111 case istr_setnb:
00112 case istr_setnbe:
00113 case istr_setnl:
00114 case istr_setnle:
00115 case istr_setno:
00116 case istr_setnp:
00117 case istr_setns:
00118 case istr_setnz:
00119 case istr_seto:
00120 case istr_setp:
00121 case istr_sets:
00122 case istr_setz:
00123 _PRG_ASSERT(numArg == 1);
00124 return USE_TYPE(res&useReadModify);
00125
00126
00127 case istr_bts:
00128 case istr_btr:
00129 case istr_btc:
00130
00131
00132 case istr_shl:
00133 case istr_shr:
00134 case istr_sar:
00135 case istr_ror:
00136
00137 case istr_sbb:
00138 case istr_adc:
00139
00140 case istr_add:
00141 _PRG_ASSERT(numArg == 2);
00142 return USE_TYPE(res&useReadModify);
00143 case istr_not:
00144 case istr_neg:
00145 case istr_inc:
00146 case istr_dec:
00147 _PRG_ASSERT(numArg==1);
00148 return USE_TYPE(res&useReadModify);
00149 case istr_or:
00150 case istr_and:
00151 _PRG_ASSERT(numArg==2);
00152
00153 if ( (res&useReadWrite) == useReadWrite && Args[1].type == Param::t_registry)
00154 return useRead;
00155 return USE_TYPE(res&useReadModify);
00156 case istr_xor:
00157 case istr_sub:
00158 _PRG_ASSERT(numArg == 2);
00159
00160 if ( (res&useReadWrite) == useReadWrite && Args[1].type == Param::t_registry)
00161 {
00162 if ( (overwriteMask&useOverwrite) && param)
00163 *param = Param(Param::Literal,0);
00164 return USE_TYPE(res&overwriteMask);
00165 }
00166 return USE_TYPE(res&useReadModify);
00167 case istr_movsx:
00168 case istr_movzx:
00169 case istr_mov:
00170 _PRG_ASSERT(numArg == 2);
00171
00172 if ( (res&useReadWrite) == useReadWrite && Args[1].type == Param::t_registry)
00173 return useNone;
00174
00175 if ( (overwriteMask&useOverwrite) && param)
00176 *param = Args[1];
00177 return USE_TYPE(res&overwriteMask);
00178
00179 case istr_repnz:
00180 case istr_repz:
00181 if (COMPLETE(reg) == REG(ecx))
00182 return useModify;
00183 break;
00184 case istr_stosd:
00185 case istr_stosw:
00186 if (reg == REG(ah)) return useRead;
00187 case istr_stosb:
00188 if (reg == REG(eax)) return useRead;
00189 if (reg == REG(ax)) return useRead;
00190 if (reg == REG(al)) return useRead;
00191 if (COMPLETE(reg) == REG(edi))
00192 return useModify;
00193 break;
00194 case istr_movsb:
00195 case istr_movsw:
00196 case istr_movsd:
00197 if (COMPLETE(reg) == REG(esi))
00198 return useModify;
00199 if (COMPLETE(reg) == REG(edi))
00200 return useModify;
00201 break;
00202 case istr_xchg:
00203 _PRG_ASSERT(numArg == 2);
00204 _PRG_ASSERT(Args[0].type == Param::t_registry);
00205 _PRG_ASSERT(Args[1].type == Param::t_registry || Args[1].type == Param::t_memory);
00206
00207 if ( (res&useReadWrite) == useReadWrite && Args[1].type == Param::t_registry)
00208 return useNone;
00209
00210 if (res & useOverwrite)
00211 {
00212 if ( (overwriteMask&useOverwrite) && param)
00213 *param = Args[1];
00214 return USE_TYPE(res&overwriteMask);
00215 }
00216
00217 if (res & useRead && Args[1].type == Param::t_registry)
00218 {
00219
00220 if ( (REG_INFO(reg).partialMask®_INFO(Args[1].mem_reg1).partialMask) == REG_INFO(reg).partialMask)
00221 {
00222 if ( param)
00223 *param = Args[0];
00224 return useOverwrite;
00225 }
00226 }
00227 break;
00228 case istr_push:
00229
00230 _PRG_ASSERT(numArg == 1);
00231 if (REG(esp) == COMPLETE(reg))
00232 return (res!=useNone?useReadModify:useModify);
00233 if (res != useNone)
00234 return useRead;
00235 break;
00236 case istr_popa:
00237 case istr_popf:
00238 if (REG(esp) == COMPLETE(reg))
00239 return useModify;
00240 break;
00241 case istr_pop:
00242
00243
00244 _PRG_ASSERT(numArg == 1);
00245 if (REG(esp) == COMPLETE(reg))
00246 {
00247
00248 if (res&useRead)
00249 return useReadModify;
00250
00251 if (res&useOverwrite)
00252 return useReadWrite;
00253 return useModify;
00254 }
00255 if (res != useNone)
00256 {
00257 if ( (overwriteMask&useOverwrite) && param)
00258
00259 *param = Param(Param::Memory,REG(esp),0,Param::memInt32);
00260 return USE_TYPE(res&overwriteMask);
00261 }
00262 break;
00263 case istr_cmp:
00264 case istr_test:
00265 _PRG_ASSERT(numArg==2);
00266 if (res & useReadWrite)
00267 return useRead;
00268 break;
00269 case istr_lea:
00270 _PRG_ASSERT(numArg==2 && Args[1].type == Param::t_memory);
00271 if (res & useReadWrite)
00272 return useModify;
00273 if (res & useOverwrite)
00274 {
00275 if ( (overwriteMask&useOverwrite) && param)
00276 {
00277
00278 _PRG_ASSERT(0);
00279
00280 *param = Args[1];
00281 }
00282 return USE_TYPE(res&overwriteMask);
00283 }
00284 break;
00285 case istr_cdq:
00286 _PRG_ASSERT(numArg == 0);
00287 if (COMPLETE(reg) == REG(eax))
00288 return useRead;
00289 if (COMPLETE(reg) == REG(edx))
00290 return useModify;
00291 break;
00292 case istr_div:
00293 case istr_idiv:
00294 {
00295 _PRG_ASSERT(numArg == 1);
00296 _PRG_ASSERT(Args[0].type == Param::t_memory || Args[0].type == Param::t_registry);
00297 _PRG_ASSERT(Args[0].type != Param::t_memory || Args[0].GetMemSize() <= 4);
00298 _PRG_ASSERT(Args[0].type != Param::t_memory || ((1<<Args[0].GetMemSize() )&026)!=0 );
00299 if (res != useNone)
00300 res = useRead;
00301 if (COMPLETE(reg) == REG(eax))
00302 return USE_TYPE(res|useModify);
00303
00304
00305 if (Args[0].type == Param::t_memory)
00306 {
00307 if (Args[0].GetMemSize() == 1)
00308 return USE_TYPE(res);
00309 }
00310 else if (REG_INFO(Args[0].mem_reg1).size == reg_info::byte)
00311 return USE_TYPE(res);
00312
00313 if (COMPLETE(reg) == REG(edx))
00314 return USE_TYPE(res|useModify);
00315 }
00316 return USE_TYPE(res);
00317 case istr_out:
00318 _PRG_ASSERT(numArg == 2);
00319 if (res)
00320 return useRead;
00321 break;
00322 case istr_in:
00323 _PRG_ASSERT(numArg == 2);
00324
00325
00326 return USE_TYPE(res&useReadModify);
00327 case istr_nop:
00328 break;
00329 default:
00330
00331 #ifdef DEBUG
00332 fprintf(stderr,"Debug: (UseMode) %s\n",x86instructions_names[instruction]);
00333 #else
00334 static bool bUnimplPassed = false;
00335 if (!bUnimplPassed)
00336 {
00337 fprintf(stderr,"Something is yet unimplemented!\n");
00338 bUnimplPassed = true;
00339 }
00340 #endif
00341
00342 throw UseTypeUnimplemented(static_cast<enum x86instructions>(instruction));
00343 #ifdef DEBUG
00344 return USE_TYPE(32);
00345 #endif
00346 break;
00347 }
00348 return useNone;
00349 }
00350
00351
00352 void Instruction::Write(char* buffer) const
00353 {
00354 char* p = buffer;
00355 strcpy(p,x86instructions_names[instruction]);
00356 p += strlen(p);
00357
00358 switch (instruction)
00359 {
00360 case istr_int3:
00361 strcpy(buffer,"int\t3");
00362 return;
00363 case istr_insb:
00364 case istr_insw:
00365 case istr_insd:
00366 case istr_outsb:
00367 case istr_outsw:
00368 case istr_outsd:
00369 case istr_movsb:
00370 case istr_movsw:
00371 case istr_movsd:
00372 case istr_cmpsb:
00373 case istr_cmpsw:
00374 case istr_cmpsd:
00375 case istr_stosb:
00376 case istr_stosw:
00377 case istr_stosd:
00378 case istr_lodsb:
00379 case istr_lodsw:
00380 case istr_lodsd:
00381 case istr_scasb:
00382 case istr_scasw:
00383 case istr_scasd:
00384 if (segOver == -1)
00385 return;
00386 break;
00387 }
00388 if (numArg)
00389 {
00390 *p++ = '\t';
00391 for (int i=0;i<numArg;++i)
00392 {
00393 const Param ¶m = Args[i];
00394 if (i!=0)
00395 *p++ = ',';
00396 switch(param.type)
00397 {
00398 default:
00399 _PRG_ASSERT(0);
00400 break;
00401 case Param::t_farliteral:
00402 _PRG_ASSERT(param.mem_reg1 >= 0 && param.mem_reg1 < 0x10000l);
00403 sprintf(p,"%04Xh:",param.mem_reg1);
00404 p += strlen(p);
00405 if (param.GetLiteralSize() == 2)
00406 sprintf(p,"%04Xh",param.literal);
00407 else
00408 sprintf(p,"%08Xh",param.literal);
00409 break;
00410 case Param::t_literal:
00411 if (param.GetLiteralSize() == 1)
00412 sprintf(p,"%02Xh",param.literal);
00413 else if (param.GetLiteralSize() == 2)
00414 sprintf(p,"%04Xh",param.literal);
00415 else
00416 sprintf(p,"%08Xh",param.literal);
00417 break;
00418 case Param::t_registry:
00419 strcpy(p,RegistryInfo::GetInfo(param.mem_reg1)->name);
00420 break;
00421 case Param::t_memory:
00422
00423 if (param.MustWriteMemSize())
00424 switch(param.GetMemSize())
00425 {
00426 default:
00427 case 0: break;
00428 case 1: strcpy(p,"byte ptr "); p+=9; break;
00429 case 2: strcpy(p,"word ptr "); p+=9; break;
00430 case 4: strcpy(p,"dword ptr "); p+=10; break;
00431 case 6: strcpy(p,"fword ptr "); p+=10; break;
00432 case 8: strcpy(p,"qword ptr "); p+=10; break;
00433 case 10: strcpy(p,"tbyte ptr "); p+=10; break;
00434 }
00435
00436 if (segOver != -1)
00437 {
00438 _PRG_ASSERT( segOver>=0 && segOver<6 );
00439 char c;
00440 switch(segOver)
00441 {
00442 case 0: c = 'e'; break;
00443 case 1: c = 'c'; break;
00444 case 2: c = 's'; break;
00445 case 3: c = 'd'; break;
00446 case 4: c = 'f'; break;
00447 default: _PRG_ASSERT(0);
00448 case 5: c = 'g'; break;
00449 }
00450 *p++ = c;
00451 *p++ = 's';
00452 *p++ = ':';
00453 }
00454 *p++ ='[';
00455 bool begin = false;
00456 if (param.mem_reg1 != null_reg)
00457 {
00458 strcpy(p,RegistryInfo::GetInfo(param.mem_reg1)->name);
00459 p += strlen(p);
00460 begin = true;
00461 }
00462 if (param.mem_reg2 != null_reg)
00463 {
00464 if (begin) *p++ = '+';
00465 strcpy(p,RegistryInfo::GetInfo(param.mem_reg2)->name);
00466 p += strlen(p);
00467 if (param.factor > 1)
00468 {
00469 sprintf(p,"*%i",param.factor);
00470 p += strlen(p);
00471 }
00472 begin = true;
00473 }
00474 if (param.literal != 0 || !begin)
00475 {
00476 if ( (param.literal & 0x80000000lu) && begin)
00477 sprintf(p,"-%08Xh",-param.literal);
00478 else
00479 {
00480 if (begin) *p++ = '+';
00481 sprintf(p,"%08Xh",param.literal);
00482 }
00483 p += strlen(p);
00484 }
00485 *p++ = ']';
00486 *p = '\0';
00487 break;
00488 }
00489 p += strlen(p);
00490 }
00491 }
00492 *p = '\0';
00493 }
00494
00495 enum FlowTypes Instruction::GetFlowType() const
00496 {
00497 switch(instruction)
00498 {
00499
00500 case istr_ret:
00501 case istr_retf:
00502 case istr_iret:
00503 return FLOW_RET;
00504
00505 case istr_call:
00506 return FLOW_CALL;
00507
00508 case istr_jmp:
00509 return FLOW_JUMP;
00510 default:
00511
00512 if (x86instructions_names[instruction][0] == 'j')
00513 return FLOW_CJUMP;
00514 return FLOW_NONE;
00515 }
00516 }
00517
00518 typedef enum { Assign,Negate,Complement,Zero,Xor,Sub,Add,And,Or } Operations;
00519 typedef enum { UsuallyFlag,FlagCarry,FlagZero,FlagParity,FlagNone } FlagCombine;
00520 void Operation1(Operations op,const Param& param,FlagCombine flag)
00521 {}
00522 void Operation2(Operations op,const Param* dst,const Param& p1,FlagCombine flag)
00523 {}
00524 void Operation3(Operations op,const Param* dst,const Param& p1,const Param& p2,FlagCombine flag)
00525 {}
00526 void SetFlag(FlagCombine flag,FlagCombine mask)
00527 {}
00528
00529 void Instruction::WriteRegUsage(FILE* f) const
00530 {
00531 switch(instruction)
00532 {
00533 case istr_sbb:
00534 case istr_adc:
00535
00536
00537 break;
00538
00539 case istr_xor:
00540 case istr_sub:
00541
00542 if (Args[0].RegEqual(Args[1]))
00543 {
00544 Operation1(Zero,Args[0],UsuallyFlag);
00545 break;
00546 }
00547 if (instruction == istr_xor)
00548 Operation3(Xor,&Args[0],Args[0],Args[1],UsuallyFlag);
00549 else
00550 Operation3(Sub,&Args[0],Args[0],Args[1],UsuallyFlag);
00551 break;
00552
00553 case istr_inc:
00554 Operation3(Add,&Args[0],Args[0],Param(Param::Literal,1,(unsigned char)4),(FlagCombine)(UsuallyFlag&~FlagCarry));
00555 break;
00556
00557 case istr_dec:
00558 Operation3(Sub,&Args[0],Args[0],Param(Param::Literal,1,(unsigned char)4),(FlagCombine)(UsuallyFlag&~FlagCarry));
00559 break;
00560
00561
00562
00563
00564
00565
00566 case istr_and:
00567 Operation3(And,&Args[0],Args[0],Args[1],UsuallyFlag);
00568 break;
00569
00570 case istr_or:
00571 Operation3(Or,&Args[0],Args[0],Args[1],UsuallyFlag);
00572 break;
00573
00574 case istr_add:
00575 Operation3(Add,&Args[0],Args[0],Args[1],UsuallyFlag);
00576 break;
00577
00578 case istr_neg:
00579 Operation2(Complement,&Args[0],Args[0],UsuallyFlag);
00580 break;
00581
00582 case istr_not:
00583
00584 Operation2(Negate,&Args[0],Args[0],UsuallyFlag);
00585 break;
00586
00587 case istr_mov:
00588
00589
00590
00591 if (Args[0].RegEqual(Args[1]))
00592 break;
00593
00594
00595 Operation2(Assign,&Args[0],Args[1],FlagNone);
00596 break;
00597
00598 case istr_lea:
00599
00600 if (Args[1].literal == 0)
00601 {
00602
00603 if (Args[0].mem_reg1 == Args[1].mem_reg1 && Args[1].mem_reg2 == null_reg)
00604 break;
00605
00606 if (Args[0].mem_reg1 == Args[1].mem_reg2 && Args[1].mem_reg1 == null_reg && Args[1].factor == 1)
00607 break;
00608 }
00609
00610
00611
00612
00613
00614 if (Args[1].mem_reg2 != null_reg)
00615 {
00616 int s = 1;
00617 switch(Args[1].factor)
00618 {
00619 case 1:
00620
00621 break;
00622 case 8:
00623 ++s;
00624 case 4:
00625 ++s;
00626 case 2:
00627
00628
00629
00630 break;
00631 }
00632 }
00633
00634
00635 break;
00636
00637
00638 case istr_test:
00639 Operation3(And,NULL,Args[0],Args[1],UsuallyFlag);
00640 break;
00641
00642 case istr_cmp:
00643
00644 if (Args[0].RegEqual(Args[1]))
00645 {
00646 SetFlag((FlagCombine)(FlagParity|FlagZero),UsuallyFlag);
00647 break;
00648 }
00649 Operation3(Sub,NULL,Args[0],Args[1],UsuallyFlag);
00650 break;
00651
00652 case istr_jnz:
00653
00654 break;
00655
00656 case istr_push:
00657
00658 {
00659
00660 Param resp(Param::Registry,REG(esp));
00661 Operation3(Sub,&resp,resp,Param(Param::Literal,Args[0].GetSize()==2?2:4,(unsigned char)4),FlagNone);
00662 Param stack(Param::Memory,REG(esp));
00663 Operation2(Assign,&stack,Args[0],FlagNone);
00664 }
00665 break;
00666 case istr_pop:
00667
00668
00669 {
00670 Param stack(Param::Memory,REG(esp));
00671 Operation2(Assign,&Args[0],stack,FlagNone);
00672 Param resp(Param::Registry,REG(esp));
00673 Operation3(Add,&resp,resp,Param(Param::Literal,Args[0].GetSize()==2?2:4,(unsigned char)4),FlagNone);
00674 }
00675 break;
00676
00677 case istr_call:
00678
00679 break;
00680
00681 case istr_ret:
00682
00683 break;
00684 case istr_leave:
00685
00686
00687 break;
00688
00689
00690 default:
00691 fprintf(f,"unknown");
00692 }
00693 fprintf(f,"\n");
00694 }
00695