00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "x86asm.h"
00022
00023 #include <stdlib.h>
00024 #include <string.h>
00025
00026 #define X86ASM_PREFIX_NO 0
00027 #define X86ASM_PREFIX_0F 1
00028 #define X86ASM_PREFIX_0F0F 2
00029 #define X86ASM_PREFIX_D8 3
00030 #define X86ASM_PREFIX_D9 4
00031 #define X86ASM_PREFIX_DA 5
00032 #define X86ASM_PREFIX_DB 6
00033 #define X86ASM_PREFIX_DC 7
00034 #define X86ASM_PREFIX_DD 8
00035 #define X86ASM_PREFIX_DE 9
00036 #define X86ASM_PREFIX_DF 10
00037
00038 #define X86ASM_ERRMSG_AMBIGUOUS "ambiguous command"
00039 #define X86ASM_ERRMSG_UNKNOWN_COMMAND "unknown command '%s'"
00040 #define X86ASM_ERRMSG_UNKNOWN_SYMBOL "unknown symbol '%s'"
00041 #define X86ASM_ERRMSG_INVALID_OPERANDS "invalid operand(s)"
00042 #define X86ASM_ERRMSG_INTERNAL "internal error: "
00043
00044 x86addrcoding modrm16[3][8] = {
00045
00046 {
00047 {X86_REG_BX, X86_REG_SI, 0},
00048 {X86_REG_BX, X86_REG_DI, 0},
00049 {X86_REG_BP, X86_REG_SI, 0},
00050 {X86_REG_BP, X86_REG_DI, 0},
00051 {X86_REG_SI, X86_REG_NO, 0},
00052 {X86_REG_DI, X86_REG_NO, 0},
00053 {X86_REG_NO, X86_REG_NO, 2},
00054 {X86_REG_BX, X86_REG_NO, 0}
00055 },
00056
00057 {
00058 {X86_REG_BX, X86_REG_SI, 1},
00059 {X86_REG_BX, X86_REG_DI, 1},
00060 {X86_REG_BP, X86_REG_SI, 1},
00061 {X86_REG_BP, X86_REG_DI, 1},
00062 {X86_REG_SI, X86_REG_NO, 1},
00063 {X86_REG_DI, X86_REG_NO, 1},
00064 {X86_REG_BP, X86_REG_NO, 1},
00065 {X86_REG_BX, X86_REG_NO, 1}
00066 },
00067
00068 {
00069 {X86_REG_BX, X86_REG_SI, 2},
00070 {X86_REG_BX, X86_REG_DI, 2},
00071 {X86_REG_BP, X86_REG_SI, 2},
00072 {X86_REG_BP, X86_REG_DI, 2},
00073 {X86_REG_SI, X86_REG_NO, 2},
00074 {X86_REG_DI, X86_REG_NO, 2},
00075 {X86_REG_BP, X86_REG_NO, 2},
00076 {X86_REG_BX, X86_REG_NO, 2}
00077 }
00078 };
00079
00080 x86addrcoding modrm32[3][8] = {
00081
00082 {
00083 {X86_REG_AX, X86_REG_NO, 0},
00084 {X86_REG_CX, X86_REG_NO, 0},
00085 {X86_REG_DX, X86_REG_NO, 0},
00086 {X86_REG_BX, X86_REG_NO, 0},
00087 {X86_REG_INVALID, X86_REG_INVALID, -1},
00088 {X86_REG_NO, X86_REG_NO, 4},
00089 {X86_REG_SI, X86_REG_NO, 0},
00090 {X86_REG_DI, X86_REG_NO, 0}
00091 },
00092
00093 {
00094 {X86_REG_AX, X86_REG_NO, 1},
00095 {X86_REG_CX, X86_REG_NO, 1},
00096 {X86_REG_DX, X86_REG_NO, 1},
00097 {X86_REG_BX, X86_REG_NO, 1},
00098 {X86_REG_INVALID, X86_REG_INVALID, -1},
00099 {X86_REG_BP, X86_REG_NO, 1},
00100 {X86_REG_SI, X86_REG_NO, 1},
00101 {X86_REG_DI, X86_REG_NO, 1}
00102 },
00103
00104 {
00105 {X86_REG_AX, X86_REG_NO, 4},
00106 {X86_REG_CX, X86_REG_NO, 4},
00107 {X86_REG_DX, X86_REG_NO, 4},
00108 {X86_REG_BX, X86_REG_NO, 4},
00109 {X86_REG_INVALID, X86_REG_INVALID, -1},
00110 {X86_REG_BP, X86_REG_NO, 4},
00111 {X86_REG_SI, X86_REG_NO, 4},
00112 {X86_REG_DI, X86_REG_NO, 4}
00113 }
00114 };
00115
00116
00117 int lop2hop[10][8] = {
00118
00119 {},
00120
00121 {TYPE_I, TYPE_Is, TYPE_J, TYPE_A, TYPE_Ix},
00122
00123 {TYPE_R, TYPE_Rx, TYPE_G, TYPE_E},
00124
00125 {TYPE_S, TYPE_Sx},
00126
00127 {TYPE_E, TYPE_M, TYPE_O},
00128
00129 {TYPE_C},
00130
00131 {TYPE_D},
00132
00133 {TYPE_T},
00134
00135 {TYPE_F, TYPE_Fx},
00136
00137 {TYPE_P, TYPE_Q}
00138 };
00139
00140
00141 char immhsz8_16[] = { SIZE_B, SIZE_C, SIZE_W, SIZE_V, SIZE_D, 0 };
00142
00143 char immhsz16_16[] = { SIZE_W, SIZE_V, SIZE_D, 0 };
00144
00145 char immhsz32_16[] = { SIZE_D, 0 };
00146
00147
00148 char immhsz8_32[] = { SIZE_B, SIZE_C, SIZE_W, SIZE_V, SIZE_D, 0 };
00149
00150 char immhsz16_32[] = { SIZE_W, SIZE_C, SIZE_D, SIZE_V, 0 };
00151
00152 char immhsz32_32[] = { SIZE_D, SIZE_V, 0 };
00153
00154
00155 char hsz8_16[] = { SIZE_B, SIZE_C, 0 };
00156
00157 char hsz16_16[] = { SIZE_W, SIZE_V, 0 };
00158
00159 char hsz32_16[] = { SIZE_D, SIZE_P, 0 };
00160
00161 char hsz48_16[] = { 0 };
00162
00163 char hsz64_16[] = { SIZE_Q, 0};
00164
00165
00166 char hsz8_32[] = { SIZE_B, 0 };
00167
00168 char hsz16_32[] = { SIZE_W, SIZE_C, 0 };
00169
00170 char hsz32_32[] = { SIZE_D, SIZE_V, 0 };
00171
00172 char hsz48_32[] = { SIZE_P, 0 };
00173
00174 char hsz64_32[] = { SIZE_Q, 0};
00175
00176 int reg2size[3]= {1, 2, 4};
00177
00178 int iswhitespace(char c)
00179 {
00180 return ((((unsigned char)c)<=' ') && c);
00181 }
00182
00183 int isnotwhitespace(char c)
00184 {
00185 return ( !(((unsigned char)c)<=' ') && c);
00186 }
00187
00188
00189
00190
00191
00192 x86asm::x86asm(int o, int a)
00193 : Assembler(false)
00194 {
00195 opsize=o;
00196 addrsize=a;
00197 }
00198
00199 x86asm::~x86asm()
00200 {
00201 }
00202
00203 asm_insn *x86asm::alloc_insn()
00204 {
00205 return (asm_insn *)malloc(sizeof(x86asm_insn));
00206 }
00207
00208 void x86asm::delete_nonsense()
00209 {
00210 restart:
00211 asm_code *c=codes;
00212 while (c) {
00213 if (delete_nonsense_insn(c)) goto restart;
00214 c=c->next;
00215 }
00216 }
00217
00218 int x86asm::delete_nonsense_insn(asm_code *code)
00219 {
00220 byte *d=code->data;
00221 int size=code->size;
00222 while ((*d==0x66) || (*d==0x67)) {
00223 d++;
00224 size--;
00225 }
00226 asm_code *c=codes;
00227 while (c) {
00228 if ((bool)c->context==0) {
00229 byte *cd=c->data;
00230 int csize=c->size;
00231 while ((*cd==0x66) || (*cd==0x67)) {
00232 cd++;
00233 csize--;
00234 }
00235 if ((c->size < code->size) && (size==csize)) {
00236 if (memcmp(d, cd, size)==0) {
00237 deletecode(code);
00238 return 1;
00239 }
00240 }
00241 }
00242 c=c->next;
00243 }
00244 return 0;
00245 }
00246
00247 void x86asm::emitdisp(dword d, int size)
00248 {
00249 dispsize=size;
00250 disp=d;
00251 }
00252
00253 void x86asm::emitimm(dword i, int size)
00254 {
00255 immsize=size;
00256 imm=i;
00257 }
00258
00259 void x86asm::emitfarptr(dword s, dword o, bool big)
00260 {
00261 if (big) {
00262 immsize=6;
00263 imm=o;
00264 imm2=s;
00265 } else {
00266 immsize=4;
00267 imm=(s<<16) | (o & 0xffff);
00268 }
00269 }
00270
00271 void x86asm::emitmodrm(int modrm)
00272 {
00273 if (modrmv==-1) modrmv=0;
00274 modrmv=modrm;
00275 }
00276
00277 void x86asm::emitmodrm_mod(int mod)
00278 {
00279 if (modrmv==-1) modrmv=0;
00280 modrmv=(modrmv& ~(3<<6))|((mod&3)<<6);
00281 }
00282
00283 void x86asm::emitmodrm_reg(int reg)
00284 {
00285 if (modrmv==-1) modrmv=0;
00286 modrmv=(modrmv& ~(7<<3))|((reg&7)<<3);
00287 }
00288
00289 void x86asm::emitmodrm_rm(int rm)
00290 {
00291 if (modrmv==-1) modrmv=0;
00292 modrmv=(modrmv& ~(7))|(rm&7);
00293 }
00294
00295 void x86asm::emitsib_base(int base)
00296 {
00297 if (sibv==-1) sibv=0;
00298 sibv=(sibv& ~7)|(base&7);
00299 }
00300
00301 void x86asm::emitsib_index(int index)
00302 {
00303 if (sibv==-1) sibv=0;
00304 sibv=(sibv& ~(7<<3))|((index&7)<<3);
00305 }
00306
00307 void x86asm::emitsib_scale(int scale)
00308 {
00309 if (sibv==-1) sibv=0;
00310 sibv=(sibv& ~(3<<6))|((scale&3)<<6);
00311 }
00312
00313 asm_code *x86asm::encode(asm_insn *asm_insn, int options, CPU_ADDR cur_address)
00314 {
00315 Assembler::encode(asm_insn, options, cur_address);
00316 x86asm_insn *insn=(x86asm_insn*)asm_insn;
00317
00318 addrsize_depend=0;
00319 for (int i=0; i<3; i++) {
00320 if (insn->op[i].type==X86_OPTYPE_MEM) {
00321 addrsize_depend=1;
00322 break;
00323 }
00324 }
00325
00326 newcode();
00327 namefound=0;
00328 address=cur_address.addr32.offset;
00329 esizes[0]=0;
00330 esizes[1]=0;
00331 esizes[2]=0;
00332 ambiguous=0;
00333 match_opcodes(x86_insns, insn, X86ASM_PREFIX_NO);
00334 match_opcodes(x86_insns_ext, insn, X86ASM_PREFIX_0F);
00335 match_fopcodes(insn);
00336 if (error) {
00337 free_asm_codes();
00338 } else if (!codes) {
00339 if (namefound) {
00340 set_error_msg(X86ASM_ERRMSG_INVALID_OPERANDS);
00341 } else {
00342 set_error_msg(X86ASM_ERRMSG_UNKNOWN_COMMAND, insn->name);
00343 }
00344 } else {
00345 delete_nonsense();
00346 }
00347 return codes;
00348 }
00349
00350 int x86asm::encode_insn(x86asm_insn *insn, x86opc_insn *opcode, int opcodeb, int additional_opcode, int prefix, int eopsize, int eaddrsize)
00351 {
00352 bool opsize_depend=0;
00353 for (int i=0; i<3; i++) {
00354 switch (opcode->op[i].size) {
00355 case SIZE_C:
00356 case SIZE_V:
00357 case SIZE_P:
00358 opsize_depend=1;
00359 break;
00360 }
00361 }
00362
00363 code.context=(void*)opsize_depend;
00364
00365 modrmv=-1;
00366 sibv=-1;
00367 dispsize=0;
00368 immsize=0;
00369 if (additional_opcode!=-1) {
00370 emitmodrm_reg(additional_opcode);
00371 }
00372
00373 if (eopsize!=opsize) emitbyte(0x66);
00374 if (eaddrsize!=addrsize) emitbyte(0x67);
00375
00376 switch (insn->lockprefix) {
00377 case X86_PREFIX_LOCK: emitbyte(0xf0); break;
00378 }
00379 switch (insn->repprefix) {
00380 case X86_PREFIX_REPNZ: emitbyte(0xf2); break;
00381 case X86_PREFIX_REPZ: emitbyte(0xf3); break;
00382 }
00383 switch (insn->segprefix) {
00384 case X86_PREFIX_ES: emitbyte(0x26); break;
00385 case X86_PREFIX_CS: emitbyte(0x2e); break;
00386 case X86_PREFIX_SS: emitbyte(0x36); break;
00387 case X86_PREFIX_DS: emitbyte(0x3e); break;
00388 case X86_PREFIX_FS: emitbyte(0x64); break;
00389 case X86_PREFIX_GS: emitbyte(0x65); break;
00390 }
00391
00392 int i=0;
00393 switch (prefix) {
00394 case X86ASM_PREFIX_0F0F:
00395 emitword(0x0f);
00396 case X86ASM_PREFIX_0F:
00397 emitbyte(0x0f);
00398 case X86ASM_PREFIX_NO:
00399 emitbyte(opcodeb);
00400 break;
00401 case X86ASM_PREFIX_DF: i++;
00402 case X86ASM_PREFIX_DE: i++;
00403 case X86ASM_PREFIX_DD: i++;
00404 case X86ASM_PREFIX_DC: i++;
00405 case X86ASM_PREFIX_DB: i++;
00406 case X86ASM_PREFIX_DA: i++;
00407 case X86ASM_PREFIX_D9: i++;
00408 case X86ASM_PREFIX_D8:
00409 emitbyte(0xd8+i);
00410 emitmodrm(opcodeb);
00411 break;
00412 }
00413
00414 for (int i=0; i<3; i++) {
00415 if (!encode_op(&insn->op[i], &opcode->op[i], &esizes[i], eopsize, eaddrsize)) {
00416 clearcode();
00417 return 0;
00418 }
00419 }
00420
00421 if (modrmv!=-1) emitbyte(modrmv);
00422 if (sibv!=-1) emitbyte(sibv);
00423 switch (dispsize) {
00424 case 1:
00425 emitbyte(disp);
00426 break;
00427 case 2:
00428 emitword(disp);
00429 break;
00430 case 4:
00431 emitdword(disp);
00432 break;
00433 }
00434 switch (immsize) {
00435 case 1:
00436 emitbyte(imm);
00437 break;
00438 case 2:
00439 emitword(imm);
00440 break;
00441 case 4:
00442 emitdword(imm);
00443 break;
00444 case 6:
00445 emitdword(imm);
00446 emitword(imm2);
00447 break;
00448 }
00449 return 1;
00450 }
00451
00452 int x86asm::encode_modrm(x86_insn_op *op, char size, int allow_reg, int allow_mem, int eopsize, int eaddrsize)
00453 {
00454 switch (op->type) {
00455 case X86_OPTYPE_REG:
00456 if (!allow_reg) return 0;
00457 emitmodrm_mod(3);
00458 emitmodrm_rm(op->reg);
00459 break;
00460 case X86_OPTYPE_MEM: {
00461 if (!allow_mem) return 0;
00462
00463
00464 int mindispsize=op->mem.disp ? simmsize(op->mem.disp, 4) : 0;
00465 int addrsize=op->mem.addrsize;
00466 if (addrsize==X86_ADDRSIZEUNKNOWN) addrsize=eaddrsize;
00467 if (addrsize==X86_ADDRSIZE16) {
00468 int mod, rm, dispsize;
00469 if (!encode_modrm_v(&modrm16, op, mindispsize, &mod, &rm, &dispsize)) return 0;
00470 emitmodrm_mod(mod);
00471 emitmodrm_rm(rm);
00472 emitdisp(op->mem.disp, dispsize);
00473 } else {
00474 int mod, rm, dispsize;
00475 if (!encode_modrm_v(&modrm32, op, mindispsize, &mod, &rm, &dispsize)) {
00476 int scale, index, base, disp=op->mem.disp;
00477 if (encode_sib_v(op, mindispsize, &scale, &index, &base, &mod, &dispsize, &disp)) {
00478 emitmodrm_mod(mod);
00479 emitmodrm_rm(4);
00480 emitsib_scale(scale);
00481 emitsib_index(index);
00482 emitsib_base(base);
00483 emitdisp(disp, dispsize);
00484 } else return 0;
00485 } else {
00486 emitmodrm_mod(mod);
00487 emitmodrm_rm(rm);
00488 emitdisp(op->mem.disp, dispsize);
00489 }
00490 }
00491 break;
00492 }
00493 default:
00494 return 0;
00495 }
00496 return 1;
00497 }
00498
00499 int x86asm::encode_modrm_v(x86addrcoding (*modrmc)[3][8], x86_insn_op *op, int mindispsize, int *_mod, int *_rm, int *_dispsize)
00500 {
00501 if (op->mem.scale>1) return 0;
00502 for (int mod=0; mod<3; mod++) {
00503 for (int rm=0; rm<8; rm++) {
00504 x86addrcoding *c=&(*modrmc)[mod][rm];
00505 int r1=c->reg1, r2=c->reg2;
00506 if (r2==op->mem.base) {
00507 int t=r1;
00508 r1=r2;
00509 r2=t;
00510 }
00511 if ((r1==op->mem.base) && (r2==op->mem.index) && (c->dispsize>=mindispsize)) {
00512 *_mod=mod;
00513 *_rm=rm;
00514 *_dispsize=c->dispsize;
00515 return 1;
00516 }
00517 }
00518 }
00519 return 0;
00520 }
00521
00522 int x86asm::encode_op(x86_insn_op *op, x86opc_insn_op *xop, int *esize, int eopsize, int eaddrsize)
00523 {
00524 int psize=op->size;
00525 switch (xop->type) {
00526 case TYPE_0:
00527 return 1;
00528 case TYPE_A:
00529
00530 if (op->type == X86_OPTYPE_FARPTR) {
00531 int size = esizeop(xop->size, eopsize);
00532 emitfarptr(op->farptr.seg, op->farptr.offset, size == 6);
00533 } else {
00534 emitimm(op->imm, op->size);
00535 }
00536 break;
00537 case TYPE_C:
00538
00539 emitmodrm_reg(op->crx);
00540 break;
00541 case TYPE_D:
00542
00543 emitmodrm_reg(op->drx);
00544 break;
00545 case TYPE_E:
00546
00547 if (!encode_modrm(op, xop->extendedsize, 1, 1, eopsize, eaddrsize)) return 0;
00548 psize=esizeop(xop->extendedsize, eopsize);
00549 break;
00550 case TYPE_F:
00551
00552 emitmodrm_rm(op->stx);
00553 break;
00554 case TYPE_Fx:
00555
00556 return 1;
00557 case TYPE_G:
00558
00559 emitmodrm_reg(op->reg);
00560 break;
00561 case TYPE_Is: {
00562
00563 int size=esizeop(xop->size, eopsize);
00564 emitimm(op->imm, size);
00565 break;
00566 }
00567 case TYPE_I: {
00568
00569 int size=esizeop(xop->size, eopsize);
00570 emitimm(op->imm, size);
00571 break;
00572 }
00573 case TYPE_Ix:
00574
00575 return 1;
00576 case TYPE_J: {
00577
00578 int size=esizeop(xop->size, eopsize);
00579 emitimm(op->imm-address-code.size-size, size);
00580 break;
00581 }
00582 case TYPE_M:
00583
00584 if (!encode_modrm(op, xop->extendedsize, 0, 1, eopsize, eaddrsize)) return 0;
00585 psize=esizeop(xop->extendedsize, eopsize);
00586 break;
00587 case TYPE_O: {
00588
00589 if (op->mem.base!=X86_REG_NO) return 0;
00590 if (op->mem.index!=X86_REG_NO) return 0;
00591 psize=esizeop(xop->extendedsize, eopsize);
00592 switch (eaddrsize) {
00593 case X86_ADDRSIZE16:
00594 emitdisp(op->mem.disp, 2);
00595 break;
00596 case X86_ADDRSIZE32:
00597 emitdisp(op->mem.disp, 4);
00598 break;
00599 }
00600 break;
00601 }
00602 case TYPE_P:
00603
00604 break;
00605 case TYPE_Q:
00606
00607 break;
00608 case TYPE_R:
00609
00610 emitmodrm_rm(op->reg);
00611 break;
00612 case TYPE_Rx:
00613
00614 return 1;
00615 case TYPE_S:
00616
00617 emitmodrm_reg(op->seg);
00618 break;
00619 case TYPE_Sx:
00620
00621 return 1;
00622 case TYPE_T:
00623
00624 emitmodrm_reg(op->trx);
00625 break;
00626 }
00627 if (!psize) {
00628
00629 }
00630 if (!*esize) *esize=psize;
00631
00632
00633
00634
00635
00636 return 1;
00637 }
00638
00639 int x86asm::encode_sib_v(x86_insn_op *op, int mindispsize, int *_ss, int *_index, int *_base, int *_mod, int *_dispsize, int *disp)
00640 {
00641 int ss, scale=op->mem.scale, index=op->mem.index, base=op->mem.base, mod, dispsize;
00642 if ((base==X86_REG_NO) && (index!=X86_REG_NO)) {
00643 switch (scale) {
00644 case 1:case 4:case 8:
00645 break;
00646 case 2:case 3:case 5:case 9:
00647 scale--;
00648 base=index;
00649 break;
00650 default:
00651 return 0;
00652 }
00653 }
00654 if (index==X86_REG_SP) {
00655 if (scale>1) return 0;
00656 if (scale == 1) {
00657 if (base==X86_REG_SP) return 0;
00658 int temp = index;
00659 index = base;
00660 base = temp;
00661 }
00662 }
00663 if (index!=X86_REG_NO) {
00664 switch (scale) {
00665 case 1:
00666 ss=0;
00667 break;
00668 case 2:
00669 ss=1;
00670 break;
00671 case 4:
00672 ss=2;
00673 break;
00674 case 8:
00675 ss=3;
00676 break;
00677 default:
00678 return 0;
00679 }
00680 } else {
00681 ss=0;
00682 index=4;
00683 }
00684 switch (mindispsize) {
00685 case 0:
00686 mod=0;
00687 dispsize=0;
00688 break;
00689 case 1:
00690 mod=1;
00691 dispsize=1;
00692 break;
00693 case 2:case 4:
00694 mod=2;
00695 dispsize=4;
00696 break;
00697 default:
00698 return 0;
00699 }
00700 if ((base==X86_REG_BP) && (mod==0)) {
00701 mod=1;
00702 dispsize=1;
00703 if (!mindispsize) *disp=0;
00704 }
00705 if (base==X86_REG_NO) {
00706 base=5;
00707 mod=0;
00708 dispsize=4;
00709 if (!mindispsize) *disp=0;
00710 }
00711 *_mod=mod;
00712 *_ss=ss;
00713 *_index=index;
00714 *_base=base;
00715 *_dispsize=dispsize;
00716 return 1;
00717 }
00718
00719 int x86asm::esizeaddr(char c, int size)
00720 {
00721 switch (c) {
00722 case SIZE_A:
00723 if (size==X86_ADDRSIZE16) return 4; else return 6;
00724 case SIZE_B:
00725 return 1;
00726 case SIZE_W:
00727 return 2;
00728 case SIZE_D:
00729 return 4;
00730 case SIZE_Q:
00731 return 8;
00732 case SIZE_C:
00733 if (size==X86_ADDRSIZE16) return 1; else return 2;
00734 case SIZE_V:
00735 if (size==X86_ADDRSIZE16) return 2; else return 4;
00736 case SIZE_P:
00737 if (size==X86_ADDRSIZE16) return 4; else return 6;
00738 }
00739 return 0;
00740 }
00741
00742 int x86asm::esizeop(char c, int size)
00743 {
00744 switch (c) {
00745 case SIZE_B:
00746 return 1;
00747 case SIZE_W:
00748 return 2;
00749 case SIZE_D:
00750 return 4;
00751 case SIZE_Q:
00752 return 8;
00753 case SIZE_S:
00754 return 4;
00755 case SIZE_L:
00756 return 8;
00757 case SIZE_T:
00758 return 10;
00759 case SIZE_C:
00760 if (size==X86_OPSIZE16) return 1; else return 2;
00761 case SIZE_V:
00762 if (size==X86_OPSIZE16) return 2; else return 4;
00763 case SIZE_P:
00764 if (size==X86_OPSIZE16) return 4; else return 6;
00765 }
00766 return 0;
00767 }
00768
00769 int x86asm::fetch_number(char **s, dword *value)
00770 {
00771 char *e;
00772 char *t=*s;
00773
00774 dword i=strtoul(t, &e, 0);
00775 if ((*t>='0') && (*t<='9')) {
00776 while (strchr("0123456789abcdef", *t) && *t) t++;
00777 if (*t=='h') {
00778
00779 i=strtoul(*s, &e, 16);
00780 e=t+1;
00781 }
00782 }
00783 if (e==*s) return 0;
00784 *s=e;
00785 *value=i;
00786 return 1;
00787 }
00788
00789 char x86asm::flsz2hsz(int size)
00790 {
00791 switch (size) {
00792 case 4:
00793 return SIZE_S;
00794 case 8:
00795 return SIZE_L;
00796 case 10:
00797 return SIZE_T;
00798 }
00799 return 0;
00800 }
00801
00802 char *x86asm::get_name()
00803 {
00804 return "x86asm";
00805 }
00806
00807 char *x86asm::immlsz2hsz(int size, int opsize)
00808 {
00809 if (opsize==X86_OPSIZE16) {
00810 switch (size) {
00811 case 1:
00812 return immhsz8_16;
00813 case 2:
00814 return immhsz16_16;
00815 case 4:
00816 return immhsz32_16;
00817 }
00818 } else {
00819 switch (size) {
00820 case 1:
00821 return immhsz8_32;
00822 case 2:
00823 return immhsz16_32;
00824 case 4:
00825 return immhsz32_32;
00826 }
00827 }
00828 return 0;
00829 }
00830
00831 char *x86asm::lsz2hsz(int size, int opsize)
00832 {
00833 if (opsize==X86_OPSIZE16) {
00834 switch (size) {
00835 case 1:
00836 return hsz8_16;
00837 case 2:
00838 return hsz16_16;
00839 case 4:
00840 return hsz32_16;
00841 case 6:
00842 return hsz48_16;
00843 case 8:
00844 return hsz64_16;
00845 }
00846 } else {
00847 switch (size) {
00848 case 1:
00849 return hsz8_32;
00850 case 2:
00851 return hsz16_32;
00852 case 4:
00853 return hsz32_32;
00854 case 6:
00855 return hsz48_32;
00856 case 8:
00857 return hsz64_32;
00858 }
00859 }
00860 return 0;
00861 }
00862
00863 int x86asm::match_type(x86_insn_op *op, x86opc_insn_op *xop, int addrsize)
00864 {
00865 int *hop=lop2hop[op->type];
00866 if ((op->type==X86_OPTYPE_EMPTY) && (xop->type==TYPE_0)) return 1;
00867 while (*hop) {
00868 if (*hop==xop->type) {
00869 if (xop->type==TYPE_Rx) {
00870 if (xop->extra==op->reg) return 1;
00871 } else if (xop->type==TYPE_Sx) {
00872 if (xop->extra==op->seg) return 1;
00873 } else if (xop->type==TYPE_Ix) {
00874 if ((unsigned)xop->extra==op->imm) return 1;
00875 } else if (xop->type==TYPE_Fx) {
00876 if (xop->extra==op->stx) return 1;
00877 } else if (op->type==X86_OPTYPE_MEM) {
00878 if (op->mem.addrsize==addrsize) return 1;
00879 if (op->mem.addrsize==X86_ADDRSIZEUNKNOWN) return 1;
00880 } else return 1;
00881 }
00882 hop++;
00883 }
00884 return 0;
00885 }
00886
00887 int x86asm::match_size(x86_insn_op *op, x86opc_insn_op *xop, int opsize)
00888 {
00889 if ((op->type==X86_OPTYPE_EMPTY) && (xop->type==TYPE_0)) return 1;
00890 if ((!op->size) && (xop->type!=TYPE_0)) return 1;
00891 char *hsz = NULL;
00892 if (((op->type==X86_OPTYPE_MEM) && (op->mem.floatptr)) || (op->type==X86_OPTYPE_STX)) {
00893 return (xop->size==flsz2hsz(op->size));
00894 } else if (op->type==X86_OPTYPE_IMM) {
00895 if (xop->type==TYPE_Is) {
00896 hsz=immlsz2hsz(simmsize(op->imm, esizeop(xop->extendedsize, opsize)), opsize);
00897 } else if (xop->type==TYPE_J) {
00898 int size=esizeop(xop->size, opsize);
00899
00900 hsz=immlsz2hsz(simmsize(op->imm-address-code.size-size-1, 4), opsize);
00901 } else {
00902 hsz=immlsz2hsz(op->size, opsize);
00903 }
00904 } else {
00905 hsz=lsz2hsz(op->size, opsize);
00906 }
00907 if (hsz) {
00908 while (*hsz) {
00909 if (*hsz==xop->size) return 1;
00910 hsz++;
00911 }
00912 }
00913 return 0;
00914 }
00915
00916 int x86asm::match_allops(x86asm_insn *insn, x86opc_insn *xinsn, int opsize, int addrsize)
00917 {
00918 for (int i=0; i<3; i++) {
00919 if (!match_type(&insn->op[i], &xinsn->op[i], addrsize)) return 0;
00920 if (!match_size(&insn->op[i], &xinsn->op[i], opsize)) return 0;
00921 }
00922 return 1;
00923 }
00924
00925 #define MATCHOPNAME_NOMATCH 0
00926 #define MATCHOPNAME_MATCH 1
00927 #define MATCHOPNAME_MATCH_IF_OPSIZE16 2
00928 #define MATCHOPNAME_MATCH_IF_OPSIZE32 3
00929
00930 int x86asm::match_opcode_name(char *input_name, char *opcodelist_name)
00931 {
00932 if (opcodelist_name) {
00933 if (strstr(opcodelist_name, "%c")) {
00934 char n[32];
00935 sprintf(n, opcodelist_name, 'w');
00936 if (strcmp(input_name, n)==0) return MATCHOPNAME_MATCH_IF_OPSIZE16;
00937 sprintf(n, opcodelist_name, 'd');
00938 if (strcmp(input_name, n)==0) return MATCHOPNAME_MATCH_IF_OPSIZE32;
00939 } else {
00940 if (strcmp(input_name, opcodelist_name)==0) return MATCHOPNAME_MATCH;
00941 }
00942 }
00943 return MATCHOPNAME_NOMATCH;
00944 }
00945
00946 #define OPSIZE_INV(opsize) (opsize==X86_OPSIZE16 ? X86_OPSIZE32 : X86_OPSIZE16)
00947 #define ADDRSIZE_INV(addrsize) (addrsize==X86_ADDRSIZE16 ? X86_ADDRSIZE32 : X86_ADDRSIZE16)
00948
00949 void x86asm::match_opcode(x86opc_insn *opcode, x86asm_insn *insn, int prefix, byte opcodebyte, int additional_opcode)
00950 {
00951 int n=match_opcode_name(insn->name, opcode->name);
00952 namefound|=n;
00953 if (n!=MATCHOPNAME_NOMATCH) {
00954 if (((opsize==X86_OPSIZE16) && (n!=MATCHOPNAME_MATCH_IF_OPSIZE32)) || ((opsize==X86_OPSIZE32) && (n!=MATCHOPNAME_MATCH_IF_OPSIZE16))) {
00955 if ((match_opcode_final(opcode, insn, prefix, opcodebyte, additional_opcode, opsize, addrsize) && !addrsize_depend) || error) return;
00956 if ((match_opcode_final(opcode, insn, prefix, opcodebyte, additional_opcode, opsize, ADDRSIZE_INV(addrsize)) && !addrsize_depend) || error) return;
00957 }
00958 if (((opsize==X86_OPSIZE16) && (n!=MATCHOPNAME_MATCH_IF_OPSIZE16)) || ((opsize==X86_OPSIZE32) && (n!=MATCHOPNAME_MATCH_IF_OPSIZE32))) {
00959 if ((match_opcode_final(opcode, insn, prefix, opcodebyte, additional_opcode, OPSIZE_INV(opsize), addrsize) && !addrsize_depend) || error) return;
00960 if ((match_opcode_final(opcode, insn, prefix, opcodebyte, additional_opcode, OPSIZE_INV(opsize), ADDRSIZE_INV(addrsize)) && !addrsize_depend) || error) return;
00961 }
00962 }
00963 }
00964
00965 int x86asm::match_opcode_final(x86opc_insn *opcode, x86asm_insn *insn, int prefix, byte opcodebyte, int additional_opcode, int opsize, int addrsize)
00966 {
00967 if (match_allops(insn, opcode, opsize, addrsize)) {
00968
00969 if (encode_insn(insn, opcode, opcodebyte, additional_opcode, prefix, opsize, addrsize)) {
00970 pushcode();
00971 newcode();
00972 }
00973 return 1;
00974 }
00975 return 0;
00976 }
00977
00978 void x86asm::match_opcodes(x86opc_insn *opcodes, x86asm_insn *insn, int prefix)
00979 {
00980 for (int i=0; i<256; i++) {
00981 if (!opcodes[i].name) {
00982 x86opc_insn_op_special special=*((x86opc_insn_op_special*)(&opcodes[i].op[0]));
00983 if (special.type==SPECIAL_TYPE_GROUP) {
00984 x86opc_insn *group=x86_group_insns[(unsigned char)special.data];
00985 for (int g=0; g<8; g++) {
00986 match_opcode(&group[g], insn, prefix, i, g);
00987 }
00988 }
00989 }
00990 match_opcode(&opcodes[i], insn, prefix, i, -1);
00991 }
00992 }
00993
00994 void x86asm::match_fopcodes(x86asm_insn *insn)
00995 {
00996
00997 for (int i=0; i<8; i++) {
00998 for (int j=0; j<8; j++) {
00999 int n=match_opcode_name(insn->name, x86_modfloat_group_insns[i][j].name);
01000 namefound|=n;
01001 if (n!=MATCHOPNAME_NOMATCH) {
01002 int addrsize=X86_ADDRSIZE16;
01003 while (1) {
01004 if (match_allops(insn, &x86_modfloat_group_insns[i][j], opsize, addrsize)) {
01005 if (encode_insn(insn, &x86_modfloat_group_insns[i][j], j<<3, -1, X86ASM_PREFIX_D8+i, opsize, addrsize)) {
01006 pushcode();
01007 newcode();
01008 }
01009 if (error) return;
01010 }
01011 if (addrsize==X86_ADDRSIZE16) addrsize=X86_ADDRSIZE32; else break;
01012 }
01013 }
01014 }
01015 }
01016
01017 for (int i=0; i<8; i++) {
01018 for (int j=0; j<8; j++) {
01019 if (x86_float_group_insns[i][j].group==0) {
01020 int n=match_opcode_name(insn->name, x86_float_group_insns[i][j].insn.name);
01021 namefound|=n;
01022 if (n!=MATCHOPNAME_NOMATCH) {
01023 if (match_allops(insn, &x86_float_group_insns[i][j].insn, opsize, addrsize)) {
01024 if (encode_insn(insn, &x86_float_group_insns[i][j].insn, 0xc0 | j<<3, -1, X86ASM_PREFIX_D8+i, opsize, addrsize)) {
01025 pushcode();
01026 newcode();
01027 }
01028 if (error) return;
01029 }
01030 }
01031 } else {
01032 x86opc_insn *group=x86_float_group_insns[i][j].group;
01033 for (int k=0; k<8; k++) {
01034 int n=match_opcode_name(insn->name, group[k].name);
01035 namefound|=n;
01036 if (n!=MATCHOPNAME_NOMATCH) {
01037 int addrsize=X86_ADDRSIZE16;
01038 while (1) {
01039 if (match_allops(insn, &group[k], opsize, addrsize)) {
01040 if (encode_insn(insn, &group[k], 0xc0 | j<<3 | k, -1, X86ASM_PREFIX_D8+i, opsize, addrsize)) {
01041 pushcode();
01042 newcode();
01043 }
01044 if (error) return;
01045 }
01046 if (addrsize==X86_ADDRSIZE16) addrsize=X86_ADDRSIZE32; else break;
01047 }
01048 }
01049 }
01050 }
01051 }
01052 }
01053 }
01054
01055 int x86asm::opreg(x86_insn_op *op, char *xop)
01056 {
01057 for (int i=0; i<3; i++) {
01058 for (int j=0; j<8; j++) {
01059 if (x86_regs[i][j] && strcmp(xop, x86_regs[i][j])==0) {
01060 op->type=X86_OPTYPE_REG;
01061 op->size=reg2size[i];
01062 op->reg=j;
01063 return 1;
01064 }
01065 }
01066 }
01067 return 0;
01068 }
01069
01070 int x86asm::opseg(x86_insn_op *op, char *xop)
01071 {
01072 for (int i=0; i<8; i++) {
01073 if (x86_segs[i] && strcmp(xop, x86_segs[i])==0) {
01074 op->type=X86_OPTYPE_SEG;
01075 op->size=2;
01076 op->seg=i;
01077 return 1;
01078 }
01079 }
01080 return 0;
01081 }
01082
01083 int x86asm::opfarptr(x86_insn_op *op, char *xop)
01084 {
01085 dword seg, offset;
01086 char *x = xop;
01087 if (!fetch_number(&x, &seg)) return 0;
01088 if (*x!=':') return 0;
01089 x++;
01090 if (!fetch_number(&x, &offset)) return 0;
01091 if (*x) return 0;
01092 op->type=X86_OPTYPE_FARPTR;
01093 if (offset>0xffff) op->size=6; else op->size=4;
01094 op->farptr.seg=seg;
01095 op->farptr.offset=offset;
01096 return 1;
01097 }
01098
01099 int x86asm::opimm(x86_insn_op *op, char *xop)
01100 {
01101 dword i;
01102 if (!fetch_number(&xop, &i)) return 0;
01103 if (*xop) return 0;
01104 op->type=X86_OPTYPE_IMM;
01105 if (i>0xffff) op->size=4; else if (i>0xff) op->size=2; else op->size=1;
01106 op->imm=i;
01107 return 1;
01108 }
01109
01110 int x86asm::opplugimm(x86_insn_op *op, char *xop)
01111 {
01112 dword d;
01113 if (imm_eval_proc && imm_eval_proc(imm_eval_context, &xop, &d)) {
01114 if (*xop) return 0;
01115 op->type=X86_OPTYPE_IMM;
01116 if (d>0xffff) op->size=4; else if (d>0xff) op->size=2; else op->size=1;
01117 op->imm=d;
01118 return 1;
01119 }
01120 return 0;
01121 }
01122
01123 int x86asm::opmem(x86asm_insn *asm_insn, x86_insn_op *op, char *s)
01124 {
01125
01126 int opsize=0, hsize=0;
01127 int floatptr=0;
01128
01129
01130 while (strchr(" \t", *s) && *s) s++;
01131 if (strncmp(s, "byte", 4)==0) {
01132 hsize=1;
01133 s+=4;
01134 } else if (strncmp(s, "word", 4)==0) {
01135 hsize=2;
01136 s+=4;
01137 } else if (strncmp(s, "dword", 5)==0) {
01138 hsize=4;
01139 s+=5;
01140 } else if (strncmp(s, "pword", 5)==0) {
01141 hsize=6;
01142 s+=5;
01143 } else if (strncmp(s, "qword", 5)==0) {
01144 hsize=8;
01145 s+=5;
01146 } else if (strncmp(s, "single", 6)==0) {
01147 hsize=4;
01148 s+=6;
01149 floatptr=1;
01150 } else if (strncmp(s, "double", 6)==0) {
01151 hsize=8;
01152 s+=6;
01153 floatptr=1;
01154 } else if (strncmp(s, "extended", 8)==0) {
01155 hsize=10;
01156 s+=8;
01157 floatptr=1;
01158 }
01159 if (hsize) {
01160 if (!strchr(" \t", *s) || !*s) return 0;
01161 while (strchr(" \t", *s) && *s) s++;
01162 if (!strncmp(s, "ptr", 3)==0) return 0;
01163 opsize=hsize;
01164 s+=3;
01165 while (strchr(" \t", *s) && *s) s++;
01166 }
01167
01168
01169 while (strchr(" \t", *s) && *s) s++;
01170 for (int i=0; i<8; i++) {
01171 if (x86_segs[i]) {
01172 int l=strlen(x86_segs[i]);
01173 if ((strncmp(s, x86_segs[i], l)==0) && (s[l]==':')) {
01174 s+=l+1;
01175 int c2p[8]={X86_PREFIX_ES, X86_PREFIX_CS, X86_PREFIX_SS, X86_PREFIX_DS, X86_PREFIX_FS, X86_PREFIX_GS, 0, 0};
01176 asm_insn->segprefix=c2p[i];
01177 break;
01178 }
01179 }
01180 }
01181
01182
01183 if (*s!='[') return 0;
01184 s++;
01185
01186 int scale=0, index=X86_REG_NO, base=X86_REG_NO;
01187 dword disp=0;
01188 int addrsize=X86_ADDRSIZEUNKNOWN;
01189 int lasttokenreg=X86_REG_NO;
01190
01191 int sign=0;
01192 char buf[64];
01193 while (1) {
01194 cont:
01195 char *t;
01196 while (strchr(" \t", *s) && *s) s++;
01197 t=s;
01198 if (strchr("*+-[]()", *s) && *s) {
01199 s++;
01200 } else {
01201 while (!strchr(" \t*+-[]()", *s) && *s) s++;
01202 }
01203 strncpy(buf, t, s-t);
01204 buf[s-t]=0;
01205 t=buf;
01206 if (*t=='+') {
01207 sign=0;
01208 continue;
01209 }
01210 if (*t=='-') {
01211 sign=1;
01212 continue;
01213 }
01214 if (*t==']') break;
01215 if (*t=='*') {
01216 if (lasttokenreg==X86_REG_NO) {
01217
01218 return 0;
01219 } else {
01220 dword v;
01221 if (!fetch_number(&s, &v)) return 0;
01222 if (v>1) {
01223 if (index==lasttokenreg) {
01224 scale+=v-1;
01225 } else if (base==lasttokenreg) {
01226 if (index!=X86_REG_NO) return 0;
01227 index=base;
01228 base=X86_REG_NO;
01229 scale=v;
01230 }
01231 }
01232 }
01233 lasttokenreg=X86_REG_NO;
01234 continue;
01235 }
01236
01237 for (int i=1; i<3; i++) {
01238 for (int j=0; j<8; j++) {
01239 if (x86_regs[i][j] && strcmp(t, x86_regs[i][j])==0) {
01240 if (sign) return 0;
01241 int caddrsize=(i==1) ? X86_ADDRSIZE16 : X86_ADDRSIZE32;
01242 if (addrsize==X86_ADDRSIZEUNKNOWN) {
01243 addrsize=caddrsize;
01244 } else if (addrsize!=caddrsize) return 0;
01245 if (index==j) {
01246 scale++;
01247 } else if (base==X86_REG_NO) {
01248 base=j;
01249 } else if (index==X86_REG_NO) {
01250 index=j;
01251 scale=1;
01252 } else if ((base==j) && (scale==1)) {
01253 int t=index;
01254 index=base;
01255 base=t;
01256 scale=2;
01257 } else return 0;
01258 lasttokenreg=j;
01259 goto cont;
01260 }
01261 }
01262 }
01263 lasttokenreg=X86_REG_NO;
01264
01265 dword v;
01266
01267 if (imm_eval_proc && imm_eval_proc(imm_eval_context, &t, &v)) {
01268 if (sign) disp-=v; else disp+=v;
01269 continue;
01270 } else if (fetch_number(&t, &v)) {
01271 if (sign) disp-=v; else disp+=v;
01272 continue;
01273 }
01274 return 0;
01275 }
01276
01277 if ((base==X86_REG_NO) && (index==X86_REG_NO)) {
01278
01279 if (disp>0xffff) {
01280 if (addrsize==X86_ADDRSIZEUNKNOWN) {
01281 addrsize=X86_ADDRSIZE32;
01282 } else if (addrsize!=X86_ADDRSIZE32) return 0;
01283 }
01284 } else {
01285
01286 if ((disp>0x7fff) && (disp<0xffff8000)) {
01287 if (addrsize==X86_ADDRSIZEUNKNOWN) {
01288 addrsize=X86_ADDRSIZE32;
01289 } else if (addrsize!=X86_ADDRSIZE32) return 0;
01290 }
01291 }
01292 op->type=X86_OPTYPE_MEM;
01293 op->size=opsize;
01294 op->mem.base=base;
01295 op->mem.index=index;
01296 op->mem.scale=scale;
01297 op->mem.addrsize=addrsize;
01298 op->mem.disp=disp;
01299 op->mem.floatptr=floatptr;
01300
01301
01302 return 1;
01303 }
01304
01305 int x86asm::opspecialregs(x86_insn_op *op, char *xop)
01306 {
01307 char *e;
01308 if (strcmp(xop, "st")==0) {
01309 op->type=X86_OPTYPE_STX;
01310 op->size=10;
01311 op->stx=0;
01312 return 1;
01313 } else if ((strncmp(xop, "st", 2)==0) && (xop[2]=='(') && (xop[4]==')')) {
01314 int w=strtol(xop+3, &e, 10);
01315 if ((e!=xop+4) || (w>7)) return 0;
01316 op->type=X86_OPTYPE_STX;
01317 op->size=10;
01318 op->stx=w;
01319 return 1;
01320 }
01321
01322 if (strlen(xop)!=3) return 0;
01323
01324 int w=strtol(xop+2, &e, 10);
01325 if ((*e) || (w>7)) return 0;
01326 if (strncmp(xop, "cr", 2)==0) {
01327 op->type=X86_OPTYPE_CRX;
01328 op->size=4;
01329 op->crx=w;
01330 return 1;
01331 } else if (strncmp(xop, "dr", 2)==0) {
01332 op->type=X86_OPTYPE_DRX;
01333 op->size=4;
01334 op->drx=w;
01335 return 1;
01336 } else if (strncmp(xop, "tr", 2)==0) {
01337 op->type=X86_OPTYPE_TRX;
01338 op->size=4;
01339 op->trx=w;
01340 return 1;
01341 }
01342 return 0;
01343 }
01344
01345 int x86asm::translate_str(asm_insn *asm_insn, const char *s)
01346 {
01347 x86asm_insn *insn=(x86asm_insn*)asm_insn;
01348 char *opp[3], op[3][256];
01349 opp[0]=op[0];
01350 opp[1]=op[1];
01351 opp[2]=op[2];
01352 for (int i=0; i<3; i++) insn->op[i].type=X86_OPTYPE_EMPTY;
01353
01354 insn->lockprefix=X86_PREFIX_NO;
01355 insn->repprefix=X86_PREFIX_NO;
01356 insn->segprefix=X86_PREFIX_NO;
01357
01358 const char *p = s, *a, *b;
01359
01360 while (iswhitespace(*p)) p++;
01361 a=p;
01362 while (isnotwhitespace(*p)) p++;
01363 b=p;
01364 if ((strncmp(a, "rep", b-a) == 0) || (strncmp(a, "repe", b-a) == 0) ||
01365 (strncmp(a, "repz", b-a) == 0)) {
01366 insn->repprefix=X86_PREFIX_REPZ;
01367 s = p;
01368 } else if ((strncmp(a, "repne", b-a) == 0) || (strncmp(a, "repnz", b-a) == 0)) {
01369 insn->repprefix=X86_PREFIX_REPNZ;
01370 s = p;
01371 } else if (strncmp(a, "lock", b-a) == 0) {
01372 insn->lockprefix=X86_PREFIX_LOCK;
01373 s = p;
01374 }
01375
01376 splitstr(s, insn->n, (char**)&opp);
01377 insn->name=insn->n;
01378 for (int i=0; i<3; i++) {
01379 if (!*op[i]) break;
01380
01381 if (!(opplugimm(&insn->op[i], op[i]) ||
01382 opreg(&insn->op[i], op[i]) ||
01383 opfarptr(&insn->op[i], op[i]) ||
01384 opimm(&insn->op[i], op[i]) ||
01385 opseg(&insn->op[i], op[i]) ||
01386 opmem(insn, &insn->op[i], op[i]) ||
01387 opspecialregs(&insn->op[i], op[i]))) {
01388 set_error_msg(X86ASM_ERRMSG_UNKNOWN_SYMBOL, op[i]);
01389 return 0;
01390 }
01391 }
01392 return 1;
01393 }
01394
01395 int x86asm::simmsize(dword imm, int immsize)
01396 {
01397 int i;
01398 switch (immsize) {
01399 case 1:
01400 if (imm > 0xff) return 0;
01401 i = (sint8)imm;
01402 break;
01403 case 2:
01404 if (imm > 0xffff) return 0;
01405 i = (sint16)imm;
01406 break;
01407 case 4:
01408 if (imm > 0xffffffff) return 0;
01409 i = (sint32)imm;
01410 break;
01411 }
01412 if ((i >= -0x80) && (i < 0x80)) return 1;
01413 if ((i >= -0x8000) && (i < 0x8000)) return 2;
01414 return 4;
01415 }
01416
01417 void x86asm::splitstr(const char *s, char *name, char *op[3])
01418 {
01419 const char *a, *b;
01420 int wantbreak=0;
01421 *name=0;
01422 *op[0]=0;
01423 *op[1]=0;
01424 *op[2]=0;
01425
01426 while (iswhitespace(*s)) s++;
01427 a=s;
01428 while (isnotwhitespace(*s)) s++;
01429 b=s;
01430 strncpy(name, a, b-a);
01431 name[b-a]=0;
01432
01433 for (int i=0; i<3; i++) {
01434 while (iswhitespace(*s)) s++;
01435 if (!*s) break;
01436 a=s;
01437 while (*s && (*s!=',')) s++;
01438 while (iswhitespace(*(s-1))) s--;
01439 if (!*s) wantbreak=1;
01440 b=s;
01441 while (iswhitespace(*s)) s++;
01442 if (!*s) wantbreak=1;
01443 strncpy(op[i], a, b-a);
01444 op[i][b-a]=0;
01445 while (iswhitespace(*s)) s++;
01446 if (wantbreak) break;
01447 if (*s!=',') break;
01448 s++;
01449 }
01450 }