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 "cutils/log.h"
21 #include "enc_base.h"
22 #include "enc_wrapper.h"
23 #include "dec_base.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
add_r(EncoderBase::Operands & args,int physicalReg,OpndSize sz,OpndExt ext=OpndExt_None)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 }
add_m(EncoderBase::Operands & args,int baseReg,int disp,OpndSize sz,OpndExt ext=OpndExt_None)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 }
add_m_scale(EncoderBase::Operands & args,int baseReg,int indexReg,int scale,OpndSize sz,OpndExt ext=OpndExt_None)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 }
add_m_disp_scale(EncoderBase::Operands & args,int baseReg,int disp,int indexReg,int scale,OpndSize sz,OpndExt ext=OpndExt_None)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
add_fp(EncoderBase::Operands & args,unsigned i,bool dbl)73 inline void add_fp(EncoderBase::Operands & args, unsigned i, bool dbl) {
74 return args.add((RegName)( (dbl ? RegName_FP0D : RegName_FP0S) + i));
75 }
add_imm(EncoderBase::Operands & args,OpndSize sz,int value,bool is_signed)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
printOperand(const EncoderBase::Operand & opnd)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
printDecoderInst(Inst & decInst)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 }
printOperands(EncoderBase::Operands & opnds)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 }
printEncoderInst(Mnemonic m,EncoderBase::Operands & opnds)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 }
decodeThenPrint(char * stream_start)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
encoder_imm(Mnemonic m,OpndSize size,int imm,char * stream)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 }
encoder_get_inst_size(char * stream)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
encoder_get_cur_operand_offset(int opnd_id)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
encoder_update_imm(int imm,char * stream)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 }
encoder_mem(Mnemonic m,OpndSize size,int disp,int base_reg,bool isBasePhysical,char * stream)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 }
encoder_reg(Mnemonic m,OpndSize size,int reg,bool isPhysical,LowOpndRegType type,char * stream)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
encoder_reg_reg(Mnemonic m,OpndSize size,int reg,bool isPhysical,int reg2,bool isPhysical2,LowOpndRegType type,char * stream)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 }
encoder_mem_reg(Mnemonic m,OpndSize size,int disp,int base_reg,bool isBasePhysical,int reg,bool isPhysical,LowOpndRegType type,char * stream)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 }
encoder_mem_scale_reg(Mnemonic m,OpndSize size,int base_reg,bool isBasePhysical,int index_reg,bool isIndexPhysical,int scale,int reg,bool isPhysical,LowOpndRegType type,char * stream)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 }
encoder_reg_mem_scale(Mnemonic m,OpndSize size,int reg,bool isPhysical,int base_reg,bool isBasePhysical,int index_reg,bool isIndexPhysical,int scale,LowOpndRegType type,char * stream)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 }
encoder_mem_disp_scale_reg(Mnemonic m,OpndSize size,int base_reg,bool isBasePhysical,int disp,int index_reg,bool isIndexPhysical,int scale,int reg,bool isPhysical,LowOpndRegType type,char * stream)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 }
encoder_movzs_mem_disp_scale_reg(Mnemonic m,OpndSize size,int base_reg,bool isBasePhysical,int disp,int index_reg,bool isIndexPhysical,int scale,int reg,bool isPhysical,LowOpndRegType type,char * stream)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
encoder_reg_mem_disp_scale(Mnemonic m,OpndSize size,int reg,bool isPhysical,int base_reg,bool isBasePhysical,int disp,int index_reg,bool isIndexPhysical,int scale,LowOpndRegType type,char * stream)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
encoder_reg_mem(Mnemonic m,OpndSize size,int reg,bool isPhysical,int disp,int base_reg,bool isBasePhysical,LowOpndRegType type,char * stream)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 }
encoder_imm_reg(Mnemonic m,OpndSize size,int imm,int reg,bool isPhysical,LowOpndRegType type,char * stream)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 }
encoder_update_imm_rm(int imm,char * stream)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 }
encoder_imm_mem(Mnemonic m,OpndSize size,int imm,int disp,int base_reg,bool isBasePhysical,char * stream)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 }
encoder_fp_mem(Mnemonic m,OpndSize size,int reg,int disp,int base_reg,bool isBasePhysical,char * stream)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 }
encoder_mem_fp(Mnemonic m,OpndSize size,int disp,int base_reg,bool isBasePhysical,int reg,char * stream)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
encoder_return(char * stream)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 }
encoder_compare_fp_stack(bool pop,int reg,bool isDouble,char * stream)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 }
encoder_movez_mem_to_reg(OpndSize size,int disp,int base_reg,bool isBasePhysical,int reg,bool isPhysical,char * stream)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 }
encoder_moves_mem_to_reg(OpndSize size,int disp,int base_reg,bool isBasePhysical,int reg,bool isPhysical,char * stream)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 }
encoder_movez_reg_to_reg(OpndSize size,int reg,bool isPhysical,int reg2,bool isPhysical2,LowOpndRegType type,char * stream)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 }
encoder_moves_reg_to_reg(OpndSize size,int reg,bool isPhysical,int reg2,bool isPhysical2,LowOpndRegType type,char * stream)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".
DisassembleOperandToBuf(const EncoderBase::Operand & opnd,char * strbuf,unsigned int 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".
DisassembleInstToBuf(Inst & decInst,char * strbuf,unsigned int 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
decoder_disassemble_instr(char * stream,char * strbuf,unsigned int len)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