Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

x86asm.cc

Go to the documentation of this file.
00001 /*
00002  *      HT Editor
00003  *      x86asm.cc
00004  *
00005  *      Copyright (C) 1999-2002 Stefan Weyergraf (stefan@weyergraf.de)
00006  *
00007  *      This program is free software; you can redistribute it and/or modify
00008  *      it under the terms of the GNU General Public License version 2 as
00009  *      published by the Free Software Foundation.
00010  *
00011  *      This program is distributed in the hope that it will be useful,
00012  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *      GNU General Public License for more details.
00015  *
00016  *      You should have received a copy of the GNU General Public License
00017  *      along with this program; if not, write to the Free Software
00018  *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
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 /* mod = 0 */
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 /* mod = 1 */
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 /* mod = 2 */
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 /* mod = 0 */
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},         /* special: SIB */
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 /* mod = 1 */
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},         /* special: SIB + disp8 */
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 /* mod = 2 */
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},         /* special: SIB + disp32 */
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 /* convert logical operand types to hardware operand types */
00117 int lop2hop[10][8] = {
00118 /* X86_OPTYPE_EMPTY */
00119         {},
00120 /* X86_OPTYPE_IMM */
00121         {TYPE_I, TYPE_Is, TYPE_J, TYPE_A, TYPE_Ix},
00122 /* X86_OPTYPE_REG */
00123         {TYPE_R, TYPE_Rx, TYPE_G, TYPE_E},
00124 /* X86_OPTYPE_SEG */
00125         {TYPE_S, TYPE_Sx},
00126 /* X86_OPTYPE_MEM */
00127         {TYPE_E, TYPE_M, TYPE_O},
00128 /* X86_OPTYPE_CRX */
00129         {TYPE_C},
00130 /* X86_OPTYPE_DRX */
00131         {TYPE_D},
00132 /* X86_OPTYPE_TRX */
00133         {TYPE_T},
00134 /* X86_OPTYPE_STX */
00135         {TYPE_F, TYPE_Fx},
00136 /* X86_OPTYPE_MMX */
00137         {TYPE_P, TYPE_Q}
00138 };
00139 
00140 /* byte */
00141 char immhsz8_16[] = { SIZE_B, SIZE_C, SIZE_W, SIZE_V, SIZE_D, 0 };
00142 /* word */
00143 char immhsz16_16[] = { SIZE_W, SIZE_V, SIZE_D, 0 };
00144 /* dword */
00145 char immhsz32_16[] = { SIZE_D, 0 };
00146 
00147 /* byte */
00148 char immhsz8_32[] = { SIZE_B, SIZE_C, SIZE_W, SIZE_V, SIZE_D, 0 };
00149 /* word */
00150 char immhsz16_32[] = { SIZE_W, SIZE_C, SIZE_D, SIZE_V, 0 };
00151 /* dword */
00152 char immhsz32_32[] = { SIZE_D, SIZE_V, 0 };
00153 
00154 /* byte */
00155 char hsz8_16[] = { SIZE_B, SIZE_C, 0 };
00156 /* word */
00157 char hsz16_16[] = { SIZE_W, SIZE_V, 0 };
00158 /* dword */
00159 char hsz32_16[] = { SIZE_D, SIZE_P, 0 };
00160 /* pword */
00161 char hsz48_16[] = { 0 };
00162 /* qword */
00163 char hsz64_16[] = { SIZE_Q, 0};
00164 
00165 /* byte */
00166 char hsz8_32[] = { SIZE_B, 0 };
00167 /* word */
00168 char hsz16_32[] = { SIZE_W, SIZE_C, 0 };
00169 /* dword */
00170 char hsz32_32[] = { SIZE_D, SIZE_V, 0 };
00171 /* pword */
00172 char hsz48_32[] = { SIZE_P, 0 };
00173 /* qword */
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  *      CLASS x86asm
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 /* write lock, rep and/or seg prefixes if needed */
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 /* write opcodeprefixes and opcode */
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 /* encode the ops */
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 /* write the rest */
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                         // FIXME: !
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);                        /* SIB */
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 /* direct address without ModR/M */
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 /* reg of ModR/M picks control register */
00539                         emitmodrm_reg(op->crx);
00540                         break;
00541                 case TYPE_D:
00542 /* reg of ModR/M picks debug register */
00543                         emitmodrm_reg(op->drx);
00544                         break;
00545                 case TYPE_E:
00546 /* ModR/M (general reg or memory) */
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 /* r/m of ModR/M picks a fpu register */
00552                         emitmodrm_rm(op->stx);
00553                         break;
00554                 case TYPE_Fx:
00555 /* extra picks a fpu register */
00556                         return 1;
00557                 case TYPE_G:
00558 /* reg of ModR/M picks general register */
00559                         emitmodrm_reg(op->reg);
00560                         break;
00561                 case TYPE_Is: {
00562 /* signed immediate */
00563                         int size=esizeop(xop->size, eopsize);
00564                         emitimm(op->imm, size);
00565                         break;
00566                 }
00567                 case TYPE_I: {
00568 /* unsigned immediate */
00569                         int size=esizeop(xop->size, eopsize);
00570                         emitimm(op->imm, size);
00571                         break;
00572                 }
00573                 case TYPE_Ix:
00574 /* fixed immediate */
00575                         return 1;
00576                 case TYPE_J: {
00577 /* relative branch offset */
00578                         int size=esizeop(xop->size, eopsize);
00579                         emitimm(op->imm-address-code.size-size, size);
00580                         break;
00581                 }
00582                 case TYPE_M:
00583 /* ModR/M (memory only) */
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 /* direct memory without ModR/M */
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 /* ModR/M picks MMX register */
00604                         break;
00605                 case TYPE_Q:
00606 /* ModR/M (MMX reg or memory) */
00607                         break;
00608                 case TYPE_R:
00609 /* rm of ModR/M picks general register */
00610                         emitmodrm_rm(op->reg);
00611                         break;
00612                 case TYPE_Rx:
00613 /* extra picks register */
00614                         return 1;
00615                 case TYPE_S:
00616 /* reg of ModR/M picks segment register */
00617                         emitmodrm_reg(op->seg);
00618                         break;
00619                 case TYPE_Sx:
00620 /* extra picks segment register */
00621                         return 1;
00622                 case TYPE_T:
00623 /* reg of ModR/M picks test register */
00624                         emitmodrm_reg(op->trx);
00625                         break;
00626         }
00627         if (!psize) {
00628 //              set_error_msg(X86ASM_ERRMSG_INTERNAL"FIXME: size ??? %s, %d\n", __FILE__, __LINE__);
00629         }
00630         if (!*esize) *esize=psize;
00631 /*      if (!(options & X86ASM_ALLOW_AMBIGUOUS) && (*esize!=psize)) {
00632                 ambiguous=1;
00633                 set_error_msg(X86ASM_ERRMSG_AMBIGUOUS);
00634                 return 0;
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 /* c-style numbers */
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 /* assembler style numbers */
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                         // FIXME: ?!
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 //              printf("o%ds%d: %02x (%d)\n", (opsize==X86_OPSIZE16) ? 16 : 32, (addrsize==X86_ADDRSIZE16) ? 16 : 32, opcodebyte, opcodebyte);
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 /* try modrm fopcodes */
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 /* try the rest */
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 /* FIXME: dirty implementation ! */
01126         int opsize=0, hsize=0;
01127         int floatptr=0;
01128 
01129 // typecast
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 // segprefixes (e.g. fs:)
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]; /* FIXME: possible buffer overflow */
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 /* FIXME: case "imm*reg" not yet supported ! cleaner implementation needed ! */
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 /* test if reg */
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 /* test if number */
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 /* unsigned disp */
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 /* signed disp */
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 //      int r=(addrsize==X86_ADDRSIZE16) ? 1 : 2;
01301 //      printf("%s.%d: opmem(): size=%d, base = %s, index = %s, scale = %d, disp=%08lx, addrsize = %d\n", __FILE__, __LINE__, opsize, (base==X86_REG_NO) ? "" : x86_regs[r][base], (index==X86_REG_NO) ? "" : x86_regs[r][index], scale, disp, addrsize);
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;   /* FIXME: do we need this ? strtol sets e to next untranslatable char, this case is caught below... */
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 /* prefixes */
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 /* find name */
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 /* find ops*/
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 }

Generated on Fri May 7 21:15:45 2004 by doxygen 1.3.5