Revision 14ce26e7 target-i386/translate.c
b/target-i386/translate.c | ||
---|---|---|
39 | 39 |
#define PREFIX_DATA 0x08 |
40 | 40 |
#define PREFIX_ADR 0x10 |
41 | 41 |
|
42 |
#ifdef TARGET_X86_64 |
|
43 |
#define X86_64_ONLY(x) x |
|
44 |
#define X86_64_DEF(x...) x |
|
45 |
#define CODE64(s) ((s)->code64) |
|
46 |
#define REX_X(s) ((s)->rex_x) |
|
47 |
#define REX_B(s) ((s)->rex_b) |
|
48 |
/* XXX: gcc generates push/pop in some opcodes, so we cannot use them */ |
|
49 |
#if 1 |
|
50 |
#define BUGGY_64(x) NULL |
|
51 |
#endif |
|
52 |
#else |
|
53 |
#define X86_64_ONLY(x) NULL |
|
54 |
#define X86_64_DEF(x...) |
|
55 |
#define CODE64(s) 0 |
|
56 |
#define REX_X(s) 0 |
|
57 |
#define REX_B(s) 0 |
|
58 |
#endif |
|
59 |
|
|
60 |
#ifdef TARGET_X86_64 |
|
61 |
static int x86_64_hregs; |
|
62 |
#endif |
|
63 |
|
|
42 | 64 |
typedef struct DisasContext { |
43 | 65 |
/* current insn context */ |
44 | 66 |
int override; /* -1 if no override */ |
45 | 67 |
int prefix; |
46 | 68 |
int aflag, dflag; |
47 |
uint8_t *pc; /* pc = eip + cs_base */
|
|
69 |
target_ulong pc; /* pc = eip + cs_base */
|
|
48 | 70 |
int is_jmp; /* 1 = means jump (stop translation), 2 means CPU |
49 | 71 |
static state change (stop translation) */ |
50 | 72 |
/* current block context */ |
51 |
uint8_t *cs_base; /* base of CS segment */
|
|
73 |
target_ulong cs_base; /* base of CS segment */
|
|
52 | 74 |
int pe; /* protected mode */ |
53 | 75 |
int code32; /* 32 bit code segment */ |
76 |
#ifdef TARGET_X86_64 |
|
77 |
int lma; /* long mode active */ |
|
78 |
int code64; /* 64 bit code segment */ |
|
79 |
int rex_x, rex_b; |
|
80 |
#endif |
|
54 | 81 |
int ss32; /* 32 bit stack segment */ |
55 | 82 |
int cc_op; /* current CC operation */ |
56 | 83 |
int addseg; /* non zero if either DS/ES/SS have a non zero base */ |
... | ... | |
65 | 92 |
int flags; /* all execution flags */ |
66 | 93 |
struct TranslationBlock *tb; |
67 | 94 |
int popl_esp_hack; /* for correct popl with esp base handling */ |
95 |
int rip_offset; /* only used in x86_64, but left for simplicity */ |
|
96 |
int cpuid_features; |
|
68 | 97 |
} DisasContext; |
69 | 98 |
|
70 | 99 |
static void gen_eob(DisasContext *s); |
71 |
static void gen_jmp(DisasContext *s, unsigned int eip); |
|
100 |
static void gen_jmp(DisasContext *s, target_ulong eip); |
|
101 |
static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num); |
|
72 | 102 |
|
73 | 103 |
/* i386 arith/logic operations */ |
74 | 104 |
enum { |
... | ... | |
121 | 151 |
OR_EBP, |
122 | 152 |
OR_ESI, |
123 | 153 |
OR_EDI, |
124 |
OR_TMP0, /* temporary operand register */ |
|
154 |
|
|
155 |
OR_TMP0 = 16, /* temporary operand register */ |
|
125 | 156 |
OR_TMP1, |
126 | 157 |
OR_A0, /* temporary register used when doing address evaluation */ |
127 |
OR_ZERO, /* fixed zero register */ |
|
128 |
NB_OREGS, |
|
129 | 158 |
}; |
130 | 159 |
|
131 |
static GenOpFunc *gen_op_mov_reg_T0[3][8] = { |
|
160 |
#ifdef TARGET_X86_64 |
|
161 |
|
|
162 |
#define NB_OP_SIZES 4 |
|
163 |
|
|
164 |
#define DEF_REGS(prefix, suffix) \ |
|
165 |
prefix ## EAX ## suffix,\ |
|
166 |
prefix ## ECX ## suffix,\ |
|
167 |
prefix ## EDX ## suffix,\ |
|
168 |
prefix ## EBX ## suffix,\ |
|
169 |
prefix ## ESP ## suffix,\ |
|
170 |
prefix ## EBP ## suffix,\ |
|
171 |
prefix ## ESI ## suffix,\ |
|
172 |
prefix ## EDI ## suffix,\ |
|
173 |
prefix ## R8 ## suffix,\ |
|
174 |
prefix ## R9 ## suffix,\ |
|
175 |
prefix ## R10 ## suffix,\ |
|
176 |
prefix ## R11 ## suffix,\ |
|
177 |
prefix ## R12 ## suffix,\ |
|
178 |
prefix ## R13 ## suffix,\ |
|
179 |
prefix ## R14 ## suffix,\ |
|
180 |
prefix ## R15 ## suffix, |
|
181 |
|
|
182 |
#define DEF_BREGS(prefixb, prefixh, suffix) \ |
|
183 |
\ |
|
184 |
static void prefixb ## ESP ## suffix ## _wrapper(void) \ |
|
185 |
{ \ |
|
186 |
if (x86_64_hregs) \ |
|
187 |
prefixb ## ESP ## suffix (); \ |
|
188 |
else \ |
|
189 |
prefixh ## EAX ## suffix (); \ |
|
190 |
} \ |
|
191 |
\ |
|
192 |
static void prefixb ## EBP ## suffix ## _wrapper(void) \ |
|
193 |
{ \ |
|
194 |
if (x86_64_hregs) \ |
|
195 |
prefixb ## EBP ## suffix (); \ |
|
196 |
else \ |
|
197 |
prefixh ## ECX ## suffix (); \ |
|
198 |
} \ |
|
199 |
\ |
|
200 |
static void prefixb ## ESI ## suffix ## _wrapper(void) \ |
|
201 |
{ \ |
|
202 |
if (x86_64_hregs) \ |
|
203 |
prefixb ## ESI ## suffix (); \ |
|
204 |
else \ |
|
205 |
prefixh ## EDX ## suffix (); \ |
|
206 |
} \ |
|
207 |
\ |
|
208 |
static void prefixb ## EDI ## suffix ## _wrapper(void) \ |
|
209 |
{ \ |
|
210 |
if (x86_64_hregs) \ |
|
211 |
prefixb ## EDI ## suffix (); \ |
|
212 |
else \ |
|
213 |
prefixh ## EBX ## suffix (); \ |
|
214 |
} |
|
215 |
|
|
216 |
DEF_BREGS(gen_op_movb_, gen_op_movh_, _T0) |
|
217 |
DEF_BREGS(gen_op_movb_, gen_op_movh_, _T1) |
|
218 |
DEF_BREGS(gen_op_movl_T0_, gen_op_movh_T0_, ) |
|
219 |
DEF_BREGS(gen_op_movl_T1_, gen_op_movh_T1_, ) |
|
220 |
|
|
221 |
#else /* !TARGET_X86_64 */ |
|
222 |
|
|
223 |
#define NB_OP_SIZES 3 |
|
224 |
|
|
225 |
#define DEF_REGS(prefix, suffix) \ |
|
226 |
prefix ## EAX ## suffix,\ |
|
227 |
prefix ## ECX ## suffix,\ |
|
228 |
prefix ## EDX ## suffix,\ |
|
229 |
prefix ## EBX ## suffix,\ |
|
230 |
prefix ## ESP ## suffix,\ |
|
231 |
prefix ## EBP ## suffix,\ |
|
232 |
prefix ## ESI ## suffix,\ |
|
233 |
prefix ## EDI ## suffix, |
|
234 |
|
|
235 |
#endif /* !TARGET_X86_64 */ |
|
236 |
|
|
237 |
static GenOpFunc *gen_op_mov_reg_T0[NB_OP_SIZES][CPU_NB_REGS] = { |
|
132 | 238 |
[OT_BYTE] = { |
133 | 239 |
gen_op_movb_EAX_T0, |
134 | 240 |
gen_op_movb_ECX_T0, |
135 | 241 |
gen_op_movb_EDX_T0, |
136 | 242 |
gen_op_movb_EBX_T0, |
243 |
#ifdef TARGET_X86_64 |
|
244 |
gen_op_movb_ESP_T0_wrapper, |
|
245 |
gen_op_movb_EBP_T0_wrapper, |
|
246 |
gen_op_movb_ESI_T0_wrapper, |
|
247 |
gen_op_movb_EDI_T0_wrapper, |
|
248 |
gen_op_movb_R8_T0, |
|
249 |
gen_op_movb_R9_T0, |
|
250 |
gen_op_movb_R10_T0, |
|
251 |
gen_op_movb_R11_T0, |
|
252 |
gen_op_movb_R12_T0, |
|
253 |
gen_op_movb_R13_T0, |
|
254 |
gen_op_movb_R14_T0, |
|
255 |
gen_op_movb_R15_T0, |
|
256 |
#else |
|
137 | 257 |
gen_op_movh_EAX_T0, |
138 | 258 |
gen_op_movh_ECX_T0, |
139 | 259 |
gen_op_movh_EDX_T0, |
140 | 260 |
gen_op_movh_EBX_T0, |
261 |
#endif |
|
141 | 262 |
}, |
142 | 263 |
[OT_WORD] = { |
143 |
gen_op_movw_EAX_T0, |
|
144 |
gen_op_movw_ECX_T0, |
|
145 |
gen_op_movw_EDX_T0, |
|
146 |
gen_op_movw_EBX_T0, |
|
147 |
gen_op_movw_ESP_T0, |
|
148 |
gen_op_movw_EBP_T0, |
|
149 |
gen_op_movw_ESI_T0, |
|
150 |
gen_op_movw_EDI_T0, |
|
264 |
DEF_REGS(gen_op_movw_, _T0) |
|
151 | 265 |
}, |
152 | 266 |
[OT_LONG] = { |
153 |
gen_op_movl_EAX_T0, |
|
154 |
gen_op_movl_ECX_T0, |
|
155 |
gen_op_movl_EDX_T0, |
|
156 |
gen_op_movl_EBX_T0, |
|
157 |
gen_op_movl_ESP_T0, |
|
158 |
gen_op_movl_EBP_T0, |
|
159 |
gen_op_movl_ESI_T0, |
|
160 |
gen_op_movl_EDI_T0, |
|
267 |
DEF_REGS(gen_op_movl_, _T0) |
|
161 | 268 |
}, |
269 |
#ifdef TARGET_X86_64 |
|
270 |
[OT_QUAD] = { |
|
271 |
DEF_REGS(gen_op_movq_, _T0) |
|
272 |
}, |
|
273 |
#endif |
|
162 | 274 |
}; |
163 | 275 |
|
164 |
static GenOpFunc *gen_op_mov_reg_T1[3][8] = {
|
|
276 |
static GenOpFunc *gen_op_mov_reg_T1[NB_OP_SIZES][CPU_NB_REGS] = {
|
|
165 | 277 |
[OT_BYTE] = { |
166 | 278 |
gen_op_movb_EAX_T1, |
167 | 279 |
gen_op_movb_ECX_T1, |
168 | 280 |
gen_op_movb_EDX_T1, |
169 | 281 |
gen_op_movb_EBX_T1, |
282 |
#ifdef TARGET_X86_64 |
|
283 |
gen_op_movb_ESP_T1_wrapper, |
|
284 |
gen_op_movb_EBP_T1_wrapper, |
|
285 |
gen_op_movb_ESI_T1_wrapper, |
|
286 |
gen_op_movb_EDI_T1_wrapper, |
|
287 |
gen_op_movb_R8_T1, |
|
288 |
gen_op_movb_R9_T1, |
|
289 |
gen_op_movb_R10_T1, |
|
290 |
gen_op_movb_R11_T1, |
|
291 |
gen_op_movb_R12_T1, |
|
292 |
gen_op_movb_R13_T1, |
|
293 |
gen_op_movb_R14_T1, |
|
294 |
gen_op_movb_R15_T1, |
|
295 |
#else |
|
170 | 296 |
gen_op_movh_EAX_T1, |
171 | 297 |
gen_op_movh_ECX_T1, |
172 | 298 |
gen_op_movh_EDX_T1, |
173 | 299 |
gen_op_movh_EBX_T1, |
300 |
#endif |
|
174 | 301 |
}, |
175 | 302 |
[OT_WORD] = { |
176 |
gen_op_movw_EAX_T1, |
|
177 |
gen_op_movw_ECX_T1, |
|
178 |
gen_op_movw_EDX_T1, |
|
179 |
gen_op_movw_EBX_T1, |
|
180 |
gen_op_movw_ESP_T1, |
|
181 |
gen_op_movw_EBP_T1, |
|
182 |
gen_op_movw_ESI_T1, |
|
183 |
gen_op_movw_EDI_T1, |
|
303 |
DEF_REGS(gen_op_movw_, _T1) |
|
184 | 304 |
}, |
185 | 305 |
[OT_LONG] = { |
186 |
gen_op_movl_EAX_T1, |
|
187 |
gen_op_movl_ECX_T1, |
|
188 |
gen_op_movl_EDX_T1, |
|
189 |
gen_op_movl_EBX_T1, |
|
190 |
gen_op_movl_ESP_T1, |
|
191 |
gen_op_movl_EBP_T1, |
|
192 |
gen_op_movl_ESI_T1, |
|
193 |
gen_op_movl_EDI_T1, |
|
306 |
DEF_REGS(gen_op_movl_, _T1) |
|
307 |
}, |
|
308 |
#ifdef TARGET_X86_64 |
|
309 |
[OT_QUAD] = { |
|
310 |
DEF_REGS(gen_op_movq_, _T1) |
|
194 | 311 |
}, |
312 |
#endif |
|
195 | 313 |
}; |
196 | 314 |
|
197 |
static GenOpFunc *gen_op_mov_reg_A0[2][8] = {
|
|
315 |
static GenOpFunc *gen_op_mov_reg_A0[NB_OP_SIZES - 1][CPU_NB_REGS] = {
|
|
198 | 316 |
[0] = { |
199 |
gen_op_movw_EAX_A0, |
|
200 |
gen_op_movw_ECX_A0, |
|
201 |
gen_op_movw_EDX_A0, |
|
202 |
gen_op_movw_EBX_A0, |
|
203 |
gen_op_movw_ESP_A0, |
|
204 |
gen_op_movw_EBP_A0, |
|
205 |
gen_op_movw_ESI_A0, |
|
206 |
gen_op_movw_EDI_A0, |
|
317 |
DEF_REGS(gen_op_movw_, _A0) |
|
207 | 318 |
}, |
208 | 319 |
[1] = { |
209 |
gen_op_movl_EAX_A0, |
|
210 |
gen_op_movl_ECX_A0, |
|
211 |
gen_op_movl_EDX_A0, |
|
212 |
gen_op_movl_EBX_A0, |
|
213 |
gen_op_movl_ESP_A0, |
|
214 |
gen_op_movl_EBP_A0, |
|
215 |
gen_op_movl_ESI_A0, |
|
216 |
gen_op_movl_EDI_A0, |
|
320 |
DEF_REGS(gen_op_movl_, _A0) |
|
321 |
}, |
|
322 |
#ifdef TARGET_X86_64 |
|
323 |
[2] = { |
|
324 |
DEF_REGS(gen_op_movq_, _A0) |
|
217 | 325 |
}, |
326 |
#endif |
|
218 | 327 |
}; |
219 | 328 |
|
220 |
static GenOpFunc *gen_op_mov_TN_reg[3][2][8] =
|
|
329 |
static GenOpFunc *gen_op_mov_TN_reg[NB_OP_SIZES][2][CPU_NB_REGS] =
|
|
221 | 330 |
{ |
222 | 331 |
[OT_BYTE] = { |
223 | 332 |
{ |
... | ... | |
225 | 334 |
gen_op_movl_T0_ECX, |
226 | 335 |
gen_op_movl_T0_EDX, |
227 | 336 |
gen_op_movl_T0_EBX, |
337 |
#ifdef TARGET_X86_64 |
|
338 |
gen_op_movl_T0_ESP_wrapper, |
|
339 |
gen_op_movl_T0_EBP_wrapper, |
|
340 |
gen_op_movl_T0_ESI_wrapper, |
|
341 |
gen_op_movl_T0_EDI_wrapper, |
|
342 |
gen_op_movl_T0_R8, |
|
343 |
gen_op_movl_T0_R9, |
|
344 |
gen_op_movl_T0_R10, |
|
345 |
gen_op_movl_T0_R11, |
|
346 |
gen_op_movl_T0_R12, |
|
347 |
gen_op_movl_T0_R13, |
|
348 |
gen_op_movl_T0_R14, |
|
349 |
gen_op_movl_T0_R15, |
|
350 |
#else |
|
228 | 351 |
gen_op_movh_T0_EAX, |
229 | 352 |
gen_op_movh_T0_ECX, |
230 | 353 |
gen_op_movh_T0_EDX, |
231 | 354 |
gen_op_movh_T0_EBX, |
355 |
#endif |
|
232 | 356 |
}, |
233 | 357 |
{ |
234 | 358 |
gen_op_movl_T1_EAX, |
235 | 359 |
gen_op_movl_T1_ECX, |
236 | 360 |
gen_op_movl_T1_EDX, |
237 | 361 |
gen_op_movl_T1_EBX, |
362 |
#ifdef TARGET_X86_64 |
|
363 |
gen_op_movl_T1_ESP_wrapper, |
|
364 |
gen_op_movl_T1_EBP_wrapper, |
|
365 |
gen_op_movl_T1_ESI_wrapper, |
|
366 |
gen_op_movl_T1_EDI_wrapper, |
|
367 |
gen_op_movl_T1_R8, |
|
368 |
gen_op_movl_T1_R9, |
|
369 |
gen_op_movl_T1_R10, |
|
370 |
gen_op_movl_T1_R11, |
|
371 |
gen_op_movl_T1_R12, |
|
372 |
gen_op_movl_T1_R13, |
|
373 |
gen_op_movl_T1_R14, |
|
374 |
gen_op_movl_T1_R15, |
|
375 |
#else |
|
238 | 376 |
gen_op_movh_T1_EAX, |
239 | 377 |
gen_op_movh_T1_ECX, |
240 | 378 |
gen_op_movh_T1_EDX, |
241 | 379 |
gen_op_movh_T1_EBX, |
380 |
#endif |
|
242 | 381 |
}, |
243 | 382 |
}, |
244 | 383 |
[OT_WORD] = { |
245 | 384 |
{ |
246 |
gen_op_movl_T0_EAX, |
|
247 |
gen_op_movl_T0_ECX, |
|
248 |
gen_op_movl_T0_EDX, |
|
249 |
gen_op_movl_T0_EBX, |
|
250 |
gen_op_movl_T0_ESP, |
|
251 |
gen_op_movl_T0_EBP, |
|
252 |
gen_op_movl_T0_ESI, |
|
253 |
gen_op_movl_T0_EDI, |
|
385 |
DEF_REGS(gen_op_movl_T0_, ) |
|
254 | 386 |
}, |
255 | 387 |
{ |
256 |
gen_op_movl_T1_EAX, |
|
257 |
gen_op_movl_T1_ECX, |
|
258 |
gen_op_movl_T1_EDX, |
|
259 |
gen_op_movl_T1_EBX, |
|
260 |
gen_op_movl_T1_ESP, |
|
261 |
gen_op_movl_T1_EBP, |
|
262 |
gen_op_movl_T1_ESI, |
|
263 |
gen_op_movl_T1_EDI, |
|
388 |
DEF_REGS(gen_op_movl_T1_, ) |
|
264 | 389 |
}, |
265 | 390 |
}, |
266 | 391 |
[OT_LONG] = { |
267 | 392 |
{ |
268 |
gen_op_movl_T0_EAX, |
|
269 |
gen_op_movl_T0_ECX, |
|
270 |
gen_op_movl_T0_EDX, |
|
271 |
gen_op_movl_T0_EBX, |
|
272 |
gen_op_movl_T0_ESP, |
|
273 |
gen_op_movl_T0_EBP, |
|
274 |
gen_op_movl_T0_ESI, |
|
275 |
gen_op_movl_T0_EDI, |
|
393 |
DEF_REGS(gen_op_movl_T0_, ) |
|
276 | 394 |
}, |
277 | 395 |
{ |
278 |
gen_op_movl_T1_EAX, |
|
279 |
gen_op_movl_T1_ECX, |
|
280 |
gen_op_movl_T1_EDX, |
|
281 |
gen_op_movl_T1_EBX, |
|
282 |
gen_op_movl_T1_ESP, |
|
283 |
gen_op_movl_T1_EBP, |
|
284 |
gen_op_movl_T1_ESI, |
|
285 |
gen_op_movl_T1_EDI, |
|
396 |
DEF_REGS(gen_op_movl_T1_, ) |
|
286 | 397 |
}, |
287 | 398 |
}, |
399 |
#ifdef TARGET_X86_64 |
|
400 |
[OT_QUAD] = { |
|
401 |
{ |
|
402 |
DEF_REGS(gen_op_movl_T0_, ) |
|
403 |
}, |
|
404 |
{ |
|
405 |
DEF_REGS(gen_op_movl_T1_, ) |
|
406 |
}, |
|
407 |
}, |
|
408 |
#endif |
|
288 | 409 |
}; |
289 | 410 |
|
290 |
static GenOpFunc *gen_op_movl_A0_reg[8] = { |
|
291 |
gen_op_movl_A0_EAX, |
|
292 |
gen_op_movl_A0_ECX, |
|
293 |
gen_op_movl_A0_EDX, |
|
294 |
gen_op_movl_A0_EBX, |
|
295 |
gen_op_movl_A0_ESP, |
|
296 |
gen_op_movl_A0_EBP, |
|
297 |
gen_op_movl_A0_ESI, |
|
298 |
gen_op_movl_A0_EDI, |
|
411 |
static GenOpFunc *gen_op_movl_A0_reg[CPU_NB_REGS] = { |
|
412 |
DEF_REGS(gen_op_movl_A0_, ) |
|
299 | 413 |
}; |
300 | 414 |
|
301 |
static GenOpFunc *gen_op_addl_A0_reg_sN[4][8] = {
|
|
415 |
static GenOpFunc *gen_op_addl_A0_reg_sN[4][CPU_NB_REGS] = {
|
|
302 | 416 |
[0] = { |
303 |
gen_op_addl_A0_EAX, |
|
304 |
gen_op_addl_A0_ECX, |
|
305 |
gen_op_addl_A0_EDX, |
|
306 |
gen_op_addl_A0_EBX, |
|
307 |
gen_op_addl_A0_ESP, |
|
308 |
gen_op_addl_A0_EBP, |
|
309 |
gen_op_addl_A0_ESI, |
|
310 |
gen_op_addl_A0_EDI, |
|
417 |
DEF_REGS(gen_op_addl_A0_, ) |
|
311 | 418 |
}, |
312 | 419 |
[1] = { |
313 |
gen_op_addl_A0_EAX_s1, |
|
314 |
gen_op_addl_A0_ECX_s1, |
|
315 |
gen_op_addl_A0_EDX_s1, |
|
316 |
gen_op_addl_A0_EBX_s1, |
|
317 |
gen_op_addl_A0_ESP_s1, |
|
318 |
gen_op_addl_A0_EBP_s1, |
|
319 |
gen_op_addl_A0_ESI_s1, |
|
320 |
gen_op_addl_A0_EDI_s1, |
|
420 |
DEF_REGS(gen_op_addl_A0_, _s1) |
|
321 | 421 |
}, |
322 | 422 |
[2] = { |
323 |
gen_op_addl_A0_EAX_s2, |
|
324 |
gen_op_addl_A0_ECX_s2, |
|
325 |
gen_op_addl_A0_EDX_s2, |
|
326 |
gen_op_addl_A0_EBX_s2, |
|
327 |
gen_op_addl_A0_ESP_s2, |
|
328 |
gen_op_addl_A0_EBP_s2, |
|
329 |
gen_op_addl_A0_ESI_s2, |
|
330 |
gen_op_addl_A0_EDI_s2, |
|
423 |
DEF_REGS(gen_op_addl_A0_, _s2) |
|
331 | 424 |
}, |
332 | 425 |
[3] = { |
333 |
gen_op_addl_A0_EAX_s3, |
|
334 |
gen_op_addl_A0_ECX_s3, |
|
335 |
gen_op_addl_A0_EDX_s3, |
|
336 |
gen_op_addl_A0_EBX_s3, |
|
337 |
gen_op_addl_A0_ESP_s3, |
|
338 |
gen_op_addl_A0_EBP_s3, |
|
339 |
gen_op_addl_A0_ESI_s3, |
|
340 |
gen_op_addl_A0_EDI_s3, |
|
426 |
DEF_REGS(gen_op_addl_A0_, _s3) |
|
341 | 427 |
}, |
342 | 428 |
}; |
343 | 429 |
|
344 |
static GenOpFunc *gen_op_cmov_reg_T1_T0[2][8] = { |
|
430 |
#ifdef TARGET_X86_64 |
|
431 |
static GenOpFunc *gen_op_movq_A0_reg[CPU_NB_REGS] = { |
|
432 |
DEF_REGS(gen_op_movq_A0_, ) |
|
433 |
}; |
|
434 |
|
|
435 |
static GenOpFunc *gen_op_addq_A0_reg_sN[4][CPU_NB_REGS] = { |
|
345 | 436 |
[0] = { |
346 |
gen_op_cmovw_EAX_T1_T0, |
|
347 |
gen_op_cmovw_ECX_T1_T0, |
|
348 |
gen_op_cmovw_EDX_T1_T0, |
|
349 |
gen_op_cmovw_EBX_T1_T0, |
|
350 |
gen_op_cmovw_ESP_T1_T0, |
|
351 |
gen_op_cmovw_EBP_T1_T0, |
|
352 |
gen_op_cmovw_ESI_T1_T0, |
|
353 |
gen_op_cmovw_EDI_T1_T0, |
|
437 |
DEF_REGS(gen_op_addq_A0_, ) |
|
354 | 438 |
}, |
355 | 439 |
[1] = { |
356 |
gen_op_cmovl_EAX_T1_T0, |
|
357 |
gen_op_cmovl_ECX_T1_T0, |
|
358 |
gen_op_cmovl_EDX_T1_T0, |
|
359 |
gen_op_cmovl_EBX_T1_T0, |
|
360 |
gen_op_cmovl_ESP_T1_T0, |
|
361 |
gen_op_cmovl_EBP_T1_T0, |
|
362 |
gen_op_cmovl_ESI_T1_T0, |
|
363 |
gen_op_cmovl_EDI_T1_T0, |
|
440 |
DEF_REGS(gen_op_addq_A0_, _s1) |
|
441 |
}, |
|
442 |
[2] = { |
|
443 |
DEF_REGS(gen_op_addq_A0_, _s2) |
|
444 |
}, |
|
445 |
[3] = { |
|
446 |
DEF_REGS(gen_op_addq_A0_, _s3) |
|
364 | 447 |
}, |
365 | 448 |
}; |
449 |
#endif |
|
450 |
|
|
451 |
static GenOpFunc *gen_op_cmov_reg_T1_T0[NB_OP_SIZES - 1][CPU_NB_REGS] = { |
|
452 |
[0] = { |
|
453 |
DEF_REGS(gen_op_cmovw_, _T1_T0) |
|
454 |
}, |
|
455 |
[1] = { |
|
456 |
DEF_REGS(gen_op_cmovl_, _T1_T0) |
|
457 |
}, |
|
458 |
#ifdef TARGET_X86_64 |
|
459 |
[2] = { |
|
460 |
DEF_REGS(gen_op_cmovq_, _T1_T0) |
|
461 |
}, |
|
462 |
#endif |
|
463 |
}; |
|
366 | 464 |
|
367 | 465 |
static GenOpFunc *gen_op_arith_T0_T1_cc[8] = { |
368 | 466 |
NULL, |
... | ... | |
387 | 485 |
{\ |
388 | 486 |
gen_op_adcl ## SUFFIX ## _T0_T1_cc,\ |
389 | 487 |
gen_op_sbbl ## SUFFIX ## _T0_T1_cc,\ |
488 |
},\ |
|
489 |
{\ |
|
490 |
X86_64_ONLY(gen_op_adcq ## SUFFIX ## _T0_T1_cc),\ |
|
491 |
X86_64_ONLY(gen_op_sbbq ## SUFFIX ## _T0_T1_cc),\ |
|
390 | 492 |
}, |
391 | 493 |
|
392 |
static GenOpFunc *gen_op_arithc_T0_T1_cc[3][2] = {
|
|
494 |
static GenOpFunc *gen_op_arithc_T0_T1_cc[4][2] = {
|
|
393 | 495 |
DEF_ARITHC( ) |
394 | 496 |
}; |
395 | 497 |
|
396 |
static GenOpFunc *gen_op_arithc_mem_T0_T1_cc[9][2] = {
|
|
498 |
static GenOpFunc *gen_op_arithc_mem_T0_T1_cc[3 * 4][2] = {
|
|
397 | 499 |
DEF_ARITHC(_raw) |
398 | 500 |
#ifndef CONFIG_USER_ONLY |
399 | 501 |
DEF_ARITHC(_kernel) |
... | ... | |
415 | 517 |
#define DEF_CMPXCHG(SUFFIX)\ |
416 | 518 |
gen_op_cmpxchgb ## SUFFIX ## _T0_T1_EAX_cc,\ |
417 | 519 |
gen_op_cmpxchgw ## SUFFIX ## _T0_T1_EAX_cc,\ |
418 |
gen_op_cmpxchgl ## SUFFIX ## _T0_T1_EAX_cc, |
|
419 |
|
|
520 |
gen_op_cmpxchgl ## SUFFIX ## _T0_T1_EAX_cc,\
|
|
521 |
X86_64_ONLY(gen_op_cmpxchgq ## SUFFIX ## _T0_T1_EAX_cc), |
|
420 | 522 |
|
421 |
static GenOpFunc *gen_op_cmpxchg_T0_T1_EAX_cc[3] = {
|
|
523 |
static GenOpFunc *gen_op_cmpxchg_T0_T1_EAX_cc[4] = {
|
|
422 | 524 |
DEF_CMPXCHG( ) |
423 | 525 |
}; |
424 | 526 |
|
425 |
static GenOpFunc *gen_op_cmpxchg_mem_T0_T1_EAX_cc[9] = {
|
|
527 |
static GenOpFunc *gen_op_cmpxchg_mem_T0_T1_EAX_cc[3 * 4] = {
|
|
426 | 528 |
DEF_CMPXCHG(_raw) |
427 | 529 |
#ifndef CONFIG_USER_ONLY |
428 | 530 |
DEF_CMPXCHG(_kernel) |
... | ... | |
460 | 562 |
gen_op_shrl ## SUFFIX ## _T0_T1_cc,\ |
461 | 563 |
gen_op_shll ## SUFFIX ## _T0_T1_cc,\ |
462 | 564 |
gen_op_sarl ## SUFFIX ## _T0_T1_cc,\ |
565 |
},\ |
|
566 |
{\ |
|
567 |
X86_64_ONLY(gen_op_rolq ## SUFFIX ## _T0_T1_cc),\ |
|
568 |
X86_64_ONLY(gen_op_rorq ## SUFFIX ## _T0_T1_cc),\ |
|
569 |
X86_64_ONLY(gen_op_rclq ## SUFFIX ## _T0_T1_cc),\ |
|
570 |
X86_64_ONLY(gen_op_rcrq ## SUFFIX ## _T0_T1_cc),\ |
|
571 |
X86_64_ONLY(gen_op_shlq ## SUFFIX ## _T0_T1_cc),\ |
|
572 |
X86_64_ONLY(gen_op_shrq ## SUFFIX ## _T0_T1_cc),\ |
|
573 |
X86_64_ONLY(gen_op_shlq ## SUFFIX ## _T0_T1_cc),\ |
|
574 |
X86_64_ONLY(gen_op_sarq ## SUFFIX ## _T0_T1_cc),\ |
|
463 | 575 |
}, |
464 | 576 |
|
465 |
static GenOpFunc *gen_op_shift_T0_T1_cc[3][8] = {
|
|
577 |
static GenOpFunc *gen_op_shift_T0_T1_cc[4][8] = {
|
|
466 | 578 |
DEF_SHIFT( ) |
467 | 579 |
}; |
468 | 580 |
|
469 |
static GenOpFunc *gen_op_shift_mem_T0_T1_cc[9][8] = {
|
|
581 |
static GenOpFunc *gen_op_shift_mem_T0_T1_cc[3 * 4][8] = {
|
|
470 | 582 |
DEF_SHIFT(_raw) |
471 | 583 |
#ifndef CONFIG_USER_ONLY |
472 | 584 |
DEF_SHIFT(_kernel) |
... | ... | |
486 | 598 |
{\ |
487 | 599 |
gen_op_shldl ## SUFFIX ## _T0_T1_ ## op ## _cc,\ |
488 | 600 |
gen_op_shrdl ## SUFFIX ## _T0_T1_ ## op ## _cc,\ |
601 |
},\ |
|
602 |
{\ |
|
489 | 603 |
}, |
490 | 604 |
|
491 |
|
|
492 |
static GenOpFunc1 *gen_op_shiftd_T0_T1_im_cc[3][2] = { |
|
605 |
static GenOpFunc1 *gen_op_shiftd_T0_T1_im_cc[4][2] = { |
|
493 | 606 |
DEF_SHIFTD(, im) |
494 | 607 |
}; |
495 | 608 |
|
496 |
static GenOpFunc *gen_op_shiftd_T0_T1_ECX_cc[3][2] = {
|
|
609 |
static GenOpFunc *gen_op_shiftd_T0_T1_ECX_cc[4][2] = {
|
|
497 | 610 |
DEF_SHIFTD(, ECX) |
498 | 611 |
}; |
499 | 612 |
|
500 |
static GenOpFunc1 *gen_op_shiftd_mem_T0_T1_im_cc[9][2] = {
|
|
613 |
static GenOpFunc1 *gen_op_shiftd_mem_T0_T1_im_cc[3 * 4][2] = {
|
|
501 | 614 |
DEF_SHIFTD(_raw, im) |
502 | 615 |
#ifndef CONFIG_USER_ONLY |
503 | 616 |
DEF_SHIFTD(_kernel, im) |
... | ... | |
505 | 618 |
#endif |
506 | 619 |
}; |
507 | 620 |
|
508 |
static GenOpFunc *gen_op_shiftd_mem_T0_T1_ECX_cc[9][2] = {
|
|
621 |
static GenOpFunc *gen_op_shiftd_mem_T0_T1_ECX_cc[3 * 4][2] = {
|
|
509 | 622 |
DEF_SHIFTD(_raw, ECX) |
510 | 623 |
#ifndef CONFIG_USER_ONLY |
511 | 624 |
DEF_SHIFTD(_kernel, ECX) |
... | ... | |
513 | 626 |
#endif |
514 | 627 |
}; |
515 | 628 |
|
516 |
static GenOpFunc *gen_op_btx_T0_T1_cc[2][4] = {
|
|
629 |
static GenOpFunc *gen_op_btx_T0_T1_cc[3][4] = {
|
|
517 | 630 |
[0] = { |
518 | 631 |
gen_op_btw_T0_T1_cc, |
519 | 632 |
gen_op_btsw_T0_T1_cc, |
... | ... | |
526 | 639 |
gen_op_btrl_T0_T1_cc, |
527 | 640 |
gen_op_btcl_T0_T1_cc, |
528 | 641 |
}, |
642 |
#ifdef TARGET_X86_64 |
|
643 |
[2] = { |
|
644 |
gen_op_btq_T0_T1_cc, |
|
645 |
gen_op_btsq_T0_T1_cc, |
|
646 |
gen_op_btrq_T0_T1_cc, |
|
647 |
gen_op_btcq_T0_T1_cc, |
|
648 |
}, |
|
649 |
#endif |
|
650 |
}; |
|
651 |
|
|
652 |
static GenOpFunc *gen_op_add_bit_A0_T1[3] = { |
|
653 |
gen_op_add_bitw_A0_T1, |
|
654 |
gen_op_add_bitl_A0_T1, |
|
655 |
X86_64_ONLY(gen_op_add_bitq_A0_T1), |
|
529 | 656 |
}; |
530 | 657 |
|
531 |
static GenOpFunc *gen_op_bsx_T0_cc[2][2] = {
|
|
658 |
static GenOpFunc *gen_op_bsx_T0_cc[3][2] = {
|
|
532 | 659 |
[0] = { |
533 | 660 |
gen_op_bsfw_T0_cc, |
534 | 661 |
gen_op_bsrw_T0_cc, |
... | ... | |
537 | 664 |
gen_op_bsfl_T0_cc, |
538 | 665 |
gen_op_bsrl_T0_cc, |
539 | 666 |
}, |
667 |
#ifdef TARGET_X86_64 |
|
668 |
[2] = { |
|
669 |
gen_op_bsfq_T0_cc, |
|
670 |
gen_op_bsrq_T0_cc, |
|
671 |
}, |
|
672 |
#endif |
|
540 | 673 |
}; |
541 | 674 |
|
542 |
static GenOpFunc *gen_op_lds_T0_A0[3 * 3] = {
|
|
675 |
static GenOpFunc *gen_op_lds_T0_A0[3 * 4] = {
|
|
543 | 676 |
gen_op_ldsb_raw_T0_A0, |
544 | 677 |
gen_op_ldsw_raw_T0_A0, |
678 |
X86_64_ONLY(gen_op_ldsl_raw_T0_A0), |
|
545 | 679 |
NULL, |
546 | 680 |
#ifndef CONFIG_USER_ONLY |
547 | 681 |
gen_op_ldsb_kernel_T0_A0, |
548 | 682 |
gen_op_ldsw_kernel_T0_A0, |
683 |
X86_64_ONLY(gen_op_ldsl_kernel_T0_A0), |
|
549 | 684 |
NULL, |
550 | 685 |
|
551 | 686 |
gen_op_ldsb_user_T0_A0, |
552 | 687 |
gen_op_ldsw_user_T0_A0, |
688 |
X86_64_ONLY(gen_op_ldsl_user_T0_A0), |
|
553 | 689 |
NULL, |
554 | 690 |
#endif |
555 | 691 |
}; |
556 | 692 |
|
557 |
static GenOpFunc *gen_op_ldu_T0_A0[3 * 3] = {
|
|
693 |
static GenOpFunc *gen_op_ldu_T0_A0[3 * 4] = {
|
|
558 | 694 |
gen_op_ldub_raw_T0_A0, |
559 | 695 |
gen_op_lduw_raw_T0_A0, |
560 | 696 |
NULL, |
697 |
NULL, |
|
561 | 698 |
|
562 | 699 |
#ifndef CONFIG_USER_ONLY |
563 | 700 |
gen_op_ldub_kernel_T0_A0, |
564 | 701 |
gen_op_lduw_kernel_T0_A0, |
565 | 702 |
NULL, |
703 |
NULL, |
|
566 | 704 |
|
567 | 705 |
gen_op_ldub_user_T0_A0, |
568 | 706 |
gen_op_lduw_user_T0_A0, |
569 | 707 |
NULL, |
708 |
NULL, |
|
570 | 709 |
#endif |
571 | 710 |
}; |
572 | 711 |
|
573 | 712 |
/* sign does not matter, except for lidt/lgdt call (TODO: fix it) */ |
574 |
static GenOpFunc *gen_op_ld_T0_A0[3 * 3] = {
|
|
713 |
static GenOpFunc *gen_op_ld_T0_A0[3 * 4] = {
|
|
575 | 714 |
gen_op_ldub_raw_T0_A0, |
576 | 715 |
gen_op_lduw_raw_T0_A0, |
577 | 716 |
gen_op_ldl_raw_T0_A0, |
717 |
X86_64_ONLY(gen_op_ldq_raw_T0_A0), |
|
578 | 718 |
|
579 | 719 |
#ifndef CONFIG_USER_ONLY |
580 | 720 |
gen_op_ldub_kernel_T0_A0, |
581 | 721 |
gen_op_lduw_kernel_T0_A0, |
582 | 722 |
gen_op_ldl_kernel_T0_A0, |
723 |
X86_64_ONLY(gen_op_ldq_kernel_T0_A0), |
|
583 | 724 |
|
584 | 725 |
gen_op_ldub_user_T0_A0, |
585 | 726 |
gen_op_lduw_user_T0_A0, |
586 | 727 |
gen_op_ldl_user_T0_A0, |
728 |
X86_64_ONLY(gen_op_ldq_user_T0_A0), |
|
587 | 729 |
#endif |
588 | 730 |
}; |
589 | 731 |
|
590 |
static GenOpFunc *gen_op_ld_T1_A0[3 * 3] = {
|
|
732 |
static GenOpFunc *gen_op_ld_T1_A0[3 * 4] = {
|
|
591 | 733 |
gen_op_ldub_raw_T1_A0, |
592 | 734 |
gen_op_lduw_raw_T1_A0, |
593 | 735 |
gen_op_ldl_raw_T1_A0, |
736 |
X86_64_ONLY(gen_op_ldq_raw_T1_A0), |
|
594 | 737 |
|
595 | 738 |
#ifndef CONFIG_USER_ONLY |
596 | 739 |
gen_op_ldub_kernel_T1_A0, |
597 | 740 |
gen_op_lduw_kernel_T1_A0, |
598 | 741 |
gen_op_ldl_kernel_T1_A0, |
742 |
X86_64_ONLY(gen_op_ldq_kernel_T1_A0), |
|
599 | 743 |
|
600 | 744 |
gen_op_ldub_user_T1_A0, |
601 | 745 |
gen_op_lduw_user_T1_A0, |
602 | 746 |
gen_op_ldl_user_T1_A0, |
747 |
X86_64_ONLY(gen_op_ldq_user_T1_A0), |
|
603 | 748 |
#endif |
604 | 749 |
}; |
605 | 750 |
|
606 |
static GenOpFunc *gen_op_st_T0_A0[3 * 3] = {
|
|
751 |
static GenOpFunc *gen_op_st_T0_A0[3 * 4] = {
|
|
607 | 752 |
gen_op_stb_raw_T0_A0, |
608 | 753 |
gen_op_stw_raw_T0_A0, |
609 | 754 |
gen_op_stl_raw_T0_A0, |
755 |
X86_64_ONLY(gen_op_stq_raw_T0_A0), |
|
610 | 756 |
|
611 | 757 |
#ifndef CONFIG_USER_ONLY |
612 | 758 |
gen_op_stb_kernel_T0_A0, |
613 | 759 |
gen_op_stw_kernel_T0_A0, |
614 | 760 |
gen_op_stl_kernel_T0_A0, |
761 |
X86_64_ONLY(gen_op_stq_kernel_T0_A0), |
|
615 | 762 |
|
616 | 763 |
gen_op_stb_user_T0_A0, |
617 | 764 |
gen_op_stw_user_T0_A0, |
618 | 765 |
gen_op_stl_user_T0_A0, |
766 |
X86_64_ONLY(gen_op_stq_user_T0_A0), |
|
619 | 767 |
#endif |
620 | 768 |
}; |
621 | 769 |
|
622 |
static GenOpFunc *gen_op_st_T1_A0[3 * 3] = {
|
|
770 |
static GenOpFunc *gen_op_st_T1_A0[3 * 4] = {
|
|
623 | 771 |
NULL, |
624 | 772 |
gen_op_stw_raw_T1_A0, |
625 | 773 |
gen_op_stl_raw_T1_A0, |
774 |
X86_64_ONLY(gen_op_stq_raw_T1_A0), |
|
626 | 775 |
|
627 | 776 |
#ifndef CONFIG_USER_ONLY |
628 | 777 |
NULL, |
629 | 778 |
gen_op_stw_kernel_T1_A0, |
630 | 779 |
gen_op_stl_kernel_T1_A0, |
780 |
X86_64_ONLY(gen_op_stq_kernel_T1_A0), |
|
631 | 781 |
|
632 | 782 |
NULL, |
633 | 783 |
gen_op_stw_user_T1_A0, |
634 | 784 |
gen_op_stl_user_T1_A0, |
785 |
X86_64_ONLY(gen_op_stq_user_T1_A0), |
|
635 | 786 |
#endif |
636 | 787 |
}; |
637 | 788 |
|
789 |
static inline void gen_jmp_im(target_ulong pc) |
|
790 |
{ |
|
791 |
#ifdef TARGET_X86_64 |
|
792 |
if (pc == (uint32_t)pc) { |
|
793 |
gen_op_movl_eip_im(pc); |
|
794 |
} else if (pc == (int32_t)pc) { |
|
795 |
gen_op_movq_eip_im(pc); |
|
796 |
} else { |
|
797 |
gen_op_movq_eip_im64(pc >> 32, pc); |
|
798 |
} |
|
799 |
#else |
|
800 |
gen_op_movl_eip_im(pc); |
|
801 |
#endif |
|
802 |
} |
|
803 |
|
|
638 | 804 |
static inline void gen_string_movl_A0_ESI(DisasContext *s) |
639 | 805 |
{ |
640 | 806 |
int override; |
641 | 807 |
|
642 | 808 |
override = s->override; |
809 |
#ifdef TARGET_X86_64 |
|
810 |
if (s->aflag == 2) { |
|
811 |
if (override >= 0) { |
|
812 |
gen_op_movq_A0_seg(offsetof(CPUX86State,segs[override].base)); |
|
813 |
gen_op_addq_A0_reg_sN[0][R_ESI](); |
|
814 |
} else { |
|
815 |
gen_op_movq_A0_reg[R_ESI](); |
|
816 |
} |
|
817 |
} else |
|
818 |
#endif |
|
643 | 819 |
if (s->aflag) { |
644 | 820 |
/* 32 bit address */ |
645 | 821 |
if (s->addseg && override < 0) |
... | ... | |
662 | 838 |
|
663 | 839 |
static inline void gen_string_movl_A0_EDI(DisasContext *s) |
664 | 840 |
{ |
841 |
#ifdef TARGET_X86_64 |
|
842 |
if (s->aflag == 2) { |
|
843 |
gen_op_movq_A0_reg[R_EDI](); |
|
844 |
} else |
|
845 |
#endif |
|
665 | 846 |
if (s->aflag) { |
666 | 847 |
if (s->addseg) { |
667 | 848 |
gen_op_movl_A0_seg(offsetof(CPUX86State,segs[R_ES].base)); |
... | ... | |
676 | 857 |
} |
677 | 858 |
} |
678 | 859 |
|
679 |
static GenOpFunc *gen_op_movl_T0_Dshift[3] = {
|
|
860 |
static GenOpFunc *gen_op_movl_T0_Dshift[4] = {
|
|
680 | 861 |
gen_op_movl_T0_Dshiftb, |
681 | 862 |
gen_op_movl_T0_Dshiftw, |
682 | 863 |
gen_op_movl_T0_Dshiftl, |
864 |
X86_64_ONLY(gen_op_movl_T0_Dshiftq), |
|
683 | 865 |
}; |
684 | 866 |
|
685 |
static GenOpFunc2 *gen_op_jz_ecx[2] = { |
|
686 |
gen_op_jz_ecxw, |
|
687 |
gen_op_jz_ecxl, |
|
867 |
static GenOpFunc1 *gen_op_jnz_ecx[3] = { |
|
868 |
gen_op_jnz_ecxw, |
|
869 |
gen_op_jnz_ecxl, |
|
870 |
X86_64_ONLY(gen_op_jnz_ecxq), |
|
688 | 871 |
}; |
689 | 872 |
|
690 |
static GenOpFunc1 *gen_op_jz_ecx_im[2] = { |
|
691 |
gen_op_jz_ecxw_im, |
|
692 |
gen_op_jz_ecxl_im, |
|
873 |
static GenOpFunc1 *gen_op_jz_ecx[3] = { |
|
874 |
gen_op_jz_ecxw, |
|
875 |
gen_op_jz_ecxl, |
|
876 |
X86_64_ONLY(gen_op_jz_ecxq), |
|
693 | 877 |
}; |
694 | 878 |
|
695 |
static GenOpFunc *gen_op_dec_ECX[2] = {
|
|
879 |
static GenOpFunc *gen_op_dec_ECX[3] = {
|
|
696 | 880 |
gen_op_decw_ECX, |
697 | 881 |
gen_op_decl_ECX, |
882 |
X86_64_ONLY(gen_op_decq_ECX), |
|
698 | 883 |
}; |
699 | 884 |
|
700 |
#ifdef USE_DIRECT_JUMP |
|
701 |
typedef GenOpFunc GenOpFuncTB2; |
|
702 |
#define gen_op_string_jnz_sub(nz, ot, tb) gen_op_string_jnz_sub2[nz][ot]() |
|
703 |
#else |
|
704 |
typedef GenOpFunc1 GenOpFuncTB2; |
|
705 |
#define gen_op_string_jnz_sub(nz, ot, tb) gen_op_string_jnz_sub2[nz][ot](tb) |
|
706 |
#endif |
|
707 |
|
|
708 |
static GenOpFuncTB2 *gen_op_string_jnz_sub2[2][3] = { |
|
885 |
static GenOpFunc1 *gen_op_string_jnz_sub[2][4] = { |
|
709 | 886 |
{ |
710 |
gen_op_string_jnz_subb, |
|
711 |
gen_op_string_jnz_subw, |
|
712 |
gen_op_string_jnz_subl, |
|
887 |
gen_op_jnz_subb, |
|
888 |
gen_op_jnz_subw, |
|
889 |
gen_op_jnz_subl, |
|
890 |
X86_64_ONLY(gen_op_jnz_subq), |
|
713 | 891 |
}, |
714 | 892 |
{ |
715 |
gen_op_string_jz_subb, |
|
716 |
gen_op_string_jz_subw, |
|
717 |
gen_op_string_jz_subl, |
|
718 |
}, |
|
719 |
}; |
|
720 |
|
|
721 |
static GenOpFunc1 *gen_op_string_jnz_sub_im[2][3] = { |
|
722 |
{ |
|
723 |
gen_op_string_jnz_subb_im, |
|
724 |
gen_op_string_jnz_subw_im, |
|
725 |
gen_op_string_jnz_subl_im, |
|
726 |
}, |
|
727 |
{ |
|
728 |
gen_op_string_jz_subb_im, |
|
729 |
gen_op_string_jz_subw_im, |
|
730 |
gen_op_string_jz_subl_im, |
|
893 |
gen_op_jz_subb, |
|
894 |
gen_op_jz_subw, |
|
895 |
gen_op_jz_subl, |
|
896 |
X86_64_ONLY(gen_op_jz_subq), |
|
731 | 897 |
}, |
732 | 898 |
}; |
733 | 899 |
|
... | ... | |
767 | 933 |
gen_op_check_iol_DX, |
768 | 934 |
}; |
769 | 935 |
|
770 |
static void gen_check_io(DisasContext *s, int ot, int use_dx, int cur_eip)
|
|
936 |
static void gen_check_io(DisasContext *s, int ot, int use_dx, target_ulong cur_eip)
|
|
771 | 937 |
{ |
772 | 938 |
if (s->pe && (s->cpl > s->iopl || s->vm86)) { |
773 | 939 |
if (s->cc_op != CC_OP_DYNAMIC) |
774 | 940 |
gen_op_set_cc_op(s->cc_op); |
775 |
gen_op_jmp_im(cur_eip);
|
|
941 |
gen_jmp_im(cur_eip); |
|
776 | 942 |
if (use_dx) |
777 | 943 |
gen_check_io_DX[ot](); |
778 | 944 |
else |
... | ... | |
787 | 953 |
gen_string_movl_A0_EDI(s); |
788 | 954 |
gen_op_st_T0_A0[ot + s->mem_index](); |
789 | 955 |
gen_op_movl_T0_Dshift[ot](); |
956 |
#ifdef TARGET_X86_64 |
|
957 |
if (s->aflag == 2) { |
|
958 |
gen_op_addq_ESI_T0(); |
|
959 |
gen_op_addq_EDI_T0(); |
|
960 |
} else |
|
961 |
#endif |
|
790 | 962 |
if (s->aflag) { |
791 | 963 |
gen_op_addl_ESI_T0(); |
792 | 964 |
gen_op_addl_EDI_T0(); |
... | ... | |
804 | 976 |
} |
805 | 977 |
} |
806 | 978 |
|
807 |
static inline void gen_jz_ecx_string(DisasContext *s, unsigned int next_eip) |
|
979 |
/* XXX: does not work with gdbstub "ice" single step - not a |
|
980 |
serious problem */ |
|
981 |
static int gen_jz_ecx_string(DisasContext *s, target_ulong next_eip) |
|
808 | 982 |
{ |
809 |
if (s->jmp_opt) { |
|
810 |
gen_op_jz_ecx[s->aflag]((long)s->tb, next_eip); |
|
811 |
} else { |
|
812 |
/* XXX: does not work with gdbstub "ice" single step - not a |
|
813 |
serious problem */ |
|
814 |
gen_op_jz_ecx_im[s->aflag](next_eip); |
|
815 |
} |
|
983 |
int l1, l2; |
|
984 |
|
|
985 |
l1 = gen_new_label(); |
|
986 |
l2 = gen_new_label(); |
|
987 |
gen_op_jnz_ecx[s->aflag](l1); |
|
988 |
gen_set_label(l2); |
|
989 |
gen_jmp_tb(s, next_eip, 1); |
|
990 |
gen_set_label(l1); |
|
991 |
return l2; |
|
816 | 992 |
} |
817 | 993 |
|
818 | 994 |
static inline void gen_stos(DisasContext *s, int ot) |
... | ... | |
821 | 997 |
gen_string_movl_A0_EDI(s); |
822 | 998 |
gen_op_st_T0_A0[ot + s->mem_index](); |
823 | 999 |
gen_op_movl_T0_Dshift[ot](); |
1000 |
#ifdef TARGET_X86_64 |
|
1001 |
if (s->aflag == 2) { |
|
1002 |
gen_op_addq_EDI_T0(); |
|
1003 |
} else |
|
1004 |
#endif |
|
824 | 1005 |
if (s->aflag) { |
825 | 1006 |
gen_op_addl_EDI_T0(); |
826 | 1007 |
} else { |
... | ... | |
834 | 1015 |
gen_op_ld_T0_A0[ot + s->mem_index](); |
835 | 1016 |
gen_op_mov_reg_T0[ot][R_EAX](); |
836 | 1017 |
gen_op_movl_T0_Dshift[ot](); |
1018 |
#ifdef TARGET_X86_64 |
|
1019 |
if (s->aflag == 2) { |
|
1020 |
gen_op_addq_ESI_T0(); |
|
1021 |
} else |
|
1022 |
#endif |
|
837 | 1023 |
if (s->aflag) { |
838 | 1024 |
gen_op_addl_ESI_T0(); |
839 | 1025 |
} else { |
... | ... | |
848 | 1034 |
gen_op_ld_T1_A0[ot + s->mem_index](); |
849 | 1035 |
gen_op_cmpl_T0_T1_cc(); |
850 | 1036 |
gen_op_movl_T0_Dshift[ot](); |
1037 |
#ifdef TARGET_X86_64 |
|
1038 |
if (s->aflag == 2) { |
|
1039 |
gen_op_addq_EDI_T0(); |
|
1040 |
} else |
|
1041 |
#endif |
|
851 | 1042 |
if (s->aflag) { |
852 | 1043 |
gen_op_addl_EDI_T0(); |
853 | 1044 |
} else { |
... | ... | |
863 | 1054 |
gen_op_ld_T1_A0[ot + s->mem_index](); |
864 | 1055 |
gen_op_cmpl_T0_T1_cc(); |
865 | 1056 |
gen_op_movl_T0_Dshift[ot](); |
1057 |
#ifdef TARGET_X86_64 |
|
1058 |
if (s->aflag == 2) { |
|
1059 |
gen_op_addq_ESI_T0(); |
|
1060 |
gen_op_addq_EDI_T0(); |
|
1061 |
} else |
|
1062 |
#endif |
|
866 | 1063 |
if (s->aflag) { |
867 | 1064 |
gen_op_addl_ESI_T0(); |
868 | 1065 |
gen_op_addl_EDI_T0(); |
... | ... | |
880 | 1077 |
gen_op_in_DX_T0[ot](); |
881 | 1078 |
gen_op_st_T0_A0[ot + s->mem_index](); |
882 | 1079 |
gen_op_movl_T0_Dshift[ot](); |
1080 |
#ifdef TARGET_X86_64 |
|
1081 |
if (s->aflag == 2) { |
|
1082 |
gen_op_addq_EDI_T0(); |
|
1083 |
} else |
|
1084 |
#endif |
|
883 | 1085 |
if (s->aflag) { |
884 | 1086 |
gen_op_addl_EDI_T0(); |
885 | 1087 |
} else { |
... | ... | |
893 | 1095 |
gen_op_ld_T0_A0[ot + s->mem_index](); |
894 | 1096 |
gen_op_out_DX_T0[ot](); |
895 | 1097 |
gen_op_movl_T0_Dshift[ot](); |
1098 |
#ifdef TARGET_X86_64 |
|
1099 |
if (s->aflag == 2) { |
|
1100 |
gen_op_addq_ESI_T0(); |
|
1101 |
} else |
|
1102 |
#endif |
|
896 | 1103 |
if (s->aflag) { |
897 | 1104 |
gen_op_addl_ESI_T0(); |
898 | 1105 |
} else { |
... | ... | |
904 | 1111 |
instruction */ |
905 | 1112 |
#define GEN_REPZ(op) \ |
906 | 1113 |
static inline void gen_repz_ ## op(DisasContext *s, int ot, \ |
907 |
unsigned int cur_eip, unsigned int next_eip) \
|
|
1114 |
target_ulong cur_eip, target_ulong next_eip) \
|
|
908 | 1115 |
{ \ |
1116 |
int l2;\ |
|
909 | 1117 |
gen_update_cc_op(s); \ |
910 |
gen_jz_ecx_string(s, next_eip); \
|
|
1118 |
l2 = gen_jz_ecx_string(s, next_eip); \
|
|
911 | 1119 |
gen_ ## op(s, ot); \ |
912 | 1120 |
gen_op_dec_ECX[s->aflag](); \ |
913 | 1121 |
/* a loop would cause two single step exceptions if ECX = 1 \ |
914 | 1122 |
before rep string_insn */ \ |
915 | 1123 |
if (!s->jmp_opt) \ |
916 |
gen_op_jz_ecx_im[s->aflag](next_eip); \
|
|
1124 |
gen_op_jz_ecx[s->aflag](l2); \
|
|
917 | 1125 |
gen_jmp(s, cur_eip); \ |
918 | 1126 |
} |
919 | 1127 |
|
920 | 1128 |
#define GEN_REPZ2(op) \ |
921 | 1129 |
static inline void gen_repz_ ## op(DisasContext *s, int ot, \ |
922 |
unsigned int cur_eip, \
|
|
923 |
unsigned int next_eip, \
|
|
1130 |
target_ulong cur_eip, \
|
|
1131 |
target_ulong next_eip, \
|
|
924 | 1132 |
int nz) \ |
925 | 1133 |
{ \ |
1134 |
int l2;\ |
|
926 | 1135 |
gen_update_cc_op(s); \ |
927 |
gen_jz_ecx_string(s, next_eip); \
|
|
1136 |
l2 = gen_jz_ecx_string(s, next_eip); \
|
|
928 | 1137 |
gen_ ## op(s, ot); \ |
929 | 1138 |
gen_op_dec_ECX[s->aflag](); \ |
930 | 1139 |
gen_op_set_cc_op(CC_OP_SUBB + ot); \ |
1140 |
gen_op_string_jnz_sub[nz][ot](l2);\ |
|
931 | 1141 |
if (!s->jmp_opt) \ |
932 |
gen_op_string_jnz_sub_im[nz][ot](next_eip); \ |
|
933 |
else \ |
|
934 |
gen_op_string_jnz_sub(nz, ot, (long)s->tb); \ |
|
935 |
if (!s->jmp_opt) \ |
|
936 |
gen_op_jz_ecx_im[s->aflag](next_eip); \ |
|
1142 |
gen_op_jz_ecx[s->aflag](l2); \ |
|
937 | 1143 |
gen_jmp(s, cur_eip); \ |
938 | 1144 |
} |
939 | 1145 |
|
... | ... | |
956 | 1162 |
JCC_LE, |
957 | 1163 |
}; |
958 | 1164 |
|
959 |
static GenOpFunc3 *gen_jcc_sub[3][8] = {
|
|
1165 |
static GenOpFunc1 *gen_jcc_sub[4][8] = {
|
|
960 | 1166 |
[OT_BYTE] = { |
961 | 1167 |
NULL, |
962 | 1168 |
gen_op_jb_subb, |
... | ... | |
987 | 1193 |
gen_op_jl_subl, |
988 | 1194 |
gen_op_jle_subl, |
989 | 1195 |
}, |
1196 |
#ifdef TARGET_X86_64 |
|
1197 |
[OT_QUAD] = { |
|
1198 |
NULL, |
|
1199 |
BUGGY_64(gen_op_jb_subq), |
|
1200 |
gen_op_jz_subq, |
|
1201 |
BUGGY_64(gen_op_jbe_subq), |
|
1202 |
gen_op_js_subq, |
|
1203 |
NULL, |
|
1204 |
BUGGY_64(gen_op_jl_subq), |
|
1205 |
BUGGY_64(gen_op_jle_subq), |
|
1206 |
}, |
|
1207 |
#endif |
|
990 | 1208 |
}; |
991 |
static GenOpFunc2 *gen_op_loop[2][4] = {
|
|
1209 |
static GenOpFunc1 *gen_op_loop[3][4] = {
|
|
992 | 1210 |
[0] = { |
993 | 1211 |
gen_op_loopnzw, |
994 | 1212 |
gen_op_loopzw, |
995 |
gen_op_loopw, |
|
996 |
gen_op_jecxzw, |
|
1213 |
gen_op_jnz_ecxw, |
|
997 | 1214 |
}, |
998 | 1215 |
[1] = { |
999 | 1216 |
gen_op_loopnzl, |
1000 | 1217 |
gen_op_loopzl, |
1001 |
gen_op_loopl, |
|
1002 |
gen_op_jecxzl, |
|
1218 |
gen_op_jnz_ecxl, |
|
1219 |
}, |
|
1220 |
#ifdef TARGET_X86_64 |
|
1221 |
[2] = { |
|
1222 |
gen_op_loopnzq, |
|
1223 |
gen_op_loopzq, |
|
1224 |
gen_op_jnz_ecxq, |
|
1003 | 1225 |
}, |
1226 |
#endif |
|
1004 | 1227 |
}; |
1005 | 1228 |
|
1006 | 1229 |
static GenOpFunc *gen_setcc_slow[8] = { |
... | ... | |
1014 | 1237 |
gen_op_setle_T0_cc, |
1015 | 1238 |
}; |
1016 | 1239 |
|
1017 |
static GenOpFunc *gen_setcc_sub[3][8] = {
|
|
1240 |
static GenOpFunc *gen_setcc_sub[4][8] = {
|
|
1018 | 1241 |
[OT_BYTE] = { |
1019 | 1242 |
NULL, |
1020 | 1243 |
gen_op_setb_T0_subb, |
... | ... | |
1045 | 1268 |
gen_op_setl_T0_subl, |
1046 | 1269 |
gen_op_setle_T0_subl, |
1047 | 1270 |
}, |
1271 |
#ifdef TARGET_X86_64 |
|
1272 |
[OT_QUAD] = { |
|
1273 |
NULL, |
|
1274 |
gen_op_setb_T0_subq, |
|
1275 |
gen_op_setz_T0_subq, |
|
1276 |
gen_op_setbe_T0_subq, |
|
1277 |
gen_op_sets_T0_subq, |
|
1278 |
NULL, |
|
1279 |
gen_op_setl_T0_subq, |
|
1280 |
gen_op_setle_T0_subq, |
|
1281 |
}, |
|
1282 |
#endif |
|
1048 | 1283 |
}; |
1049 | 1284 |
|
1050 | 1285 |
static GenOpFunc *gen_op_fp_arith_ST0_FT0[8] = { |
... | ... | |
1183 | 1418 |
|
1184 | 1419 |
static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ptr) |
1185 | 1420 |
{ |
1421 |
target_long disp; |
|
1186 | 1422 |
int havesib; |
1187 |
int base, disp;
|
|
1423 |
int base; |
|
1188 | 1424 |
int index; |
1189 | 1425 |
int scale; |
1190 | 1426 |
int opreg; |
... | ... | |
1208 | 1444 |
havesib = 1; |
1209 | 1445 |
code = ldub_code(s->pc++); |
1210 | 1446 |
scale = (code >> 6) & 3; |
1211 |
index = (code >> 3) & 7;
|
|
1212 |
base = code & 7;
|
|
1447 |
index = ((code >> 3) & 7) | REX_X(s);
|
|
1448 |
base = (code & 7);
|
|
1213 | 1449 |
} |
1450 |
base |= REX_B(s); |
|
1214 | 1451 |
|
1215 | 1452 |
switch (mod) { |
1216 | 1453 |
case 0: |
1217 |
if (base == 5) {
|
|
1454 |
if ((base & 7) == 5) {
|
|
1218 | 1455 |
base = -1; |
1219 |
disp = ldl_code(s->pc); |
|
1456 |
disp = (int32_t)ldl_code(s->pc);
|
|
1220 | 1457 |
s->pc += 4; |
1458 |
if (CODE64(s) && !havesib) { |
|
1459 |
disp += s->pc + s->rip_offset; |
|
1460 |
} |
|
1221 | 1461 |
} else { |
1222 | 1462 |
disp = 0; |
1223 | 1463 |
} |
... | ... | |
1236 | 1476 |
/* for correct popl handling with esp */ |
1237 | 1477 |
if (base == 4 && s->popl_esp_hack) |
1238 | 1478 |
disp += s->popl_esp_hack; |
1239 |
gen_op_movl_A0_reg[base](); |
|
1240 |
if (disp != 0) |
|
1241 |
gen_op_addl_A0_im(disp); |
|
1479 |
#ifdef TARGET_X86_64 |
|
1480 |
if (s->aflag == 2) { |
|
1481 |
gen_op_movq_A0_reg[base](); |
|
1482 |
if (disp != 0) { |
|
1483 |
if ((int32_t)disp == disp) |
|
1484 |
gen_op_addq_A0_im(disp); |
|
1485 |
else |
|
1486 |
gen_op_addq_A0_im64(disp >> 32, disp); |
|
1487 |
} |
|
1488 |
} else |
|
1489 |
#endif |
|
1490 |
{ |
|
1491 |
gen_op_movl_A0_reg[base](); |
|
1492 |
if (disp != 0) |
|
1493 |
gen_op_addl_A0_im(disp); |
|
1494 |
} |
|
1242 | 1495 |
} else { |
1243 |
gen_op_movl_A0_im(disp); |
|
1496 |
#ifdef TARGET_X86_64 |
|
1497 |
if (s->aflag == 2) { |
|
1498 |
if ((int32_t)disp == disp) |
|
1499 |
gen_op_movq_A0_im(disp); |
|
1500 |
else |
|
1501 |
gen_op_movq_A0_im64(disp >> 32, disp); |
|
1502 |
} else |
|
1503 |
#endif |
|
1504 |
{ |
|
1505 |
gen_op_movl_A0_im(disp); |
|
1506 |
} |
|
1244 | 1507 |
} |
1245 | 1508 |
/* XXX: index == 4 is always invalid */ |
1246 | 1509 |
if (havesib && (index != 4 || scale != 0)) { |
1247 |
gen_op_addl_A0_reg_sN[scale][index](); |
|
1510 |
#ifdef TARGET_X86_64 |
|
1511 |
if (s->aflag == 2) { |
|
1512 |
gen_op_addq_A0_reg_sN[scale][index](); |
|
1513 |
} else |
|
1514 |
#endif |
|
1515 |
{ |
|
1516 |
gen_op_addl_A0_reg_sN[scale][index](); |
|
1517 |
} |
|
1248 | 1518 |
} |
1249 | 1519 |
if (must_add_seg) { |
1250 | 1520 |
if (override < 0) { |
... | ... | |
1253 | 1523 |
else |
1254 | 1524 |
override = R_DS; |
1255 | 1525 |
} |
1256 |
gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base)); |
|
1526 |
#ifdef TARGET_X86_64 |
|
1527 |
if (s->aflag == 2) { |
|
1528 |
gen_op_addq_A0_seg(offsetof(CPUX86State,segs[override].base)); |
|
1529 |
} else |
|
1530 |
#endif |
|
1531 |
{ |
|
1532 |
gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base)); |
|
1533 |
} |
|
1257 | 1534 |
} |
1258 | 1535 |
} else { |
1259 | 1536 |
switch (mod) { |
... | ... | |
1336 | 1613 |
int mod, rm, opreg, disp; |
1337 | 1614 |
|
1338 | 1615 |
mod = (modrm >> 6) & 3; |
1339 |
rm = modrm & 7;
|
|
1616 |
rm = (modrm & 7) | REX_B(s);
|
|
1340 | 1617 |
if (mod == 3) { |
1341 | 1618 |
if (is_store) { |
1342 | 1619 |
if (reg != OR_TMP0) |
... | ... | |
1383 | 1660 |
return ret; |
1384 | 1661 |
} |
1385 | 1662 |
|
1386 |
static inline void gen_jcc(DisasContext *s, int b, int val, int next_eip) |
|
1663 |
static inline int insn_const_size(unsigned int ot) |
|
1664 |
{ |
|
1665 |
if (ot <= OT_LONG) |
|
1666 |
return 1 << ot; |
|
1667 |
else |
|
1668 |
return 4; |
|
1669 |
} |
|
1670 |
|
|
1671 |
static inline void gen_jcc(DisasContext *s, int b, |
|
1672 |
target_ulong val, target_ulong next_eip) |
|
1387 | 1673 |
{ |
1388 | 1674 |
TranslationBlock *tb; |
1389 | 1675 |
int inv, jcc_op; |
1390 |
GenOpFunc3 *func; |
|
1676 |
GenOpFunc1 *func; |
|
1677 |
target_ulong tmp; |
|
1678 |
int l1, l2; |
|
1391 | 1679 |
|
1392 | 1680 |
inv = b & 1; |
1393 | 1681 |
jcc_op = (b >> 1) & 7; |
... | ... | |
1398 | 1686 |
case CC_OP_SUBB: |
1399 | 1687 |
case CC_OP_SUBW: |
1400 | 1688 |
case CC_OP_SUBL: |
1689 |
case CC_OP_SUBQ: |
|
1401 | 1690 |
func = gen_jcc_sub[s->cc_op - CC_OP_SUBB][jcc_op]; |
1402 | 1691 |
break; |
1403 | 1692 |
|
... | ... | |
1405 | 1694 |
case CC_OP_ADDB: |
1406 | 1695 |
case CC_OP_ADDW: |
1407 | 1696 |
case CC_OP_ADDL: |
1697 |
case CC_OP_ADDQ: |
|
1698 |
|
|
1408 | 1699 |
case CC_OP_ADCB: |
1409 | 1700 |
case CC_OP_ADCW: |
1410 | 1701 |
case CC_OP_ADCL: |
1702 |
case CC_OP_ADCQ: |
|
1703 |
|
|
1411 | 1704 |
case CC_OP_SBBB: |
1412 | 1705 |
case CC_OP_SBBW: |
1413 | 1706 |
case CC_OP_SBBL: |
1707 |
case CC_OP_SBBQ: |
|
1708 |
|
|
1414 | 1709 |
case CC_OP_LOGICB: |
1415 | 1710 |
case CC_OP_LOGICW: |
1416 | 1711 |
case CC_OP_LOGICL: |
1712 |
case CC_OP_LOGICQ: |
|
1713 |
|
|
1417 | 1714 |
case CC_OP_INCB: |
1418 | 1715 |
case CC_OP_INCW: |
1419 | 1716 |
case CC_OP_INCL: |
1717 |
case CC_OP_INCQ: |
|
1718 |
|
|
1420 | 1719 |
case CC_OP_DECB: |
1421 | 1720 |
case CC_OP_DECW: |
1422 | 1721 |
case CC_OP_DECL: |
1722 |
case CC_OP_DECQ: |
|
1723 |
|
|
1423 | 1724 |
case CC_OP_SHLB: |
1424 | 1725 |
case CC_OP_SHLW: |
1425 | 1726 |
case CC_OP_SHLL: |
1727 |
case CC_OP_SHLQ: |
|
1728 |
|
|
1426 | 1729 |
case CC_OP_SARB: |
1427 | 1730 |
case CC_OP_SARW: |
1428 | 1731 |
case CC_OP_SARL: |
1732 |
case CC_OP_SARQ: |
|
1429 | 1733 |
switch(jcc_op) { |
1430 | 1734 |
case JCC_Z: |
1431 |
func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
|
|
1735 |
func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 4][jcc_op];
|
|
1432 | 1736 |
break; |
1433 | 1737 |
case JCC_S: |
1434 |
func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
|
|
1738 |
func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 4][jcc_op];
|
|
1435 | 1739 |
break; |
1436 | 1740 |
default: |
1437 | 1741 |
func = NULL; |
... | ... | |
1448 | 1752 |
|
1449 | 1753 |
if (!func) { |
1450 | 1754 |
gen_setcc_slow[jcc_op](); |
1451 |
func = gen_op_jcc;
|
|
1755 |
func = gen_op_jnz_T0_label;
|
|
1452 | 1756 |
} |
1453 | 1757 |
|
1454 |
tb = s->tb; |
|
1455 |
if (!inv) { |
|
1456 |
func((long)tb, val, next_eip); |
|
1457 |
} else { |
|
1458 |
func((long)tb, next_eip, val); |
|
1758 |
if (inv) { |
|
1759 |
tmp = val; |
|
1760 |
val = next_eip; |
|
1761 |
next_eip = tmp; |
|
1459 | 1762 |
} |
1763 |
tb = s->tb; |
|
1764 |
|
|
1765 |
l1 = gen_new_label(); |
|
1766 |
func(l1); |
|
1767 |
|
|
1768 |
gen_op_goto_tb0(); |
|
1769 |
gen_jmp_im(next_eip); |
|
1770 |
gen_op_movl_T0_im((long)tb + 0); |
|
1771 |
gen_op_exit_tb(); |
|
1772 |
|
|
1773 |
gen_set_label(l1); |
|
1774 |
gen_op_goto_tb1(); |
|
1775 |
gen_jmp_im(val); |
|
1776 |
gen_op_movl_T0_im((long)tb + 1); |
|
1777 |
gen_op_exit_tb(); |
|
1778 |
|
|
1460 | 1779 |
s->is_jmp = 3; |
1461 | 1780 |
} else { |
1781 |
|
|
1462 | 1782 |
if (s->cc_op != CC_OP_DYNAMIC) { |
1463 | 1783 |
gen_op_set_cc_op(s->cc_op); |
1464 | 1784 |
s->cc_op = CC_OP_DYNAMIC; |
1465 | 1785 |
} |
1466 | 1786 |
gen_setcc_slow[jcc_op](); |
1467 |
if (!inv) {
|
|
1468 |
gen_op_jcc_im(val, next_eip);
|
|
1469 |
} else {
|
|
1470 |
gen_op_jcc_im(next_eip, val);
|
|
1787 |
if (inv) { |
|
1788 |
tmp = val;
|
|
1789 |
val = next_eip;
|
|
1790 |
next_eip = tmp;
|
|
1471 | 1791 |
} |
1792 |
l1 = gen_new_label(); |
|
1793 |
l2 = gen_new_label(); |
|
1794 |
gen_op_jnz_T0_label(l1); |
|
1795 |
gen_jmp_im(next_eip); |
|
1796 |
gen_op_jmp_label(l2); |
|
1797 |
gen_set_label(l1); |
|
1798 |
gen_jmp_im(val); |
|
1799 |
gen_set_label(l2); |
|
1472 | 1800 |
gen_eob(s); |
1473 | 1801 |
} |
1474 | 1802 |
} |
... | ... | |
1485 | 1813 |
case CC_OP_SUBB: |
1486 | 1814 |
case CC_OP_SUBW: |
1487 | 1815 |
case CC_OP_SUBL: |
1816 |
case CC_OP_SUBQ: |
|
1488 | 1817 |
func = gen_setcc_sub[s->cc_op - CC_OP_SUBB][jcc_op]; |
1489 | 1818 |
if (!func) |
1490 | 1819 |
goto slow_jcc; |
... | ... | |
1494 | 1823 |
case CC_OP_ADDB: |
1495 | 1824 |
case CC_OP_ADDW: |
1496 | 1825 |
case CC_OP_ADDL: |
1826 |
case CC_OP_ADDQ: |
|
1827 |
|
|
1497 | 1828 |
case CC_OP_LOGICB: |
1498 | 1829 |
case CC_OP_LOGICW: |
1499 | 1830 |
case CC_OP_LOGICL: |
1831 |
case CC_OP_LOGICQ: |
|
1832 |
|
|
1500 | 1833 |
case CC_OP_INCB: |
1501 | 1834 |
case CC_OP_INCW: |
1502 | 1835 |
case CC_OP_INCL: |
1836 |
case CC_OP_INCQ: |
|
1837 |
|
|
1503 | 1838 |
case CC_OP_DECB: |
1504 | 1839 |
case CC_OP_DECW: |
1505 | 1840 |
case CC_OP_DECL: |
1841 |
case CC_OP_DECQ: |
|
1842 |
|
|
1506 | 1843 |
case CC_OP_SHLB: |
1507 | 1844 |
case CC_OP_SHLW: |
1508 | 1845 |
case CC_OP_SHLL: |
1846 |
case CC_OP_SHLQ: |
|
1509 | 1847 |
switch(jcc_op) { |
1510 | 1848 |
case JCC_Z: |
1511 |
func = gen_setcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
|
|
1849 |
func = gen_setcc_sub[(s->cc_op - CC_OP_ADDB) % 4][jcc_op];
|
|
1512 | 1850 |
break; |
1513 | 1851 |
case JCC_S: |
1514 |
func = gen_setcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
|
|
1852 |
func = gen_setcc_sub[(s->cc_op - CC_OP_ADDB) % 4][jcc_op];
|
|
1515 | 1853 |
break; |
1516 | 1854 |
default: |
1517 | 1855 |
goto slow_jcc; |
... | ... | |
1532 | 1870 |
|
1533 | 1871 |
/* move T0 to seg_reg and compute if the CPU state may change. Never |
1534 | 1872 |
call this function with seg_reg == R_CS */ |
1535 |
static void gen_movl_seg_T0(DisasContext *s, int seg_reg, unsigned int cur_eip)
|
|
1873 |
static void gen_movl_seg_T0(DisasContext *s, int seg_reg, target_ulong cur_eip)
|
|
1536 | 1874 |
{ |
1537 | 1875 |
if (s->pe && !s->vm86) { |
1538 | 1876 |
/* XXX: optimize by finding processor state dynamically */ |
1539 | 1877 |
if (s->cc_op != CC_OP_DYNAMIC) |
1540 | 1878 |
gen_op_set_cc_op(s->cc_op); |
1541 |
gen_op_jmp_im(cur_eip);
|
|
1879 |
gen_jmp_im(cur_eip); |
|
1542 | 1880 |
gen_op_movl_seg_T0(seg_reg); |
1543 | 1881 |
/* abort translation because the addseg value may change or |
Also available in: Unified diff