1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <stdio.h> 18 #include <assert.h> 19 #include <limits.h> 20 #include "enc_base.h" 21 #include "enc_wrapper.h" 22 #include "dec_base.h" 23 #include "utils/Log.h" 24 25 //#define PRINT_ENCODER_STREAM 26 bool dump_x86_inst = false; 27 //map_reg 28 const RegName map_of_regno_2_regname[] = { 29 RegName_EAX, RegName_EBX, RegName_ECX, RegName_EDX, 30 RegName_EDI, RegName_ESI, RegName_ESP, RegName_EBP, 31 RegName_XMM0, RegName_XMM1, RegName_XMM2, RegName_XMM3, 32 RegName_XMM4, RegName_XMM5, RegName_XMM6, RegName_XMM7, 33 RegName_Null, RegName_Null, RegName_Null, RegName_Null, 34 RegName_Null, RegName_Null, RegName_Null, RegName_Null, 35 RegName_Null, 36 RegName_Null, RegName_Null, RegName_Null, RegName_Null, RegName_Null, 37 RegName_Null, RegName_Null, RegName_Null, RegName_Null, 38 RegName_Null, RegName_Null, RegName_Null, RegName_Null, 39 RegName_Null, RegName_Null, //SCRATCH 40 RegName_Null, RegName_Null, RegName_Null, RegName_Null 41 }; 42 43 //getRegSize, getAliasReg: 44 //OpndSize, RegName, OpndExt: enum enc_defs.h 45 inline void add_r(EncoderBase::Operands & args, int physicalReg, OpndSize sz, OpndExt ext = OpndExt_None) { 46 RegName reg = map_of_regno_2_regname[physicalReg]; 47 if (sz != getRegSize(reg)) { 48 reg = getAliasReg(reg, sz); 49 } 50 args.add(EncoderBase::Operand(reg, ext)); 51 } 52 inline void add_m(EncoderBase::Operands & args, int baseReg, int disp, OpndSize sz, OpndExt ext = OpndExt_None) { 53 args.add(EncoderBase::Operand(sz, 54 map_of_regno_2_regname[baseReg], 55 RegName_Null, 0, 56 disp, ext)); 57 } 58 inline void add_m_scale(EncoderBase::Operands & args, int baseReg, int indexReg, int scale, 59 OpndSize sz, OpndExt ext = OpndExt_None) { 60 args.add(EncoderBase::Operand(sz, 61 map_of_regno_2_regname[baseReg], 62 map_of_regno_2_regname[indexReg], scale, 63 0, ext)); 64 } 65 inline void add_m_disp_scale(EncoderBase::Operands & args, int baseReg, int disp, int indexReg, int scale, 66 OpndSize sz, OpndExt ext = OpndExt_None) { 67 args.add(EncoderBase::Operand(sz, 68 map_of_regno_2_regname[baseReg], 69 map_of_regno_2_regname[indexReg], scale, 70 disp, ext)); 71 } 72 73 inline void add_fp(EncoderBase::Operands & args, unsigned i, bool dbl) { 74 return args.add((RegName)( (dbl ? RegName_FP0D : RegName_FP0S) + i)); 75 } 76 inline void add_imm(EncoderBase::Operands & args, OpndSize sz, int value, bool is_signed) { 77 //assert(n_size != imm.get_size()); 78 args.add(EncoderBase::Operand(sz, value, 79 is_signed ? OpndExt_Signed : OpndExt_Zero)); 80 } 81 82 #define MAX_DECODED_STRING_LEN 1024 83 char tmpBuffer[MAX_DECODED_STRING_LEN]; 84 85 void printOperand(const EncoderBase::Operand & opnd) { 86 unsigned int sz; 87 if(!dump_x86_inst) return; 88 sz = strlen(tmpBuffer); 89 if(opnd.size() != OpndSize_32) { 90 sz += snprintf(&tmpBuffer[sz], MAX_DECODED_STRING_LEN-sz, "%s ", 91 getOpndSizeString(opnd.size())); 92 } 93 if(opnd.is_mem()) { 94 if(opnd.scale() != 0) { 95 sz += snprintf(&tmpBuffer[sz], MAX_DECODED_STRING_LEN-sz, 96 "%d(%s,%s,%d)", opnd.disp(), 97 getRegNameString(opnd.base()), 98 getRegNameString(opnd.index()), opnd.scale()); 99 } else { 100 sz += snprintf(&tmpBuffer[sz], MAX_DECODED_STRING_LEN-sz, "%d(%s)", 101 opnd.disp(), getRegNameString(opnd.base())); 102 } 103 } 104 if(opnd.is_imm()) { 105 sz += snprintf(&tmpBuffer[sz], MAX_DECODED_STRING_LEN-sz, "#%x", 106 (int)opnd.imm()); 107 } 108 if(opnd.is_reg()) { 109 sz += snprintf(&tmpBuffer[sz], MAX_DECODED_STRING_LEN-sz, "%s", 110 getRegNameString(opnd.reg())); 111 } 112 } 113 //TODO: the order of operands 114 //to make the printout have the same order as assembly in .S 115 //I reverse the order here 116 void printDecoderInst(Inst & decInst) { 117 unsigned int sz; 118 if(!dump_x86_inst) return; 119 sz = strlen(tmpBuffer); 120 sz += snprintf(&tmpBuffer[sz], MAX_DECODED_STRING_LEN-sz, "%s ", 121 EncoderBase::toStr(decInst.mn)); 122 for(unsigned int k = 0; k < decInst.argc; k++) { 123 if(k > 0) { 124 sz = strlen(tmpBuffer); 125 sz += snprintf(&tmpBuffer[sz], MAX_DECODED_STRING_LEN-sz, ", "); 126 } 127 printOperand(decInst.operands[decInst.argc-1-k]); 128 } 129 ALOGE("%s", tmpBuffer); 130 } 131 void printOperands(EncoderBase::Operands& opnds) { 132 unsigned int sz; 133 if(!dump_x86_inst) return; 134 for(unsigned int k = 0; k < opnds.count(); k++) { 135 if(k > 0) { 136 sz = strlen(tmpBuffer); 137 sz += snprintf(&tmpBuffer[sz], MAX_DECODED_STRING_LEN-sz, ", "); 138 } 139 printOperand(opnds[opnds.count()-1-k]); 140 } 141 } 142 void printEncoderInst(Mnemonic m, EncoderBase::Operands& opnds) { 143 if(!dump_x86_inst) return; 144 snprintf(tmpBuffer, MAX_DECODED_STRING_LEN, "--- ENC %s ", 145 EncoderBase::toStr(m)); 146 printOperands(opnds); 147 ALOGE("%s", tmpBuffer); 148 } 149 int decodeThenPrint(char* stream_start) { 150 if(!dump_x86_inst) return 0; 151 snprintf(tmpBuffer, MAX_DECODED_STRING_LEN, "--- INST @ %p: ", 152 stream_start); 153 Inst decInst; 154 unsigned numBytes = DecoderBase::decode(stream_start, &decInst); 155 printDecoderInst(decInst); 156 return numBytes; 157 } 158 159 extern "C" ENCODER_DECLARE_EXPORT char * encoder_imm(Mnemonic m, OpndSize size, int imm, char * stream) { 160 EncoderBase::Operands args; 161 //assert(imm.get_size() == size_32); 162 add_imm(args, size, imm, true/*is_signed*/); 163 char* stream_start = stream; 164 stream = (char *)EncoderBase::encode(stream, m, args); 165 #ifdef PRINT_ENCODER_STREAM 166 printEncoderInst(m, args); 167 decodeThenPrint(stream_start); 168 #endif 169 return stream; 170 } 171 extern "C" ENCODER_DECLARE_EXPORT unsigned encoder_get_inst_size(char * stream) { 172 Inst decInst; 173 unsigned numBytes = DecoderBase::decode(stream, &decInst); 174 return numBytes; 175 } 176 177 extern "C" ENCODER_DECLARE_EXPORT unsigned encoder_get_cur_operand_offset(int opnd_id) 178 { 179 return (unsigned)EncoderBase::getOpndLocation(opnd_id); 180 } 181 182 extern "C" ENCODER_DECLARE_EXPORT char * encoder_update_imm(int imm, char * stream) { 183 Inst decInst; 184 unsigned numBytes = DecoderBase::decode(stream, &decInst); 185 EncoderBase::Operands args; 186 //assert(imm.get_size() == size_32); 187 add_imm(args, decInst.operands[0].size(), imm, true/*is_signed*/); 188 char* stream_next = (char *)EncoderBase::encode(stream, decInst.mn, args); 189 #ifdef PRINT_ENCODER_STREAM 190 printEncoderInst(decInst.mn, args); 191 decodeThenPrint(stream); 192 #endif 193 return stream_next; 194 } 195 extern "C" ENCODER_DECLARE_EXPORT char * encoder_mem(Mnemonic m, OpndSize size, 196 int disp, int base_reg, bool isBasePhysical, char * stream) { 197 EncoderBase::Operands args; 198 add_m(args, base_reg, disp, size); 199 char* stream_start = stream; 200 stream = (char *)EncoderBase::encode(stream, m, args); 201 #ifdef PRINT_ENCODER_STREAM 202 printEncoderInst(m, args); 203 decodeThenPrint(stream_start); 204 #endif 205 return stream; 206 } 207 extern "C" ENCODER_DECLARE_EXPORT char * encoder_reg(Mnemonic m, OpndSize size, 208 int reg, bool isPhysical, LowOpndRegType type, char * stream) { 209 EncoderBase::Operands args; 210 if(m == Mnemonic_IDIV || m == Mnemonic_MUL || m == Mnemonic_IMUL) { 211 add_r(args, 0/*eax*/, size); 212 add_r(args, 3/*edx*/, size); 213 } 214 add_r(args, reg, size); 215 char* stream_start = stream; 216 stream = (char *)EncoderBase::encode(stream, m, args); 217 #ifdef PRINT_ENCODER_STREAM 218 printEncoderInst(m, args); 219 decodeThenPrint(stream_start); 220 #endif 221 return stream; 222 } 223 //both operands have same size 224 extern "C" ENCODER_DECLARE_EXPORT char * encoder_reg_reg(Mnemonic m, OpndSize size, 225 int reg, bool isPhysical, 226 int reg2, bool isPhysical2, LowOpndRegType type, char * stream) { 227 if((m == Mnemonic_MOV || m == Mnemonic_MOVQ) && reg == reg2) return stream; 228 EncoderBase::Operands args; 229 add_r(args, reg2, size); //destination 230 if(m == Mnemonic_SAL || m == Mnemonic_SHR || m == Mnemonic_SHL || m == Mnemonic_SAR) 231 add_r(args, reg, OpndSize_8); 232 else 233 add_r(args, reg, size); 234 char* stream_start = stream; 235 stream = (char *)EncoderBase::encode(stream, m, args); 236 #ifdef PRINT_ENCODER_STREAM 237 printEncoderInst(m, args); 238 decodeThenPrint(stream_start); 239 #endif 240 return stream; 241 } 242 extern "C" ENCODER_DECLARE_EXPORT char * encoder_mem_reg(Mnemonic m, OpndSize size, 243 int disp, int base_reg, bool isBasePhysical, 244 int reg, bool isPhysical, LowOpndRegType type, char * stream) { 245 EncoderBase::Operands args; 246 add_r(args, reg, size); 247 add_m(args, base_reg, disp, size); 248 char* stream_start = stream; 249 stream = (char *)EncoderBase::encode(stream, m, args); 250 #ifdef PRINT_ENCODER_STREAM 251 printEncoderInst(m, args); 252 decodeThenPrint(stream_start); 253 #endif 254 return stream; 255 } 256 extern "C" ENCODER_DECLARE_EXPORT char * encoder_mem_scale_reg(Mnemonic m, OpndSize size, 257 int base_reg, bool isBasePhysical, int index_reg, bool isIndexPhysical, int scale, 258 int reg, bool isPhysical, LowOpndRegType type, char * stream) { 259 EncoderBase::Operands args; 260 add_r(args, reg, size); 261 add_m_scale(args, base_reg, index_reg, scale, size); 262 char* stream_start = stream; 263 stream = (char *)EncoderBase::encode(stream, m, args); 264 #ifdef PRINT_ENCODER_STREAM 265 printEncoderInst(m, args); 266 decodeThenPrint(stream_start); 267 #endif 268 return stream; 269 } 270 extern "C" ENCODER_DECLARE_EXPORT char * encoder_reg_mem_scale(Mnemonic m, OpndSize size, 271 int reg, bool isPhysical, 272 int base_reg, bool isBasePhysical, int index_reg, bool isIndexPhysical, int scale, 273 LowOpndRegType type, char * stream) { 274 EncoderBase::Operands args; 275 add_m_scale(args, base_reg, index_reg, scale, size); 276 add_r(args, reg, size); 277 char* stream_start = stream; 278 stream = (char *)EncoderBase::encode(stream, m, args); 279 #ifdef PRINT_ENCODER_STREAM 280 printEncoderInst(m, args); 281 decodeThenPrint(stream_start); 282 #endif 283 return stream; 284 } 285 extern "C" ENCODER_DECLARE_EXPORT char * encoder_mem_disp_scale_reg(Mnemonic m, OpndSize size, 286 int base_reg, bool isBasePhysical, int disp, int index_reg, bool isIndexPhysical, int scale, 287 int reg, bool isPhysical, LowOpndRegType type, char * stream) { 288 EncoderBase::Operands args; 289 add_r(args, reg, size); 290 add_m_disp_scale(args, base_reg, disp, index_reg, scale, size); 291 char* stream_start = stream; 292 stream = (char *)EncoderBase::encode(stream, m, args); 293 #ifdef PRINT_ENCODER_STREAM 294 printEncoderInst(m, args); 295 decodeThenPrint(stream_start); 296 #endif 297 return stream; 298 } 299 extern "C" ENCODER_DECLARE_EXPORT char * encoder_movzs_mem_disp_scale_reg(Mnemonic m, OpndSize size, 300 int base_reg, bool isBasePhysical, int disp, int index_reg, bool isIndexPhysical, int scale, 301 int reg, bool isPhysical, LowOpndRegType type, char * stream) { 302 EncoderBase::Operands args; 303 add_r(args, reg, OpndSize_32); 304 add_m_disp_scale(args, base_reg, disp, index_reg, scale, size); 305 char* stream_start = stream; 306 stream = (char *)EncoderBase::encode(stream, m, args); 307 #ifdef PRINT_ENCODER_STREAM 308 printEncoderInst(m, args); 309 decodeThenPrint(stream_start); 310 #endif 311 return stream; 312 } 313 314 extern "C" ENCODER_DECLARE_EXPORT char* encoder_reg_mem_disp_scale(Mnemonic m, OpndSize size, 315 int reg, bool isPhysical, 316 int base_reg, bool isBasePhysical, int disp, int index_reg, bool isIndexPhysical, int scale, 317 LowOpndRegType type, char* stream) { 318 EncoderBase::Operands args; 319 add_m_disp_scale(args, base_reg, disp, index_reg, scale, size); 320 add_r(args, reg, size); 321 char* stream_start = stream; 322 stream = (char *)EncoderBase::encode(stream, m, args); 323 #ifdef PRINT_ENCODER_STREAM 324 printEncoderInst(m, args); 325 decodeThenPrint(stream_start); 326 #endif 327 return stream; 328 } 329 330 extern "C" ENCODER_DECLARE_EXPORT char * encoder_reg_mem(Mnemonic m, OpndSize size, 331 int reg, bool isPhysical, 332 int disp, int base_reg, bool isBasePhysical, LowOpndRegType type, char * stream) { 333 EncoderBase::Operands args; 334 add_m(args, base_reg, disp, size); 335 add_r(args, reg, size); 336 char* stream_start = stream; 337 stream = (char *)EncoderBase::encode(stream, m, args); 338 #ifdef PRINT_ENCODER_STREAM 339 printEncoderInst(m, args); 340 decodeThenPrint(stream_start); 341 #endif 342 return stream; 343 } 344 extern "C" ENCODER_DECLARE_EXPORT char * encoder_imm_reg(Mnemonic m, OpndSize size, 345 int imm, int reg, bool isPhysical, LowOpndRegType type, char * stream) { 346 EncoderBase::Operands args; 347 add_r(args, reg, size); //dst 348 if(m == Mnemonic_IMUL) add_r(args, reg, size); //src CHECK 349 if(m == Mnemonic_SAL || m == Mnemonic_SHR || m == Mnemonic_SHL 350 || m == Mnemonic_SAR || m == Mnemonic_ROR) //fix for shift opcodes 351 add_imm(args, OpndSize_8, imm, true/*is_signed*/); 352 else 353 add_imm(args, size, imm, true/*is_signed*/); 354 char* stream_start = stream; 355 stream = (char *)EncoderBase::encode(stream, m, args); 356 #ifdef PRINT_ENCODER_STREAM 357 printEncoderInst(m, args); 358 decodeThenPrint(stream_start); 359 #endif 360 return stream; 361 } 362 extern "C" ENCODER_DECLARE_EXPORT char * encoder_update_imm_rm(int imm, char * stream) { 363 Inst decInst; 364 unsigned numBytes = DecoderBase::decode(stream, &decInst); 365 EncoderBase::Operands args; 366 args.add(decInst.operands[0]); 367 add_imm(args, decInst.operands[1].size(), imm, true/*is_signed*/); 368 char* stream_next = (char *)EncoderBase::encode(stream, decInst.mn, args); 369 #ifdef PRINT_ENCODER_STREAM 370 printEncoderInst(decInst.mn, args); 371 decodeThenPrint(stream); 372 #endif 373 return stream_next; 374 } 375 extern "C" ENCODER_DECLARE_EXPORT char * encoder_imm_mem(Mnemonic m, OpndSize size, 376 int imm, 377 int disp, int base_reg, bool isBasePhysical, char * stream) { 378 EncoderBase::Operands args; 379 add_m(args, base_reg, disp, size); 380 if (m == Mnemonic_SAL || m == Mnemonic_SHR || m == Mnemonic_SHL 381 || m == Mnemonic_SAR || m == Mnemonic_ROR) 382 size = OpndSize_8; 383 add_imm(args, size, imm, true); 384 char* stream_start = stream; 385 stream = (char *)EncoderBase::encode(stream, m, args); 386 #ifdef PRINT_ENCODER_STREAM 387 printEncoderInst(m, args); 388 decodeThenPrint(stream_start); 389 #endif 390 return stream; 391 } 392 extern "C" ENCODER_DECLARE_EXPORT char * encoder_fp_mem(Mnemonic m, OpndSize size, int reg, 393 int disp, int base_reg, bool isBasePhysical, char * stream) { 394 EncoderBase::Operands args; 395 add_m(args, base_reg, disp, size); 396 // a fake FP register as operand 397 add_fp(args, reg, size == OpndSize_64/*is_double*/); 398 char* stream_start = stream; 399 stream = (char *)EncoderBase::encode(stream, m, args); 400 #ifdef PRINT_ENCODER_STREAM 401 printEncoderInst(m, args); 402 decodeThenPrint(stream_start); 403 #endif 404 return stream; 405 } 406 extern "C" ENCODER_DECLARE_EXPORT char * encoder_mem_fp(Mnemonic m, OpndSize size, 407 int disp, int base_reg, bool isBasePhysical, 408 int reg, char * stream) { 409 EncoderBase::Operands args; 410 // a fake FP register as operand 411 add_fp(args, reg, size == OpndSize_64/*is_double*/); 412 add_m(args, base_reg, disp, size); 413 char* stream_start = stream; 414 stream = (char *)EncoderBase::encode(stream, m, args); 415 #ifdef PRINT_ENCODER_STREAM 416 printEncoderInst(m, args); 417 decodeThenPrint(stream_start); 418 #endif 419 return stream; 420 } 421 422 extern "C" ENCODER_DECLARE_EXPORT char * encoder_return(char * stream) { 423 EncoderBase::Operands args; 424 char* stream_start = stream; 425 stream = (char *)EncoderBase::encode(stream, Mnemonic_RET, args); 426 #ifdef PRINT_ENCODER_STREAM 427 printEncoderInst(Mnemonic_RET, args); 428 decodeThenPrint(stream_start); 429 #endif 430 return stream; 431 } 432 extern "C" ENCODER_DECLARE_EXPORT char * encoder_compare_fp_stack(bool pop, int reg, bool isDouble, char * stream) { 433 //Mnemonic m = pop ? Mnemonic_FUCOMP : Mnemonic_FUCOM; 434 Mnemonic m = pop ? Mnemonic_FUCOMIP : Mnemonic_FUCOMI; 435 //a single operand or 2 operands? 436 //FST ST(i) has a single operand in encoder.inl? 437 EncoderBase::Operands args; 438 add_fp(args, reg, isDouble); 439 char* stream_start = stream; 440 stream = (char *)EncoderBase::encode(stream, m, args); 441 #ifdef PRINT_ENCODER_STREAM 442 printEncoderInst(m, args); 443 decodeThenPrint(stream_start); 444 #endif 445 return stream; 446 } 447 extern "C" ENCODER_DECLARE_EXPORT char * encoder_movez_mem_to_reg(OpndSize size, 448 int disp, int base_reg, bool isBasePhysical, 449 int reg, bool isPhysical, char * stream) { 450 EncoderBase::Operands args; 451 add_r(args, reg, OpndSize_32); 452 add_m(args, base_reg, disp, size); 453 char* stream_start = stream; 454 stream = (char *)EncoderBase::encode(stream, Mnemonic_MOVZX, args); 455 #ifdef PRINT_ENCODER_STREAM 456 printEncoderInst(Mnemonic_MOVZX, args); 457 decodeThenPrint(stream_start); 458 #endif 459 return stream; 460 } 461 extern "C" ENCODER_DECLARE_EXPORT char * encoder_moves_mem_to_reg(OpndSize size, 462 int disp, int base_reg, bool isBasePhysical, 463 int reg, bool isPhysical, char * stream) { 464 EncoderBase::Operands args; 465 add_r(args, reg, OpndSize_32); 466 add_m(args, base_reg, disp, size); 467 char* stream_start = stream; 468 stream = (char *)EncoderBase::encode(stream, Mnemonic_MOVSX, args); 469 #ifdef PRINT_ENCODER_STREAM 470 printEncoderInst(Mnemonic_MOVSX, args); 471 decodeThenPrint(stream_start); 472 #endif 473 return stream; 474 } 475 extern "C" ENCODER_DECLARE_EXPORT char * encoder_movez_reg_to_reg(OpndSize size, 476 int reg, bool isPhysical, int reg2, 477 bool isPhysical2, LowOpndRegType type, char * stream) { 478 EncoderBase::Operands args; 479 add_r(args, reg2, OpndSize_32); //destination 480 add_r(args, reg, size); 481 char* stream_start = stream; 482 stream = (char *)EncoderBase::encode(stream, Mnemonic_MOVZX, args); 483 #ifdef PRINT_ENCODER_STREAM 484 printEncoderInst(Mnemonic_MOVZX, args); 485 decodeThenPrint(stream_start); 486 #endif 487 return stream; 488 } 489 extern "C" ENCODER_DECLARE_EXPORT char * encoder_moves_reg_to_reg(OpndSize size, 490 int reg, bool isPhysical,int reg2, 491 bool isPhysical2, LowOpndRegType type, char * stream) { 492 EncoderBase::Operands args; 493 add_r(args, reg2, OpndSize_32); //destination 494 add_r(args, reg, size); 495 char* stream_start = stream; 496 stream = (char *)EncoderBase::encode(stream, Mnemonic_MOVSX, args); 497 #ifdef PRINT_ENCODER_STREAM 498 printEncoderInst(Mnemonic_MOVSX, args); 499 decodeThenPrint(stream_start); 500 #endif 501 return stream; 502 } 503 504 // Disassemble the operand "opnd" and put the readable format in "strbuf" 505 // up to a string length of "len". 506 unsigned int DisassembleOperandToBuf(const EncoderBase::Operand& opnd, char* strbuf, unsigned int len) 507 { 508 unsigned int sz = 0; 509 if(opnd.size() != OpndSize_32) { 510 sz += snprintf(&strbuf[sz], len-sz, "%s ", 511 getOpndSizeString(opnd.size())); 512 } 513 if(opnd.is_mem()) { 514 if(opnd.scale() != 0) { 515 sz += snprintf(&strbuf[sz], len-sz, "%d(%s,%s,%d)", opnd.disp(), 516 getRegNameString(opnd.base()), 517 getRegNameString(opnd.index()), opnd.scale()); 518 } else { 519 sz += snprintf(&strbuf[sz], len-sz, "%d(%s)", 520 opnd.disp(), getRegNameString(opnd.base())); 521 } 522 } else if(opnd.is_imm()) { 523 sz += snprintf(&strbuf[sz], len-sz, "#%x", (int)opnd.imm()); 524 } else if(opnd.is_reg()) { 525 sz += snprintf(&strbuf[sz], len-sz, "%s", 526 getRegNameString(opnd.reg())); 527 } 528 return sz; 529 } 530 531 // Disassemble the instruction "decInst" and put the readable format 532 // in "strbuf" up to a string length of "len". 533 void DisassembleInstToBuf(Inst& decInst, char* strbuf, unsigned int len) 534 { 535 unsigned int sz = 0; 536 int k; 537 sz += snprintf(&strbuf[sz], len-sz, "%s ", EncoderBase::toStr(decInst.mn)); 538 if (decInst.argc > 0) { 539 sz += DisassembleOperandToBuf(decInst.operands[decInst.argc-1], 540 &strbuf[sz], len-sz); 541 for(k = decInst.argc-2; k >= 0; k--) { 542 sz += snprintf(&strbuf[sz], len-sz, ", "); 543 sz += DisassembleOperandToBuf(decInst.operands[k], &strbuf[sz], len-sz); 544 } 545 } 546 } 547 548 // Disassmble the x86 instruction pointed to by code pointer "stream." 549 // Put the disassemble text in the "strbuf" up to string length "len". 550 // Return the code pointer after the disassemble x86 instruction. 551 extern "C" ENCODER_DECLARE_EXPORT 552 char* decoder_disassemble_instr(char* stream, char* strbuf, unsigned int len) 553 { 554 Inst decInst; 555 unsigned numBytes = DecoderBase::decode(stream, &decInst); 556 DisassembleInstToBuf(decInst, strbuf, len); 557 return (stream + numBytes); 558 } 559