|
1 /* |
|
2 * i386 translation |
|
3 * |
|
4 * Copyright (c) 2003 Fabrice Bellard |
|
5 * |
|
6 * This library is free software; you can redistribute it and/or |
|
7 * modify it under the terms of the GNU Lesser General Public |
|
8 * License as published by the Free Software Foundation; either |
|
9 * version 2 of the License, or (at your option) any later version. |
|
10 * |
|
11 * This library is distributed in the hope that it will be useful, |
|
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
14 * Lesser General Public License for more details. |
|
15 * |
|
16 * You should have received a copy of the GNU Lesser General Public |
|
17 * License along with this library; if not, write to the Free Software |
|
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
19 */ |
|
20 #include <stdarg.h> |
|
21 #include <stdlib.h> |
|
22 #include <stdio.h> |
|
23 #include <string.h> |
|
24 #include <inttypes.h> |
|
25 #include <signal.h> |
|
26 #include <assert.h> |
|
27 |
|
28 #include "cpu.h" |
|
29 #include "exec-all.h" |
|
30 #include "disas.h" |
|
31 #include "tcg-op.h" |
|
32 |
|
33 #include "helper.h" |
|
34 #define GEN_HELPER 1 |
|
35 #include "helper.h" |
|
36 |
|
37 #define PREFIX_REPZ 0x01 |
|
38 #define PREFIX_REPNZ 0x02 |
|
39 #define PREFIX_LOCK 0x04 |
|
40 #define PREFIX_DATA 0x08 |
|
41 #define PREFIX_ADR 0x10 |
|
42 |
|
43 #ifdef TARGET_X86_64 |
|
44 #define X86_64_ONLY(x) x |
|
45 #define X86_64_DEF(x...) x |
|
46 #define CODE64(s) ((s)->code64) |
|
47 #define REX_X(s) ((s)->rex_x) |
|
48 #define REX_B(s) ((s)->rex_b) |
|
49 /* XXX: gcc generates push/pop in some opcodes, so we cannot use them */ |
|
50 #if 1 |
|
51 #define BUGGY_64(x) NULL |
|
52 #endif |
|
53 #else |
|
54 #define X86_64_ONLY(x) NULL |
|
55 #define X86_64_DEF(x...) |
|
56 #define CODE64(s) 0 |
|
57 #define REX_X(s) 0 |
|
58 #define REX_B(s) 0 |
|
59 #endif |
|
60 |
|
61 //#define MACRO_TEST 1 |
|
62 |
|
63 /* global register indexes */ |
|
64 static TCGv_ptr cpu_env; |
|
65 static TCGv cpu_A0, cpu_cc_src, cpu_cc_dst, cpu_cc_tmp; |
|
66 static TCGv_i32 cpu_cc_op; |
|
67 /* local temps */ |
|
68 static TCGv cpu_T[2], cpu_T3; |
|
69 /* local register indexes (only used inside old micro ops) */ |
|
70 static TCGv cpu_tmp0, cpu_tmp4; |
|
71 static TCGv_ptr cpu_ptr0, cpu_ptr1; |
|
72 static TCGv_i32 cpu_tmp2_i32, cpu_tmp3_i32; |
|
73 static TCGv_i64 cpu_tmp1_i64; |
|
74 static TCGv cpu_tmp5, cpu_tmp6; |
|
75 |
|
76 #include "gen-icount.h" |
|
77 |
|
78 #ifdef TARGET_X86_64 |
|
79 static int x86_64_hregs; |
|
80 #endif |
|
81 |
|
82 typedef struct DisasContext { |
|
83 /* current insn context */ |
|
84 int override; /* -1 if no override */ |
|
85 int prefix; |
|
86 int aflag, dflag; |
|
87 target_ulong pc; /* pc = eip + cs_base */ |
|
88 int is_jmp; /* 1 = means jump (stop translation), 2 means CPU |
|
89 static state change (stop translation) */ |
|
90 /* current block context */ |
|
91 target_ulong cs_base; /* base of CS segment */ |
|
92 int pe; /* protected mode */ |
|
93 int code32; /* 32 bit code segment */ |
|
94 #ifdef TARGET_X86_64 |
|
95 int lma; /* long mode active */ |
|
96 int code64; /* 64 bit code segment */ |
|
97 int rex_x, rex_b; |
|
98 #endif |
|
99 int ss32; /* 32 bit stack segment */ |
|
100 int cc_op; /* current CC operation */ |
|
101 int addseg; /* non zero if either DS/ES/SS have a non zero base */ |
|
102 int f_st; /* currently unused */ |
|
103 int vm86; /* vm86 mode */ |
|
104 int cpl; |
|
105 int iopl; |
|
106 int tf; /* TF cpu flag */ |
|
107 int singlestep_enabled; /* "hardware" single step enabled */ |
|
108 int jmp_opt; /* use direct block chaining for direct jumps */ |
|
109 int mem_index; /* select memory access functions */ |
|
110 uint64_t flags; /* all execution flags */ |
|
111 struct TranslationBlock *tb; |
|
112 int popl_esp_hack; /* for correct popl with esp base handling */ |
|
113 int rip_offset; /* only used in x86_64, but left for simplicity */ |
|
114 int cpuid_features; |
|
115 int cpuid_ext_features; |
|
116 int cpuid_ext2_features; |
|
117 int cpuid_ext3_features; |
|
118 } DisasContext; |
|
119 |
|
120 static void gen_eob(DisasContext *s); |
|
121 static void gen_jmp(DisasContext *s, target_ulong eip); |
|
122 static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num); |
|
123 |
|
124 /* i386 arith/logic operations */ |
|
125 enum { |
|
126 OP_ADDL, |
|
127 OP_ORL, |
|
128 OP_ADCL, |
|
129 OP_SBBL, |
|
130 OP_ANDL, |
|
131 OP_SUBL, |
|
132 OP_XORL, |
|
133 OP_CMPL, |
|
134 }; |
|
135 |
|
136 /* i386 shift ops */ |
|
137 enum { |
|
138 OP_ROL, |
|
139 OP_ROR, |
|
140 OP_RCL, |
|
141 OP_RCR, |
|
142 OP_SHL, |
|
143 OP_SHR, |
|
144 OP_SHL1, /* undocumented */ |
|
145 OP_SAR = 7, |
|
146 }; |
|
147 |
|
148 enum { |
|
149 JCC_O, |
|
150 JCC_B, |
|
151 JCC_Z, |
|
152 JCC_BE, |
|
153 JCC_S, |
|
154 JCC_P, |
|
155 JCC_L, |
|
156 JCC_LE, |
|
157 }; |
|
158 |
|
159 /* operand size */ |
|
160 enum { |
|
161 OT_BYTE = 0, |
|
162 OT_WORD, |
|
163 OT_LONG, |
|
164 OT_QUAD, |
|
165 }; |
|
166 |
|
167 enum { |
|
168 /* I386 int registers */ |
|
169 OR_EAX, /* MUST be even numbered */ |
|
170 OR_ECX, |
|
171 OR_EDX, |
|
172 OR_EBX, |
|
173 OR_ESP, |
|
174 OR_EBP, |
|
175 OR_ESI, |
|
176 OR_EDI, |
|
177 |
|
178 OR_TMP0 = 16, /* temporary operand register */ |
|
179 OR_TMP1, |
|
180 OR_A0, /* temporary register used when doing address evaluation */ |
|
181 }; |
|
182 |
|
183 static inline void gen_op_movl_T0_0(void) |
|
184 { |
|
185 tcg_gen_movi_tl(cpu_T[0], 0); |
|
186 } |
|
187 |
|
188 static inline void gen_op_movl_T0_im(int32_t val) |
|
189 { |
|
190 tcg_gen_movi_tl(cpu_T[0], val); |
|
191 } |
|
192 |
|
193 static inline void gen_op_movl_T0_imu(uint32_t val) |
|
194 { |
|
195 tcg_gen_movi_tl(cpu_T[0], val); |
|
196 } |
|
197 |
|
198 static inline void gen_op_movl_T1_im(int32_t val) |
|
199 { |
|
200 tcg_gen_movi_tl(cpu_T[1], val); |
|
201 } |
|
202 |
|
203 static inline void gen_op_movl_T1_imu(uint32_t val) |
|
204 { |
|
205 tcg_gen_movi_tl(cpu_T[1], val); |
|
206 } |
|
207 |
|
208 static inline void gen_op_movl_A0_im(uint32_t val) |
|
209 { |
|
210 tcg_gen_movi_tl(cpu_A0, val); |
|
211 } |
|
212 |
|
213 #ifdef TARGET_X86_64 |
|
214 static inline void gen_op_movq_A0_im(int64_t val) |
|
215 { |
|
216 tcg_gen_movi_tl(cpu_A0, val); |
|
217 } |
|
218 #endif |
|
219 |
|
220 static inline void gen_movtl_T0_im(target_ulong val) |
|
221 { |
|
222 tcg_gen_movi_tl(cpu_T[0], val); |
|
223 } |
|
224 |
|
225 static inline void gen_movtl_T1_im(target_ulong val) |
|
226 { |
|
227 tcg_gen_movi_tl(cpu_T[1], val); |
|
228 } |
|
229 |
|
230 static inline void gen_op_andl_T0_ffff(void) |
|
231 { |
|
232 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xffff); |
|
233 } |
|
234 |
|
235 static inline void gen_op_andl_T0_im(uint32_t val) |
|
236 { |
|
237 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], val); |
|
238 } |
|
239 |
|
240 static inline void gen_op_movl_T0_T1(void) |
|
241 { |
|
242 tcg_gen_mov_tl(cpu_T[0], cpu_T[1]); |
|
243 } |
|
244 |
|
245 static inline void gen_op_andl_A0_ffff(void) |
|
246 { |
|
247 tcg_gen_andi_tl(cpu_A0, cpu_A0, 0xffff); |
|
248 } |
|
249 |
|
250 #ifdef TARGET_X86_64 |
|
251 |
|
252 #define NB_OP_SIZES 4 |
|
253 |
|
254 #else /* !TARGET_X86_64 */ |
|
255 |
|
256 #define NB_OP_SIZES 3 |
|
257 |
|
258 #endif /* !TARGET_X86_64 */ |
|
259 |
|
260 #if defined(WORDS_BIGENDIAN) |
|
261 #define REG_B_OFFSET (sizeof(target_ulong) - 1) |
|
262 #define REG_H_OFFSET (sizeof(target_ulong) - 2) |
|
263 #define REG_W_OFFSET (sizeof(target_ulong) - 2) |
|
264 #define REG_L_OFFSET (sizeof(target_ulong) - 4) |
|
265 #define REG_LH_OFFSET (sizeof(target_ulong) - 8) |
|
266 #else |
|
267 #define REG_B_OFFSET 0 |
|
268 #define REG_H_OFFSET 1 |
|
269 #define REG_W_OFFSET 0 |
|
270 #define REG_L_OFFSET 0 |
|
271 #define REG_LH_OFFSET 4 |
|
272 #endif |
|
273 |
|
274 static inline void gen_op_mov_reg_v(int ot, int reg, TCGv t0) |
|
275 { |
|
276 switch(ot) { |
|
277 case OT_BYTE: |
|
278 if (reg < 4 X86_64_DEF( || reg >= 8 || x86_64_hregs)) { |
|
279 tcg_gen_st8_tl(t0, cpu_env, offsetof(CPUState, regs[reg]) + REG_B_OFFSET); |
|
280 } else { |
|
281 tcg_gen_st8_tl(t0, cpu_env, offsetof(CPUState, regs[reg - 4]) + REG_H_OFFSET); |
|
282 } |
|
283 break; |
|
284 case OT_WORD: |
|
285 tcg_gen_st16_tl(t0, cpu_env, offsetof(CPUState, regs[reg]) + REG_W_OFFSET); |
|
286 break; |
|
287 #ifdef TARGET_X86_64 |
|
288 case OT_LONG: |
|
289 tcg_gen_st32_tl(t0, cpu_env, offsetof(CPUState, regs[reg]) + REG_L_OFFSET); |
|
290 /* high part of register set to zero */ |
|
291 tcg_gen_movi_tl(cpu_tmp0, 0); |
|
292 tcg_gen_st32_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg]) + REG_LH_OFFSET); |
|
293 break; |
|
294 default: |
|
295 case OT_QUAD: |
|
296 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, regs[reg])); |
|
297 break; |
|
298 #else |
|
299 default: |
|
300 case OT_LONG: |
|
301 tcg_gen_st32_tl(t0, cpu_env, offsetof(CPUState, regs[reg]) + REG_L_OFFSET); |
|
302 break; |
|
303 #endif |
|
304 } |
|
305 } |
|
306 |
|
307 static inline void gen_op_mov_reg_T0(int ot, int reg) |
|
308 { |
|
309 gen_op_mov_reg_v(ot, reg, cpu_T[0]); |
|
310 } |
|
311 |
|
312 static inline void gen_op_mov_reg_T1(int ot, int reg) |
|
313 { |
|
314 gen_op_mov_reg_v(ot, reg, cpu_T[1]); |
|
315 } |
|
316 |
|
317 static inline void gen_op_mov_reg_A0(int size, int reg) |
|
318 { |
|
319 switch(size) { |
|
320 case 0: |
|
321 tcg_gen_st16_tl(cpu_A0, cpu_env, offsetof(CPUState, regs[reg]) + REG_W_OFFSET); |
|
322 break; |
|
323 #ifdef TARGET_X86_64 |
|
324 case 1: |
|
325 tcg_gen_st32_tl(cpu_A0, cpu_env, offsetof(CPUState, regs[reg]) + REG_L_OFFSET); |
|
326 /* high part of register set to zero */ |
|
327 tcg_gen_movi_tl(cpu_tmp0, 0); |
|
328 tcg_gen_st32_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg]) + REG_LH_OFFSET); |
|
329 break; |
|
330 default: |
|
331 case 2: |
|
332 tcg_gen_st_tl(cpu_A0, cpu_env, offsetof(CPUState, regs[reg])); |
|
333 break; |
|
334 #else |
|
335 default: |
|
336 case 1: |
|
337 tcg_gen_st32_tl(cpu_A0, cpu_env, offsetof(CPUState, regs[reg]) + REG_L_OFFSET); |
|
338 break; |
|
339 #endif |
|
340 } |
|
341 } |
|
342 |
|
343 static inline void gen_op_mov_v_reg(int ot, TCGv t0, int reg) |
|
344 { |
|
345 switch(ot) { |
|
346 case OT_BYTE: |
|
347 if (reg < 4 X86_64_DEF( || reg >= 8 || x86_64_hregs)) { |
|
348 goto std_case; |
|
349 } else { |
|
350 tcg_gen_ld8u_tl(t0, cpu_env, offsetof(CPUState, regs[reg - 4]) + REG_H_OFFSET); |
|
351 } |
|
352 break; |
|
353 default: |
|
354 std_case: |
|
355 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, regs[reg])); |
|
356 break; |
|
357 } |
|
358 } |
|
359 |
|
360 static inline void gen_op_mov_TN_reg(int ot, int t_index, int reg) |
|
361 { |
|
362 gen_op_mov_v_reg(ot, cpu_T[t_index], reg); |
|
363 } |
|
364 |
|
365 static inline void gen_op_movl_A0_reg(int reg) |
|
366 { |
|
367 tcg_gen_ld32u_tl(cpu_A0, cpu_env, offsetof(CPUState, regs[reg]) + REG_L_OFFSET); |
|
368 } |
|
369 |
|
370 static inline void gen_op_addl_A0_im(int32_t val) |
|
371 { |
|
372 tcg_gen_addi_tl(cpu_A0, cpu_A0, val); |
|
373 #ifdef TARGET_X86_64 |
|
374 tcg_gen_andi_tl(cpu_A0, cpu_A0, 0xffffffff); |
|
375 #endif |
|
376 } |
|
377 |
|
378 #ifdef TARGET_X86_64 |
|
379 static inline void gen_op_addq_A0_im(int64_t val) |
|
380 { |
|
381 tcg_gen_addi_tl(cpu_A0, cpu_A0, val); |
|
382 } |
|
383 #endif |
|
384 |
|
385 static void gen_add_A0_im(DisasContext *s, int val) |
|
386 { |
|
387 #ifdef TARGET_X86_64 |
|
388 if (CODE64(s)) |
|
389 gen_op_addq_A0_im(val); |
|
390 else |
|
391 #endif |
|
392 gen_op_addl_A0_im(val); |
|
393 } |
|
394 |
|
395 static inline void gen_op_addl_T0_T1(void) |
|
396 { |
|
397 tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]); |
|
398 } |
|
399 |
|
400 static inline void gen_op_jmp_T0(void) |
|
401 { |
|
402 tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUState, eip)); |
|
403 } |
|
404 |
|
405 static inline void gen_op_add_reg_im(int size, int reg, int32_t val) |
|
406 { |
|
407 switch(size) { |
|
408 case 0: |
|
409 tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg])); |
|
410 tcg_gen_addi_tl(cpu_tmp0, cpu_tmp0, val); |
|
411 tcg_gen_st16_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg]) + REG_W_OFFSET); |
|
412 break; |
|
413 case 1: |
|
414 tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg])); |
|
415 tcg_gen_addi_tl(cpu_tmp0, cpu_tmp0, val); |
|
416 #ifdef TARGET_X86_64 |
|
417 tcg_gen_andi_tl(cpu_tmp0, cpu_tmp0, 0xffffffff); |
|
418 #endif |
|
419 tcg_gen_st_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg])); |
|
420 break; |
|
421 #ifdef TARGET_X86_64 |
|
422 case 2: |
|
423 tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg])); |
|
424 tcg_gen_addi_tl(cpu_tmp0, cpu_tmp0, val); |
|
425 tcg_gen_st_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg])); |
|
426 break; |
|
427 #endif |
|
428 } |
|
429 } |
|
430 |
|
431 static inline void gen_op_add_reg_T0(int size, int reg) |
|
432 { |
|
433 switch(size) { |
|
434 case 0: |
|
435 tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg])); |
|
436 tcg_gen_add_tl(cpu_tmp0, cpu_tmp0, cpu_T[0]); |
|
437 tcg_gen_st16_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg]) + REG_W_OFFSET); |
|
438 break; |
|
439 case 1: |
|
440 tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg])); |
|
441 tcg_gen_add_tl(cpu_tmp0, cpu_tmp0, cpu_T[0]); |
|
442 #ifdef TARGET_X86_64 |
|
443 tcg_gen_andi_tl(cpu_tmp0, cpu_tmp0, 0xffffffff); |
|
444 #endif |
|
445 tcg_gen_st_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg])); |
|
446 break; |
|
447 #ifdef TARGET_X86_64 |
|
448 case 2: |
|
449 tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg])); |
|
450 tcg_gen_add_tl(cpu_tmp0, cpu_tmp0, cpu_T[0]); |
|
451 tcg_gen_st_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg])); |
|
452 break; |
|
453 #endif |
|
454 } |
|
455 } |
|
456 |
|
457 static inline void gen_op_set_cc_op(int32_t val) |
|
458 { |
|
459 tcg_gen_movi_i32(cpu_cc_op, val); |
|
460 } |
|
461 |
|
462 static inline void gen_op_addl_A0_reg_sN(int shift, int reg) |
|
463 { |
|
464 tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg])); |
|
465 if (shift != 0) |
|
466 tcg_gen_shli_tl(cpu_tmp0, cpu_tmp0, shift); |
|
467 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0); |
|
468 #ifdef TARGET_X86_64 |
|
469 tcg_gen_andi_tl(cpu_A0, cpu_A0, 0xffffffff); |
|
470 #endif |
|
471 } |
|
472 |
|
473 static inline void gen_op_movl_A0_seg(int reg) |
|
474 { |
|
475 tcg_gen_ld32u_tl(cpu_A0, cpu_env, offsetof(CPUState, segs[reg].base) + REG_L_OFFSET); |
|
476 } |
|
477 |
|
478 static inline void gen_op_addl_A0_seg(int reg) |
|
479 { |
|
480 tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, segs[reg].base)); |
|
481 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0); |
|
482 #ifdef TARGET_X86_64 |
|
483 tcg_gen_andi_tl(cpu_A0, cpu_A0, 0xffffffff); |
|
484 #endif |
|
485 } |
|
486 |
|
487 #ifdef TARGET_X86_64 |
|
488 static inline void gen_op_movq_A0_seg(int reg) |
|
489 { |
|
490 tcg_gen_ld_tl(cpu_A0, cpu_env, offsetof(CPUState, segs[reg].base)); |
|
491 } |
|
492 |
|
493 static inline void gen_op_addq_A0_seg(int reg) |
|
494 { |
|
495 tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, segs[reg].base)); |
|
496 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0); |
|
497 } |
|
498 |
|
499 static inline void gen_op_movq_A0_reg(int reg) |
|
500 { |
|
501 tcg_gen_ld_tl(cpu_A0, cpu_env, offsetof(CPUState, regs[reg])); |
|
502 } |
|
503 |
|
504 static inline void gen_op_addq_A0_reg_sN(int shift, int reg) |
|
505 { |
|
506 tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg])); |
|
507 if (shift != 0) |
|
508 tcg_gen_shli_tl(cpu_tmp0, cpu_tmp0, shift); |
|
509 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0); |
|
510 } |
|
511 #endif |
|
512 |
|
513 static inline void gen_op_lds_T0_A0(int idx) |
|
514 { |
|
515 int mem_index = (idx >> 2) - 1; |
|
516 switch(idx & 3) { |
|
517 case 0: |
|
518 tcg_gen_qemu_ld8s(cpu_T[0], cpu_A0, mem_index); |
|
519 break; |
|
520 case 1: |
|
521 tcg_gen_qemu_ld16s(cpu_T[0], cpu_A0, mem_index); |
|
522 break; |
|
523 default: |
|
524 case 2: |
|
525 tcg_gen_qemu_ld32s(cpu_T[0], cpu_A0, mem_index); |
|
526 break; |
|
527 } |
|
528 } |
|
529 |
|
530 static inline void gen_op_ld_v(int idx, TCGv t0, TCGv a0) |
|
531 { |
|
532 int mem_index = (idx >> 2) - 1; |
|
533 switch(idx & 3) { |
|
534 case 0: |
|
535 tcg_gen_qemu_ld8u(t0, a0, mem_index); |
|
536 break; |
|
537 case 1: |
|
538 tcg_gen_qemu_ld16u(t0, a0, mem_index); |
|
539 break; |
|
540 case 2: |
|
541 tcg_gen_qemu_ld32u(t0, a0, mem_index); |
|
542 break; |
|
543 default: |
|
544 case 3: |
|
545 /* Should never happen on 32-bit targets. */ |
|
546 #ifdef TARGET_X86_64 |
|
547 tcg_gen_qemu_ld64(t0, a0, mem_index); |
|
548 #endif |
|
549 break; |
|
550 } |
|
551 } |
|
552 |
|
553 /* XXX: always use ldu or lds */ |
|
554 static inline void gen_op_ld_T0_A0(int idx) |
|
555 { |
|
556 gen_op_ld_v(idx, cpu_T[0], cpu_A0); |
|
557 } |
|
558 |
|
559 static inline void gen_op_ldu_T0_A0(int idx) |
|
560 { |
|
561 gen_op_ld_v(idx, cpu_T[0], cpu_A0); |
|
562 } |
|
563 |
|
564 static inline void gen_op_ld_T1_A0(int idx) |
|
565 { |
|
566 gen_op_ld_v(idx, cpu_T[1], cpu_A0); |
|
567 } |
|
568 |
|
569 static inline void gen_op_st_v(int idx, TCGv t0, TCGv a0) |
|
570 { |
|
571 int mem_index = (idx >> 2) - 1; |
|
572 switch(idx & 3) { |
|
573 case 0: |
|
574 tcg_gen_qemu_st8(t0, a0, mem_index); |
|
575 break; |
|
576 case 1: |
|
577 tcg_gen_qemu_st16(t0, a0, mem_index); |
|
578 break; |
|
579 case 2: |
|
580 tcg_gen_qemu_st32(t0, a0, mem_index); |
|
581 break; |
|
582 default: |
|
583 case 3: |
|
584 /* Should never happen on 32-bit targets. */ |
|
585 #ifdef TARGET_X86_64 |
|
586 tcg_gen_qemu_st64(t0, a0, mem_index); |
|
587 #endif |
|
588 break; |
|
589 } |
|
590 } |
|
591 |
|
592 static inline void gen_op_st_T0_A0(int idx) |
|
593 { |
|
594 gen_op_st_v(idx, cpu_T[0], cpu_A0); |
|
595 } |
|
596 |
|
597 static inline void gen_op_st_T1_A0(int idx) |
|
598 { |
|
599 gen_op_st_v(idx, cpu_T[1], cpu_A0); |
|
600 } |
|
601 |
|
602 static inline void gen_jmp_im(target_ulong pc) |
|
603 { |
|
604 tcg_gen_movi_tl(cpu_tmp0, pc); |
|
605 tcg_gen_st_tl(cpu_tmp0, cpu_env, offsetof(CPUState, eip)); |
|
606 } |
|
607 |
|
608 static inline void gen_string_movl_A0_ESI(DisasContext *s) |
|
609 { |
|
610 int override; |
|
611 |
|
612 override = s->override; |
|
613 #ifdef TARGET_X86_64 |
|
614 if (s->aflag == 2) { |
|
615 if (override >= 0) { |
|
616 gen_op_movq_A0_seg(override); |
|
617 gen_op_addq_A0_reg_sN(0, R_ESI); |
|
618 } else { |
|
619 gen_op_movq_A0_reg(R_ESI); |
|
620 } |
|
621 } else |
|
622 #endif |
|
623 if (s->aflag) { |
|
624 /* 32 bit address */ |
|
625 if (s->addseg && override < 0) |
|
626 override = R_DS; |
|
627 if (override >= 0) { |
|
628 gen_op_movl_A0_seg(override); |
|
629 gen_op_addl_A0_reg_sN(0, R_ESI); |
|
630 } else { |
|
631 gen_op_movl_A0_reg(R_ESI); |
|
632 } |
|
633 } else { |
|
634 /* 16 address, always override */ |
|
635 if (override < 0) |
|
636 override = R_DS; |
|
637 gen_op_movl_A0_reg(R_ESI); |
|
638 gen_op_andl_A0_ffff(); |
|
639 gen_op_addl_A0_seg(override); |
|
640 } |
|
641 } |
|
642 |
|
643 static inline void gen_string_movl_A0_EDI(DisasContext *s) |
|
644 { |
|
645 #ifdef TARGET_X86_64 |
|
646 if (s->aflag == 2) { |
|
647 gen_op_movq_A0_reg(R_EDI); |
|
648 } else |
|
649 #endif |
|
650 if (s->aflag) { |
|
651 if (s->addseg) { |
|
652 gen_op_movl_A0_seg(R_ES); |
|
653 gen_op_addl_A0_reg_sN(0, R_EDI); |
|
654 } else { |
|
655 gen_op_movl_A0_reg(R_EDI); |
|
656 } |
|
657 } else { |
|
658 gen_op_movl_A0_reg(R_EDI); |
|
659 gen_op_andl_A0_ffff(); |
|
660 gen_op_addl_A0_seg(R_ES); |
|
661 } |
|
662 } |
|
663 |
|
664 static inline void gen_op_movl_T0_Dshift(int ot) |
|
665 { |
|
666 tcg_gen_ld32s_tl(cpu_T[0], cpu_env, offsetof(CPUState, df)); |
|
667 tcg_gen_shli_tl(cpu_T[0], cpu_T[0], ot); |
|
668 }; |
|
669 |
|
670 static void gen_extu(int ot, TCGv reg) |
|
671 { |
|
672 switch(ot) { |
|
673 case OT_BYTE: |
|
674 tcg_gen_ext8u_tl(reg, reg); |
|
675 break; |
|
676 case OT_WORD: |
|
677 tcg_gen_ext16u_tl(reg, reg); |
|
678 break; |
|
679 case OT_LONG: |
|
680 tcg_gen_ext32u_tl(reg, reg); |
|
681 break; |
|
682 default: |
|
683 break; |
|
684 } |
|
685 } |
|
686 |
|
687 static void gen_exts(int ot, TCGv reg) |
|
688 { |
|
689 switch(ot) { |
|
690 case OT_BYTE: |
|
691 tcg_gen_ext8s_tl(reg, reg); |
|
692 break; |
|
693 case OT_WORD: |
|
694 tcg_gen_ext16s_tl(reg, reg); |
|
695 break; |
|
696 case OT_LONG: |
|
697 tcg_gen_ext32s_tl(reg, reg); |
|
698 break; |
|
699 default: |
|
700 break; |
|
701 } |
|
702 } |
|
703 |
|
704 static inline void gen_op_jnz_ecx(int size, int label1) |
|
705 { |
|
706 tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[R_ECX])); |
|
707 gen_extu(size + 1, cpu_tmp0); |
|
708 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_tmp0, 0, label1); |
|
709 } |
|
710 |
|
711 static inline void gen_op_jz_ecx(int size, int label1) |
|
712 { |
|
713 tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[R_ECX])); |
|
714 gen_extu(size + 1, cpu_tmp0); |
|
715 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_tmp0, 0, label1); |
|
716 } |
|
717 |
|
718 static void gen_helper_in_func(int ot, TCGv v, TCGv_i32 n) |
|
719 { |
|
720 switch (ot) { |
|
721 case 0: gen_helper_inb(v, n); break; |
|
722 case 1: gen_helper_inw(v, n); break; |
|
723 case 2: gen_helper_inl(v, n); break; |
|
724 } |
|
725 |
|
726 } |
|
727 |
|
728 static void gen_helper_out_func(int ot, TCGv_i32 v, TCGv_i32 n) |
|
729 { |
|
730 switch (ot) { |
|
731 case 0: gen_helper_outb(v, n); break; |
|
732 case 1: gen_helper_outw(v, n); break; |
|
733 case 2: gen_helper_outl(v, n); break; |
|
734 } |
|
735 |
|
736 } |
|
737 |
|
738 static void gen_check_io(DisasContext *s, int ot, target_ulong cur_eip, |
|
739 uint32_t svm_flags) |
|
740 { |
|
741 int state_saved; |
|
742 target_ulong next_eip; |
|
743 |
|
744 state_saved = 0; |
|
745 if (s->pe && (s->cpl > s->iopl || s->vm86)) { |
|
746 if (s->cc_op != CC_OP_DYNAMIC) |
|
747 gen_op_set_cc_op(s->cc_op); |
|
748 gen_jmp_im(cur_eip); |
|
749 state_saved = 1; |
|
750 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); |
|
751 switch (ot) { |
|
752 case 0: gen_helper_check_iob(cpu_tmp2_i32); break; |
|
753 case 1: gen_helper_check_iow(cpu_tmp2_i32); break; |
|
754 case 2: gen_helper_check_iol(cpu_tmp2_i32); break; |
|
755 } |
|
756 } |
|
757 if(s->flags & HF_SVMI_MASK) { |
|
758 if (!state_saved) { |
|
759 if (s->cc_op != CC_OP_DYNAMIC) |
|
760 gen_op_set_cc_op(s->cc_op); |
|
761 gen_jmp_im(cur_eip); |
|
762 state_saved = 1; |
|
763 } |
|
764 svm_flags |= (1 << (4 + ot)); |
|
765 next_eip = s->pc - s->cs_base; |
|
766 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); |
|
767 gen_helper_svm_check_io(cpu_tmp2_i32, tcg_const_i32(svm_flags), |
|
768 tcg_const_i32(next_eip - cur_eip)); |
|
769 } |
|
770 } |
|
771 |
|
772 static inline void gen_movs(DisasContext *s, int ot) |
|
773 { |
|
774 gen_string_movl_A0_ESI(s); |
|
775 gen_op_ld_T0_A0(ot + s->mem_index); |
|
776 gen_string_movl_A0_EDI(s); |
|
777 gen_op_st_T0_A0(ot + s->mem_index); |
|
778 gen_op_movl_T0_Dshift(ot); |
|
779 gen_op_add_reg_T0(s->aflag, R_ESI); |
|
780 gen_op_add_reg_T0(s->aflag, R_EDI); |
|
781 } |
|
782 |
|
783 static inline void gen_update_cc_op(DisasContext *s) |
|
784 { |
|
785 if (s->cc_op != CC_OP_DYNAMIC) { |
|
786 gen_op_set_cc_op(s->cc_op); |
|
787 s->cc_op = CC_OP_DYNAMIC; |
|
788 } |
|
789 } |
|
790 |
|
791 static void gen_op_update1_cc(void) |
|
792 { |
|
793 tcg_gen_discard_tl(cpu_cc_src); |
|
794 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]); |
|
795 } |
|
796 |
|
797 static void gen_op_update2_cc(void) |
|
798 { |
|
799 tcg_gen_mov_tl(cpu_cc_src, cpu_T[1]); |
|
800 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]); |
|
801 } |
|
802 |
|
803 static inline void gen_op_cmpl_T0_T1_cc(void) |
|
804 { |
|
805 tcg_gen_mov_tl(cpu_cc_src, cpu_T[1]); |
|
806 tcg_gen_sub_tl(cpu_cc_dst, cpu_T[0], cpu_T[1]); |
|
807 } |
|
808 |
|
809 static inline void gen_op_testl_T0_T1_cc(void) |
|
810 { |
|
811 tcg_gen_discard_tl(cpu_cc_src); |
|
812 tcg_gen_and_tl(cpu_cc_dst, cpu_T[0], cpu_T[1]); |
|
813 } |
|
814 |
|
815 static void gen_op_update_neg_cc(void) |
|
816 { |
|
817 tcg_gen_neg_tl(cpu_cc_src, cpu_T[0]); |
|
818 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]); |
|
819 } |
|
820 |
|
821 /* compute eflags.C to reg */ |
|
822 static void gen_compute_eflags_c(TCGv reg) |
|
823 { |
|
824 gen_helper_cc_compute_c(cpu_tmp2_i32, cpu_cc_op); |
|
825 tcg_gen_extu_i32_tl(reg, cpu_tmp2_i32); |
|
826 } |
|
827 |
|
828 /* compute all eflags to cc_src */ |
|
829 static void gen_compute_eflags(TCGv reg) |
|
830 { |
|
831 gen_helper_cc_compute_all(cpu_tmp2_i32, cpu_cc_op); |
|
832 tcg_gen_extu_i32_tl(reg, cpu_tmp2_i32); |
|
833 } |
|
834 |
|
835 static inline void gen_setcc_slow_T0(DisasContext *s, int jcc_op) |
|
836 { |
|
837 if (s->cc_op != CC_OP_DYNAMIC) |
|
838 gen_op_set_cc_op(s->cc_op); |
|
839 switch(jcc_op) { |
|
840 case JCC_O: |
|
841 gen_compute_eflags(cpu_T[0]); |
|
842 tcg_gen_shri_tl(cpu_T[0], cpu_T[0], 11); |
|
843 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 1); |
|
844 break; |
|
845 case JCC_B: |
|
846 gen_compute_eflags_c(cpu_T[0]); |
|
847 break; |
|
848 case JCC_Z: |
|
849 gen_compute_eflags(cpu_T[0]); |
|
850 tcg_gen_shri_tl(cpu_T[0], cpu_T[0], 6); |
|
851 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 1); |
|
852 break; |
|
853 case JCC_BE: |
|
854 gen_compute_eflags(cpu_tmp0); |
|
855 tcg_gen_shri_tl(cpu_T[0], cpu_tmp0, 6); |
|
856 tcg_gen_or_tl(cpu_T[0], cpu_T[0], cpu_tmp0); |
|
857 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 1); |
|
858 break; |
|
859 case JCC_S: |
|
860 gen_compute_eflags(cpu_T[0]); |
|
861 tcg_gen_shri_tl(cpu_T[0], cpu_T[0], 7); |
|
862 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 1); |
|
863 break; |
|
864 case JCC_P: |
|
865 gen_compute_eflags(cpu_T[0]); |
|
866 tcg_gen_shri_tl(cpu_T[0], cpu_T[0], 2); |
|
867 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 1); |
|
868 break; |
|
869 case JCC_L: |
|
870 gen_compute_eflags(cpu_tmp0); |
|
871 tcg_gen_shri_tl(cpu_T[0], cpu_tmp0, 11); /* CC_O */ |
|
872 tcg_gen_shri_tl(cpu_tmp0, cpu_tmp0, 7); /* CC_S */ |
|
873 tcg_gen_xor_tl(cpu_T[0], cpu_T[0], cpu_tmp0); |
|
874 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 1); |
|
875 break; |
|
876 default: |
|
877 case JCC_LE: |
|
878 gen_compute_eflags(cpu_tmp0); |
|
879 tcg_gen_shri_tl(cpu_T[0], cpu_tmp0, 11); /* CC_O */ |
|
880 tcg_gen_shri_tl(cpu_tmp4, cpu_tmp0, 7); /* CC_S */ |
|
881 tcg_gen_shri_tl(cpu_tmp0, cpu_tmp0, 6); /* CC_Z */ |
|
882 tcg_gen_xor_tl(cpu_T[0], cpu_T[0], cpu_tmp4); |
|
883 tcg_gen_or_tl(cpu_T[0], cpu_T[0], cpu_tmp0); |
|
884 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 1); |
|
885 break; |
|
886 } |
|
887 } |
|
888 |
|
889 /* return true if setcc_slow is not needed (WARNING: must be kept in |
|
890 sync with gen_jcc1) */ |
|
891 static int is_fast_jcc_case(DisasContext *s, int b) |
|
892 { |
|
893 int jcc_op; |
|
894 jcc_op = (b >> 1) & 7; |
|
895 switch(s->cc_op) { |
|
896 /* we optimize the cmp/jcc case */ |
|
897 case CC_OP_SUBB: |
|
898 case CC_OP_SUBW: |
|
899 case CC_OP_SUBL: |
|
900 case CC_OP_SUBQ: |
|
901 if (jcc_op == JCC_O || jcc_op == JCC_P) |
|
902 goto slow_jcc; |
|
903 break; |
|
904 |
|
905 /* some jumps are easy to compute */ |
|
906 case CC_OP_ADDB: |
|
907 case CC_OP_ADDW: |
|
908 case CC_OP_ADDL: |
|
909 case CC_OP_ADDQ: |
|
910 |
|
911 case CC_OP_LOGICB: |
|
912 case CC_OP_LOGICW: |
|
913 case CC_OP_LOGICL: |
|
914 case CC_OP_LOGICQ: |
|
915 |
|
916 case CC_OP_INCB: |
|
917 case CC_OP_INCW: |
|
918 case CC_OP_INCL: |
|
919 case CC_OP_INCQ: |
|
920 |
|
921 case CC_OP_DECB: |
|
922 case CC_OP_DECW: |
|
923 case CC_OP_DECL: |
|
924 case CC_OP_DECQ: |
|
925 |
|
926 case CC_OP_SHLB: |
|
927 case CC_OP_SHLW: |
|
928 case CC_OP_SHLL: |
|
929 case CC_OP_SHLQ: |
|
930 if (jcc_op != JCC_Z && jcc_op != JCC_S) |
|
931 goto slow_jcc; |
|
932 break; |
|
933 default: |
|
934 slow_jcc: |
|
935 return 0; |
|
936 } |
|
937 return 1; |
|
938 } |
|
939 |
|
940 /* generate a conditional jump to label 'l1' according to jump opcode |
|
941 value 'b'. In the fast case, T0 is guaranted not to be used. */ |
|
942 static inline void gen_jcc1(DisasContext *s, int cc_op, int b, int l1) |
|
943 { |
|
944 int inv, jcc_op, size, cond; |
|
945 TCGv t0; |
|
946 |
|
947 inv = b & 1; |
|
948 jcc_op = (b >> 1) & 7; |
|
949 |
|
950 switch(cc_op) { |
|
951 /* we optimize the cmp/jcc case */ |
|
952 case CC_OP_SUBB: |
|
953 case CC_OP_SUBW: |
|
954 case CC_OP_SUBL: |
|
955 case CC_OP_SUBQ: |
|
956 |
|
957 size = cc_op - CC_OP_SUBB; |
|
958 switch(jcc_op) { |
|
959 case JCC_Z: |
|
960 fast_jcc_z: |
|
961 switch(size) { |
|
962 case 0: |
|
963 tcg_gen_andi_tl(cpu_tmp0, cpu_cc_dst, 0xff); |
|
964 t0 = cpu_tmp0; |
|
965 break; |
|
966 case 1: |
|
967 tcg_gen_andi_tl(cpu_tmp0, cpu_cc_dst, 0xffff); |
|
968 t0 = cpu_tmp0; |
|
969 break; |
|
970 #ifdef TARGET_X86_64 |
|
971 case 2: |
|
972 tcg_gen_andi_tl(cpu_tmp0, cpu_cc_dst, 0xffffffff); |
|
973 t0 = cpu_tmp0; |
|
974 break; |
|
975 #endif |
|
976 default: |
|
977 t0 = cpu_cc_dst; |
|
978 break; |
|
979 } |
|
980 tcg_gen_brcondi_tl(inv ? TCG_COND_NE : TCG_COND_EQ, t0, 0, l1); |
|
981 break; |
|
982 case JCC_S: |
|
983 fast_jcc_s: |
|
984 switch(size) { |
|
985 case 0: |
|
986 tcg_gen_andi_tl(cpu_tmp0, cpu_cc_dst, 0x80); |
|
987 tcg_gen_brcondi_tl(inv ? TCG_COND_EQ : TCG_COND_NE, cpu_tmp0, |
|
988 0, l1); |
|
989 break; |
|
990 case 1: |
|
991 tcg_gen_andi_tl(cpu_tmp0, cpu_cc_dst, 0x8000); |
|
992 tcg_gen_brcondi_tl(inv ? TCG_COND_EQ : TCG_COND_NE, cpu_tmp0, |
|
993 0, l1); |
|
994 break; |
|
995 #ifdef TARGET_X86_64 |
|
996 case 2: |
|
997 tcg_gen_andi_tl(cpu_tmp0, cpu_cc_dst, 0x80000000); |
|
998 tcg_gen_brcondi_tl(inv ? TCG_COND_EQ : TCG_COND_NE, cpu_tmp0, |
|
999 0, l1); |
|
1000 break; |
|
1001 #endif |
|
1002 default: |
|
1003 tcg_gen_brcondi_tl(inv ? TCG_COND_GE : TCG_COND_LT, cpu_cc_dst, |
|
1004 0, l1); |
|
1005 break; |
|
1006 } |
|
1007 break; |
|
1008 |
|
1009 case JCC_B: |
|
1010 cond = inv ? TCG_COND_GEU : TCG_COND_LTU; |
|
1011 goto fast_jcc_b; |
|
1012 case JCC_BE: |
|
1013 cond = inv ? TCG_COND_GTU : TCG_COND_LEU; |
|
1014 fast_jcc_b: |
|
1015 tcg_gen_add_tl(cpu_tmp4, cpu_cc_dst, cpu_cc_src); |
|
1016 switch(size) { |
|
1017 case 0: |
|
1018 t0 = cpu_tmp0; |
|
1019 tcg_gen_andi_tl(cpu_tmp4, cpu_tmp4, 0xff); |
|
1020 tcg_gen_andi_tl(t0, cpu_cc_src, 0xff); |
|
1021 break; |
|
1022 case 1: |
|
1023 t0 = cpu_tmp0; |
|
1024 tcg_gen_andi_tl(cpu_tmp4, cpu_tmp4, 0xffff); |
|
1025 tcg_gen_andi_tl(t0, cpu_cc_src, 0xffff); |
|
1026 break; |
|
1027 #ifdef TARGET_X86_64 |
|
1028 case 2: |
|
1029 t0 = cpu_tmp0; |
|
1030 tcg_gen_andi_tl(cpu_tmp4, cpu_tmp4, 0xffffffff); |
|
1031 tcg_gen_andi_tl(t0, cpu_cc_src, 0xffffffff); |
|
1032 break; |
|
1033 #endif |
|
1034 default: |
|
1035 t0 = cpu_cc_src; |
|
1036 break; |
|
1037 } |
|
1038 tcg_gen_brcond_tl(cond, cpu_tmp4, t0, l1); |
|
1039 break; |
|
1040 |
|
1041 case JCC_L: |
|
1042 cond = inv ? TCG_COND_GE : TCG_COND_LT; |
|
1043 goto fast_jcc_l; |
|
1044 case JCC_LE: |
|
1045 cond = inv ? TCG_COND_GT : TCG_COND_LE; |
|
1046 fast_jcc_l: |
|
1047 tcg_gen_add_tl(cpu_tmp4, cpu_cc_dst, cpu_cc_src); |
|
1048 switch(size) { |
|
1049 case 0: |
|
1050 t0 = cpu_tmp0; |
|
1051 tcg_gen_ext8s_tl(cpu_tmp4, cpu_tmp4); |
|
1052 tcg_gen_ext8s_tl(t0, cpu_cc_src); |
|
1053 break; |
|
1054 case 1: |
|
1055 t0 = cpu_tmp0; |
|
1056 tcg_gen_ext16s_tl(cpu_tmp4, cpu_tmp4); |
|
1057 tcg_gen_ext16s_tl(t0, cpu_cc_src); |
|
1058 break; |
|
1059 #ifdef TARGET_X86_64 |
|
1060 case 2: |
|
1061 t0 = cpu_tmp0; |
|
1062 tcg_gen_ext32s_tl(cpu_tmp4, cpu_tmp4); |
|
1063 tcg_gen_ext32s_tl(t0, cpu_cc_src); |
|
1064 break; |
|
1065 #endif |
|
1066 default: |
|
1067 t0 = cpu_cc_src; |
|
1068 break; |
|
1069 } |
|
1070 tcg_gen_brcond_tl(cond, cpu_tmp4, t0, l1); |
|
1071 break; |
|
1072 |
|
1073 default: |
|
1074 goto slow_jcc; |
|
1075 } |
|
1076 break; |
|
1077 |
|
1078 /* some jumps are easy to compute */ |
|
1079 case CC_OP_ADDB: |
|
1080 case CC_OP_ADDW: |
|
1081 case CC_OP_ADDL: |
|
1082 case CC_OP_ADDQ: |
|
1083 |
|
1084 case CC_OP_ADCB: |
|
1085 case CC_OP_ADCW: |
|
1086 case CC_OP_ADCL: |
|
1087 case CC_OP_ADCQ: |
|
1088 |
|
1089 case CC_OP_SBBB: |
|
1090 case CC_OP_SBBW: |
|
1091 case CC_OP_SBBL: |
|
1092 case CC_OP_SBBQ: |
|
1093 |
|
1094 case CC_OP_LOGICB: |
|
1095 case CC_OP_LOGICW: |
|
1096 case CC_OP_LOGICL: |
|
1097 case CC_OP_LOGICQ: |
|
1098 |
|
1099 case CC_OP_INCB: |
|
1100 case CC_OP_INCW: |
|
1101 case CC_OP_INCL: |
|
1102 case CC_OP_INCQ: |
|
1103 |
|
1104 case CC_OP_DECB: |
|
1105 case CC_OP_DECW: |
|
1106 case CC_OP_DECL: |
|
1107 case CC_OP_DECQ: |
|
1108 |
|
1109 case CC_OP_SHLB: |
|
1110 case CC_OP_SHLW: |
|
1111 case CC_OP_SHLL: |
|
1112 case CC_OP_SHLQ: |
|
1113 |
|
1114 case CC_OP_SARB: |
|
1115 case CC_OP_SARW: |
|
1116 case CC_OP_SARL: |
|
1117 case CC_OP_SARQ: |
|
1118 switch(jcc_op) { |
|
1119 case JCC_Z: |
|
1120 size = (cc_op - CC_OP_ADDB) & 3; |
|
1121 goto fast_jcc_z; |
|
1122 case JCC_S: |
|
1123 size = (cc_op - CC_OP_ADDB) & 3; |
|
1124 goto fast_jcc_s; |
|
1125 default: |
|
1126 goto slow_jcc; |
|
1127 } |
|
1128 break; |
|
1129 default: |
|
1130 slow_jcc: |
|
1131 gen_setcc_slow_T0(s, jcc_op); |
|
1132 tcg_gen_brcondi_tl(inv ? TCG_COND_EQ : TCG_COND_NE, |
|
1133 cpu_T[0], 0, l1); |
|
1134 break; |
|
1135 } |
|
1136 } |
|
1137 |
|
1138 /* XXX: does not work with gdbstub "ice" single step - not a |
|
1139 serious problem */ |
|
1140 static int gen_jz_ecx_string(DisasContext *s, target_ulong next_eip) |
|
1141 { |
|
1142 int l1, l2; |
|
1143 |
|
1144 l1 = gen_new_label(); |
|
1145 l2 = gen_new_label(); |
|
1146 gen_op_jnz_ecx(s->aflag, l1); |
|
1147 gen_set_label(l2); |
|
1148 gen_jmp_tb(s, next_eip, 1); |
|
1149 gen_set_label(l1); |
|
1150 return l2; |
|
1151 } |
|
1152 |
|
1153 static inline void gen_stos(DisasContext *s, int ot) |
|
1154 { |
|
1155 gen_op_mov_TN_reg(OT_LONG, 0, R_EAX); |
|
1156 gen_string_movl_A0_EDI(s); |
|
1157 gen_op_st_T0_A0(ot + s->mem_index); |
|
1158 gen_op_movl_T0_Dshift(ot); |
|
1159 gen_op_add_reg_T0(s->aflag, R_EDI); |
|
1160 } |
|
1161 |
|
1162 static inline void gen_lods(DisasContext *s, int ot) |
|
1163 { |
|
1164 gen_string_movl_A0_ESI(s); |
|
1165 gen_op_ld_T0_A0(ot + s->mem_index); |
|
1166 gen_op_mov_reg_T0(ot, R_EAX); |
|
1167 gen_op_movl_T0_Dshift(ot); |
|
1168 gen_op_add_reg_T0(s->aflag, R_ESI); |
|
1169 } |
|
1170 |
|
1171 static inline void gen_scas(DisasContext *s, int ot) |
|
1172 { |
|
1173 gen_op_mov_TN_reg(OT_LONG, 0, R_EAX); |
|
1174 gen_string_movl_A0_EDI(s); |
|
1175 gen_op_ld_T1_A0(ot + s->mem_index); |
|
1176 gen_op_cmpl_T0_T1_cc(); |
|
1177 gen_op_movl_T0_Dshift(ot); |
|
1178 gen_op_add_reg_T0(s->aflag, R_EDI); |
|
1179 } |
|
1180 |
|
1181 static inline void gen_cmps(DisasContext *s, int ot) |
|
1182 { |
|
1183 gen_string_movl_A0_ESI(s); |
|
1184 gen_op_ld_T0_A0(ot + s->mem_index); |
|
1185 gen_string_movl_A0_EDI(s); |
|
1186 gen_op_ld_T1_A0(ot + s->mem_index); |
|
1187 gen_op_cmpl_T0_T1_cc(); |
|
1188 gen_op_movl_T0_Dshift(ot); |
|
1189 gen_op_add_reg_T0(s->aflag, R_ESI); |
|
1190 gen_op_add_reg_T0(s->aflag, R_EDI); |
|
1191 } |
|
1192 |
|
1193 static inline void gen_ins(DisasContext *s, int ot) |
|
1194 { |
|
1195 if (use_icount) |
|
1196 gen_io_start(); |
|
1197 gen_string_movl_A0_EDI(s); |
|
1198 /* Note: we must do this dummy write first to be restartable in |
|
1199 case of page fault. */ |
|
1200 gen_op_movl_T0_0(); |
|
1201 gen_op_st_T0_A0(ot + s->mem_index); |
|
1202 gen_op_mov_TN_reg(OT_WORD, 1, R_EDX); |
|
1203 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[1]); |
|
1204 tcg_gen_andi_i32(cpu_tmp2_i32, cpu_tmp2_i32, 0xffff); |
|
1205 gen_helper_in_func(ot, cpu_T[0], cpu_tmp2_i32); |
|
1206 gen_op_st_T0_A0(ot + s->mem_index); |
|
1207 gen_op_movl_T0_Dshift(ot); |
|
1208 gen_op_add_reg_T0(s->aflag, R_EDI); |
|
1209 if (use_icount) |
|
1210 gen_io_end(); |
|
1211 } |
|
1212 |
|
1213 static inline void gen_outs(DisasContext *s, int ot) |
|
1214 { |
|
1215 if (use_icount) |
|
1216 gen_io_start(); |
|
1217 gen_string_movl_A0_ESI(s); |
|
1218 gen_op_ld_T0_A0(ot + s->mem_index); |
|
1219 |
|
1220 gen_op_mov_TN_reg(OT_WORD, 1, R_EDX); |
|
1221 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[1]); |
|
1222 tcg_gen_andi_i32(cpu_tmp2_i32, cpu_tmp2_i32, 0xffff); |
|
1223 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T[0]); |
|
1224 gen_helper_out_func(ot, cpu_tmp2_i32, cpu_tmp3_i32); |
|
1225 |
|
1226 gen_op_movl_T0_Dshift(ot); |
|
1227 gen_op_add_reg_T0(s->aflag, R_ESI); |
|
1228 if (use_icount) |
|
1229 gen_io_end(); |
|
1230 } |
|
1231 |
|
1232 /* same method as Valgrind : we generate jumps to current or next |
|
1233 instruction */ |
|
1234 #define GEN_REPZ(op) \ |
|
1235 static inline void gen_repz_ ## op(DisasContext *s, int ot, \ |
|
1236 target_ulong cur_eip, target_ulong next_eip) \ |
|
1237 { \ |
|
1238 int l2;\ |
|
1239 gen_update_cc_op(s); \ |
|
1240 l2 = gen_jz_ecx_string(s, next_eip); \ |
|
1241 gen_ ## op(s, ot); \ |
|
1242 gen_op_add_reg_im(s->aflag, R_ECX, -1); \ |
|
1243 /* a loop would cause two single step exceptions if ECX = 1 \ |
|
1244 before rep string_insn */ \ |
|
1245 if (!s->jmp_opt) \ |
|
1246 gen_op_jz_ecx(s->aflag, l2); \ |
|
1247 gen_jmp(s, cur_eip); \ |
|
1248 } |
|
1249 |
|
1250 #define GEN_REPZ2(op) \ |
|
1251 static inline void gen_repz_ ## op(DisasContext *s, int ot, \ |
|
1252 target_ulong cur_eip, \ |
|
1253 target_ulong next_eip, \ |
|
1254 int nz) \ |
|
1255 { \ |
|
1256 int l2;\ |
|
1257 gen_update_cc_op(s); \ |
|
1258 l2 = gen_jz_ecx_string(s, next_eip); \ |
|
1259 gen_ ## op(s, ot); \ |
|
1260 gen_op_add_reg_im(s->aflag, R_ECX, -1); \ |
|
1261 gen_op_set_cc_op(CC_OP_SUBB + ot); \ |
|
1262 gen_jcc1(s, CC_OP_SUBB + ot, (JCC_Z << 1) | (nz ^ 1), l2); \ |
|
1263 if (!s->jmp_opt) \ |
|
1264 gen_op_jz_ecx(s->aflag, l2); \ |
|
1265 gen_jmp(s, cur_eip); \ |
|
1266 } |
|
1267 |
|
1268 GEN_REPZ(movs) |
|
1269 GEN_REPZ(stos) |
|
1270 GEN_REPZ(lods) |
|
1271 GEN_REPZ(ins) |
|
1272 GEN_REPZ(outs) |
|
1273 GEN_REPZ2(scas) |
|
1274 GEN_REPZ2(cmps) |
|
1275 |
|
1276 static void gen_helper_fp_arith_ST0_FT0(int op) |
|
1277 { |
|
1278 switch (op) { |
|
1279 case 0: gen_helper_fadd_ST0_FT0(); break; |
|
1280 case 1: gen_helper_fmul_ST0_FT0(); break; |
|
1281 case 2: gen_helper_fcom_ST0_FT0(); break; |
|
1282 case 3: gen_helper_fcom_ST0_FT0(); break; |
|
1283 case 4: gen_helper_fsub_ST0_FT0(); break; |
|
1284 case 5: gen_helper_fsubr_ST0_FT0(); break; |
|
1285 case 6: gen_helper_fdiv_ST0_FT0(); break; |
|
1286 case 7: gen_helper_fdivr_ST0_FT0(); break; |
|
1287 } |
|
1288 } |
|
1289 |
|
1290 /* NOTE the exception in "r" op ordering */ |
|
1291 static void gen_helper_fp_arith_STN_ST0(int op, int opreg) |
|
1292 { |
|
1293 TCGv_i32 tmp = tcg_const_i32(opreg); |
|
1294 switch (op) { |
|
1295 case 0: gen_helper_fadd_STN_ST0(tmp); break; |
|
1296 case 1: gen_helper_fmul_STN_ST0(tmp); break; |
|
1297 case 4: gen_helper_fsubr_STN_ST0(tmp); break; |
|
1298 case 5: gen_helper_fsub_STN_ST0(tmp); break; |
|
1299 case 6: gen_helper_fdivr_STN_ST0(tmp); break; |
|
1300 case 7: gen_helper_fdiv_STN_ST0(tmp); break; |
|
1301 } |
|
1302 } |
|
1303 |
|
1304 /* if d == OR_TMP0, it means memory operand (address in A0) */ |
|
1305 static void gen_op(DisasContext *s1, int op, int ot, int d) |
|
1306 { |
|
1307 if (d != OR_TMP0) { |
|
1308 gen_op_mov_TN_reg(ot, 0, d); |
|
1309 } else { |
|
1310 gen_op_ld_T0_A0(ot + s1->mem_index); |
|
1311 } |
|
1312 switch(op) { |
|
1313 case OP_ADCL: |
|
1314 if (s1->cc_op != CC_OP_DYNAMIC) |
|
1315 gen_op_set_cc_op(s1->cc_op); |
|
1316 gen_compute_eflags_c(cpu_tmp4); |
|
1317 tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]); |
|
1318 tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_tmp4); |
|
1319 if (d != OR_TMP0) |
|
1320 gen_op_mov_reg_T0(ot, d); |
|
1321 else |
|
1322 gen_op_st_T0_A0(ot + s1->mem_index); |
|
1323 tcg_gen_mov_tl(cpu_cc_src, cpu_T[1]); |
|
1324 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]); |
|
1325 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_tmp4); |
|
1326 tcg_gen_shli_i32(cpu_tmp2_i32, cpu_tmp2_i32, 2); |
|
1327 tcg_gen_addi_i32(cpu_cc_op, cpu_tmp2_i32, CC_OP_ADDB + ot); |
|
1328 s1->cc_op = CC_OP_DYNAMIC; |
|
1329 break; |
|
1330 case OP_SBBL: |
|
1331 if (s1->cc_op != CC_OP_DYNAMIC) |
|
1332 gen_op_set_cc_op(s1->cc_op); |
|
1333 gen_compute_eflags_c(cpu_tmp4); |
|
1334 tcg_gen_sub_tl(cpu_T[0], cpu_T[0], cpu_T[1]); |
|
1335 tcg_gen_sub_tl(cpu_T[0], cpu_T[0], cpu_tmp4); |
|
1336 if (d != OR_TMP0) |
|
1337 gen_op_mov_reg_T0(ot, d); |
|
1338 else |
|
1339 gen_op_st_T0_A0(ot + s1->mem_index); |
|
1340 tcg_gen_mov_tl(cpu_cc_src, cpu_T[1]); |
|
1341 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]); |
|
1342 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_tmp4); |
|
1343 tcg_gen_shli_i32(cpu_tmp2_i32, cpu_tmp2_i32, 2); |
|
1344 tcg_gen_addi_i32(cpu_cc_op, cpu_tmp2_i32, CC_OP_SUBB + ot); |
|
1345 s1->cc_op = CC_OP_DYNAMIC; |
|
1346 break; |
|
1347 case OP_ADDL: |
|
1348 gen_op_addl_T0_T1(); |
|
1349 if (d != OR_TMP0) |
|
1350 gen_op_mov_reg_T0(ot, d); |
|
1351 else |
|
1352 gen_op_st_T0_A0(ot + s1->mem_index); |
|
1353 gen_op_update2_cc(); |
|
1354 s1->cc_op = CC_OP_ADDB + ot; |
|
1355 break; |
|
1356 case OP_SUBL: |
|
1357 tcg_gen_sub_tl(cpu_T[0], cpu_T[0], cpu_T[1]); |
|
1358 if (d != OR_TMP0) |
|
1359 gen_op_mov_reg_T0(ot, d); |
|
1360 else |
|
1361 gen_op_st_T0_A0(ot + s1->mem_index); |
|
1362 gen_op_update2_cc(); |
|
1363 s1->cc_op = CC_OP_SUBB + ot; |
|
1364 break; |
|
1365 default: |
|
1366 case OP_ANDL: |
|
1367 tcg_gen_and_tl(cpu_T[0], cpu_T[0], cpu_T[1]); |
|
1368 if (d != OR_TMP0) |
|
1369 gen_op_mov_reg_T0(ot, d); |
|
1370 else |
|
1371 gen_op_st_T0_A0(ot + s1->mem_index); |
|
1372 gen_op_update1_cc(); |
|
1373 s1->cc_op = CC_OP_LOGICB + ot; |
|
1374 break; |
|
1375 case OP_ORL: |
|
1376 tcg_gen_or_tl(cpu_T[0], cpu_T[0], cpu_T[1]); |
|
1377 if (d != OR_TMP0) |
|
1378 gen_op_mov_reg_T0(ot, d); |
|
1379 else |
|
1380 gen_op_st_T0_A0(ot + s1->mem_index); |
|
1381 gen_op_update1_cc(); |
|
1382 s1->cc_op = CC_OP_LOGICB + ot; |
|
1383 break; |
|
1384 case OP_XORL: |
|
1385 tcg_gen_xor_tl(cpu_T[0], cpu_T[0], cpu_T[1]); |
|
1386 if (d != OR_TMP0) |
|
1387 gen_op_mov_reg_T0(ot, d); |
|
1388 else |
|
1389 gen_op_st_T0_A0(ot + s1->mem_index); |
|
1390 gen_op_update1_cc(); |
|
1391 s1->cc_op = CC_OP_LOGICB + ot; |
|
1392 break; |
|
1393 case OP_CMPL: |
|
1394 gen_op_cmpl_T0_T1_cc(); |
|
1395 s1->cc_op = CC_OP_SUBB + ot; |
|
1396 break; |
|
1397 } |
|
1398 } |
|
1399 |
|
1400 /* if d == OR_TMP0, it means memory operand (address in A0) */ |
|
1401 static void gen_inc(DisasContext *s1, int ot, int d, int c) |
|
1402 { |
|
1403 if (d != OR_TMP0) |
|
1404 gen_op_mov_TN_reg(ot, 0, d); |
|
1405 else |
|
1406 gen_op_ld_T0_A0(ot + s1->mem_index); |
|
1407 if (s1->cc_op != CC_OP_DYNAMIC) |
|
1408 gen_op_set_cc_op(s1->cc_op); |
|
1409 if (c > 0) { |
|
1410 tcg_gen_addi_tl(cpu_T[0], cpu_T[0], 1); |
|
1411 s1->cc_op = CC_OP_INCB + ot; |
|
1412 } else { |
|
1413 tcg_gen_addi_tl(cpu_T[0], cpu_T[0], -1); |
|
1414 s1->cc_op = CC_OP_DECB + ot; |
|
1415 } |
|
1416 if (d != OR_TMP0) |
|
1417 gen_op_mov_reg_T0(ot, d); |
|
1418 else |
|
1419 gen_op_st_T0_A0(ot + s1->mem_index); |
|
1420 gen_compute_eflags_c(cpu_cc_src); |
|
1421 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]); |
|
1422 } |
|
1423 |
|
1424 static void gen_shift_rm_T1(DisasContext *s, int ot, int op1, |
|
1425 int is_right, int is_arith) |
|
1426 { |
|
1427 target_ulong mask; |
|
1428 int shift_label; |
|
1429 TCGv t0, t1; |
|
1430 |
|
1431 if (ot == OT_QUAD) |
|
1432 mask = 0x3f; |
|
1433 else |
|
1434 mask = 0x1f; |
|
1435 |
|
1436 /* load */ |
|
1437 if (op1 == OR_TMP0) |
|
1438 gen_op_ld_T0_A0(ot + s->mem_index); |
|
1439 else |
|
1440 gen_op_mov_TN_reg(ot, 0, op1); |
|
1441 |
|
1442 tcg_gen_andi_tl(cpu_T[1], cpu_T[1], mask); |
|
1443 |
|
1444 tcg_gen_addi_tl(cpu_tmp5, cpu_T[1], -1); |
|
1445 |
|
1446 if (is_right) { |
|
1447 if (is_arith) { |
|
1448 gen_exts(ot, cpu_T[0]); |
|
1449 tcg_gen_sar_tl(cpu_T3, cpu_T[0], cpu_tmp5); |
|
1450 tcg_gen_sar_tl(cpu_T[0], cpu_T[0], cpu_T[1]); |
|
1451 } else { |
|
1452 gen_extu(ot, cpu_T[0]); |
|
1453 tcg_gen_shr_tl(cpu_T3, cpu_T[0], cpu_tmp5); |
|
1454 tcg_gen_shr_tl(cpu_T[0], cpu_T[0], cpu_T[1]); |
|
1455 } |
|
1456 } else { |
|
1457 tcg_gen_shl_tl(cpu_T3, cpu_T[0], cpu_tmp5); |
|
1458 tcg_gen_shl_tl(cpu_T[0], cpu_T[0], cpu_T[1]); |
|
1459 } |
|
1460 |
|
1461 /* store */ |
|
1462 if (op1 == OR_TMP0) |
|
1463 gen_op_st_T0_A0(ot + s->mem_index); |
|
1464 else |
|
1465 gen_op_mov_reg_T0(ot, op1); |
|
1466 |
|
1467 /* update eflags if non zero shift */ |
|
1468 if (s->cc_op != CC_OP_DYNAMIC) |
|
1469 gen_op_set_cc_op(s->cc_op); |
|
1470 |
|
1471 /* XXX: inefficient */ |
|
1472 t0 = tcg_temp_local_new(); |
|
1473 t1 = tcg_temp_local_new(); |
|
1474 |
|
1475 tcg_gen_mov_tl(t0, cpu_T[0]); |
|
1476 tcg_gen_mov_tl(t1, cpu_T3); |
|
1477 |
|
1478 shift_label = gen_new_label(); |
|
1479 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_T[1], 0, shift_label); |
|
1480 |
|
1481 tcg_gen_mov_tl(cpu_cc_src, t1); |
|
1482 tcg_gen_mov_tl(cpu_cc_dst, t0); |
|
1483 if (is_right) |
|
1484 tcg_gen_movi_i32(cpu_cc_op, CC_OP_SARB + ot); |
|
1485 else |
|
1486 tcg_gen_movi_i32(cpu_cc_op, CC_OP_SHLB + ot); |
|
1487 |
|
1488 gen_set_label(shift_label); |
|
1489 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */ |
|
1490 |
|
1491 tcg_temp_free(t0); |
|
1492 tcg_temp_free(t1); |
|
1493 } |
|
1494 |
|
1495 static void gen_shift_rm_im(DisasContext *s, int ot, int op1, int op2, |
|
1496 int is_right, int is_arith) |
|
1497 { |
|
1498 int mask; |
|
1499 |
|
1500 if (ot == OT_QUAD) |
|
1501 mask = 0x3f; |
|
1502 else |
|
1503 mask = 0x1f; |
|
1504 |
|
1505 /* load */ |
|
1506 if (op1 == OR_TMP0) |
|
1507 gen_op_ld_T0_A0(ot + s->mem_index); |
|
1508 else |
|
1509 gen_op_mov_TN_reg(ot, 0, op1); |
|
1510 |
|
1511 op2 &= mask; |
|
1512 if (op2 != 0) { |
|
1513 if (is_right) { |
|
1514 if (is_arith) { |
|
1515 gen_exts(ot, cpu_T[0]); |
|
1516 tcg_gen_sari_tl(cpu_tmp4, cpu_T[0], op2 - 1); |
|
1517 tcg_gen_sari_tl(cpu_T[0], cpu_T[0], op2); |
|
1518 } else { |
|
1519 gen_extu(ot, cpu_T[0]); |
|
1520 tcg_gen_shri_tl(cpu_tmp4, cpu_T[0], op2 - 1); |
|
1521 tcg_gen_shri_tl(cpu_T[0], cpu_T[0], op2); |
|
1522 } |
|
1523 } else { |
|
1524 tcg_gen_shli_tl(cpu_tmp4, cpu_T[0], op2 - 1); |
|
1525 tcg_gen_shli_tl(cpu_T[0], cpu_T[0], op2); |
|
1526 } |
|
1527 } |
|
1528 |
|
1529 /* store */ |
|
1530 if (op1 == OR_TMP0) |
|
1531 gen_op_st_T0_A0(ot + s->mem_index); |
|
1532 else |
|
1533 gen_op_mov_reg_T0(ot, op1); |
|
1534 |
|
1535 /* update eflags if non zero shift */ |
|
1536 if (op2 != 0) { |
|
1537 tcg_gen_mov_tl(cpu_cc_src, cpu_tmp4); |
|
1538 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]); |
|
1539 if (is_right) |
|
1540 s->cc_op = CC_OP_SARB + ot; |
|
1541 else |
|
1542 s->cc_op = CC_OP_SHLB + ot; |
|
1543 } |
|
1544 } |
|
1545 |
|
1546 static inline void tcg_gen_lshift(TCGv ret, TCGv arg1, target_long arg2) |
|
1547 { |
|
1548 if (arg2 >= 0) |
|
1549 tcg_gen_shli_tl(ret, arg1, arg2); |
|
1550 else |
|
1551 tcg_gen_shri_tl(ret, arg1, -arg2); |
|
1552 } |
|
1553 |
|
1554 /* XXX: add faster immediate case */ |
|
1555 static void gen_rot_rm_T1(DisasContext *s, int ot, int op1, |
|
1556 int is_right) |
|
1557 { |
|
1558 target_ulong mask; |
|
1559 int label1, label2, data_bits; |
|
1560 TCGv t0, t1, t2, a0; |
|
1561 |
|
1562 /* XXX: inefficient, but we must use local temps */ |
|
1563 t0 = tcg_temp_local_new(); |
|
1564 t1 = tcg_temp_local_new(); |
|
1565 t2 = tcg_temp_local_new(); |
|
1566 a0 = tcg_temp_local_new(); |
|
1567 |
|
1568 if (ot == OT_QUAD) |
|
1569 mask = 0x3f; |
|
1570 else |
|
1571 mask = 0x1f; |
|
1572 |
|
1573 /* load */ |
|
1574 if (op1 == OR_TMP0) { |
|
1575 tcg_gen_mov_tl(a0, cpu_A0); |
|
1576 gen_op_ld_v(ot + s->mem_index, t0, a0); |
|
1577 } else { |
|
1578 gen_op_mov_v_reg(ot, t0, op1); |
|
1579 } |
|
1580 |
|
1581 tcg_gen_mov_tl(t1, cpu_T[1]); |
|
1582 |
|
1583 tcg_gen_andi_tl(t1, t1, mask); |
|
1584 |
|
1585 /* Must test zero case to avoid using undefined behaviour in TCG |
|
1586 shifts. */ |
|
1587 label1 = gen_new_label(); |
|
1588 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, label1); |
|
1589 |
|
1590 if (ot <= OT_WORD) |
|
1591 tcg_gen_andi_tl(cpu_tmp0, t1, (1 << (3 + ot)) - 1); |
|
1592 else |
|
1593 tcg_gen_mov_tl(cpu_tmp0, t1); |
|
1594 |
|
1595 gen_extu(ot, t0); |
|
1596 tcg_gen_mov_tl(t2, t0); |
|
1597 |
|
1598 data_bits = 8 << ot; |
|
1599 /* XXX: rely on behaviour of shifts when operand 2 overflows (XXX: |
|
1600 fix TCG definition) */ |
|
1601 if (is_right) { |
|
1602 tcg_gen_shr_tl(cpu_tmp4, t0, cpu_tmp0); |
|
1603 tcg_gen_sub_tl(cpu_tmp0, tcg_const_tl(data_bits), cpu_tmp0); |
|
1604 tcg_gen_shl_tl(t0, t0, cpu_tmp0); |
|
1605 } else { |
|
1606 tcg_gen_shl_tl(cpu_tmp4, t0, cpu_tmp0); |
|
1607 tcg_gen_sub_tl(cpu_tmp0, tcg_const_tl(data_bits), cpu_tmp0); |
|
1608 tcg_gen_shr_tl(t0, t0, cpu_tmp0); |
|
1609 } |
|
1610 tcg_gen_or_tl(t0, t0, cpu_tmp4); |
|
1611 |
|
1612 gen_set_label(label1); |
|
1613 /* store */ |
|
1614 if (op1 == OR_TMP0) { |
|
1615 gen_op_st_v(ot + s->mem_index, t0, a0); |
|
1616 } else { |
|
1617 gen_op_mov_reg_v(ot, op1, t0); |
|
1618 } |
|
1619 |
|
1620 /* update eflags */ |
|
1621 if (s->cc_op != CC_OP_DYNAMIC) |
|
1622 gen_op_set_cc_op(s->cc_op); |
|
1623 |
|
1624 label2 = gen_new_label(); |
|
1625 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, label2); |
|
1626 |
|
1627 gen_compute_eflags(cpu_cc_src); |
|
1628 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~(CC_O | CC_C)); |
|
1629 tcg_gen_xor_tl(cpu_tmp0, t2, t0); |
|
1630 tcg_gen_lshift(cpu_tmp0, cpu_tmp0, 11 - (data_bits - 1)); |
|
1631 tcg_gen_andi_tl(cpu_tmp0, cpu_tmp0, CC_O); |
|
1632 tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, cpu_tmp0); |
|
1633 if (is_right) { |
|
1634 tcg_gen_shri_tl(t0, t0, data_bits - 1); |
|
1635 } |
|
1636 tcg_gen_andi_tl(t0, t0, CC_C); |
|
1637 tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, t0); |
|
1638 |
|
1639 tcg_gen_discard_tl(cpu_cc_dst); |
|
1640 tcg_gen_movi_i32(cpu_cc_op, CC_OP_EFLAGS); |
|
1641 |
|
1642 gen_set_label(label2); |
|
1643 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */ |
|
1644 |
|
1645 tcg_temp_free(t0); |
|
1646 tcg_temp_free(t1); |
|
1647 tcg_temp_free(t2); |
|
1648 tcg_temp_free(a0); |
|
1649 } |
|
1650 |
|
1651 /* XXX: add faster immediate = 1 case */ |
|
1652 static void gen_rotc_rm_T1(DisasContext *s, int ot, int op1, |
|
1653 int is_right) |
|
1654 { |
|
1655 int label1; |
|
1656 |
|
1657 if (s->cc_op != CC_OP_DYNAMIC) |
|
1658 gen_op_set_cc_op(s->cc_op); |
|
1659 |
|
1660 /* load */ |
|
1661 if (op1 == OR_TMP0) |
|
1662 gen_op_ld_T0_A0(ot + s->mem_index); |
|
1663 else |
|
1664 gen_op_mov_TN_reg(ot, 0, op1); |
|
1665 |
|
1666 if (is_right) { |
|
1667 switch (ot) { |
|
1668 case 0: gen_helper_rcrb(cpu_T[0], cpu_T[0], cpu_T[1]); break; |
|
1669 case 1: gen_helper_rcrw(cpu_T[0], cpu_T[0], cpu_T[1]); break; |
|
1670 case 2: gen_helper_rcrl(cpu_T[0], cpu_T[0], cpu_T[1]); break; |
|
1671 #ifdef TARGET_X86_64 |
|
1672 case 3: gen_helper_rcrq(cpu_T[0], cpu_T[0], cpu_T[1]); break; |
|
1673 #endif |
|
1674 } |
|
1675 } else { |
|
1676 switch (ot) { |
|
1677 case 0: gen_helper_rclb(cpu_T[0], cpu_T[0], cpu_T[1]); break; |
|
1678 case 1: gen_helper_rclw(cpu_T[0], cpu_T[0], cpu_T[1]); break; |
|
1679 case 2: gen_helper_rcll(cpu_T[0], cpu_T[0], cpu_T[1]); break; |
|
1680 #ifdef TARGET_X86_64 |
|
1681 case 3: gen_helper_rclq(cpu_T[0], cpu_T[0], cpu_T[1]); break; |
|
1682 #endif |
|
1683 } |
|
1684 } |
|
1685 /* store */ |
|
1686 if (op1 == OR_TMP0) |
|
1687 gen_op_st_T0_A0(ot + s->mem_index); |
|
1688 else |
|
1689 gen_op_mov_reg_T0(ot, op1); |
|
1690 |
|
1691 /* update eflags */ |
|
1692 label1 = gen_new_label(); |
|
1693 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_cc_tmp, -1, label1); |
|
1694 |
|
1695 tcg_gen_mov_tl(cpu_cc_src, cpu_cc_tmp); |
|
1696 tcg_gen_discard_tl(cpu_cc_dst); |
|
1697 tcg_gen_movi_i32(cpu_cc_op, CC_OP_EFLAGS); |
|
1698 |
|
1699 gen_set_label(label1); |
|
1700 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */ |
|
1701 } |
|
1702 |
|
1703 /* XXX: add faster immediate case */ |
|
1704 static void gen_shiftd_rm_T1_T3(DisasContext *s, int ot, int op1, |
|
1705 int is_right) |
|
1706 { |
|
1707 int label1, label2, data_bits; |
|
1708 target_ulong mask; |
|
1709 TCGv t0, t1, t2, a0; |
|
1710 |
|
1711 t0 = tcg_temp_local_new(); |
|
1712 t1 = tcg_temp_local_new(); |
|
1713 t2 = tcg_temp_local_new(); |
|
1714 a0 = tcg_temp_local_new(); |
|
1715 |
|
1716 if (ot == OT_QUAD) |
|
1717 mask = 0x3f; |
|
1718 else |
|
1719 mask = 0x1f; |
|
1720 |
|
1721 /* load */ |
|
1722 if (op1 == OR_TMP0) { |
|
1723 tcg_gen_mov_tl(a0, cpu_A0); |
|
1724 gen_op_ld_v(ot + s->mem_index, t0, a0); |
|
1725 } else { |
|
1726 gen_op_mov_v_reg(ot, t0, op1); |
|
1727 } |
|
1728 |
|
1729 tcg_gen_andi_tl(cpu_T3, cpu_T3, mask); |
|
1730 |
|
1731 tcg_gen_mov_tl(t1, cpu_T[1]); |
|
1732 tcg_gen_mov_tl(t2, cpu_T3); |
|
1733 |
|
1734 /* Must test zero case to avoid using undefined behaviour in TCG |
|
1735 shifts. */ |
|
1736 label1 = gen_new_label(); |
|
1737 tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 0, label1); |
|
1738 |
|
1739 tcg_gen_addi_tl(cpu_tmp5, t2, -1); |
|
1740 if (ot == OT_WORD) { |
|
1741 /* Note: we implement the Intel behaviour for shift count > 16 */ |
|
1742 if (is_right) { |
|
1743 tcg_gen_andi_tl(t0, t0, 0xffff); |
|
1744 tcg_gen_shli_tl(cpu_tmp0, t1, 16); |
|
1745 tcg_gen_or_tl(t0, t0, cpu_tmp0); |
|
1746 tcg_gen_ext32u_tl(t0, t0); |
|
1747 |
|
1748 tcg_gen_shr_tl(cpu_tmp4, t0, cpu_tmp5); |
|
1749 |
|
1750 /* only needed if count > 16, but a test would complicate */ |
|
1751 tcg_gen_sub_tl(cpu_tmp5, tcg_const_tl(32), t2); |
|
1752 tcg_gen_shl_tl(cpu_tmp0, t0, cpu_tmp5); |
|
1753 |
|
1754 tcg_gen_shr_tl(t0, t0, t2); |
|
1755 |
|
1756 tcg_gen_or_tl(t0, t0, cpu_tmp0); |
|
1757 } else { |
|
1758 /* XXX: not optimal */ |
|
1759 tcg_gen_andi_tl(t0, t0, 0xffff); |
|
1760 tcg_gen_shli_tl(t1, t1, 16); |
|
1761 tcg_gen_or_tl(t1, t1, t0); |
|
1762 tcg_gen_ext32u_tl(t1, t1); |
|
1763 |
|
1764 tcg_gen_shl_tl(cpu_tmp4, t0, cpu_tmp5); |
|
1765 tcg_gen_sub_tl(cpu_tmp0, tcg_const_tl(32), cpu_tmp5); |
|
1766 tcg_gen_shr_tl(cpu_tmp6, t1, cpu_tmp0); |
|
1767 tcg_gen_or_tl(cpu_tmp4, cpu_tmp4, cpu_tmp6); |
|
1768 |
|
1769 tcg_gen_shl_tl(t0, t0, t2); |
|
1770 tcg_gen_sub_tl(cpu_tmp5, tcg_const_tl(32), t2); |
|
1771 tcg_gen_shr_tl(t1, t1, cpu_tmp5); |
|
1772 tcg_gen_or_tl(t0, t0, t1); |
|
1773 } |
|
1774 } else { |
|
1775 data_bits = 8 << ot; |
|
1776 if (is_right) { |
|
1777 if (ot == OT_LONG) |
|
1778 tcg_gen_ext32u_tl(t0, t0); |
|
1779 |
|
1780 tcg_gen_shr_tl(cpu_tmp4, t0, cpu_tmp5); |
|
1781 |
|
1782 tcg_gen_shr_tl(t0, t0, t2); |
|
1783 tcg_gen_sub_tl(cpu_tmp5, tcg_const_tl(data_bits), t2); |
|
1784 tcg_gen_shl_tl(t1, t1, cpu_tmp5); |
|
1785 tcg_gen_or_tl(t0, t0, t1); |
|
1786 |
|
1787 } else { |
|
1788 if (ot == OT_LONG) |
|
1789 tcg_gen_ext32u_tl(t1, t1); |
|
1790 |
|
1791 tcg_gen_shl_tl(cpu_tmp4, t0, cpu_tmp5); |
|
1792 |
|
1793 tcg_gen_shl_tl(t0, t0, t2); |
|
1794 tcg_gen_sub_tl(cpu_tmp5, tcg_const_tl(data_bits), t2); |
|
1795 tcg_gen_shr_tl(t1, t1, cpu_tmp5); |
|
1796 tcg_gen_or_tl(t0, t0, t1); |
|
1797 } |
|
1798 } |
|
1799 tcg_gen_mov_tl(t1, cpu_tmp4); |
|
1800 |
|
1801 gen_set_label(label1); |
|
1802 /* store */ |
|
1803 if (op1 == OR_TMP0) { |
|
1804 gen_op_st_v(ot + s->mem_index, t0, a0); |
|
1805 } else { |
|
1806 gen_op_mov_reg_v(ot, op1, t0); |
|
1807 } |
|
1808 |
|
1809 /* update eflags */ |
|
1810 if (s->cc_op != CC_OP_DYNAMIC) |
|
1811 gen_op_set_cc_op(s->cc_op); |
|
1812 |
|
1813 label2 = gen_new_label(); |
|
1814 tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 0, label2); |
|
1815 |
|
1816 tcg_gen_mov_tl(cpu_cc_src, t1); |
|
1817 tcg_gen_mov_tl(cpu_cc_dst, t0); |
|
1818 if (is_right) { |
|
1819 tcg_gen_movi_i32(cpu_cc_op, CC_OP_SARB + ot); |
|
1820 } else { |
|
1821 tcg_gen_movi_i32(cpu_cc_op, CC_OP_SHLB + ot); |
|
1822 } |
|
1823 gen_set_label(label2); |
|
1824 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */ |
|
1825 |
|
1826 tcg_temp_free(t0); |
|
1827 tcg_temp_free(t1); |
|
1828 tcg_temp_free(t2); |
|
1829 tcg_temp_free(a0); |
|
1830 } |
|
1831 |
|
1832 static void gen_shift(DisasContext *s1, int op, int ot, int d, int s) |
|
1833 { |
|
1834 if (s != OR_TMP1) |
|
1835 gen_op_mov_TN_reg(ot, 1, s); |
|
1836 switch(op) { |
|
1837 case OP_ROL: |
|
1838 gen_rot_rm_T1(s1, ot, d, 0); |
|
1839 break; |
|
1840 case OP_ROR: |
|
1841 gen_rot_rm_T1(s1, ot, d, 1); |
|
1842 break; |
|
1843 case OP_SHL: |
|
1844 case OP_SHL1: |
|
1845 gen_shift_rm_T1(s1, ot, d, 0, 0); |
|
1846 break; |
|
1847 case OP_SHR: |
|
1848 gen_shift_rm_T1(s1, ot, d, 1, 0); |
|
1849 break; |
|
1850 case OP_SAR: |
|
1851 gen_shift_rm_T1(s1, ot, d, 1, 1); |
|
1852 break; |
|
1853 case OP_RCL: |
|
1854 gen_rotc_rm_T1(s1, ot, d, 0); |
|
1855 break; |
|
1856 case OP_RCR: |
|
1857 gen_rotc_rm_T1(s1, ot, d, 1); |
|
1858 break; |
|
1859 } |
|
1860 } |
|
1861 |
|
1862 static void gen_shifti(DisasContext *s1, int op, int ot, int d, int c) |
|
1863 { |
|
1864 switch(op) { |
|
1865 case OP_SHL: |
|
1866 case OP_SHL1: |
|
1867 gen_shift_rm_im(s1, ot, d, c, 0, 0); |
|
1868 break; |
|
1869 case OP_SHR: |
|
1870 gen_shift_rm_im(s1, ot, d, c, 1, 0); |
|
1871 break; |
|
1872 case OP_SAR: |
|
1873 gen_shift_rm_im(s1, ot, d, c, 1, 1); |
|
1874 break; |
|
1875 default: |
|
1876 /* currently not optimized */ |
|
1877 gen_op_movl_T1_im(c); |
|
1878 gen_shift(s1, op, ot, d, OR_TMP1); |
|
1879 break; |
|
1880 } |
|
1881 } |
|
1882 |
|
1883 static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ptr) |
|
1884 { |
|
1885 target_long disp; |
|
1886 int havesib; |
|
1887 int base; |
|
1888 int index; |
|
1889 int scale; |
|
1890 int opreg; |
|
1891 int mod, rm, code, override, must_add_seg; |
|
1892 |
|
1893 override = s->override; |
|
1894 must_add_seg = s->addseg; |
|
1895 if (override >= 0) |
|
1896 must_add_seg = 1; |
|
1897 mod = (modrm >> 6) & 3; |
|
1898 rm = modrm & 7; |
|
1899 |
|
1900 if (s->aflag) { |
|
1901 |
|
1902 havesib = 0; |
|
1903 base = rm; |
|
1904 index = 0; |
|
1905 scale = 0; |
|
1906 |
|
1907 if (base == 4) { |
|
1908 havesib = 1; |
|
1909 code = ldub_code(s->pc++); |
|
1910 scale = (code >> 6) & 3; |
|
1911 index = ((code >> 3) & 7) | REX_X(s); |
|
1912 base = (code & 7); |
|
1913 } |
|
1914 base |= REX_B(s); |
|
1915 |
|
1916 switch (mod) { |
|
1917 case 0: |
|
1918 if ((base & 7) == 5) { |
|
1919 base = -1; |
|
1920 disp = (int32_t)ldl_code(s->pc); |
|
1921 s->pc += 4; |
|
1922 if (CODE64(s) && !havesib) { |
|
1923 disp += s->pc + s->rip_offset; |
|
1924 } |
|
1925 } else { |
|
1926 disp = 0; |
|
1927 } |
|
1928 break; |
|
1929 case 1: |
|
1930 disp = (int8_t)ldub_code(s->pc++); |
|
1931 break; |
|
1932 default: |
|
1933 case 2: |
|
1934 disp = ldl_code(s->pc); |
|
1935 s->pc += 4; |
|
1936 break; |
|
1937 } |
|
1938 |
|
1939 if (base >= 0) { |
|
1940 /* for correct popl handling with esp */ |
|
1941 if (base == 4 && s->popl_esp_hack) |
|
1942 disp += s->popl_esp_hack; |
|
1943 #ifdef TARGET_X86_64 |
|
1944 if (s->aflag == 2) { |
|
1945 gen_op_movq_A0_reg(base); |
|
1946 if (disp != 0) { |
|
1947 gen_op_addq_A0_im(disp); |
|
1948 } |
|
1949 } else |
|
1950 #endif |
|
1951 { |
|
1952 gen_op_movl_A0_reg(base); |
|
1953 if (disp != 0) |
|
1954 gen_op_addl_A0_im(disp); |
|
1955 } |
|
1956 } else { |
|
1957 #ifdef TARGET_X86_64 |
|
1958 if (s->aflag == 2) { |
|
1959 gen_op_movq_A0_im(disp); |
|
1960 } else |
|
1961 #endif |
|
1962 { |
|
1963 gen_op_movl_A0_im(disp); |
|
1964 } |
|
1965 } |
|
1966 /* XXX: index == 4 is always invalid */ |
|
1967 if (havesib && (index != 4 || scale != 0)) { |
|
1968 #ifdef TARGET_X86_64 |
|
1969 if (s->aflag == 2) { |
|
1970 gen_op_addq_A0_reg_sN(scale, index); |
|
1971 } else |
|
1972 #endif |
|
1973 { |
|
1974 gen_op_addl_A0_reg_sN(scale, index); |
|
1975 } |
|
1976 } |
|
1977 if (must_add_seg) { |
|
1978 if (override < 0) { |
|
1979 if (base == R_EBP || base == R_ESP) |
|
1980 override = R_SS; |
|
1981 else |
|
1982 override = R_DS; |
|
1983 } |
|
1984 #ifdef TARGET_X86_64 |
|
1985 if (s->aflag == 2) { |
|
1986 gen_op_addq_A0_seg(override); |
|
1987 } else |
|
1988 #endif |
|
1989 { |
|
1990 gen_op_addl_A0_seg(override); |
|
1991 } |
|
1992 } |
|
1993 } else { |
|
1994 switch (mod) { |
|
1995 case 0: |
|
1996 if (rm == 6) { |
|
1997 disp = lduw_code(s->pc); |
|
1998 s->pc += 2; |
|
1999 gen_op_movl_A0_im(disp); |
|
2000 rm = 0; /* avoid SS override */ |
|
2001 goto no_rm; |
|
2002 } else { |
|
2003 disp = 0; |
|
2004 } |
|
2005 break; |
|
2006 case 1: |
|
2007 disp = (int8_t)ldub_code(s->pc++); |
|
2008 break; |
|
2009 default: |
|
2010 case 2: |
|
2011 disp = lduw_code(s->pc); |
|
2012 s->pc += 2; |
|
2013 break; |
|
2014 } |
|
2015 switch(rm) { |
|
2016 case 0: |
|
2017 gen_op_movl_A0_reg(R_EBX); |
|
2018 gen_op_addl_A0_reg_sN(0, R_ESI); |
|
2019 break; |
|
2020 case 1: |
|
2021 gen_op_movl_A0_reg(R_EBX); |
|
2022 gen_op_addl_A0_reg_sN(0, R_EDI); |
|
2023 break; |
|
2024 case 2: |
|
2025 gen_op_movl_A0_reg(R_EBP); |
|
2026 gen_op_addl_A0_reg_sN(0, R_ESI); |
|
2027 break; |
|
2028 case 3: |
|
2029 gen_op_movl_A0_reg(R_EBP); |
|
2030 gen_op_addl_A0_reg_sN(0, R_EDI); |
|
2031 break; |
|
2032 case 4: |
|
2033 gen_op_movl_A0_reg(R_ESI); |
|
2034 break; |
|
2035 case 5: |
|
2036 gen_op_movl_A0_reg(R_EDI); |
|
2037 break; |
|
2038 case 6: |
|
2039 gen_op_movl_A0_reg(R_EBP); |
|
2040 break; |
|
2041 default: |
|
2042 case 7: |
|
2043 gen_op_movl_A0_reg(R_EBX); |
|
2044 break; |
|
2045 } |
|
2046 if (disp != 0) |
|
2047 gen_op_addl_A0_im(disp); |
|
2048 gen_op_andl_A0_ffff(); |
|
2049 no_rm: |
|
2050 if (must_add_seg) { |
|
2051 if (override < 0) { |
|
2052 if (rm == 2 || rm == 3 || rm == 6) |
|
2053 override = R_SS; |
|
2054 else |
|
2055 override = R_DS; |
|
2056 } |
|
2057 gen_op_addl_A0_seg(override); |
|
2058 } |
|
2059 } |
|
2060 |
|
2061 opreg = OR_A0; |
|
2062 disp = 0; |
|
2063 *reg_ptr = opreg; |
|
2064 *offset_ptr = disp; |
|
2065 } |
|
2066 |
|
2067 static void gen_nop_modrm(DisasContext *s, int modrm) |
|
2068 { |
|
2069 int mod, rm, base, code; |
|
2070 |
|
2071 mod = (modrm >> 6) & 3; |
|
2072 if (mod == 3) |
|
2073 return; |
|
2074 rm = modrm & 7; |
|
2075 |
|
2076 if (s->aflag) { |
|
2077 |
|
2078 base = rm; |
|
2079 |
|
2080 if (base == 4) { |
|
2081 code = ldub_code(s->pc++); |
|
2082 base = (code & 7); |
|
2083 } |
|
2084 |
|
2085 switch (mod) { |
|
2086 case 0: |
|
2087 if (base == 5) { |
|
2088 s->pc += 4; |
|
2089 } |
|
2090 break; |
|
2091 case 1: |
|
2092 s->pc++; |
|
2093 break; |
|
2094 default: |
|
2095 case 2: |
|
2096 s->pc += 4; |
|
2097 break; |
|
2098 } |
|
2099 } else { |
|
2100 switch (mod) { |
|
2101 case 0: |
|
2102 if (rm == 6) { |
|
2103 s->pc += 2; |
|
2104 } |
|
2105 break; |
|
2106 case 1: |
|
2107 s->pc++; |
|
2108 break; |
|
2109 default: |
|
2110 case 2: |
|
2111 s->pc += 2; |
|
2112 break; |
|
2113 } |
|
2114 } |
|
2115 } |
|
2116 |
|
2117 /* used for LEA and MOV AX, mem */ |
|
2118 static void gen_add_A0_ds_seg(DisasContext *s) |
|
2119 { |
|
2120 int override, must_add_seg; |
|
2121 must_add_seg = s->addseg; |
|
2122 override = R_DS; |
|
2123 if (s->override >= 0) { |
|
2124 override = s->override; |
|
2125 must_add_seg = 1; |
|
2126 } else { |
|
2127 override = R_DS; |
|
2128 } |
|
2129 if (must_add_seg) { |
|
2130 #ifdef TARGET_X86_64 |
|
2131 if (CODE64(s)) { |
|
2132 gen_op_addq_A0_seg(override); |
|
2133 } else |
|
2134 #endif |
|
2135 { |
|
2136 gen_op_addl_A0_seg(override); |
|
2137 } |
|
2138 } |
|
2139 } |
|
2140 |
|
2141 /* generate modrm memory load or store of 'reg'. TMP0 is used if reg == |
|
2142 OR_TMP0 */ |
|
2143 static void gen_ldst_modrm(DisasContext *s, int modrm, int ot, int reg, int is_store) |
|
2144 { |
|
2145 int mod, rm, opreg, disp; |
|
2146 |
|
2147 mod = (modrm >> 6) & 3; |
|
2148 rm = (modrm & 7) | REX_B(s); |
|
2149 if (mod == 3) { |
|
2150 if (is_store) { |
|
2151 if (reg != OR_TMP0) |
|
2152 gen_op_mov_TN_reg(ot, 0, reg); |
|
2153 gen_op_mov_reg_T0(ot, rm); |
|
2154 } else { |
|
2155 gen_op_mov_TN_reg(ot, 0, rm); |
|
2156 if (reg != OR_TMP0) |
|
2157 gen_op_mov_reg_T0(ot, reg); |
|
2158 } |
|
2159 } else { |
|
2160 gen_lea_modrm(s, modrm, &opreg, &disp); |
|
2161 if (is_store) { |
|
2162 if (reg != OR_TMP0) |
|
2163 gen_op_mov_TN_reg(ot, 0, reg); |
|
2164 gen_op_st_T0_A0(ot + s->mem_index); |
|
2165 } else { |
|
2166 gen_op_ld_T0_A0(ot + s->mem_index); |
|
2167 if (reg != OR_TMP0) |
|
2168 gen_op_mov_reg_T0(ot, reg); |
|
2169 } |
|
2170 } |
|
2171 } |
|
2172 |
|
2173 static inline uint32_t insn_get(DisasContext *s, int ot) |
|
2174 { |
|
2175 uint32_t ret; |
|
2176 |
|
2177 switch(ot) { |
|
2178 case OT_BYTE: |
|
2179 ret = ldub_code(s->pc); |
|
2180 s->pc++; |
|
2181 break; |
|
2182 case OT_WORD: |
|
2183 ret = lduw_code(s->pc); |
|
2184 s->pc += 2; |
|
2185 break; |
|
2186 default: |
|
2187 case OT_LONG: |
|
2188 ret = ldl_code(s->pc); |
|
2189 s->pc += 4; |
|
2190 break; |
|
2191 } |
|
2192 return ret; |
|
2193 } |
|
2194 |
|
2195 static inline int insn_const_size(unsigned int ot) |
|
2196 { |
|
2197 if (ot <= OT_LONG) |
|
2198 return 1 << ot; |
|
2199 else |
|
2200 return 4; |
|
2201 } |
|
2202 |
|
2203 static inline void gen_goto_tb(DisasContext *s, int tb_num, target_ulong eip) |
|
2204 { |
|
2205 TranslationBlock *tb; |
|
2206 target_ulong pc; |
|
2207 |
|
2208 pc = s->cs_base + eip; |
|
2209 tb = s->tb; |
|
2210 /* NOTE: we handle the case where the TB spans two pages here */ |
|
2211 if ((pc & TARGET_PAGE_MASK) == (tb->pc & TARGET_PAGE_MASK) || |
|
2212 (pc & TARGET_PAGE_MASK) == ((s->pc - 1) & TARGET_PAGE_MASK)) { |
|
2213 /* jump to same page: we can use a direct jump */ |
|
2214 tcg_gen_goto_tb(tb_num); |
|
2215 gen_jmp_im(eip); |
|
2216 tcg_gen_exit_tb((long)tb + tb_num); |
|
2217 } else { |
|
2218 /* jump to another page: currently not optimized */ |
|
2219 gen_jmp_im(eip); |
|
2220 gen_eob(s); |
|
2221 } |
|
2222 } |
|
2223 |
|
2224 static inline void gen_jcc(DisasContext *s, int b, |
|
2225 target_ulong val, target_ulong next_eip) |
|
2226 { |
|
2227 int l1, l2, cc_op; |
|
2228 |
|
2229 cc_op = s->cc_op; |
|
2230 if (s->cc_op != CC_OP_DYNAMIC) { |
|
2231 gen_op_set_cc_op(s->cc_op); |
|
2232 s->cc_op = CC_OP_DYNAMIC; |
|
2233 } |
|
2234 if (s->jmp_opt) { |
|
2235 l1 = gen_new_label(); |
|
2236 gen_jcc1(s, cc_op, b, l1); |
|
2237 |
|
2238 gen_goto_tb(s, 0, next_eip); |
|
2239 |
|
2240 gen_set_label(l1); |
|
2241 gen_goto_tb(s, 1, val); |
|
2242 s->is_jmp = 3; |
|
2243 } else { |
|
2244 |
|
2245 l1 = gen_new_label(); |
|
2246 l2 = gen_new_label(); |
|
2247 gen_jcc1(s, cc_op, b, l1); |
|
2248 |
|
2249 gen_jmp_im(next_eip); |
|
2250 tcg_gen_br(l2); |
|
2251 |
|
2252 gen_set_label(l1); |
|
2253 gen_jmp_im(val); |
|
2254 gen_set_label(l2); |
|
2255 gen_eob(s); |
|
2256 } |
|
2257 } |
|
2258 |
|
2259 static void gen_setcc(DisasContext *s, int b) |
|
2260 { |
|
2261 int inv, jcc_op, l1; |
|
2262 TCGv t0; |
|
2263 |
|
2264 if (is_fast_jcc_case(s, b)) { |
|
2265 /* nominal case: we use a jump */ |
|
2266 /* XXX: make it faster by adding new instructions in TCG */ |
|
2267 t0 = tcg_temp_local_new(); |
|
2268 tcg_gen_movi_tl(t0, 0); |
|
2269 l1 = gen_new_label(); |
|
2270 gen_jcc1(s, s->cc_op, b ^ 1, l1); |
|
2271 tcg_gen_movi_tl(t0, 1); |
|
2272 gen_set_label(l1); |
|
2273 tcg_gen_mov_tl(cpu_T[0], t0); |
|
2274 tcg_temp_free(t0); |
|
2275 } else { |
|
2276 /* slow case: it is more efficient not to generate a jump, |
|
2277 although it is questionnable whether this optimization is |
|
2278 worth to */ |
|
2279 inv = b & 1; |
|
2280 jcc_op = (b >> 1) & 7; |
|
2281 gen_setcc_slow_T0(s, jcc_op); |
|
2282 if (inv) { |
|
2283 tcg_gen_xori_tl(cpu_T[0], cpu_T[0], 1); |
|
2284 } |
|
2285 } |
|
2286 } |
|
2287 |
|
2288 static inline void gen_op_movl_T0_seg(int seg_reg) |
|
2289 { |
|
2290 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, |
|
2291 offsetof(CPUX86State,segs[seg_reg].selector)); |
|
2292 } |
|
2293 |
|
2294 static inline void gen_op_movl_seg_T0_vm(int seg_reg) |
|
2295 { |
|
2296 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xffff); |
|
2297 tcg_gen_st32_tl(cpu_T[0], cpu_env, |
|
2298 offsetof(CPUX86State,segs[seg_reg].selector)); |
|
2299 tcg_gen_shli_tl(cpu_T[0], cpu_T[0], 4); |
|
2300 tcg_gen_st_tl(cpu_T[0], cpu_env, |
|
2301 offsetof(CPUX86State,segs[seg_reg].base)); |
|
2302 } |
|
2303 |
|
2304 /* move T0 to seg_reg and compute if the CPU state may change. Never |
|
2305 call this function with seg_reg == R_CS */ |
|
2306 static void gen_movl_seg_T0(DisasContext *s, int seg_reg, target_ulong cur_eip) |
|
2307 { |
|
2308 if (s->pe && !s->vm86) { |
|
2309 /* XXX: optimize by finding processor state dynamically */ |
|
2310 if (s->cc_op != CC_OP_DYNAMIC) |
|
2311 gen_op_set_cc_op(s->cc_op); |
|
2312 gen_jmp_im(cur_eip); |
|
2313 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); |
|
2314 gen_helper_load_seg(tcg_const_i32(seg_reg), cpu_tmp2_i32); |
|
2315 /* abort translation because the addseg value may change or |
|
2316 because ss32 may change. For R_SS, translation must always |
|
2317 stop as a special handling must be done to disable hardware |
|
2318 interrupts for the next instruction */ |
|
2319 if (seg_reg == R_SS || (s->code32 && seg_reg < R_FS)) |
|
2320 s->is_jmp = 3; |
|
2321 } else { |
|
2322 gen_op_movl_seg_T0_vm(seg_reg); |
|
2323 if (seg_reg == R_SS) |
|
2324 s->is_jmp = 3; |
|
2325 } |
|
2326 } |
|
2327 |
|
2328 static inline int svm_is_rep(int prefixes) |
|
2329 { |
|
2330 return ((prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) ? 8 : 0); |
|
2331 } |
|
2332 |
|
2333 static inline void |
|
2334 gen_svm_check_intercept_param(DisasContext *s, target_ulong pc_start, |
|
2335 uint32_t type, uint64_t param) |
|
2336 { |
|
2337 /* no SVM activated; fast case */ |
|
2338 if (likely(!(s->flags & HF_SVMI_MASK))) |
|
2339 return; |
|
2340 if (s->cc_op != CC_OP_DYNAMIC) |
|
2341 gen_op_set_cc_op(s->cc_op); |
|
2342 gen_jmp_im(pc_start - s->cs_base); |
|
2343 gen_helper_svm_check_intercept_param(tcg_const_i32(type), |
|
2344 tcg_const_i64(param)); |
|
2345 } |
|
2346 |
|
2347 static inline void |
|
2348 gen_svm_check_intercept(DisasContext *s, target_ulong pc_start, uint64_t type) |
|
2349 { |
|
2350 gen_svm_check_intercept_param(s, pc_start, type, 0); |
|
2351 } |
|
2352 |
|
2353 static inline void gen_stack_update(DisasContext *s, int addend) |
|
2354 { |
|
2355 #ifdef TARGET_X86_64 |
|
2356 if (CODE64(s)) { |
|
2357 gen_op_add_reg_im(2, R_ESP, addend); |
|
2358 } else |
|
2359 #endif |
|
2360 if (s->ss32) { |
|
2361 gen_op_add_reg_im(1, R_ESP, addend); |
|
2362 } else { |
|
2363 gen_op_add_reg_im(0, R_ESP, addend); |
|
2364 } |
|
2365 } |
|
2366 |
|
2367 /* generate a push. It depends on ss32, addseg and dflag */ |
|
2368 static void gen_push_T0(DisasContext *s) |
|
2369 { |
|
2370 #ifdef TARGET_X86_64 |
|
2371 if (CODE64(s)) { |
|
2372 gen_op_movq_A0_reg(R_ESP); |
|
2373 if (s->dflag) { |
|
2374 gen_op_addq_A0_im(-8); |
|
2375 gen_op_st_T0_A0(OT_QUAD + s->mem_index); |
|
2376 } else { |
|
2377 gen_op_addq_A0_im(-2); |
|
2378 gen_op_st_T0_A0(OT_WORD + s->mem_index); |
|
2379 } |
|
2380 gen_op_mov_reg_A0(2, R_ESP); |
|
2381 } else |
|
2382 #endif |
|
2383 { |
|
2384 gen_op_movl_A0_reg(R_ESP); |
|
2385 if (!s->dflag) |
|
2386 gen_op_addl_A0_im(-2); |
|
2387 else |
|
2388 gen_op_addl_A0_im(-4); |
|
2389 if (s->ss32) { |
|
2390 if (s->addseg) { |
|
2391 tcg_gen_mov_tl(cpu_T[1], cpu_A0); |
|
2392 gen_op_addl_A0_seg(R_SS); |
|
2393 } |
|
2394 } else { |
|
2395 gen_op_andl_A0_ffff(); |
|
2396 tcg_gen_mov_tl(cpu_T[1], cpu_A0); |
|
2397 gen_op_addl_A0_seg(R_SS); |
|
2398 } |
|
2399 gen_op_st_T0_A0(s->dflag + 1 + s->mem_index); |
|
2400 if (s->ss32 && !s->addseg) |
|
2401 gen_op_mov_reg_A0(1, R_ESP); |
|
2402 else |
|
2403 gen_op_mov_reg_T1(s->ss32 + 1, R_ESP); |
|
2404 } |
|
2405 } |
|
2406 |
|
2407 /* generate a push. It depends on ss32, addseg and dflag */ |
|
2408 /* slower version for T1, only used for call Ev */ |
|
2409 static void gen_push_T1(DisasContext *s) |
|
2410 { |
|
2411 #ifdef TARGET_X86_64 |
|
2412 if (CODE64(s)) { |
|
2413 gen_op_movq_A0_reg(R_ESP); |
|
2414 if (s->dflag) { |
|
2415 gen_op_addq_A0_im(-8); |
|
2416 gen_op_st_T1_A0(OT_QUAD + s->mem_index); |
|
2417 } else { |
|
2418 gen_op_addq_A0_im(-2); |
|
2419 gen_op_st_T0_A0(OT_WORD + s->mem_index); |
|
2420 } |
|
2421 gen_op_mov_reg_A0(2, R_ESP); |
|
2422 } else |
|
2423 #endif |
|
2424 { |
|
2425 gen_op_movl_A0_reg(R_ESP); |
|
2426 if (!s->dflag) |
|
2427 gen_op_addl_A0_im(-2); |
|
2428 else |
|
2429 gen_op_addl_A0_im(-4); |
|
2430 if (s->ss32) { |
|
2431 if (s->addseg) { |
|
2432 gen_op_addl_A0_seg(R_SS); |
|
2433 } |
|
2434 } else { |
|
2435 gen_op_andl_A0_ffff(); |
|
2436 gen_op_addl_A0_seg(R_SS); |
|
2437 } |
|
2438 gen_op_st_T1_A0(s->dflag + 1 + s->mem_index); |
|
2439 |
|
2440 if (s->ss32 && !s->addseg) |
|
2441 gen_op_mov_reg_A0(1, R_ESP); |
|
2442 else |
|
2443 gen_stack_update(s, (-2) << s->dflag); |
|
2444 } |
|
2445 } |
|
2446 |
|
2447 /* two step pop is necessary for precise exceptions */ |
|
2448 static void gen_pop_T0(DisasContext *s) |
|
2449 { |
|
2450 #ifdef TARGET_X86_64 |
|
2451 if (CODE64(s)) { |
|
2452 gen_op_movq_A0_reg(R_ESP); |
|
2453 gen_op_ld_T0_A0((s->dflag ? OT_QUAD : OT_WORD) + s->mem_index); |
|
2454 } else |
|
2455 #endif |
|
2456 { |
|
2457 gen_op_movl_A0_reg(R_ESP); |
|
2458 if (s->ss32) { |
|
2459 if (s->addseg) |
|
2460 gen_op_addl_A0_seg(R_SS); |
|
2461 } else { |
|
2462 gen_op_andl_A0_ffff(); |
|
2463 gen_op_addl_A0_seg(R_SS); |
|
2464 } |
|
2465 gen_op_ld_T0_A0(s->dflag + 1 + s->mem_index); |
|
2466 } |
|
2467 } |
|
2468 |
|
2469 static void gen_pop_update(DisasContext *s) |
|
2470 { |
|
2471 #ifdef TARGET_X86_64 |
|
2472 if (CODE64(s) && s->dflag) { |
|
2473 gen_stack_update(s, 8); |
|
2474 } else |
|
2475 #endif |
|
2476 { |
|
2477 gen_stack_update(s, 2 << s->dflag); |
|
2478 } |
|
2479 } |
|
2480 |
|
2481 static void gen_stack_A0(DisasContext *s) |
|
2482 { |
|
2483 gen_op_movl_A0_reg(R_ESP); |
|
2484 if (!s->ss32) |
|
2485 gen_op_andl_A0_ffff(); |
|
2486 tcg_gen_mov_tl(cpu_T[1], cpu_A0); |
|
2487 if (s->addseg) |
|
2488 gen_op_addl_A0_seg(R_SS); |
|
2489 } |
|
2490 |
|
2491 /* NOTE: wrap around in 16 bit not fully handled */ |
|
2492 static void gen_pusha(DisasContext *s) |
|
2493 { |
|
2494 int i; |
|
2495 gen_op_movl_A0_reg(R_ESP); |
|
2496 gen_op_addl_A0_im(-16 << s->dflag); |
|
2497 if (!s->ss32) |
|
2498 gen_op_andl_A0_ffff(); |
|
2499 tcg_gen_mov_tl(cpu_T[1], cpu_A0); |
|
2500 if (s->addseg) |
|
2501 gen_op_addl_A0_seg(R_SS); |
|
2502 for(i = 0;i < 8; i++) { |
|
2503 gen_op_mov_TN_reg(OT_LONG, 0, 7 - i); |
|
2504 gen_op_st_T0_A0(OT_WORD + s->dflag + s->mem_index); |
|
2505 gen_op_addl_A0_im(2 << s->dflag); |
|
2506 } |
|
2507 gen_op_mov_reg_T1(OT_WORD + s->ss32, R_ESP); |
|
2508 } |
|
2509 |
|
2510 /* NOTE: wrap around in 16 bit not fully handled */ |
|
2511 static void gen_popa(DisasContext *s) |
|
2512 { |
|
2513 int i; |
|
2514 gen_op_movl_A0_reg(R_ESP); |
|
2515 if (!s->ss32) |
|
2516 gen_op_andl_A0_ffff(); |
|
2517 tcg_gen_mov_tl(cpu_T[1], cpu_A0); |
|
2518 tcg_gen_addi_tl(cpu_T[1], cpu_T[1], 16 << s->dflag); |
|
2519 if (s->addseg) |
|
2520 gen_op_addl_A0_seg(R_SS); |
|
2521 for(i = 0;i < 8; i++) { |
|
2522 /* ESP is not reloaded */ |
|
2523 if (i != 3) { |
|
2524 gen_op_ld_T0_A0(OT_WORD + s->dflag + s->mem_index); |
|
2525 gen_op_mov_reg_T0(OT_WORD + s->dflag, 7 - i); |
|
2526 } |
|
2527 gen_op_addl_A0_im(2 << s->dflag); |
|
2528 } |
|
2529 gen_op_mov_reg_T1(OT_WORD + s->ss32, R_ESP); |
|
2530 } |
|
2531 |
|
2532 static void gen_enter(DisasContext *s, int esp_addend, int level) |
|
2533 { |
|
2534 int ot, opsize; |
|
2535 |
|
2536 level &= 0x1f; |
|
2537 #ifdef TARGET_X86_64 |
|
2538 if (CODE64(s)) { |
|
2539 ot = s->dflag ? OT_QUAD : OT_WORD; |
|
2540 opsize = 1 << ot; |
|
2541 |
|
2542 gen_op_movl_A0_reg(R_ESP); |
|
2543 gen_op_addq_A0_im(-opsize); |
|
2544 tcg_gen_mov_tl(cpu_T[1], cpu_A0); |
|
2545 |
|
2546 /* push bp */ |
|
2547 gen_op_mov_TN_reg(OT_LONG, 0, R_EBP); |
|
2548 gen_op_st_T0_A0(ot + s->mem_index); |
|
2549 if (level) { |
|
2550 /* XXX: must save state */ |
|
2551 gen_helper_enter64_level(tcg_const_i32(level), |
|
2552 tcg_const_i32((ot == OT_QUAD)), |
|
2553 cpu_T[1]); |
|
2554 } |
|
2555 gen_op_mov_reg_T1(ot, R_EBP); |
|
2556 tcg_gen_addi_tl(cpu_T[1], cpu_T[1], -esp_addend + (-opsize * level)); |
|
2557 gen_op_mov_reg_T1(OT_QUAD, R_ESP); |
|
2558 } else |
|
2559 #endif |
|
2560 { |
|
2561 ot = s->dflag + OT_WORD; |
|
2562 opsize = 2 << s->dflag; |
|
2563 |
|
2564 gen_op_movl_A0_reg(R_ESP); |
|
2565 gen_op_addl_A0_im(-opsize); |
|
2566 if (!s->ss32) |
|
2567 gen_op_andl_A0_ffff(); |
|
2568 tcg_gen_mov_tl(cpu_T[1], cpu_A0); |
|
2569 if (s->addseg) |
|
2570 gen_op_addl_A0_seg(R_SS); |
|
2571 /* push bp */ |
|
2572 gen_op_mov_TN_reg(OT_LONG, 0, R_EBP); |
|
2573 gen_op_st_T0_A0(ot + s->mem_index); |
|
2574 if (level) { |
|
2575 /* XXX: must save state */ |
|
2576 gen_helper_enter_level(tcg_const_i32(level), |
|
2577 tcg_const_i32(s->dflag), |
|
2578 cpu_T[1]); |
|
2579 } |
|
2580 gen_op_mov_reg_T1(ot, R_EBP); |
|
2581 tcg_gen_addi_tl(cpu_T[1], cpu_T[1], -esp_addend + (-opsize * level)); |
|
2582 gen_op_mov_reg_T1(OT_WORD + s->ss32, R_ESP); |
|
2583 } |
|
2584 } |
|
2585 |
|
2586 static void gen_exception(DisasContext *s, int trapno, target_ulong cur_eip) |
|
2587 { |
|
2588 if (s->cc_op != CC_OP_DYNAMIC) |
|
2589 gen_op_set_cc_op(s->cc_op); |
|
2590 gen_jmp_im(cur_eip); |
|
2591 gen_helper_raise_exception(tcg_const_i32(trapno)); |
|
2592 s->is_jmp = 3; |
|
2593 } |
|
2594 |
|
2595 /* an interrupt is different from an exception because of the |
|
2596 privilege checks */ |
|
2597 static void gen_interrupt(DisasContext *s, int intno, |
|
2598 target_ulong cur_eip, target_ulong next_eip) |
|
2599 { |
|
2600 if (s->cc_op != CC_OP_DYNAMIC) |
|
2601 gen_op_set_cc_op(s->cc_op); |
|
2602 gen_jmp_im(cur_eip); |
|
2603 gen_helper_raise_interrupt(tcg_const_i32(intno), |
|
2604 tcg_const_i32(next_eip - cur_eip)); |
|
2605 s->is_jmp = 3; |
|
2606 } |
|
2607 |
|
2608 static void gen_debug(DisasContext *s, target_ulong cur_eip) |
|
2609 { |
|
2610 if (s->cc_op != CC_OP_DYNAMIC) |
|
2611 gen_op_set_cc_op(s->cc_op); |
|
2612 gen_jmp_im(cur_eip); |
|
2613 gen_helper_debug(); |
|
2614 s->is_jmp = 3; |
|
2615 } |
|
2616 |
|
2617 /* generate a generic end of block. Trace exception is also generated |
|
2618 if needed */ |
|
2619 static void gen_eob(DisasContext *s) |
|
2620 { |
|
2621 if (s->cc_op != CC_OP_DYNAMIC) |
|
2622 gen_op_set_cc_op(s->cc_op); |
|
2623 if (s->tb->flags & HF_INHIBIT_IRQ_MASK) { |
|
2624 gen_helper_reset_inhibit_irq(); |
|
2625 } |
|
2626 if (s->singlestep_enabled) { |
|
2627 gen_helper_debug(); |
|
2628 } else if (s->tf) { |
|
2629 gen_helper_single_step(); |
|
2630 } else { |
|
2631 tcg_gen_exit_tb(0); |
|
2632 } |
|
2633 s->is_jmp = 3; |
|
2634 } |
|
2635 |
|
2636 /* generate a jump to eip. No segment change must happen before as a |
|
2637 direct call to the next block may occur */ |
|
2638 static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num) |
|
2639 { |
|
2640 if (s->jmp_opt) { |
|
2641 if (s->cc_op != CC_OP_DYNAMIC) { |
|
2642 gen_op_set_cc_op(s->cc_op); |
|
2643 s->cc_op = CC_OP_DYNAMIC; |
|
2644 } |
|
2645 gen_goto_tb(s, tb_num, eip); |
|
2646 s->is_jmp = 3; |
|
2647 } else { |
|
2648 gen_jmp_im(eip); |
|
2649 gen_eob(s); |
|
2650 } |
|
2651 } |
|
2652 |
|
2653 static void gen_jmp(DisasContext *s, target_ulong eip) |
|
2654 { |
|
2655 gen_jmp_tb(s, eip, 0); |
|
2656 } |
|
2657 |
|
2658 static inline void gen_ldq_env_A0(int idx, int offset) |
|
2659 { |
|
2660 int mem_index = (idx >> 2) - 1; |
|
2661 tcg_gen_qemu_ld64(cpu_tmp1_i64, cpu_A0, mem_index); |
|
2662 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, offset); |
|
2663 } |
|
2664 |
|
2665 static inline void gen_stq_env_A0(int idx, int offset) |
|
2666 { |
|
2667 int mem_index = (idx >> 2) - 1; |
|
2668 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, offset); |
|
2669 tcg_gen_qemu_st64(cpu_tmp1_i64, cpu_A0, mem_index); |
|
2670 } |
|
2671 |
|
2672 static inline void gen_ldo_env_A0(int idx, int offset) |
|
2673 { |
|
2674 int mem_index = (idx >> 2) - 1; |
|
2675 tcg_gen_qemu_ld64(cpu_tmp1_i64, cpu_A0, mem_index); |
|
2676 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, offset + offsetof(XMMReg, XMM_Q(0))); |
|
2677 tcg_gen_addi_tl(cpu_tmp0, cpu_A0, 8); |
|
2678 tcg_gen_qemu_ld64(cpu_tmp1_i64, cpu_tmp0, mem_index); |
|
2679 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, offset + offsetof(XMMReg, XMM_Q(1))); |
|
2680 } |
|
2681 |
|
2682 static inline void gen_sto_env_A0(int idx, int offset) |
|
2683 { |
|
2684 int mem_index = (idx >> 2) - 1; |
|
2685 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, offset + offsetof(XMMReg, XMM_Q(0))); |
|
2686 tcg_gen_qemu_st64(cpu_tmp1_i64, cpu_A0, mem_index); |
|
2687 tcg_gen_addi_tl(cpu_tmp0, cpu_A0, 8); |
|
2688 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, offset + offsetof(XMMReg, XMM_Q(1))); |
|
2689 tcg_gen_qemu_st64(cpu_tmp1_i64, cpu_tmp0, mem_index); |
|
2690 } |
|
2691 |
|
2692 static inline void gen_op_movo(int d_offset, int s_offset) |
|
2693 { |
|
2694 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, s_offset); |
|
2695 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset); |
|
2696 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, s_offset + 8); |
|
2697 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset + 8); |
|
2698 } |
|
2699 |
|
2700 static inline void gen_op_movq(int d_offset, int s_offset) |
|
2701 { |
|
2702 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, s_offset); |
|
2703 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset); |
|
2704 } |
|
2705 |
|
2706 static inline void gen_op_movl(int d_offset, int s_offset) |
|
2707 { |
|
2708 tcg_gen_ld_i32(cpu_tmp2_i32, cpu_env, s_offset); |
|
2709 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, d_offset); |
|
2710 } |
|
2711 |
|
2712 static inline void gen_op_movq_env_0(int d_offset) |
|
2713 { |
|
2714 tcg_gen_movi_i64(cpu_tmp1_i64, 0); |
|
2715 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset); |
|
2716 } |
|
2717 |
|
2718 #define SSE_SPECIAL ((void *)1) |
|
2719 #define SSE_DUMMY ((void *)2) |
|
2720 |
|
2721 #define MMX_OP2(x) { gen_helper_ ## x ## _mmx, gen_helper_ ## x ## _xmm } |
|
2722 #define SSE_FOP(x) { gen_helper_ ## x ## ps, gen_helper_ ## x ## pd, \ |
|
2723 gen_helper_ ## x ## ss, gen_helper_ ## x ## sd, } |
|
2724 |
|
2725 static void *sse_op_table1[256][4] = { |
|
2726 /* 3DNow! extensions */ |
|
2727 [0x0e] = { SSE_DUMMY }, /* femms */ |
|
2728 [0x0f] = { SSE_DUMMY }, /* pf... */ |
|
2729 /* pure SSE operations */ |
|
2730 [0x10] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movups, movupd, movss, movsd */ |
|
2731 [0x11] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movups, movupd, movss, movsd */ |
|
2732 [0x12] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movlps, movlpd, movsldup, movddup */ |
|
2733 [0x13] = { SSE_SPECIAL, SSE_SPECIAL }, /* movlps, movlpd */ |
|
2734 [0x14] = { gen_helper_punpckldq_xmm, gen_helper_punpcklqdq_xmm }, |
|
2735 [0x15] = { gen_helper_punpckhdq_xmm, gen_helper_punpckhqdq_xmm }, |
|
2736 [0x16] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movhps, movhpd, movshdup */ |
|
2737 [0x17] = { SSE_SPECIAL, SSE_SPECIAL }, /* movhps, movhpd */ |
|
2738 |
|
2739 [0x28] = { SSE_SPECIAL, SSE_SPECIAL }, /* movaps, movapd */ |
|
2740 [0x29] = { SSE_SPECIAL, SSE_SPECIAL }, /* movaps, movapd */ |
|
2741 [0x2a] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvtpi2ps, cvtpi2pd, cvtsi2ss, cvtsi2sd */ |
|
2742 [0x2b] = { SSE_SPECIAL, SSE_SPECIAL }, /* movntps, movntpd */ |
|
2743 [0x2c] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvttps2pi, cvttpd2pi, cvttsd2si, cvttss2si */ |
|
2744 [0x2d] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvtps2pi, cvtpd2pi, cvtsd2si, cvtss2si */ |
|
2745 [0x2e] = { gen_helper_ucomiss, gen_helper_ucomisd }, |
|
2746 [0x2f] = { gen_helper_comiss, gen_helper_comisd }, |
|
2747 [0x50] = { SSE_SPECIAL, SSE_SPECIAL }, /* movmskps, movmskpd */ |
|
2748 [0x51] = SSE_FOP(sqrt), |
|
2749 [0x52] = { gen_helper_rsqrtps, NULL, gen_helper_rsqrtss, NULL }, |
|
2750 [0x53] = { gen_helper_rcpps, NULL, gen_helper_rcpss, NULL }, |
|
2751 [0x54] = { gen_helper_pand_xmm, gen_helper_pand_xmm }, /* andps, andpd */ |
|
2752 [0x55] = { gen_helper_pandn_xmm, gen_helper_pandn_xmm }, /* andnps, andnpd */ |
|
2753 [0x56] = { gen_helper_por_xmm, gen_helper_por_xmm }, /* orps, orpd */ |
|
2754 [0x57] = { gen_helper_pxor_xmm, gen_helper_pxor_xmm }, /* xorps, xorpd */ |
|
2755 [0x58] = SSE_FOP(add), |
|
2756 [0x59] = SSE_FOP(mul), |
|
2757 [0x5a] = { gen_helper_cvtps2pd, gen_helper_cvtpd2ps, |
|
2758 gen_helper_cvtss2sd, gen_helper_cvtsd2ss }, |
|
2759 [0x5b] = { gen_helper_cvtdq2ps, gen_helper_cvtps2dq, gen_helper_cvttps2dq }, |
|
2760 [0x5c] = SSE_FOP(sub), |
|
2761 [0x5d] = SSE_FOP(min), |
|
2762 [0x5e] = SSE_FOP(div), |
|
2763 [0x5f] = SSE_FOP(max), |
|
2764 |
|
2765 [0xc2] = SSE_FOP(cmpeq), |
|
2766 [0xc6] = { gen_helper_shufps, gen_helper_shufpd }, |
|
2767 |
|
2768 [0x38] = { SSE_SPECIAL, SSE_SPECIAL, NULL, SSE_SPECIAL }, /* SSSE3/SSE4 */ |
|
2769 [0x3a] = { SSE_SPECIAL, SSE_SPECIAL }, /* SSSE3/SSE4 */ |
|
2770 |
|
2771 /* MMX ops and their SSE extensions */ |
|
2772 [0x60] = MMX_OP2(punpcklbw), |
|
2773 [0x61] = MMX_OP2(punpcklwd), |
|
2774 [0x62] = MMX_OP2(punpckldq), |
|
2775 [0x63] = MMX_OP2(packsswb), |
|
2776 [0x64] = MMX_OP2(pcmpgtb), |
|
2777 [0x65] = MMX_OP2(pcmpgtw), |
|
2778 [0x66] = MMX_OP2(pcmpgtl), |
|
2779 [0x67] = MMX_OP2(packuswb), |
|
2780 [0x68] = MMX_OP2(punpckhbw), |
|
2781 [0x69] = MMX_OP2(punpckhwd), |
|
2782 [0x6a] = MMX_OP2(punpckhdq), |
|
2783 [0x6b] = MMX_OP2(packssdw), |
|
2784 [0x6c] = { NULL, gen_helper_punpcklqdq_xmm }, |
|
2785 [0x6d] = { NULL, gen_helper_punpckhqdq_xmm }, |
|
2786 [0x6e] = { SSE_SPECIAL, SSE_SPECIAL }, /* movd mm, ea */ |
|
2787 [0x6f] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movq, movdqa, , movqdu */ |
|
2788 [0x70] = { gen_helper_pshufw_mmx, |
|
2789 gen_helper_pshufd_xmm, |
|
2790 gen_helper_pshufhw_xmm, |
|
2791 gen_helper_pshuflw_xmm }, |
|
2792 [0x71] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftw */ |
|
2793 [0x72] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftd */ |
|
2794 [0x73] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftq */ |
|
2795 [0x74] = MMX_OP2(pcmpeqb), |
|
2796 [0x75] = MMX_OP2(pcmpeqw), |
|
2797 [0x76] = MMX_OP2(pcmpeql), |
|
2798 [0x77] = { SSE_DUMMY }, /* emms */ |
|
2799 [0x7c] = { NULL, gen_helper_haddpd, NULL, gen_helper_haddps }, |
|
2800 [0x7d] = { NULL, gen_helper_hsubpd, NULL, gen_helper_hsubps }, |
|
2801 [0x7e] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movd, movd, , movq */ |
|
2802 [0x7f] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movq, movdqa, movdqu */ |
|
2803 [0xc4] = { SSE_SPECIAL, SSE_SPECIAL }, /* pinsrw */ |
|
2804 [0xc5] = { SSE_SPECIAL, SSE_SPECIAL }, /* pextrw */ |
|
2805 [0xd0] = { NULL, gen_helper_addsubpd, NULL, gen_helper_addsubps }, |
|
2806 [0xd1] = MMX_OP2(psrlw), |
|
2807 [0xd2] = MMX_OP2(psrld), |
|
2808 [0xd3] = MMX_OP2(psrlq), |
|
2809 [0xd4] = MMX_OP2(paddq), |
|
2810 [0xd5] = MMX_OP2(pmullw), |
|
2811 [0xd6] = { NULL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, |
|
2812 [0xd7] = { SSE_SPECIAL, SSE_SPECIAL }, /* pmovmskb */ |
|
2813 [0xd8] = MMX_OP2(psubusb), |
|
2814 [0xd9] = MMX_OP2(psubusw), |
|
2815 [0xda] = MMX_OP2(pminub), |
|
2816 [0xdb] = MMX_OP2(pand), |
|
2817 [0xdc] = MMX_OP2(paddusb), |
|
2818 [0xdd] = MMX_OP2(paddusw), |
|
2819 [0xde] = MMX_OP2(pmaxub), |
|
2820 [0xdf] = MMX_OP2(pandn), |
|
2821 [0xe0] = MMX_OP2(pavgb), |
|
2822 [0xe1] = MMX_OP2(psraw), |
|
2823 [0xe2] = MMX_OP2(psrad), |
|
2824 [0xe3] = MMX_OP2(pavgw), |
|
2825 [0xe4] = MMX_OP2(pmulhuw), |
|
2826 [0xe5] = MMX_OP2(pmulhw), |
|
2827 [0xe6] = { NULL, gen_helper_cvttpd2dq, gen_helper_cvtdq2pd, gen_helper_cvtpd2dq }, |
|
2828 [0xe7] = { SSE_SPECIAL , SSE_SPECIAL }, /* movntq, movntq */ |
|
2829 [0xe8] = MMX_OP2(psubsb), |
|
2830 [0xe9] = MMX_OP2(psubsw), |
|
2831 [0xea] = MMX_OP2(pminsw), |
|
2832 [0xeb] = MMX_OP2(por), |
|
2833 [0xec] = MMX_OP2(paddsb), |
|
2834 [0xed] = MMX_OP2(paddsw), |
|
2835 [0xee] = MMX_OP2(pmaxsw), |
|
2836 [0xef] = MMX_OP2(pxor), |
|
2837 [0xf0] = { NULL, NULL, NULL, SSE_SPECIAL }, /* lddqu */ |
|
2838 [0xf1] = MMX_OP2(psllw), |
|
2839 [0xf2] = MMX_OP2(pslld), |
|
2840 [0xf3] = MMX_OP2(psllq), |
|
2841 [0xf4] = MMX_OP2(pmuludq), |
|
2842 [0xf5] = MMX_OP2(pmaddwd), |
|
2843 [0xf6] = MMX_OP2(psadbw), |
|
2844 [0xf7] = MMX_OP2(maskmov), |
|
2845 [0xf8] = MMX_OP2(psubb), |
|
2846 [0xf9] = MMX_OP2(psubw), |
|
2847 [0xfa] = MMX_OP2(psubl), |
|
2848 [0xfb] = MMX_OP2(psubq), |
|
2849 [0xfc] = MMX_OP2(paddb), |
|
2850 [0xfd] = MMX_OP2(paddw), |
|
2851 [0xfe] = MMX_OP2(paddl), |
|
2852 }; |
|
2853 |
|
2854 static void *sse_op_table2[3 * 8][2] = { |
|
2855 [0 + 2] = MMX_OP2(psrlw), |
|
2856 [0 + 4] = MMX_OP2(psraw), |
|
2857 [0 + 6] = MMX_OP2(psllw), |
|
2858 [8 + 2] = MMX_OP2(psrld), |
|
2859 [8 + 4] = MMX_OP2(psrad), |
|
2860 [8 + 6] = MMX_OP2(pslld), |
|
2861 [16 + 2] = MMX_OP2(psrlq), |
|
2862 [16 + 3] = { NULL, gen_helper_psrldq_xmm }, |
|
2863 [16 + 6] = MMX_OP2(psllq), |
|
2864 [16 + 7] = { NULL, gen_helper_pslldq_xmm }, |
|
2865 }; |
|
2866 |
|
2867 static void *sse_op_table3[4 * 3] = { |
|
2868 gen_helper_cvtsi2ss, |
|
2869 gen_helper_cvtsi2sd, |
|
2870 X86_64_ONLY(gen_helper_cvtsq2ss), |
|
2871 X86_64_ONLY(gen_helper_cvtsq2sd), |
|
2872 |
|
2873 gen_helper_cvttss2si, |
|
2874 gen_helper_cvttsd2si, |
|
2875 X86_64_ONLY(gen_helper_cvttss2sq), |
|
2876 X86_64_ONLY(gen_helper_cvttsd2sq), |
|
2877 |
|
2878 gen_helper_cvtss2si, |
|
2879 gen_helper_cvtsd2si, |
|
2880 X86_64_ONLY(gen_helper_cvtss2sq), |
|
2881 X86_64_ONLY(gen_helper_cvtsd2sq), |
|
2882 }; |
|
2883 |
|
2884 static void *sse_op_table4[8][4] = { |
|
2885 SSE_FOP(cmpeq), |
|
2886 SSE_FOP(cmplt), |
|
2887 SSE_FOP(cmple), |
|
2888 SSE_FOP(cmpunord), |
|
2889 SSE_FOP(cmpneq), |
|
2890 SSE_FOP(cmpnlt), |
|
2891 SSE_FOP(cmpnle), |
|
2892 SSE_FOP(cmpord), |
|
2893 }; |
|
2894 |
|
2895 static void *sse_op_table5[256] = { |
|
2896 [0x0c] = gen_helper_pi2fw, |
|
2897 [0x0d] = gen_helper_pi2fd, |
|
2898 [0x1c] = gen_helper_pf2iw, |
|
2899 [0x1d] = gen_helper_pf2id, |
|
2900 [0x8a] = gen_helper_pfnacc, |
|
2901 [0x8e] = gen_helper_pfpnacc, |
|
2902 [0x90] = gen_helper_pfcmpge, |
|
2903 [0x94] = gen_helper_pfmin, |
|
2904 [0x96] = gen_helper_pfrcp, |
|
2905 [0x97] = gen_helper_pfrsqrt, |
|
2906 [0x9a] = gen_helper_pfsub, |
|
2907 [0x9e] = gen_helper_pfadd, |
|
2908 [0xa0] = gen_helper_pfcmpgt, |
|
2909 [0xa4] = gen_helper_pfmax, |
|
2910 [0xa6] = gen_helper_movq, /* pfrcpit1; no need to actually increase precision */ |
|
2911 [0xa7] = gen_helper_movq, /* pfrsqit1 */ |
|
2912 [0xaa] = gen_helper_pfsubr, |
|
2913 [0xae] = gen_helper_pfacc, |
|
2914 [0xb0] = gen_helper_pfcmpeq, |
|
2915 [0xb4] = gen_helper_pfmul, |
|
2916 [0xb6] = gen_helper_movq, /* pfrcpit2 */ |
|
2917 [0xb7] = gen_helper_pmulhrw_mmx, |
|
2918 [0xbb] = gen_helper_pswapd, |
|
2919 [0xbf] = gen_helper_pavgb_mmx /* pavgusb */ |
|
2920 }; |
|
2921 |
|
2922 struct sse_op_helper_s { |
|
2923 void *op[2]; uint32_t ext_mask; |
|
2924 }; |
|
2925 #define SSSE3_OP(x) { MMX_OP2(x), CPUID_EXT_SSSE3 } |
|
2926 #define SSE41_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, CPUID_EXT_SSE41 } |
|
2927 #define SSE42_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, CPUID_EXT_SSE42 } |
|
2928 #define SSE41_SPECIAL { { NULL, SSE_SPECIAL }, CPUID_EXT_SSE41 } |
|
2929 static struct sse_op_helper_s sse_op_table6[256] = { |
|
2930 [0x00] = SSSE3_OP(pshufb), |
|
2931 [0x01] = SSSE3_OP(phaddw), |
|
2932 [0x02] = SSSE3_OP(phaddd), |
|
2933 [0x03] = SSSE3_OP(phaddsw), |
|
2934 [0x04] = SSSE3_OP(pmaddubsw), |
|
2935 [0x05] = SSSE3_OP(phsubw), |
|
2936 [0x06] = SSSE3_OP(phsubd), |
|
2937 [0x07] = SSSE3_OP(phsubsw), |
|
2938 [0x08] = SSSE3_OP(psignb), |
|
2939 [0x09] = SSSE3_OP(psignw), |
|
2940 [0x0a] = SSSE3_OP(psignd), |
|
2941 [0x0b] = SSSE3_OP(pmulhrsw), |
|
2942 [0x10] = SSE41_OP(pblendvb), |
|
2943 [0x14] = SSE41_OP(blendvps), |
|
2944 [0x15] = SSE41_OP(blendvpd), |
|
2945 [0x17] = SSE41_OP(ptest), |
|
2946 [0x1c] = SSSE3_OP(pabsb), |
|
2947 [0x1d] = SSSE3_OP(pabsw), |
|
2948 [0x1e] = SSSE3_OP(pabsd), |
|
2949 [0x20] = SSE41_OP(pmovsxbw), |
|
2950 [0x21] = SSE41_OP(pmovsxbd), |
|
2951 [0x22] = SSE41_OP(pmovsxbq), |
|
2952 [0x23] = SSE41_OP(pmovsxwd), |
|
2953 [0x24] = SSE41_OP(pmovsxwq), |
|
2954 [0x25] = SSE41_OP(pmovsxdq), |
|
2955 [0x28] = SSE41_OP(pmuldq), |
|
2956 [0x29] = SSE41_OP(pcmpeqq), |
|
2957 [0x2a] = SSE41_SPECIAL, /* movntqda */ |
|
2958 [0x2b] = SSE41_OP(packusdw), |
|
2959 [0x30] = SSE41_OP(pmovzxbw), |
|
2960 [0x31] = SSE41_OP(pmovzxbd), |
|
2961 [0x32] = SSE41_OP(pmovzxbq), |
|
2962 [0x33] = SSE41_OP(pmovzxwd), |
|
2963 [0x34] = SSE41_OP(pmovzxwq), |
|
2964 [0x35] = SSE41_OP(pmovzxdq), |
|
2965 [0x37] = SSE42_OP(pcmpgtq), |
|
2966 [0x38] = SSE41_OP(pminsb), |
|
2967 [0x39] = SSE41_OP(pminsd), |
|
2968 [0x3a] = SSE41_OP(pminuw), |
|
2969 [0x3b] = SSE41_OP(pminud), |
|
2970 [0x3c] = SSE41_OP(pmaxsb), |
|
2971 [0x3d] = SSE41_OP(pmaxsd), |
|
2972 [0x3e] = SSE41_OP(pmaxuw), |
|
2973 [0x3f] = SSE41_OP(pmaxud), |
|
2974 [0x40] = SSE41_OP(pmulld), |
|
2975 [0x41] = SSE41_OP(phminposuw), |
|
2976 }; |
|
2977 |
|
2978 static struct sse_op_helper_s sse_op_table7[256] = { |
|
2979 [0x08] = SSE41_OP(roundps), |
|
2980 [0x09] = SSE41_OP(roundpd), |
|
2981 [0x0a] = SSE41_OP(roundss), |
|
2982 [0x0b] = SSE41_OP(roundsd), |
|
2983 [0x0c] = SSE41_OP(blendps), |
|
2984 [0x0d] = SSE41_OP(blendpd), |
|
2985 [0x0e] = SSE41_OP(pblendw), |
|
2986 [0x0f] = SSSE3_OP(palignr), |
|
2987 [0x14] = SSE41_SPECIAL, /* pextrb */ |
|
2988 [0x15] = SSE41_SPECIAL, /* pextrw */ |
|
2989 [0x16] = SSE41_SPECIAL, /* pextrd/pextrq */ |
|
2990 [0x17] = SSE41_SPECIAL, /* extractps */ |
|
2991 [0x20] = SSE41_SPECIAL, /* pinsrb */ |
|
2992 [0x21] = SSE41_SPECIAL, /* insertps */ |
|
2993 [0x22] = SSE41_SPECIAL, /* pinsrd/pinsrq */ |
|
2994 [0x40] = SSE41_OP(dpps), |
|
2995 [0x41] = SSE41_OP(dppd), |
|
2996 [0x42] = SSE41_OP(mpsadbw), |
|
2997 [0x60] = SSE42_OP(pcmpestrm), |
|
2998 [0x61] = SSE42_OP(pcmpestri), |
|
2999 [0x62] = SSE42_OP(pcmpistrm), |
|
3000 [0x63] = SSE42_OP(pcmpistri), |
|
3001 }; |
|
3002 |
|
3003 static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r) |
|
3004 { |
|
3005 int b1, op1_offset, op2_offset, is_xmm, val, ot; |
|
3006 int modrm, mod, rm, reg, reg_addr, offset_addr; |
|
3007 void *sse_op2; |
|
3008 |
|
3009 b &= 0xff; |
|
3010 if (s->prefix & PREFIX_DATA) |
|
3011 b1 = 1; |
|
3012 else if (s->prefix & PREFIX_REPZ) |
|
3013 b1 = 2; |
|
3014 else if (s->prefix & PREFIX_REPNZ) |
|
3015 b1 = 3; |
|
3016 else |
|
3017 b1 = 0; |
|
3018 sse_op2 = sse_op_table1[b][b1]; |
|
3019 if (!sse_op2) |
|
3020 goto illegal_op; |
|
3021 if ((b <= 0x5f && b >= 0x10) || b == 0xc6 || b == 0xc2) { |
|
3022 is_xmm = 1; |
|
3023 } else { |
|
3024 if (b1 == 0) { |
|
3025 /* MMX case */ |
|
3026 is_xmm = 0; |
|
3027 } else { |
|
3028 is_xmm = 1; |
|
3029 } |
|
3030 } |
|
3031 /* simple MMX/SSE operation */ |
|
3032 if (s->flags & HF_TS_MASK) { |
|
3033 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base); |
|
3034 return; |
|
3035 } |
|
3036 if (s->flags & HF_EM_MASK) { |
|
3037 illegal_op: |
|
3038 gen_exception(s, EXCP06_ILLOP, pc_start - s->cs_base); |
|
3039 return; |
|
3040 } |
|
3041 if (is_xmm && !(s->flags & HF_OSFXSR_MASK)) |
|
3042 if ((b != 0x38 && b != 0x3a) || (s->prefix & PREFIX_DATA)) |
|
3043 goto illegal_op; |
|
3044 if (b == 0x0e) { |
|
3045 if (!(s->cpuid_ext2_features & CPUID_EXT2_3DNOW)) |
|
3046 goto illegal_op; |
|
3047 /* femms */ |
|
3048 gen_helper_emms(); |
|
3049 return; |
|
3050 } |
|
3051 if (b == 0x77) { |
|
3052 /* emms */ |
|
3053 gen_helper_emms(); |
|
3054 return; |
|
3055 } |
|
3056 /* prepare MMX state (XXX: optimize by storing fptt and fptags in |
|
3057 the static cpu state) */ |
|
3058 if (!is_xmm) { |
|
3059 gen_helper_enter_mmx(); |
|
3060 } |
|
3061 |
|
3062 modrm = ldub_code(s->pc++); |
|
3063 reg = ((modrm >> 3) & 7); |
|
3064 if (is_xmm) |
|
3065 reg |= rex_r; |
|
3066 mod = (modrm >> 6) & 3; |
|
3067 if (sse_op2 == SSE_SPECIAL) { |
|
3068 b |= (b1 << 8); |
|
3069 switch(b) { |
|
3070 case 0x0e7: /* movntq */ |
|
3071 if (mod == 3) |
|
3072 goto illegal_op; |
|
3073 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
3074 gen_stq_env_A0(s->mem_index, offsetof(CPUX86State,fpregs[reg].mmx)); |
|
3075 break; |
|
3076 case 0x1e7: /* movntdq */ |
|
3077 case 0x02b: /* movntps */ |
|
3078 case 0x12b: /* movntps */ |
|
3079 case 0x3f0: /* lddqu */ |
|
3080 if (mod == 3) |
|
3081 goto illegal_op; |
|
3082 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
3083 gen_sto_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg])); |
|
3084 break; |
|
3085 case 0x6e: /* movd mm, ea */ |
|
3086 #ifdef TARGET_X86_64 |
|
3087 if (s->dflag == 2) { |
|
3088 gen_ldst_modrm(s, modrm, OT_QUAD, OR_TMP0, 0); |
|
3089 tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,fpregs[reg].mmx)); |
|
3090 } else |
|
3091 #endif |
|
3092 { |
|
3093 gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 0); |
|
3094 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, |
|
3095 offsetof(CPUX86State,fpregs[reg].mmx)); |
|
3096 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); |
|
3097 gen_helper_movl_mm_T0_mmx(cpu_ptr0, cpu_tmp2_i32); |
|
3098 } |
|
3099 break; |
|
3100 case 0x16e: /* movd xmm, ea */ |
|
3101 #ifdef TARGET_X86_64 |
|
3102 if (s->dflag == 2) { |
|
3103 gen_ldst_modrm(s, modrm, OT_QUAD, OR_TMP0, 0); |
|
3104 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, |
|
3105 offsetof(CPUX86State,xmm_regs[reg])); |
|
3106 gen_helper_movq_mm_T0_xmm(cpu_ptr0, cpu_T[0]); |
|
3107 } else |
|
3108 #endif |
|
3109 { |
|
3110 gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 0); |
|
3111 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, |
|
3112 offsetof(CPUX86State,xmm_regs[reg])); |
|
3113 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); |
|
3114 gen_helper_movl_mm_T0_xmm(cpu_ptr0, cpu_tmp2_i32); |
|
3115 } |
|
3116 break; |
|
3117 case 0x6f: /* movq mm, ea */ |
|
3118 if (mod != 3) { |
|
3119 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
3120 gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,fpregs[reg].mmx)); |
|
3121 } else { |
|
3122 rm = (modrm & 7); |
|
3123 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, |
|
3124 offsetof(CPUX86State,fpregs[rm].mmx)); |
|
3125 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, |
|
3126 offsetof(CPUX86State,fpregs[reg].mmx)); |
|
3127 } |
|
3128 break; |
|
3129 case 0x010: /* movups */ |
|
3130 case 0x110: /* movupd */ |
|
3131 case 0x028: /* movaps */ |
|
3132 case 0x128: /* movapd */ |
|
3133 case 0x16f: /* movdqa xmm, ea */ |
|
3134 case 0x26f: /* movdqu xmm, ea */ |
|
3135 if (mod != 3) { |
|
3136 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
3137 gen_ldo_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg])); |
|
3138 } else { |
|
3139 rm = (modrm & 7) | REX_B(s); |
|
3140 gen_op_movo(offsetof(CPUX86State,xmm_regs[reg]), |
|
3141 offsetof(CPUX86State,xmm_regs[rm])); |
|
3142 } |
|
3143 break; |
|
3144 case 0x210: /* movss xmm, ea */ |
|
3145 if (mod != 3) { |
|
3146 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
3147 gen_op_ld_T0_A0(OT_LONG + s->mem_index); |
|
3148 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(0))); |
|
3149 gen_op_movl_T0_0(); |
|
3150 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(1))); |
|
3151 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(2))); |
|
3152 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(3))); |
|
3153 } else { |
|
3154 rm = (modrm & 7) | REX_B(s); |
|
3155 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)), |
|
3156 offsetof(CPUX86State,xmm_regs[rm].XMM_L(0))); |
|
3157 } |
|
3158 break; |
|
3159 case 0x310: /* movsd xmm, ea */ |
|
3160 if (mod != 3) { |
|
3161 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
3162 gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0))); |
|
3163 gen_op_movl_T0_0(); |
|
3164 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(2))); |
|
3165 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(3))); |
|
3166 } else { |
|
3167 rm = (modrm & 7) | REX_B(s); |
|
3168 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)), |
|
3169 offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0))); |
|
3170 } |
|
3171 break; |
|
3172 case 0x012: /* movlps */ |
|
3173 case 0x112: /* movlpd */ |
|
3174 if (mod != 3) { |
|
3175 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
3176 gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0))); |
|
3177 } else { |
|
3178 /* movhlps */ |
|
3179 rm = (modrm & 7) | REX_B(s); |
|
3180 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)), |
|
3181 offsetof(CPUX86State,xmm_regs[rm].XMM_Q(1))); |
|
3182 } |
|
3183 break; |
|
3184 case 0x212: /* movsldup */ |
|
3185 if (mod != 3) { |
|
3186 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
3187 gen_ldo_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg])); |
|
3188 } else { |
|
3189 rm = (modrm & 7) | REX_B(s); |
|
3190 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)), |
|
3191 offsetof(CPUX86State,xmm_regs[rm].XMM_L(0))); |
|
3192 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)), |
|
3193 offsetof(CPUX86State,xmm_regs[rm].XMM_L(2))); |
|
3194 } |
|
3195 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)), |
|
3196 offsetof(CPUX86State,xmm_regs[reg].XMM_L(0))); |
|
3197 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)), |
|
3198 offsetof(CPUX86State,xmm_regs[reg].XMM_L(2))); |
|
3199 break; |
|
3200 case 0x312: /* movddup */ |
|
3201 if (mod != 3) { |
|
3202 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
3203 gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0))); |
|
3204 } else { |
|
3205 rm = (modrm & 7) | REX_B(s); |
|
3206 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)), |
|
3207 offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0))); |
|
3208 } |
|
3209 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)), |
|
3210 offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0))); |
|
3211 break; |
|
3212 case 0x016: /* movhps */ |
|
3213 case 0x116: /* movhpd */ |
|
3214 if (mod != 3) { |
|
3215 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
3216 gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1))); |
|
3217 } else { |
|
3218 /* movlhps */ |
|
3219 rm = (modrm & 7) | REX_B(s); |
|
3220 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)), |
|
3221 offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0))); |
|
3222 } |
|
3223 break; |
|
3224 case 0x216: /* movshdup */ |
|
3225 if (mod != 3) { |
|
3226 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
3227 gen_ldo_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg])); |
|
3228 } else { |
|
3229 rm = (modrm & 7) | REX_B(s); |
|
3230 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)), |
|
3231 offsetof(CPUX86State,xmm_regs[rm].XMM_L(1))); |
|
3232 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)), |
|
3233 offsetof(CPUX86State,xmm_regs[rm].XMM_L(3))); |
|
3234 } |
|
3235 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)), |
|
3236 offsetof(CPUX86State,xmm_regs[reg].XMM_L(1))); |
|
3237 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)), |
|
3238 offsetof(CPUX86State,xmm_regs[reg].XMM_L(3))); |
|
3239 break; |
|
3240 case 0x7e: /* movd ea, mm */ |
|
3241 #ifdef TARGET_X86_64 |
|
3242 if (s->dflag == 2) { |
|
3243 tcg_gen_ld_i64(cpu_T[0], cpu_env, |
|
3244 offsetof(CPUX86State,fpregs[reg].mmx)); |
|
3245 gen_ldst_modrm(s, modrm, OT_QUAD, OR_TMP0, 1); |
|
3246 } else |
|
3247 #endif |
|
3248 { |
|
3249 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, |
|
3250 offsetof(CPUX86State,fpregs[reg].mmx.MMX_L(0))); |
|
3251 gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 1); |
|
3252 } |
|
3253 break; |
|
3254 case 0x17e: /* movd ea, xmm */ |
|
3255 #ifdef TARGET_X86_64 |
|
3256 if (s->dflag == 2) { |
|
3257 tcg_gen_ld_i64(cpu_T[0], cpu_env, |
|
3258 offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0))); |
|
3259 gen_ldst_modrm(s, modrm, OT_QUAD, OR_TMP0, 1); |
|
3260 } else |
|
3261 #endif |
|
3262 { |
|
3263 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, |
|
3264 offsetof(CPUX86State,xmm_regs[reg].XMM_L(0))); |
|
3265 gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 1); |
|
3266 } |
|
3267 break; |
|
3268 case 0x27e: /* movq xmm, ea */ |
|
3269 if (mod != 3) { |
|
3270 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
3271 gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0))); |
|
3272 } else { |
|
3273 rm = (modrm & 7) | REX_B(s); |
|
3274 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)), |
|
3275 offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0))); |
|
3276 } |
|
3277 gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1))); |
|
3278 break; |
|
3279 case 0x7f: /* movq ea, mm */ |
|
3280 if (mod != 3) { |
|
3281 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
3282 gen_stq_env_A0(s->mem_index, offsetof(CPUX86State,fpregs[reg].mmx)); |
|
3283 } else { |
|
3284 rm = (modrm & 7); |
|
3285 gen_op_movq(offsetof(CPUX86State,fpregs[rm].mmx), |
|
3286 offsetof(CPUX86State,fpregs[reg].mmx)); |
|
3287 } |
|
3288 break; |
|
3289 case 0x011: /* movups */ |
|
3290 case 0x111: /* movupd */ |
|
3291 case 0x029: /* movaps */ |
|
3292 case 0x129: /* movapd */ |
|
3293 case 0x17f: /* movdqa ea, xmm */ |
|
3294 case 0x27f: /* movdqu ea, xmm */ |
|
3295 if (mod != 3) { |
|
3296 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
3297 gen_sto_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg])); |
|
3298 } else { |
|
3299 rm = (modrm & 7) | REX_B(s); |
|
3300 gen_op_movo(offsetof(CPUX86State,xmm_regs[rm]), |
|
3301 offsetof(CPUX86State,xmm_regs[reg])); |
|
3302 } |
|
3303 break; |
|
3304 case 0x211: /* movss ea, xmm */ |
|
3305 if (mod != 3) { |
|
3306 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
3307 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(0))); |
|
3308 gen_op_st_T0_A0(OT_LONG + s->mem_index); |
|
3309 } else { |
|
3310 rm = (modrm & 7) | REX_B(s); |
|
3311 gen_op_movl(offsetof(CPUX86State,xmm_regs[rm].XMM_L(0)), |
|
3312 offsetof(CPUX86State,xmm_regs[reg].XMM_L(0))); |
|
3313 } |
|
3314 break; |
|
3315 case 0x311: /* movsd ea, xmm */ |
|
3316 if (mod != 3) { |
|
3317 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
3318 gen_stq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0))); |
|
3319 } else { |
|
3320 rm = (modrm & 7) | REX_B(s); |
|
3321 gen_op_movq(offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)), |
|
3322 offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0))); |
|
3323 } |
|
3324 break; |
|
3325 case 0x013: /* movlps */ |
|
3326 case 0x113: /* movlpd */ |
|
3327 if (mod != 3) { |
|
3328 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
3329 gen_stq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0))); |
|
3330 } else { |
|
3331 goto illegal_op; |
|
3332 } |
|
3333 break; |
|
3334 case 0x017: /* movhps */ |
|
3335 case 0x117: /* movhpd */ |
|
3336 if (mod != 3) { |
|
3337 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
3338 gen_stq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1))); |
|
3339 } else { |
|
3340 goto illegal_op; |
|
3341 } |
|
3342 break; |
|
3343 case 0x71: /* shift mm, im */ |
|
3344 case 0x72: |
|
3345 case 0x73: |
|
3346 case 0x171: /* shift xmm, im */ |
|
3347 case 0x172: |
|
3348 case 0x173: |
|
3349 val = ldub_code(s->pc++); |
|
3350 if (is_xmm) { |
|
3351 gen_op_movl_T0_im(val); |
|
3352 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_t0.XMM_L(0))); |
|
3353 gen_op_movl_T0_0(); |
|
3354 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_t0.XMM_L(1))); |
|
3355 op1_offset = offsetof(CPUX86State,xmm_t0); |
|
3356 } else { |
|
3357 gen_op_movl_T0_im(val); |
|
3358 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,mmx_t0.MMX_L(0))); |
|
3359 gen_op_movl_T0_0(); |
|
3360 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,mmx_t0.MMX_L(1))); |
|
3361 op1_offset = offsetof(CPUX86State,mmx_t0); |
|
3362 } |
|
3363 sse_op2 = sse_op_table2[((b - 1) & 3) * 8 + (((modrm >> 3)) & 7)][b1]; |
|
3364 if (!sse_op2) |
|
3365 goto illegal_op; |
|
3366 if (is_xmm) { |
|
3367 rm = (modrm & 7) | REX_B(s); |
|
3368 op2_offset = offsetof(CPUX86State,xmm_regs[rm]); |
|
3369 } else { |
|
3370 rm = (modrm & 7); |
|
3371 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx); |
|
3372 } |
|
3373 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op2_offset); |
|
3374 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op1_offset); |
|
3375 ((void (*)(TCGv_ptr, TCGv_ptr))sse_op2)(cpu_ptr0, cpu_ptr1); |
|
3376 break; |
|
3377 case 0x050: /* movmskps */ |
|
3378 rm = (modrm & 7) | REX_B(s); |
|
3379 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, |
|
3380 offsetof(CPUX86State,xmm_regs[rm])); |
|
3381 gen_helper_movmskps(cpu_tmp2_i32, cpu_ptr0); |
|
3382 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32); |
|
3383 gen_op_mov_reg_T0(OT_LONG, reg); |
|
3384 break; |
|
3385 case 0x150: /* movmskpd */ |
|
3386 rm = (modrm & 7) | REX_B(s); |
|
3387 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, |
|
3388 offsetof(CPUX86State,xmm_regs[rm])); |
|
3389 gen_helper_movmskpd(cpu_tmp2_i32, cpu_ptr0); |
|
3390 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32); |
|
3391 gen_op_mov_reg_T0(OT_LONG, reg); |
|
3392 break; |
|
3393 case 0x02a: /* cvtpi2ps */ |
|
3394 case 0x12a: /* cvtpi2pd */ |
|
3395 gen_helper_enter_mmx(); |
|
3396 if (mod != 3) { |
|
3397 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
3398 op2_offset = offsetof(CPUX86State,mmx_t0); |
|
3399 gen_ldq_env_A0(s->mem_index, op2_offset); |
|
3400 } else { |
|
3401 rm = (modrm & 7); |
|
3402 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx); |
|
3403 } |
|
3404 op1_offset = offsetof(CPUX86State,xmm_regs[reg]); |
|
3405 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset); |
|
3406 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset); |
|
3407 switch(b >> 8) { |
|
3408 case 0x0: |
|
3409 gen_helper_cvtpi2ps(cpu_ptr0, cpu_ptr1); |
|
3410 break; |
|
3411 default: |
|
3412 case 0x1: |
|
3413 gen_helper_cvtpi2pd(cpu_ptr0, cpu_ptr1); |
|
3414 break; |
|
3415 } |
|
3416 break; |
|
3417 case 0x22a: /* cvtsi2ss */ |
|
3418 case 0x32a: /* cvtsi2sd */ |
|
3419 ot = (s->dflag == 2) ? OT_QUAD : OT_LONG; |
|
3420 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0); |
|
3421 op1_offset = offsetof(CPUX86State,xmm_regs[reg]); |
|
3422 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset); |
|
3423 sse_op2 = sse_op_table3[(s->dflag == 2) * 2 + ((b >> 8) - 2)]; |
|
3424 if (ot == OT_LONG) { |
|
3425 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); |
|
3426 ((void (*)(TCGv_ptr, TCGv_i32))sse_op2)(cpu_ptr0, cpu_tmp2_i32); |
|
3427 } else { |
|
3428 ((void (*)(TCGv_ptr, TCGv))sse_op2)(cpu_ptr0, cpu_T[0]); |
|
3429 } |
|
3430 break; |
|
3431 case 0x02c: /* cvttps2pi */ |
|
3432 case 0x12c: /* cvttpd2pi */ |
|
3433 case 0x02d: /* cvtps2pi */ |
|
3434 case 0x12d: /* cvtpd2pi */ |
|
3435 gen_helper_enter_mmx(); |
|
3436 if (mod != 3) { |
|
3437 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
3438 op2_offset = offsetof(CPUX86State,xmm_t0); |
|
3439 gen_ldo_env_A0(s->mem_index, op2_offset); |
|
3440 } else { |
|
3441 rm = (modrm & 7) | REX_B(s); |
|
3442 op2_offset = offsetof(CPUX86State,xmm_regs[rm]); |
|
3443 } |
|
3444 op1_offset = offsetof(CPUX86State,fpregs[reg & 7].mmx); |
|
3445 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset); |
|
3446 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset); |
|
3447 switch(b) { |
|
3448 case 0x02c: |
|
3449 gen_helper_cvttps2pi(cpu_ptr0, cpu_ptr1); |
|
3450 break; |
|
3451 case 0x12c: |
|
3452 gen_helper_cvttpd2pi(cpu_ptr0, cpu_ptr1); |
|
3453 break; |
|
3454 case 0x02d: |
|
3455 gen_helper_cvtps2pi(cpu_ptr0, cpu_ptr1); |
|
3456 break; |
|
3457 case 0x12d: |
|
3458 gen_helper_cvtpd2pi(cpu_ptr0, cpu_ptr1); |
|
3459 break; |
|
3460 } |
|
3461 break; |
|
3462 case 0x22c: /* cvttss2si */ |
|
3463 case 0x32c: /* cvttsd2si */ |
|
3464 case 0x22d: /* cvtss2si */ |
|
3465 case 0x32d: /* cvtsd2si */ |
|
3466 ot = (s->dflag == 2) ? OT_QUAD : OT_LONG; |
|
3467 if (mod != 3) { |
|
3468 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
3469 if ((b >> 8) & 1) { |
|
3470 gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_t0.XMM_Q(0))); |
|
3471 } else { |
|
3472 gen_op_ld_T0_A0(OT_LONG + s->mem_index); |
|
3473 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_t0.XMM_L(0))); |
|
3474 } |
|
3475 op2_offset = offsetof(CPUX86State,xmm_t0); |
|
3476 } else { |
|
3477 rm = (modrm & 7) | REX_B(s); |
|
3478 op2_offset = offsetof(CPUX86State,xmm_regs[rm]); |
|
3479 } |
|
3480 sse_op2 = sse_op_table3[(s->dflag == 2) * 2 + ((b >> 8) - 2) + 4 + |
|
3481 (b & 1) * 4]; |
|
3482 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op2_offset); |
|
3483 if (ot == OT_LONG) { |
|
3484 ((void (*)(TCGv_i32, TCGv_ptr))sse_op2)(cpu_tmp2_i32, cpu_ptr0); |
|
3485 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32); |
|
3486 } else { |
|
3487 ((void (*)(TCGv, TCGv_ptr))sse_op2)(cpu_T[0], cpu_ptr0); |
|
3488 } |
|
3489 gen_op_mov_reg_T0(ot, reg); |
|
3490 break; |
|
3491 case 0xc4: /* pinsrw */ |
|
3492 case 0x1c4: |
|
3493 s->rip_offset = 1; |
|
3494 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0); |
|
3495 val = ldub_code(s->pc++); |
|
3496 if (b1) { |
|
3497 val &= 7; |
|
3498 tcg_gen_st16_tl(cpu_T[0], cpu_env, |
|
3499 offsetof(CPUX86State,xmm_regs[reg].XMM_W(val))); |
|
3500 } else { |
|
3501 val &= 3; |
|
3502 tcg_gen_st16_tl(cpu_T[0], cpu_env, |
|
3503 offsetof(CPUX86State,fpregs[reg].mmx.MMX_W(val))); |
|
3504 } |
|
3505 break; |
|
3506 case 0xc5: /* pextrw */ |
|
3507 case 0x1c5: |
|
3508 if (mod != 3) |
|
3509 goto illegal_op; |
|
3510 ot = (s->dflag == 2) ? OT_QUAD : OT_LONG; |
|
3511 val = ldub_code(s->pc++); |
|
3512 if (b1) { |
|
3513 val &= 7; |
|
3514 rm = (modrm & 7) | REX_B(s); |
|
3515 tcg_gen_ld16u_tl(cpu_T[0], cpu_env, |
|
3516 offsetof(CPUX86State,xmm_regs[rm].XMM_W(val))); |
|
3517 } else { |
|
3518 val &= 3; |
|
3519 rm = (modrm & 7); |
|
3520 tcg_gen_ld16u_tl(cpu_T[0], cpu_env, |
|
3521 offsetof(CPUX86State,fpregs[rm].mmx.MMX_W(val))); |
|
3522 } |
|
3523 reg = ((modrm >> 3) & 7) | rex_r; |
|
3524 gen_op_mov_reg_T0(ot, reg); |
|
3525 break; |
|
3526 case 0x1d6: /* movq ea, xmm */ |
|
3527 if (mod != 3) { |
|
3528 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
3529 gen_stq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0))); |
|
3530 } else { |
|
3531 rm = (modrm & 7) | REX_B(s); |
|
3532 gen_op_movq(offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)), |
|
3533 offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0))); |
|
3534 gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[rm].XMM_Q(1))); |
|
3535 } |
|
3536 break; |
|
3537 case 0x2d6: /* movq2dq */ |
|
3538 gen_helper_enter_mmx(); |
|
3539 rm = (modrm & 7); |
|
3540 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)), |
|
3541 offsetof(CPUX86State,fpregs[rm].mmx)); |
|
3542 gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1))); |
|
3543 break; |
|
3544 case 0x3d6: /* movdq2q */ |
|
3545 gen_helper_enter_mmx(); |
|
3546 rm = (modrm & 7) | REX_B(s); |
|
3547 gen_op_movq(offsetof(CPUX86State,fpregs[reg & 7].mmx), |
|
3548 offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0))); |
|
3549 break; |
|
3550 case 0xd7: /* pmovmskb */ |
|
3551 case 0x1d7: |
|
3552 if (mod != 3) |
|
3553 goto illegal_op; |
|
3554 if (b1) { |
|
3555 rm = (modrm & 7) | REX_B(s); |
|
3556 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, offsetof(CPUX86State,xmm_regs[rm])); |
|
3557 gen_helper_pmovmskb_xmm(cpu_tmp2_i32, cpu_ptr0); |
|
3558 } else { |
|
3559 rm = (modrm & 7); |
|
3560 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, offsetof(CPUX86State,fpregs[rm].mmx)); |
|
3561 gen_helper_pmovmskb_mmx(cpu_tmp2_i32, cpu_ptr0); |
|
3562 } |
|
3563 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32); |
|
3564 reg = ((modrm >> 3) & 7) | rex_r; |
|
3565 gen_op_mov_reg_T0(OT_LONG, reg); |
|
3566 break; |
|
3567 case 0x138: |
|
3568 if (s->prefix & PREFIX_REPNZ) |
|
3569 goto crc32; |
|
3570 case 0x038: |
|
3571 b = modrm; |
|
3572 modrm = ldub_code(s->pc++); |
|
3573 rm = modrm & 7; |
|
3574 reg = ((modrm >> 3) & 7) | rex_r; |
|
3575 mod = (modrm >> 6) & 3; |
|
3576 |
|
3577 sse_op2 = sse_op_table6[b].op[b1]; |
|
3578 if (!sse_op2) |
|
3579 goto illegal_op; |
|
3580 if (!(s->cpuid_ext_features & sse_op_table6[b].ext_mask)) |
|
3581 goto illegal_op; |
|
3582 |
|
3583 if (b1) { |
|
3584 op1_offset = offsetof(CPUX86State,xmm_regs[reg]); |
|
3585 if (mod == 3) { |
|
3586 op2_offset = offsetof(CPUX86State,xmm_regs[rm | REX_B(s)]); |
|
3587 } else { |
|
3588 op2_offset = offsetof(CPUX86State,xmm_t0); |
|
3589 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
3590 switch (b) { |
|
3591 case 0x20: case 0x30: /* pmovsxbw, pmovzxbw */ |
|
3592 case 0x23: case 0x33: /* pmovsxwd, pmovzxwd */ |
|
3593 case 0x25: case 0x35: /* pmovsxdq, pmovzxdq */ |
|
3594 gen_ldq_env_A0(s->mem_index, op2_offset + |
|
3595 offsetof(XMMReg, XMM_Q(0))); |
|
3596 break; |
|
3597 case 0x21: case 0x31: /* pmovsxbd, pmovzxbd */ |
|
3598 case 0x24: case 0x34: /* pmovsxwq, pmovzxwq */ |
|
3599 tcg_gen_qemu_ld32u(cpu_tmp0, cpu_A0, |
|
3600 (s->mem_index >> 2) - 1); |
|
3601 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_tmp0); |
|
3602 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, op2_offset + |
|
3603 offsetof(XMMReg, XMM_L(0))); |
|
3604 break; |
|
3605 case 0x22: case 0x32: /* pmovsxbq, pmovzxbq */ |
|
3606 tcg_gen_qemu_ld16u(cpu_tmp0, cpu_A0, |
|
3607 (s->mem_index >> 2) - 1); |
|
3608 tcg_gen_st16_tl(cpu_tmp0, cpu_env, op2_offset + |
|
3609 offsetof(XMMReg, XMM_W(0))); |
|
3610 break; |
|
3611 case 0x2a: /* movntqda */ |
|
3612 gen_ldo_env_A0(s->mem_index, op1_offset); |
|
3613 return; |
|
3614 default: |
|
3615 gen_ldo_env_A0(s->mem_index, op2_offset); |
|
3616 } |
|
3617 } |
|
3618 } else { |
|
3619 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx); |
|
3620 if (mod == 3) { |
|
3621 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx); |
|
3622 } else { |
|
3623 op2_offset = offsetof(CPUX86State,mmx_t0); |
|
3624 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
3625 gen_ldq_env_A0(s->mem_index, op2_offset); |
|
3626 } |
|
3627 } |
|
3628 if (sse_op2 == SSE_SPECIAL) |
|
3629 goto illegal_op; |
|
3630 |
|
3631 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset); |
|
3632 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset); |
|
3633 ((void (*)(TCGv_ptr, TCGv_ptr))sse_op2)(cpu_ptr0, cpu_ptr1); |
|
3634 |
|
3635 if (b == 0x17) |
|
3636 s->cc_op = CC_OP_EFLAGS; |
|
3637 break; |
|
3638 case 0x338: /* crc32 */ |
|
3639 crc32: |
|
3640 b = modrm; |
|
3641 modrm = ldub_code(s->pc++); |
|
3642 reg = ((modrm >> 3) & 7) | rex_r; |
|
3643 |
|
3644 if (b != 0xf0 && b != 0xf1) |
|
3645 goto illegal_op; |
|
3646 if (!(s->cpuid_ext_features & CPUID_EXT_SSE42)) |
|
3647 goto illegal_op; |
|
3648 |
|
3649 if (b == 0xf0) |
|
3650 ot = OT_BYTE; |
|
3651 else if (b == 0xf1 && s->dflag != 2) |
|
3652 if (s->prefix & PREFIX_DATA) |
|
3653 ot = OT_WORD; |
|
3654 else |
|
3655 ot = OT_LONG; |
|
3656 else |
|
3657 ot = OT_QUAD; |
|
3658 |
|
3659 gen_op_mov_TN_reg(OT_LONG, 0, reg); |
|
3660 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); |
|
3661 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0); |
|
3662 gen_helper_crc32(cpu_T[0], cpu_tmp2_i32, |
|
3663 cpu_T[0], tcg_const_i32(8 << ot)); |
|
3664 |
|
3665 ot = (s->dflag == 2) ? OT_QUAD : OT_LONG; |
|
3666 gen_op_mov_reg_T0(ot, reg); |
|
3667 break; |
|
3668 case 0x03a: |
|
3669 case 0x13a: |
|
3670 b = modrm; |
|
3671 modrm = ldub_code(s->pc++); |
|
3672 rm = modrm & 7; |
|
3673 reg = ((modrm >> 3) & 7) | rex_r; |
|
3674 mod = (modrm >> 6) & 3; |
|
3675 |
|
3676 sse_op2 = sse_op_table7[b].op[b1]; |
|
3677 if (!sse_op2) |
|
3678 goto illegal_op; |
|
3679 if (!(s->cpuid_ext_features & sse_op_table7[b].ext_mask)) |
|
3680 goto illegal_op; |
|
3681 |
|
3682 if (sse_op2 == SSE_SPECIAL) { |
|
3683 ot = (s->dflag == 2) ? OT_QUAD : OT_LONG; |
|
3684 rm = (modrm & 7) | REX_B(s); |
|
3685 if (mod != 3) |
|
3686 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
3687 reg = ((modrm >> 3) & 7) | rex_r; |
|
3688 val = ldub_code(s->pc++); |
|
3689 switch (b) { |
|
3690 case 0x14: /* pextrb */ |
|
3691 tcg_gen_ld8u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, |
|
3692 xmm_regs[reg].XMM_B(val & 15))); |
|
3693 if (mod == 3) |
|
3694 gen_op_mov_reg_T0(ot, rm); |
|
3695 else |
|
3696 tcg_gen_qemu_st8(cpu_T[0], cpu_A0, |
|
3697 (s->mem_index >> 2) - 1); |
|
3698 break; |
|
3699 case 0x15: /* pextrw */ |
|
3700 tcg_gen_ld16u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, |
|
3701 xmm_regs[reg].XMM_W(val & 7))); |
|
3702 if (mod == 3) |
|
3703 gen_op_mov_reg_T0(ot, rm); |
|
3704 else |
|
3705 tcg_gen_qemu_st16(cpu_T[0], cpu_A0, |
|
3706 (s->mem_index >> 2) - 1); |
|
3707 break; |
|
3708 case 0x16: |
|
3709 if (ot == OT_LONG) { /* pextrd */ |
|
3710 tcg_gen_ld_i32(cpu_tmp2_i32, cpu_env, |
|
3711 offsetof(CPUX86State, |
|
3712 xmm_regs[reg].XMM_L(val & 3))); |
|
3713 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32); |
|
3714 if (mod == 3) |
|
3715 gen_op_mov_reg_v(ot, rm, cpu_T[0]); |
|
3716 else |
|
3717 tcg_gen_qemu_st32(cpu_T[0], cpu_A0, |
|
3718 (s->mem_index >> 2) - 1); |
|
3719 } else { /* pextrq */ |
|
3720 #ifdef TARGET_X86_64 |
|
3721 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, |
|
3722 offsetof(CPUX86State, |
|
3723 xmm_regs[reg].XMM_Q(val & 1))); |
|
3724 if (mod == 3) |
|
3725 gen_op_mov_reg_v(ot, rm, cpu_tmp1_i64); |
|
3726 else |
|
3727 tcg_gen_qemu_st64(cpu_tmp1_i64, cpu_A0, |
|
3728 (s->mem_index >> 2) - 1); |
|
3729 #else |
|
3730 goto illegal_op; |
|
3731 #endif |
|
3732 } |
|
3733 break; |
|
3734 case 0x17: /* extractps */ |
|
3735 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, |
|
3736 xmm_regs[reg].XMM_L(val & 3))); |
|
3737 if (mod == 3) |
|
3738 gen_op_mov_reg_T0(ot, rm); |
|
3739 else |
|
3740 tcg_gen_qemu_st32(cpu_T[0], cpu_A0, |
|
3741 (s->mem_index >> 2) - 1); |
|
3742 break; |
|
3743 case 0x20: /* pinsrb */ |
|
3744 if (mod == 3) |
|
3745 gen_op_mov_TN_reg(OT_LONG, 0, rm); |
|
3746 else |
|
3747 tcg_gen_qemu_ld8u(cpu_tmp0, cpu_A0, |
|
3748 (s->mem_index >> 2) - 1); |
|
3749 tcg_gen_st8_tl(cpu_tmp0, cpu_env, offsetof(CPUX86State, |
|
3750 xmm_regs[reg].XMM_B(val & 15))); |
|
3751 break; |
|
3752 case 0x21: /* insertps */ |
|
3753 if (mod == 3) { |
|
3754 tcg_gen_ld_i32(cpu_tmp2_i32, cpu_env, |
|
3755 offsetof(CPUX86State,xmm_regs[rm] |
|
3756 .XMM_L((val >> 6) & 3))); |
|
3757 } else { |
|
3758 tcg_gen_qemu_ld32u(cpu_tmp0, cpu_A0, |
|
3759 (s->mem_index >> 2) - 1); |
|
3760 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_tmp0); |
|
3761 } |
|
3762 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, |
|
3763 offsetof(CPUX86State,xmm_regs[reg] |
|
3764 .XMM_L((val >> 4) & 3))); |
|
3765 if ((val >> 0) & 1) |
|
3766 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/), |
|
3767 cpu_env, offsetof(CPUX86State, |
|
3768 xmm_regs[reg].XMM_L(0))); |
|
3769 if ((val >> 1) & 1) |
|
3770 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/), |
|
3771 cpu_env, offsetof(CPUX86State, |
|
3772 xmm_regs[reg].XMM_L(1))); |
|
3773 if ((val >> 2) & 1) |
|
3774 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/), |
|
3775 cpu_env, offsetof(CPUX86State, |
|
3776 xmm_regs[reg].XMM_L(2))); |
|
3777 if ((val >> 3) & 1) |
|
3778 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/), |
|
3779 cpu_env, offsetof(CPUX86State, |
|
3780 xmm_regs[reg].XMM_L(3))); |
|
3781 break; |
|
3782 case 0x22: |
|
3783 if (ot == OT_LONG) { /* pinsrd */ |
|
3784 if (mod == 3) |
|
3785 gen_op_mov_v_reg(ot, cpu_tmp0, rm); |
|
3786 else |
|
3787 tcg_gen_qemu_ld32u(cpu_tmp0, cpu_A0, |
|
3788 (s->mem_index >> 2) - 1); |
|
3789 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_tmp0); |
|
3790 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, |
|
3791 offsetof(CPUX86State, |
|
3792 xmm_regs[reg].XMM_L(val & 3))); |
|
3793 } else { /* pinsrq */ |
|
3794 #ifdef TARGET_X86_64 |
|
3795 if (mod == 3) |
|
3796 gen_op_mov_v_reg(ot, cpu_tmp1_i64, rm); |
|
3797 else |
|
3798 tcg_gen_qemu_ld64(cpu_tmp1_i64, cpu_A0, |
|
3799 (s->mem_index >> 2) - 1); |
|
3800 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, |
|
3801 offsetof(CPUX86State, |
|
3802 xmm_regs[reg].XMM_Q(val & 1))); |
|
3803 #else |
|
3804 goto illegal_op; |
|
3805 #endif |
|
3806 } |
|
3807 break; |
|
3808 } |
|
3809 return; |
|
3810 } |
|
3811 |
|
3812 if (b1) { |
|
3813 op1_offset = offsetof(CPUX86State,xmm_regs[reg]); |
|
3814 if (mod == 3) { |
|
3815 op2_offset = offsetof(CPUX86State,xmm_regs[rm | REX_B(s)]); |
|
3816 } else { |
|
3817 op2_offset = offsetof(CPUX86State,xmm_t0); |
|
3818 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
3819 gen_ldo_env_A0(s->mem_index, op2_offset); |
|
3820 } |
|
3821 } else { |
|
3822 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx); |
|
3823 if (mod == 3) { |
|
3824 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx); |
|
3825 } else { |
|
3826 op2_offset = offsetof(CPUX86State,mmx_t0); |
|
3827 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
3828 gen_ldq_env_A0(s->mem_index, op2_offset); |
|
3829 } |
|
3830 } |
|
3831 val = ldub_code(s->pc++); |
|
3832 |
|
3833 if ((b & 0xfc) == 0x60) { /* pcmpXstrX */ |
|
3834 s->cc_op = CC_OP_EFLAGS; |
|
3835 |
|
3836 if (s->dflag == 2) |
|
3837 /* The helper must use entire 64-bit gp registers */ |
|
3838 val |= 1 << 8; |
|
3839 } |
|
3840 |
|
3841 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset); |
|
3842 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset); |
|
3843 ((void (*)(TCGv_ptr, TCGv_ptr, TCGv_i32))sse_op2)(cpu_ptr0, cpu_ptr1, tcg_const_i32(val)); |
|
3844 break; |
|
3845 default: |
|
3846 goto illegal_op; |
|
3847 } |
|
3848 } else { |
|
3849 /* generic MMX or SSE operation */ |
|
3850 switch(b) { |
|
3851 case 0x70: /* pshufx insn */ |
|
3852 case 0xc6: /* pshufx insn */ |
|
3853 case 0xc2: /* compare insns */ |
|
3854 s->rip_offset = 1; |
|
3855 break; |
|
3856 default: |
|
3857 break; |
|
3858 } |
|
3859 if (is_xmm) { |
|
3860 op1_offset = offsetof(CPUX86State,xmm_regs[reg]); |
|
3861 if (mod != 3) { |
|
3862 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
3863 op2_offset = offsetof(CPUX86State,xmm_t0); |
|
3864 if (b1 >= 2 && ((b >= 0x50 && b <= 0x5f && b != 0x5b) || |
|
3865 b == 0xc2)) { |
|
3866 /* specific case for SSE single instructions */ |
|
3867 if (b1 == 2) { |
|
3868 /* 32 bit access */ |
|
3869 gen_op_ld_T0_A0(OT_LONG + s->mem_index); |
|
3870 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_t0.XMM_L(0))); |
|
3871 } else { |
|
3872 /* 64 bit access */ |
|
3873 gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_t0.XMM_D(0))); |
|
3874 } |
|
3875 } else { |
|
3876 gen_ldo_env_A0(s->mem_index, op2_offset); |
|
3877 } |
|
3878 } else { |
|
3879 rm = (modrm & 7) | REX_B(s); |
|
3880 op2_offset = offsetof(CPUX86State,xmm_regs[rm]); |
|
3881 } |
|
3882 } else { |
|
3883 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx); |
|
3884 if (mod != 3) { |
|
3885 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
3886 op2_offset = offsetof(CPUX86State,mmx_t0); |
|
3887 gen_ldq_env_A0(s->mem_index, op2_offset); |
|
3888 } else { |
|
3889 rm = (modrm & 7); |
|
3890 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx); |
|
3891 } |
|
3892 } |
|
3893 switch(b) { |
|
3894 case 0x0f: /* 3DNow! data insns */ |
|
3895 if (!(s->cpuid_ext2_features & CPUID_EXT2_3DNOW)) |
|
3896 goto illegal_op; |
|
3897 val = ldub_code(s->pc++); |
|
3898 sse_op2 = sse_op_table5[val]; |
|
3899 if (!sse_op2) |
|
3900 goto illegal_op; |
|
3901 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset); |
|
3902 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset); |
|
3903 ((void (*)(TCGv_ptr, TCGv_ptr))sse_op2)(cpu_ptr0, cpu_ptr1); |
|
3904 break; |
|
3905 case 0x70: /* pshufx insn */ |
|
3906 case 0xc6: /* pshufx insn */ |
|
3907 val = ldub_code(s->pc++); |
|
3908 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset); |
|
3909 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset); |
|
3910 ((void (*)(TCGv_ptr, TCGv_ptr, TCGv_i32))sse_op2)(cpu_ptr0, cpu_ptr1, tcg_const_i32(val)); |
|
3911 break; |
|
3912 case 0xc2: |
|
3913 /* compare insns */ |
|
3914 val = ldub_code(s->pc++); |
|
3915 if (val >= 8) |
|
3916 goto illegal_op; |
|
3917 sse_op2 = sse_op_table4[val][b1]; |
|
3918 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset); |
|
3919 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset); |
|
3920 ((void (*)(TCGv_ptr, TCGv_ptr))sse_op2)(cpu_ptr0, cpu_ptr1); |
|
3921 break; |
|
3922 case 0xf7: |
|
3923 /* maskmov : we must prepare A0 */ |
|
3924 if (mod != 3) |
|
3925 goto illegal_op; |
|
3926 #ifdef TARGET_X86_64 |
|
3927 if (s->aflag == 2) { |
|
3928 gen_op_movq_A0_reg(R_EDI); |
|
3929 } else |
|
3930 #endif |
|
3931 { |
|
3932 gen_op_movl_A0_reg(R_EDI); |
|
3933 if (s->aflag == 0) |
|
3934 gen_op_andl_A0_ffff(); |
|
3935 } |
|
3936 gen_add_A0_ds_seg(s); |
|
3937 |
|
3938 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset); |
|
3939 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset); |
|
3940 ((void (*)(TCGv_ptr, TCGv_ptr, TCGv))sse_op2)(cpu_ptr0, cpu_ptr1, cpu_A0); |
|
3941 break; |
|
3942 default: |
|
3943 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset); |
|
3944 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset); |
|
3945 ((void (*)(TCGv_ptr, TCGv_ptr))sse_op2)(cpu_ptr0, cpu_ptr1); |
|
3946 break; |
|
3947 } |
|
3948 if (b == 0x2e || b == 0x2f) { |
|
3949 s->cc_op = CC_OP_EFLAGS; |
|
3950 } |
|
3951 } |
|
3952 } |
|
3953 |
|
3954 /* convert one instruction. s->is_jmp is set if the translation must |
|
3955 be stopped. Return the next pc value */ |
|
3956 static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) |
|
3957 { |
|
3958 int b, prefixes, aflag, dflag; |
|
3959 int shift, ot; |
|
3960 int modrm, reg, rm, mod, reg_addr, op, opreg, offset_addr, val; |
|
3961 target_ulong next_eip, tval; |
|
3962 int rex_w, rex_r; |
|
3963 |
|
3964 if (unlikely(loglevel & CPU_LOG_TB_OP)) |
|
3965 tcg_gen_debug_insn_start(pc_start); |
|
3966 s->pc = pc_start; |
|
3967 prefixes = 0; |
|
3968 aflag = s->code32; |
|
3969 dflag = s->code32; |
|
3970 s->override = -1; |
|
3971 rex_w = -1; |
|
3972 rex_r = 0; |
|
3973 #ifdef TARGET_X86_64 |
|
3974 s->rex_x = 0; |
|
3975 s->rex_b = 0; |
|
3976 x86_64_hregs = 0; |
|
3977 #endif |
|
3978 s->rip_offset = 0; /* for relative ip address */ |
|
3979 next_byte: |
|
3980 b = ldub_code(s->pc); |
|
3981 s->pc++; |
|
3982 /* check prefixes */ |
|
3983 #ifdef TARGET_X86_64 |
|
3984 if (CODE64(s)) { |
|
3985 switch (b) { |
|
3986 case 0xf3: |
|
3987 prefixes |= PREFIX_REPZ; |
|
3988 goto next_byte; |
|
3989 case 0xf2: |
|
3990 prefixes |= PREFIX_REPNZ; |
|
3991 goto next_byte; |
|
3992 case 0xf0: |
|
3993 prefixes |= PREFIX_LOCK; |
|
3994 goto next_byte; |
|
3995 case 0x2e: |
|
3996 s->override = R_CS; |
|
3997 goto next_byte; |
|
3998 case 0x36: |
|
3999 s->override = R_SS; |
|
4000 goto next_byte; |
|
4001 case 0x3e: |
|
4002 s->override = R_DS; |
|
4003 goto next_byte; |
|
4004 case 0x26: |
|
4005 s->override = R_ES; |
|
4006 goto next_byte; |
|
4007 case 0x64: |
|
4008 s->override = R_FS; |
|
4009 goto next_byte; |
|
4010 case 0x65: |
|
4011 s->override = R_GS; |
|
4012 goto next_byte; |
|
4013 case 0x66: |
|
4014 prefixes |= PREFIX_DATA; |
|
4015 goto next_byte; |
|
4016 case 0x67: |
|
4017 prefixes |= PREFIX_ADR; |
|
4018 goto next_byte; |
|
4019 case 0x40 ... 0x4f: |
|
4020 /* REX prefix */ |
|
4021 rex_w = (b >> 3) & 1; |
|
4022 rex_r = (b & 0x4) << 1; |
|
4023 s->rex_x = (b & 0x2) << 2; |
|
4024 REX_B(s) = (b & 0x1) << 3; |
|
4025 x86_64_hregs = 1; /* select uniform byte register addressing */ |
|
4026 goto next_byte; |
|
4027 } |
|
4028 if (rex_w == 1) { |
|
4029 /* 0x66 is ignored if rex.w is set */ |
|
4030 dflag = 2; |
|
4031 } else { |
|
4032 if (prefixes & PREFIX_DATA) |
|
4033 dflag ^= 1; |
|
4034 } |
|
4035 if (!(prefixes & PREFIX_ADR)) |
|
4036 aflag = 2; |
|
4037 } else |
|
4038 #endif |
|
4039 { |
|
4040 switch (b) { |
|
4041 case 0xf3: |
|
4042 prefixes |= PREFIX_REPZ; |
|
4043 goto next_byte; |
|
4044 case 0xf2: |
|
4045 prefixes |= PREFIX_REPNZ; |
|
4046 goto next_byte; |
|
4047 case 0xf0: |
|
4048 prefixes |= PREFIX_LOCK; |
|
4049 goto next_byte; |
|
4050 case 0x2e: |
|
4051 s->override = R_CS; |
|
4052 goto next_byte; |
|
4053 case 0x36: |
|
4054 s->override = R_SS; |
|
4055 goto next_byte; |
|
4056 case 0x3e: |
|
4057 s->override = R_DS; |
|
4058 goto next_byte; |
|
4059 case 0x26: |
|
4060 s->override = R_ES; |
|
4061 goto next_byte; |
|
4062 case 0x64: |
|
4063 s->override = R_FS; |
|
4064 goto next_byte; |
|
4065 case 0x65: |
|
4066 s->override = R_GS; |
|
4067 goto next_byte; |
|
4068 case 0x66: |
|
4069 prefixes |= PREFIX_DATA; |
|
4070 goto next_byte; |
|
4071 case 0x67: |
|
4072 prefixes |= PREFIX_ADR; |
|
4073 goto next_byte; |
|
4074 } |
|
4075 if (prefixes & PREFIX_DATA) |
|
4076 dflag ^= 1; |
|
4077 if (prefixes & PREFIX_ADR) |
|
4078 aflag ^= 1; |
|
4079 } |
|
4080 |
|
4081 s->prefix = prefixes; |
|
4082 s->aflag = aflag; |
|
4083 s->dflag = dflag; |
|
4084 |
|
4085 /* lock generation */ |
|
4086 if (prefixes & PREFIX_LOCK) |
|
4087 gen_helper_lock(); |
|
4088 |
|
4089 /* now check op code */ |
|
4090 reswitch: |
|
4091 switch(b) { |
|
4092 case 0x0f: |
|
4093 /**************************/ |
|
4094 /* extended op code */ |
|
4095 b = ldub_code(s->pc++) | 0x100; |
|
4096 goto reswitch; |
|
4097 |
|
4098 /**************************/ |
|
4099 /* arith & logic */ |
|
4100 case 0x00 ... 0x05: |
|
4101 case 0x08 ... 0x0d: |
|
4102 case 0x10 ... 0x15: |
|
4103 case 0x18 ... 0x1d: |
|
4104 case 0x20 ... 0x25: |
|
4105 case 0x28 ... 0x2d: |
|
4106 case 0x30 ... 0x35: |
|
4107 case 0x38 ... 0x3d: |
|
4108 { |
|
4109 int op, f, val; |
|
4110 op = (b >> 3) & 7; |
|
4111 f = (b >> 1) & 3; |
|
4112 |
|
4113 if ((b & 1) == 0) |
|
4114 ot = OT_BYTE; |
|
4115 else |
|
4116 ot = dflag + OT_WORD; |
|
4117 |
|
4118 switch(f) { |
|
4119 case 0: /* OP Ev, Gv */ |
|
4120 modrm = ldub_code(s->pc++); |
|
4121 reg = ((modrm >> 3) & 7) | rex_r; |
|
4122 mod = (modrm >> 6) & 3; |
|
4123 rm = (modrm & 7) | REX_B(s); |
|
4124 if (mod != 3) { |
|
4125 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
4126 opreg = OR_TMP0; |
|
4127 } else if (op == OP_XORL && rm == reg) { |
|
4128 xor_zero: |
|
4129 /* xor reg, reg optimisation */ |
|
4130 gen_op_movl_T0_0(); |
|
4131 s->cc_op = CC_OP_LOGICB + ot; |
|
4132 gen_op_mov_reg_T0(ot, reg); |
|
4133 gen_op_update1_cc(); |
|
4134 break; |
|
4135 } else { |
|
4136 opreg = rm; |
|
4137 } |
|
4138 gen_op_mov_TN_reg(ot, 1, reg); |
|
4139 gen_op(s, op, ot, opreg); |
|
4140 break; |
|
4141 case 1: /* OP Gv, Ev */ |
|
4142 modrm = ldub_code(s->pc++); |
|
4143 mod = (modrm >> 6) & 3; |
|
4144 reg = ((modrm >> 3) & 7) | rex_r; |
|
4145 rm = (modrm & 7) | REX_B(s); |
|
4146 if (mod != 3) { |
|
4147 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
4148 gen_op_ld_T1_A0(ot + s->mem_index); |
|
4149 } else if (op == OP_XORL && rm == reg) { |
|
4150 goto xor_zero; |
|
4151 } else { |
|
4152 gen_op_mov_TN_reg(ot, 1, rm); |
|
4153 } |
|
4154 gen_op(s, op, ot, reg); |
|
4155 break; |
|
4156 case 2: /* OP A, Iv */ |
|
4157 val = insn_get(s, ot); |
|
4158 gen_op_movl_T1_im(val); |
|
4159 gen_op(s, op, ot, OR_EAX); |
|
4160 break; |
|
4161 } |
|
4162 } |
|
4163 break; |
|
4164 |
|
4165 case 0x82: |
|
4166 if (CODE64(s)) |
|
4167 goto illegal_op; |
|
4168 case 0x80: /* GRP1 */ |
|
4169 case 0x81: |
|
4170 case 0x83: |
|
4171 { |
|
4172 int val; |
|
4173 |
|
4174 if ((b & 1) == 0) |
|
4175 ot = OT_BYTE; |
|
4176 else |
|
4177 ot = dflag + OT_WORD; |
|
4178 |
|
4179 modrm = ldub_code(s->pc++); |
|
4180 mod = (modrm >> 6) & 3; |
|
4181 rm = (modrm & 7) | REX_B(s); |
|
4182 op = (modrm >> 3) & 7; |
|
4183 |
|
4184 if (mod != 3) { |
|
4185 if (b == 0x83) |
|
4186 s->rip_offset = 1; |
|
4187 else |
|
4188 s->rip_offset = insn_const_size(ot); |
|
4189 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
4190 opreg = OR_TMP0; |
|
4191 } else { |
|
4192 opreg = rm; |
|
4193 } |
|
4194 |
|
4195 switch(b) { |
|
4196 default: |
|
4197 case 0x80: |
|
4198 case 0x81: |
|
4199 case 0x82: |
|
4200 val = insn_get(s, ot); |
|
4201 break; |
|
4202 case 0x83: |
|
4203 val = (int8_t)insn_get(s, OT_BYTE); |
|
4204 break; |
|
4205 } |
|
4206 gen_op_movl_T1_im(val); |
|
4207 gen_op(s, op, ot, opreg); |
|
4208 } |
|
4209 break; |
|
4210 |
|
4211 /**************************/ |
|
4212 /* inc, dec, and other misc arith */ |
|
4213 case 0x40 ... 0x47: /* inc Gv */ |
|
4214 ot = dflag ? OT_LONG : OT_WORD; |
|
4215 gen_inc(s, ot, OR_EAX + (b & 7), 1); |
|
4216 break; |
|
4217 case 0x48 ... 0x4f: /* dec Gv */ |
|
4218 ot = dflag ? OT_LONG : OT_WORD; |
|
4219 gen_inc(s, ot, OR_EAX + (b & 7), -1); |
|
4220 break; |
|
4221 case 0xf6: /* GRP3 */ |
|
4222 case 0xf7: |
|
4223 if ((b & 1) == 0) |
|
4224 ot = OT_BYTE; |
|
4225 else |
|
4226 ot = dflag + OT_WORD; |
|
4227 |
|
4228 modrm = ldub_code(s->pc++); |
|
4229 mod = (modrm >> 6) & 3; |
|
4230 rm = (modrm & 7) | REX_B(s); |
|
4231 op = (modrm >> 3) & 7; |
|
4232 if (mod != 3) { |
|
4233 if (op == 0) |
|
4234 s->rip_offset = insn_const_size(ot); |
|
4235 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
4236 gen_op_ld_T0_A0(ot + s->mem_index); |
|
4237 } else { |
|
4238 gen_op_mov_TN_reg(ot, 0, rm); |
|
4239 } |
|
4240 |
|
4241 switch(op) { |
|
4242 case 0: /* test */ |
|
4243 val = insn_get(s, ot); |
|
4244 gen_op_movl_T1_im(val); |
|
4245 gen_op_testl_T0_T1_cc(); |
|
4246 s->cc_op = CC_OP_LOGICB + ot; |
|
4247 break; |
|
4248 case 2: /* not */ |
|
4249 tcg_gen_not_tl(cpu_T[0], cpu_T[0]); |
|
4250 if (mod != 3) { |
|
4251 gen_op_st_T0_A0(ot + s->mem_index); |
|
4252 } else { |
|
4253 gen_op_mov_reg_T0(ot, rm); |
|
4254 } |
|
4255 break; |
|
4256 case 3: /* neg */ |
|
4257 tcg_gen_neg_tl(cpu_T[0], cpu_T[0]); |
|
4258 if (mod != 3) { |
|
4259 gen_op_st_T0_A0(ot + s->mem_index); |
|
4260 } else { |
|
4261 gen_op_mov_reg_T0(ot, rm); |
|
4262 } |
|
4263 gen_op_update_neg_cc(); |
|
4264 s->cc_op = CC_OP_SUBB + ot; |
|
4265 break; |
|
4266 case 4: /* mul */ |
|
4267 switch(ot) { |
|
4268 case OT_BYTE: |
|
4269 gen_op_mov_TN_reg(OT_BYTE, 1, R_EAX); |
|
4270 tcg_gen_ext8u_tl(cpu_T[0], cpu_T[0]); |
|
4271 tcg_gen_ext8u_tl(cpu_T[1], cpu_T[1]); |
|
4272 /* XXX: use 32 bit mul which could be faster */ |
|
4273 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]); |
|
4274 gen_op_mov_reg_T0(OT_WORD, R_EAX); |
|
4275 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]); |
|
4276 tcg_gen_andi_tl(cpu_cc_src, cpu_T[0], 0xff00); |
|
4277 s->cc_op = CC_OP_MULB; |
|
4278 break; |
|
4279 case OT_WORD: |
|
4280 gen_op_mov_TN_reg(OT_WORD, 1, R_EAX); |
|
4281 tcg_gen_ext16u_tl(cpu_T[0], cpu_T[0]); |
|
4282 tcg_gen_ext16u_tl(cpu_T[1], cpu_T[1]); |
|
4283 /* XXX: use 32 bit mul which could be faster */ |
|
4284 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]); |
|
4285 gen_op_mov_reg_T0(OT_WORD, R_EAX); |
|
4286 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]); |
|
4287 tcg_gen_shri_tl(cpu_T[0], cpu_T[0], 16); |
|
4288 gen_op_mov_reg_T0(OT_WORD, R_EDX); |
|
4289 tcg_gen_mov_tl(cpu_cc_src, cpu_T[0]); |
|
4290 s->cc_op = CC_OP_MULW; |
|
4291 break; |
|
4292 default: |
|
4293 case OT_LONG: |
|
4294 #ifdef TARGET_X86_64 |
|
4295 gen_op_mov_TN_reg(OT_LONG, 1, R_EAX); |
|
4296 tcg_gen_ext32u_tl(cpu_T[0], cpu_T[0]); |
|
4297 tcg_gen_ext32u_tl(cpu_T[1], cpu_T[1]); |
|
4298 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]); |
|
4299 gen_op_mov_reg_T0(OT_LONG, R_EAX); |
|
4300 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]); |
|
4301 tcg_gen_shri_tl(cpu_T[0], cpu_T[0], 32); |
|
4302 gen_op_mov_reg_T0(OT_LONG, R_EDX); |
|
4303 tcg_gen_mov_tl(cpu_cc_src, cpu_T[0]); |
|
4304 #else |
|
4305 { |
|
4306 TCGv_i64 t0, t1; |
|
4307 t0 = tcg_temp_new_i64(); |
|
4308 t1 = tcg_temp_new_i64(); |
|
4309 gen_op_mov_TN_reg(OT_LONG, 1, R_EAX); |
|
4310 tcg_gen_extu_i32_i64(t0, cpu_T[0]); |
|
4311 tcg_gen_extu_i32_i64(t1, cpu_T[1]); |
|
4312 tcg_gen_mul_i64(t0, t0, t1); |
|
4313 tcg_gen_trunc_i64_i32(cpu_T[0], t0); |
|
4314 gen_op_mov_reg_T0(OT_LONG, R_EAX); |
|
4315 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]); |
|
4316 tcg_gen_shri_i64(t0, t0, 32); |
|
4317 tcg_gen_trunc_i64_i32(cpu_T[0], t0); |
|
4318 gen_op_mov_reg_T0(OT_LONG, R_EDX); |
|
4319 tcg_gen_mov_tl(cpu_cc_src, cpu_T[0]); |
|
4320 } |
|
4321 #endif |
|
4322 s->cc_op = CC_OP_MULL; |
|
4323 break; |
|
4324 #ifdef TARGET_X86_64 |
|
4325 case OT_QUAD: |
|
4326 gen_helper_mulq_EAX_T0(cpu_T[0]); |
|
4327 s->cc_op = CC_OP_MULQ; |
|
4328 break; |
|
4329 #endif |
|
4330 } |
|
4331 break; |
|
4332 case 5: /* imul */ |
|
4333 switch(ot) { |
|
4334 case OT_BYTE: |
|
4335 gen_op_mov_TN_reg(OT_BYTE, 1, R_EAX); |
|
4336 tcg_gen_ext8s_tl(cpu_T[0], cpu_T[0]); |
|
4337 tcg_gen_ext8s_tl(cpu_T[1], cpu_T[1]); |
|
4338 /* XXX: use 32 bit mul which could be faster */ |
|
4339 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]); |
|
4340 gen_op_mov_reg_T0(OT_WORD, R_EAX); |
|
4341 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]); |
|
4342 tcg_gen_ext8s_tl(cpu_tmp0, cpu_T[0]); |
|
4343 tcg_gen_sub_tl(cpu_cc_src, cpu_T[0], cpu_tmp0); |
|
4344 s->cc_op = CC_OP_MULB; |
|
4345 break; |
|
4346 case OT_WORD: |
|
4347 gen_op_mov_TN_reg(OT_WORD, 1, R_EAX); |
|
4348 tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]); |
|
4349 tcg_gen_ext16s_tl(cpu_T[1], cpu_T[1]); |
|
4350 /* XXX: use 32 bit mul which could be faster */ |
|
4351 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]); |
|
4352 gen_op_mov_reg_T0(OT_WORD, R_EAX); |
|
4353 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]); |
|
4354 tcg_gen_ext16s_tl(cpu_tmp0, cpu_T[0]); |
|
4355 tcg_gen_sub_tl(cpu_cc_src, cpu_T[0], cpu_tmp0); |
|
4356 tcg_gen_shri_tl(cpu_T[0], cpu_T[0], 16); |
|
4357 gen_op_mov_reg_T0(OT_WORD, R_EDX); |
|
4358 s->cc_op = CC_OP_MULW; |
|
4359 break; |
|
4360 default: |
|
4361 case OT_LONG: |
|
4362 #ifdef TARGET_X86_64 |
|
4363 gen_op_mov_TN_reg(OT_LONG, 1, R_EAX); |
|
4364 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); |
|
4365 tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]); |
|
4366 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]); |
|
4367 gen_op_mov_reg_T0(OT_LONG, R_EAX); |
|
4368 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]); |
|
4369 tcg_gen_ext32s_tl(cpu_tmp0, cpu_T[0]); |
|
4370 tcg_gen_sub_tl(cpu_cc_src, cpu_T[0], cpu_tmp0); |
|
4371 tcg_gen_shri_tl(cpu_T[0], cpu_T[0], 32); |
|
4372 gen_op_mov_reg_T0(OT_LONG, R_EDX); |
|
4373 #else |
|
4374 { |
|
4375 TCGv_i64 t0, t1; |
|
4376 t0 = tcg_temp_new_i64(); |
|
4377 t1 = tcg_temp_new_i64(); |
|
4378 gen_op_mov_TN_reg(OT_LONG, 1, R_EAX); |
|
4379 tcg_gen_ext_i32_i64(t0, cpu_T[0]); |
|
4380 tcg_gen_ext_i32_i64(t1, cpu_T[1]); |
|
4381 tcg_gen_mul_i64(t0, t0, t1); |
|
4382 tcg_gen_trunc_i64_i32(cpu_T[0], t0); |
|
4383 gen_op_mov_reg_T0(OT_LONG, R_EAX); |
|
4384 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]); |
|
4385 tcg_gen_sari_tl(cpu_tmp0, cpu_T[0], 31); |
|
4386 tcg_gen_shri_i64(t0, t0, 32); |
|
4387 tcg_gen_trunc_i64_i32(cpu_T[0], t0); |
|
4388 gen_op_mov_reg_T0(OT_LONG, R_EDX); |
|
4389 tcg_gen_sub_tl(cpu_cc_src, cpu_T[0], cpu_tmp0); |
|
4390 } |
|
4391 #endif |
|
4392 s->cc_op = CC_OP_MULL; |
|
4393 break; |
|
4394 #ifdef TARGET_X86_64 |
|
4395 case OT_QUAD: |
|
4396 gen_helper_imulq_EAX_T0(cpu_T[0]); |
|
4397 s->cc_op = CC_OP_MULQ; |
|
4398 break; |
|
4399 #endif |
|
4400 } |
|
4401 break; |
|
4402 case 6: /* div */ |
|
4403 switch(ot) { |
|
4404 case OT_BYTE: |
|
4405 gen_jmp_im(pc_start - s->cs_base); |
|
4406 gen_helper_divb_AL(cpu_T[0]); |
|
4407 break; |
|
4408 case OT_WORD: |
|
4409 gen_jmp_im(pc_start - s->cs_base); |
|
4410 gen_helper_divw_AX(cpu_T[0]); |
|
4411 break; |
|
4412 default: |
|
4413 case OT_LONG: |
|
4414 gen_jmp_im(pc_start - s->cs_base); |
|
4415 gen_helper_divl_EAX(cpu_T[0]); |
|
4416 break; |
|
4417 #ifdef TARGET_X86_64 |
|
4418 case OT_QUAD: |
|
4419 gen_jmp_im(pc_start - s->cs_base); |
|
4420 gen_helper_divq_EAX(cpu_T[0]); |
|
4421 break; |
|
4422 #endif |
|
4423 } |
|
4424 break; |
|
4425 case 7: /* idiv */ |
|
4426 switch(ot) { |
|
4427 case OT_BYTE: |
|
4428 gen_jmp_im(pc_start - s->cs_base); |
|
4429 gen_helper_idivb_AL(cpu_T[0]); |
|
4430 break; |
|
4431 case OT_WORD: |
|
4432 gen_jmp_im(pc_start - s->cs_base); |
|
4433 gen_helper_idivw_AX(cpu_T[0]); |
|
4434 break; |
|
4435 default: |
|
4436 case OT_LONG: |
|
4437 gen_jmp_im(pc_start - s->cs_base); |
|
4438 gen_helper_idivl_EAX(cpu_T[0]); |
|
4439 break; |
|
4440 #ifdef TARGET_X86_64 |
|
4441 case OT_QUAD: |
|
4442 gen_jmp_im(pc_start - s->cs_base); |
|
4443 gen_helper_idivq_EAX(cpu_T[0]); |
|
4444 break; |
|
4445 #endif |
|
4446 } |
|
4447 break; |
|
4448 default: |
|
4449 goto illegal_op; |
|
4450 } |
|
4451 break; |
|
4452 |
|
4453 case 0xfe: /* GRP4 */ |
|
4454 case 0xff: /* GRP5 */ |
|
4455 if ((b & 1) == 0) |
|
4456 ot = OT_BYTE; |
|
4457 else |
|
4458 ot = dflag + OT_WORD; |
|
4459 |
|
4460 modrm = ldub_code(s->pc++); |
|
4461 mod = (modrm >> 6) & 3; |
|
4462 rm = (modrm & 7) | REX_B(s); |
|
4463 op = (modrm >> 3) & 7; |
|
4464 if (op >= 2 && b == 0xfe) { |
|
4465 goto illegal_op; |
|
4466 } |
|
4467 if (CODE64(s)) { |
|
4468 if (op == 2 || op == 4) { |
|
4469 /* operand size for jumps is 64 bit */ |
|
4470 ot = OT_QUAD; |
|
4471 } else if (op == 3 || op == 5) { |
|
4472 /* for call calls, the operand is 16 or 32 bit, even |
|
4473 in long mode */ |
|
4474 ot = dflag ? OT_LONG : OT_WORD; |
|
4475 } else if (op == 6) { |
|
4476 /* default push size is 64 bit */ |
|
4477 ot = dflag ? OT_QUAD : OT_WORD; |
|
4478 } |
|
4479 } |
|
4480 if (mod != 3) { |
|
4481 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
4482 if (op >= 2 && op != 3 && op != 5) |
|
4483 gen_op_ld_T0_A0(ot + s->mem_index); |
|
4484 } else { |
|
4485 gen_op_mov_TN_reg(ot, 0, rm); |
|
4486 } |
|
4487 |
|
4488 switch(op) { |
|
4489 case 0: /* inc Ev */ |
|
4490 if (mod != 3) |
|
4491 opreg = OR_TMP0; |
|
4492 else |
|
4493 opreg = rm; |
|
4494 gen_inc(s, ot, opreg, 1); |
|
4495 break; |
|
4496 case 1: /* dec Ev */ |
|
4497 if (mod != 3) |
|
4498 opreg = OR_TMP0; |
|
4499 else |
|
4500 opreg = rm; |
|
4501 gen_inc(s, ot, opreg, -1); |
|
4502 break; |
|
4503 case 2: /* call Ev */ |
|
4504 /* XXX: optimize if memory (no 'and' is necessary) */ |
|
4505 if (s->dflag == 0) |
|
4506 gen_op_andl_T0_ffff(); |
|
4507 next_eip = s->pc - s->cs_base; |
|
4508 gen_movtl_T1_im(next_eip); |
|
4509 gen_push_T1(s); |
|
4510 gen_op_jmp_T0(); |
|
4511 gen_eob(s); |
|
4512 break; |
|
4513 case 3: /* lcall Ev */ |
|
4514 gen_op_ld_T1_A0(ot + s->mem_index); |
|
4515 gen_add_A0_im(s, 1 << (ot - OT_WORD + 1)); |
|
4516 gen_op_ldu_T0_A0(OT_WORD + s->mem_index); |
|
4517 do_lcall: |
|
4518 if (s->pe && !s->vm86) { |
|
4519 if (s->cc_op != CC_OP_DYNAMIC) |
|
4520 gen_op_set_cc_op(s->cc_op); |
|
4521 gen_jmp_im(pc_start - s->cs_base); |
|
4522 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); |
|
4523 gen_helper_lcall_protected(cpu_tmp2_i32, cpu_T[1], |
|
4524 tcg_const_i32(dflag), |
|
4525 tcg_const_i32(s->pc - pc_start)); |
|
4526 } else { |
|
4527 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); |
|
4528 gen_helper_lcall_real(cpu_tmp2_i32, cpu_T[1], |
|
4529 tcg_const_i32(dflag), |
|
4530 tcg_const_i32(s->pc - s->cs_base)); |
|
4531 } |
|
4532 gen_eob(s); |
|
4533 break; |
|
4534 case 4: /* jmp Ev */ |
|
4535 if (s->dflag == 0) |
|
4536 gen_op_andl_T0_ffff(); |
|
4537 gen_op_jmp_T0(); |
|
4538 gen_eob(s); |
|
4539 break; |
|
4540 case 5: /* ljmp Ev */ |
|
4541 gen_op_ld_T1_A0(ot + s->mem_index); |
|
4542 gen_add_A0_im(s, 1 << (ot - OT_WORD + 1)); |
|
4543 gen_op_ldu_T0_A0(OT_WORD + s->mem_index); |
|
4544 do_ljmp: |
|
4545 if (s->pe && !s->vm86) { |
|
4546 if (s->cc_op != CC_OP_DYNAMIC) |
|
4547 gen_op_set_cc_op(s->cc_op); |
|
4548 gen_jmp_im(pc_start - s->cs_base); |
|
4549 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); |
|
4550 gen_helper_ljmp_protected(cpu_tmp2_i32, cpu_T[1], |
|
4551 tcg_const_i32(s->pc - pc_start)); |
|
4552 } else { |
|
4553 gen_op_movl_seg_T0_vm(R_CS); |
|
4554 gen_op_movl_T0_T1(); |
|
4555 gen_op_jmp_T0(); |
|
4556 } |
|
4557 gen_eob(s); |
|
4558 break; |
|
4559 case 6: /* push Ev */ |
|
4560 gen_push_T0(s); |
|
4561 break; |
|
4562 default: |
|
4563 goto illegal_op; |
|
4564 } |
|
4565 break; |
|
4566 |
|
4567 case 0x84: /* test Ev, Gv */ |
|
4568 case 0x85: |
|
4569 if ((b & 1) == 0) |
|
4570 ot = OT_BYTE; |
|
4571 else |
|
4572 ot = dflag + OT_WORD; |
|
4573 |
|
4574 modrm = ldub_code(s->pc++); |
|
4575 mod = (modrm >> 6) & 3; |
|
4576 rm = (modrm & 7) | REX_B(s); |
|
4577 reg = ((modrm >> 3) & 7) | rex_r; |
|
4578 |
|
4579 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0); |
|
4580 gen_op_mov_TN_reg(ot, 1, reg); |
|
4581 gen_op_testl_T0_T1_cc(); |
|
4582 s->cc_op = CC_OP_LOGICB + ot; |
|
4583 break; |
|
4584 |
|
4585 case 0xa8: /* test eAX, Iv */ |
|
4586 case 0xa9: |
|
4587 if ((b & 1) == 0) |
|
4588 ot = OT_BYTE; |
|
4589 else |
|
4590 ot = dflag + OT_WORD; |
|
4591 val = insn_get(s, ot); |
|
4592 |
|
4593 gen_op_mov_TN_reg(ot, 0, OR_EAX); |
|
4594 gen_op_movl_T1_im(val); |
|
4595 gen_op_testl_T0_T1_cc(); |
|
4596 s->cc_op = CC_OP_LOGICB + ot; |
|
4597 break; |
|
4598 |
|
4599 case 0x98: /* CWDE/CBW */ |
|
4600 #ifdef TARGET_X86_64 |
|
4601 if (dflag == 2) { |
|
4602 gen_op_mov_TN_reg(OT_LONG, 0, R_EAX); |
|
4603 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); |
|
4604 gen_op_mov_reg_T0(OT_QUAD, R_EAX); |
|
4605 } else |
|
4606 #endif |
|
4607 if (dflag == 1) { |
|
4608 gen_op_mov_TN_reg(OT_WORD, 0, R_EAX); |
|
4609 tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]); |
|
4610 gen_op_mov_reg_T0(OT_LONG, R_EAX); |
|
4611 } else { |
|
4612 gen_op_mov_TN_reg(OT_BYTE, 0, R_EAX); |
|
4613 tcg_gen_ext8s_tl(cpu_T[0], cpu_T[0]); |
|
4614 gen_op_mov_reg_T0(OT_WORD, R_EAX); |
|
4615 } |
|
4616 break; |
|
4617 case 0x99: /* CDQ/CWD */ |
|
4618 #ifdef TARGET_X86_64 |
|
4619 if (dflag == 2) { |
|
4620 gen_op_mov_TN_reg(OT_QUAD, 0, R_EAX); |
|
4621 tcg_gen_sari_tl(cpu_T[0], cpu_T[0], 63); |
|
4622 gen_op_mov_reg_T0(OT_QUAD, R_EDX); |
|
4623 } else |
|
4624 #endif |
|
4625 if (dflag == 1) { |
|
4626 gen_op_mov_TN_reg(OT_LONG, 0, R_EAX); |
|
4627 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); |
|
4628 tcg_gen_sari_tl(cpu_T[0], cpu_T[0], 31); |
|
4629 gen_op_mov_reg_T0(OT_LONG, R_EDX); |
|
4630 } else { |
|
4631 gen_op_mov_TN_reg(OT_WORD, 0, R_EAX); |
|
4632 tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]); |
|
4633 tcg_gen_sari_tl(cpu_T[0], cpu_T[0], 15); |
|
4634 gen_op_mov_reg_T0(OT_WORD, R_EDX); |
|
4635 } |
|
4636 break; |
|
4637 case 0x1af: /* imul Gv, Ev */ |
|
4638 case 0x69: /* imul Gv, Ev, I */ |
|
4639 case 0x6b: |
|
4640 ot = dflag + OT_WORD; |
|
4641 modrm = ldub_code(s->pc++); |
|
4642 reg = ((modrm >> 3) & 7) | rex_r; |
|
4643 if (b == 0x69) |
|
4644 s->rip_offset = insn_const_size(ot); |
|
4645 else if (b == 0x6b) |
|
4646 s->rip_offset = 1; |
|
4647 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0); |
|
4648 if (b == 0x69) { |
|
4649 val = insn_get(s, ot); |
|
4650 gen_op_movl_T1_im(val); |
|
4651 } else if (b == 0x6b) { |
|
4652 val = (int8_t)insn_get(s, OT_BYTE); |
|
4653 gen_op_movl_T1_im(val); |
|
4654 } else { |
|
4655 gen_op_mov_TN_reg(ot, 1, reg); |
|
4656 } |
|
4657 |
|
4658 #ifdef TARGET_X86_64 |
|
4659 if (ot == OT_QUAD) { |
|
4660 gen_helper_imulq_T0_T1(cpu_T[0], cpu_T[0], cpu_T[1]); |
|
4661 } else |
|
4662 #endif |
|
4663 if (ot == OT_LONG) { |
|
4664 #ifdef TARGET_X86_64 |
|
4665 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); |
|
4666 tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]); |
|
4667 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]); |
|
4668 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]); |
|
4669 tcg_gen_ext32s_tl(cpu_tmp0, cpu_T[0]); |
|
4670 tcg_gen_sub_tl(cpu_cc_src, cpu_T[0], cpu_tmp0); |
|
4671 #else |
|
4672 { |
|
4673 TCGv_i64 t0, t1; |
|
4674 t0 = tcg_temp_new_i64(); |
|
4675 t1 = tcg_temp_new_i64(); |
|
4676 tcg_gen_ext_i32_i64(t0, cpu_T[0]); |
|
4677 tcg_gen_ext_i32_i64(t1, cpu_T[1]); |
|
4678 tcg_gen_mul_i64(t0, t0, t1); |
|
4679 tcg_gen_trunc_i64_i32(cpu_T[0], t0); |
|
4680 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]); |
|
4681 tcg_gen_sari_tl(cpu_tmp0, cpu_T[0], 31); |
|
4682 tcg_gen_shri_i64(t0, t0, 32); |
|
4683 tcg_gen_trunc_i64_i32(cpu_T[1], t0); |
|
4684 tcg_gen_sub_tl(cpu_cc_src, cpu_T[1], cpu_tmp0); |
|
4685 } |
|
4686 #endif |
|
4687 } else { |
|
4688 tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]); |
|
4689 tcg_gen_ext16s_tl(cpu_T[1], cpu_T[1]); |
|
4690 /* XXX: use 32 bit mul which could be faster */ |
|
4691 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]); |
|
4692 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]); |
|
4693 tcg_gen_ext16s_tl(cpu_tmp0, cpu_T[0]); |
|
4694 tcg_gen_sub_tl(cpu_cc_src, cpu_T[0], cpu_tmp0); |
|
4695 } |
|
4696 gen_op_mov_reg_T0(ot, reg); |
|
4697 s->cc_op = CC_OP_MULB + ot; |
|
4698 break; |
|
4699 case 0x1c0: |
|
4700 case 0x1c1: /* xadd Ev, Gv */ |
|
4701 if ((b & 1) == 0) |
|
4702 ot = OT_BYTE; |
|
4703 else |
|
4704 ot = dflag + OT_WORD; |
|
4705 modrm = ldub_code(s->pc++); |
|
4706 reg = ((modrm >> 3) & 7) | rex_r; |
|
4707 mod = (modrm >> 6) & 3; |
|
4708 if (mod == 3) { |
|
4709 rm = (modrm & 7) | REX_B(s); |
|
4710 gen_op_mov_TN_reg(ot, 0, reg); |
|
4711 gen_op_mov_TN_reg(ot, 1, rm); |
|
4712 gen_op_addl_T0_T1(); |
|
4713 gen_op_mov_reg_T1(ot, reg); |
|
4714 gen_op_mov_reg_T0(ot, rm); |
|
4715 } else { |
|
4716 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
4717 gen_op_mov_TN_reg(ot, 0, reg); |
|
4718 gen_op_ld_T1_A0(ot + s->mem_index); |
|
4719 gen_op_addl_T0_T1(); |
|
4720 gen_op_st_T0_A0(ot + s->mem_index); |
|
4721 gen_op_mov_reg_T1(ot, reg); |
|
4722 } |
|
4723 gen_op_update2_cc(); |
|
4724 s->cc_op = CC_OP_ADDB + ot; |
|
4725 break; |
|
4726 case 0x1b0: |
|
4727 case 0x1b1: /* cmpxchg Ev, Gv */ |
|
4728 { |
|
4729 int label1, label2; |
|
4730 TCGv t0, t1, t2, a0; |
|
4731 |
|
4732 if ((b & 1) == 0) |
|
4733 ot = OT_BYTE; |
|
4734 else |
|
4735 ot = dflag + OT_WORD; |
|
4736 modrm = ldub_code(s->pc++); |
|
4737 reg = ((modrm >> 3) & 7) | rex_r; |
|
4738 mod = (modrm >> 6) & 3; |
|
4739 t0 = tcg_temp_local_new(); |
|
4740 t1 = tcg_temp_local_new(); |
|
4741 t2 = tcg_temp_local_new(); |
|
4742 a0 = tcg_temp_local_new(); |
|
4743 gen_op_mov_v_reg(ot, t1, reg); |
|
4744 if (mod == 3) { |
|
4745 rm = (modrm & 7) | REX_B(s); |
|
4746 gen_op_mov_v_reg(ot, t0, rm); |
|
4747 } else { |
|
4748 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
4749 tcg_gen_mov_tl(a0, cpu_A0); |
|
4750 gen_op_ld_v(ot + s->mem_index, t0, a0); |
|
4751 rm = 0; /* avoid warning */ |
|
4752 } |
|
4753 label1 = gen_new_label(); |
|
4754 tcg_gen_ld_tl(t2, cpu_env, offsetof(CPUState, regs[R_EAX])); |
|
4755 tcg_gen_sub_tl(t2, t2, t0); |
|
4756 gen_extu(ot, t2); |
|
4757 tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 0, label1); |
|
4758 if (mod == 3) { |
|
4759 label2 = gen_new_label(); |
|
4760 gen_op_mov_reg_v(ot, R_EAX, t0); |
|
4761 tcg_gen_br(label2); |
|
4762 gen_set_label(label1); |
|
4763 gen_op_mov_reg_v(ot, rm, t1); |
|
4764 gen_set_label(label2); |
|
4765 } else { |
|
4766 tcg_gen_mov_tl(t1, t0); |
|
4767 gen_op_mov_reg_v(ot, R_EAX, t0); |
|
4768 gen_set_label(label1); |
|
4769 /* always store */ |
|
4770 gen_op_st_v(ot + s->mem_index, t1, a0); |
|
4771 } |
|
4772 tcg_gen_mov_tl(cpu_cc_src, t0); |
|
4773 tcg_gen_mov_tl(cpu_cc_dst, t2); |
|
4774 s->cc_op = CC_OP_SUBB + ot; |
|
4775 tcg_temp_free(t0); |
|
4776 tcg_temp_free(t1); |
|
4777 tcg_temp_free(t2); |
|
4778 tcg_temp_free(a0); |
|
4779 } |
|
4780 break; |
|
4781 case 0x1c7: /* cmpxchg8b */ |
|
4782 modrm = ldub_code(s->pc++); |
|
4783 mod = (modrm >> 6) & 3; |
|
4784 if ((mod == 3) || ((modrm & 0x38) != 0x8)) |
|
4785 goto illegal_op; |
|
4786 #ifdef TARGET_X86_64 |
|
4787 if (dflag == 2) { |
|
4788 if (!(s->cpuid_ext_features & CPUID_EXT_CX16)) |
|
4789 goto illegal_op; |
|
4790 gen_jmp_im(pc_start - s->cs_base); |
|
4791 if (s->cc_op != CC_OP_DYNAMIC) |
|
4792 gen_op_set_cc_op(s->cc_op); |
|
4793 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
4794 gen_helper_cmpxchg16b(cpu_A0); |
|
4795 } else |
|
4796 #endif |
|
4797 { |
|
4798 if (!(s->cpuid_features & CPUID_CX8)) |
|
4799 goto illegal_op; |
|
4800 gen_jmp_im(pc_start - s->cs_base); |
|
4801 if (s->cc_op != CC_OP_DYNAMIC) |
|
4802 gen_op_set_cc_op(s->cc_op); |
|
4803 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
4804 gen_helper_cmpxchg8b(cpu_A0); |
|
4805 } |
|
4806 s->cc_op = CC_OP_EFLAGS; |
|
4807 break; |
|
4808 |
|
4809 /**************************/ |
|
4810 /* push/pop */ |
|
4811 case 0x50 ... 0x57: /* push */ |
|
4812 gen_op_mov_TN_reg(OT_LONG, 0, (b & 7) | REX_B(s)); |
|
4813 gen_push_T0(s); |
|
4814 break; |
|
4815 case 0x58 ... 0x5f: /* pop */ |
|
4816 if (CODE64(s)) { |
|
4817 ot = dflag ? OT_QUAD : OT_WORD; |
|
4818 } else { |
|
4819 ot = dflag + OT_WORD; |
|
4820 } |
|
4821 gen_pop_T0(s); |
|
4822 /* NOTE: order is important for pop %sp */ |
|
4823 gen_pop_update(s); |
|
4824 gen_op_mov_reg_T0(ot, (b & 7) | REX_B(s)); |
|
4825 break; |
|
4826 case 0x60: /* pusha */ |
|
4827 if (CODE64(s)) |
|
4828 goto illegal_op; |
|
4829 gen_pusha(s); |
|
4830 break; |
|
4831 case 0x61: /* popa */ |
|
4832 if (CODE64(s)) |
|
4833 goto illegal_op; |
|
4834 gen_popa(s); |
|
4835 break; |
|
4836 case 0x68: /* push Iv */ |
|
4837 case 0x6a: |
|
4838 if (CODE64(s)) { |
|
4839 ot = dflag ? OT_QUAD : OT_WORD; |
|
4840 } else { |
|
4841 ot = dflag + OT_WORD; |
|
4842 } |
|
4843 if (b == 0x68) |
|
4844 val = insn_get(s, ot); |
|
4845 else |
|
4846 val = (int8_t)insn_get(s, OT_BYTE); |
|
4847 gen_op_movl_T0_im(val); |
|
4848 gen_push_T0(s); |
|
4849 break; |
|
4850 case 0x8f: /* pop Ev */ |
|
4851 if (CODE64(s)) { |
|
4852 ot = dflag ? OT_QUAD : OT_WORD; |
|
4853 } else { |
|
4854 ot = dflag + OT_WORD; |
|
4855 } |
|
4856 modrm = ldub_code(s->pc++); |
|
4857 mod = (modrm >> 6) & 3; |
|
4858 gen_pop_T0(s); |
|
4859 if (mod == 3) { |
|
4860 /* NOTE: order is important for pop %sp */ |
|
4861 gen_pop_update(s); |
|
4862 rm = (modrm & 7) | REX_B(s); |
|
4863 gen_op_mov_reg_T0(ot, rm); |
|
4864 } else { |
|
4865 /* NOTE: order is important too for MMU exceptions */ |
|
4866 s->popl_esp_hack = 1 << ot; |
|
4867 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1); |
|
4868 s->popl_esp_hack = 0; |
|
4869 gen_pop_update(s); |
|
4870 } |
|
4871 break; |
|
4872 case 0xc8: /* enter */ |
|
4873 { |
|
4874 int level; |
|
4875 val = lduw_code(s->pc); |
|
4876 s->pc += 2; |
|
4877 level = ldub_code(s->pc++); |
|
4878 gen_enter(s, val, level); |
|
4879 } |
|
4880 break; |
|
4881 case 0xc9: /* leave */ |
|
4882 /* XXX: exception not precise (ESP is updated before potential exception) */ |
|
4883 if (CODE64(s)) { |
|
4884 gen_op_mov_TN_reg(OT_QUAD, 0, R_EBP); |
|
4885 gen_op_mov_reg_T0(OT_QUAD, R_ESP); |
|
4886 } else if (s->ss32) { |
|
4887 gen_op_mov_TN_reg(OT_LONG, 0, R_EBP); |
|
4888 gen_op_mov_reg_T0(OT_LONG, R_ESP); |
|
4889 } else { |
|
4890 gen_op_mov_TN_reg(OT_WORD, 0, R_EBP); |
|
4891 gen_op_mov_reg_T0(OT_WORD, R_ESP); |
|
4892 } |
|
4893 gen_pop_T0(s); |
|
4894 if (CODE64(s)) { |
|
4895 ot = dflag ? OT_QUAD : OT_WORD; |
|
4896 } else { |
|
4897 ot = dflag + OT_WORD; |
|
4898 } |
|
4899 gen_op_mov_reg_T0(ot, R_EBP); |
|
4900 gen_pop_update(s); |
|
4901 break; |
|
4902 case 0x06: /* push es */ |
|
4903 case 0x0e: /* push cs */ |
|
4904 case 0x16: /* push ss */ |
|
4905 case 0x1e: /* push ds */ |
|
4906 if (CODE64(s)) |
|
4907 goto illegal_op; |
|
4908 gen_op_movl_T0_seg(b >> 3); |
|
4909 gen_push_T0(s); |
|
4910 break; |
|
4911 case 0x1a0: /* push fs */ |
|
4912 case 0x1a8: /* push gs */ |
|
4913 gen_op_movl_T0_seg((b >> 3) & 7); |
|
4914 gen_push_T0(s); |
|
4915 break; |
|
4916 case 0x07: /* pop es */ |
|
4917 case 0x17: /* pop ss */ |
|
4918 case 0x1f: /* pop ds */ |
|
4919 if (CODE64(s)) |
|
4920 goto illegal_op; |
|
4921 reg = b >> 3; |
|
4922 gen_pop_T0(s); |
|
4923 gen_movl_seg_T0(s, reg, pc_start - s->cs_base); |
|
4924 gen_pop_update(s); |
|
4925 if (reg == R_SS) { |
|
4926 /* if reg == SS, inhibit interrupts/trace. */ |
|
4927 /* If several instructions disable interrupts, only the |
|
4928 _first_ does it */ |
|
4929 if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK)) |
|
4930 gen_helper_set_inhibit_irq(); |
|
4931 s->tf = 0; |
|
4932 } |
|
4933 if (s->is_jmp) { |
|
4934 gen_jmp_im(s->pc - s->cs_base); |
|
4935 gen_eob(s); |
|
4936 } |
|
4937 break; |
|
4938 case 0x1a1: /* pop fs */ |
|
4939 case 0x1a9: /* pop gs */ |
|
4940 gen_pop_T0(s); |
|
4941 gen_movl_seg_T0(s, (b >> 3) & 7, pc_start - s->cs_base); |
|
4942 gen_pop_update(s); |
|
4943 if (s->is_jmp) { |
|
4944 gen_jmp_im(s->pc - s->cs_base); |
|
4945 gen_eob(s); |
|
4946 } |
|
4947 break; |
|
4948 |
|
4949 /**************************/ |
|
4950 /* mov */ |
|
4951 case 0x88: |
|
4952 case 0x89: /* mov Gv, Ev */ |
|
4953 if ((b & 1) == 0) |
|
4954 ot = OT_BYTE; |
|
4955 else |
|
4956 ot = dflag + OT_WORD; |
|
4957 modrm = ldub_code(s->pc++); |
|
4958 reg = ((modrm >> 3) & 7) | rex_r; |
|
4959 |
|
4960 /* generate a generic store */ |
|
4961 gen_ldst_modrm(s, modrm, ot, reg, 1); |
|
4962 break; |
|
4963 case 0xc6: |
|
4964 case 0xc7: /* mov Ev, Iv */ |
|
4965 if ((b & 1) == 0) |
|
4966 ot = OT_BYTE; |
|
4967 else |
|
4968 ot = dflag + OT_WORD; |
|
4969 modrm = ldub_code(s->pc++); |
|
4970 mod = (modrm >> 6) & 3; |
|
4971 if (mod != 3) { |
|
4972 s->rip_offset = insn_const_size(ot); |
|
4973 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
4974 } |
|
4975 val = insn_get(s, ot); |
|
4976 gen_op_movl_T0_im(val); |
|
4977 if (mod != 3) |
|
4978 gen_op_st_T0_A0(ot + s->mem_index); |
|
4979 else |
|
4980 gen_op_mov_reg_T0(ot, (modrm & 7) | REX_B(s)); |
|
4981 break; |
|
4982 case 0x8a: |
|
4983 case 0x8b: /* mov Ev, Gv */ |
|
4984 if ((b & 1) == 0) |
|
4985 ot = OT_BYTE; |
|
4986 else |
|
4987 ot = OT_WORD + dflag; |
|
4988 modrm = ldub_code(s->pc++); |
|
4989 reg = ((modrm >> 3) & 7) | rex_r; |
|
4990 |
|
4991 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0); |
|
4992 gen_op_mov_reg_T0(ot, reg); |
|
4993 break; |
|
4994 case 0x8e: /* mov seg, Gv */ |
|
4995 modrm = ldub_code(s->pc++); |
|
4996 reg = (modrm >> 3) & 7; |
|
4997 if (reg >= 6 || reg == R_CS) |
|
4998 goto illegal_op; |
|
4999 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0); |
|
5000 gen_movl_seg_T0(s, reg, pc_start - s->cs_base); |
|
5001 if (reg == R_SS) { |
|
5002 /* if reg == SS, inhibit interrupts/trace */ |
|
5003 /* If several instructions disable interrupts, only the |
|
5004 _first_ does it */ |
|
5005 if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK)) |
|
5006 gen_helper_set_inhibit_irq(); |
|
5007 s->tf = 0; |
|
5008 } |
|
5009 if (s->is_jmp) { |
|
5010 gen_jmp_im(s->pc - s->cs_base); |
|
5011 gen_eob(s); |
|
5012 } |
|
5013 break; |
|
5014 case 0x8c: /* mov Gv, seg */ |
|
5015 modrm = ldub_code(s->pc++); |
|
5016 reg = (modrm >> 3) & 7; |
|
5017 mod = (modrm >> 6) & 3; |
|
5018 if (reg >= 6) |
|
5019 goto illegal_op; |
|
5020 gen_op_movl_T0_seg(reg); |
|
5021 if (mod == 3) |
|
5022 ot = OT_WORD + dflag; |
|
5023 else |
|
5024 ot = OT_WORD; |
|
5025 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1); |
|
5026 break; |
|
5027 |
|
5028 case 0x1b6: /* movzbS Gv, Eb */ |
|
5029 case 0x1b7: /* movzwS Gv, Eb */ |
|
5030 case 0x1be: /* movsbS Gv, Eb */ |
|
5031 case 0x1bf: /* movswS Gv, Eb */ |
|
5032 { |
|
5033 int d_ot; |
|
5034 /* d_ot is the size of destination */ |
|
5035 d_ot = dflag + OT_WORD; |
|
5036 /* ot is the size of source */ |
|
5037 ot = (b & 1) + OT_BYTE; |
|
5038 modrm = ldub_code(s->pc++); |
|
5039 reg = ((modrm >> 3) & 7) | rex_r; |
|
5040 mod = (modrm >> 6) & 3; |
|
5041 rm = (modrm & 7) | REX_B(s); |
|
5042 |
|
5043 if (mod == 3) { |
|
5044 gen_op_mov_TN_reg(ot, 0, rm); |
|
5045 switch(ot | (b & 8)) { |
|
5046 case OT_BYTE: |
|
5047 tcg_gen_ext8u_tl(cpu_T[0], cpu_T[0]); |
|
5048 break; |
|
5049 case OT_BYTE | 8: |
|
5050 tcg_gen_ext8s_tl(cpu_T[0], cpu_T[0]); |
|
5051 break; |
|
5052 case OT_WORD: |
|
5053 tcg_gen_ext16u_tl(cpu_T[0], cpu_T[0]); |
|
5054 break; |
|
5055 default: |
|
5056 case OT_WORD | 8: |
|
5057 tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]); |
|
5058 break; |
|
5059 } |
|
5060 gen_op_mov_reg_T0(d_ot, reg); |
|
5061 } else { |
|
5062 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
5063 if (b & 8) { |
|
5064 gen_op_lds_T0_A0(ot + s->mem_index); |
|
5065 } else { |
|
5066 gen_op_ldu_T0_A0(ot + s->mem_index); |
|
5067 } |
|
5068 gen_op_mov_reg_T0(d_ot, reg); |
|
5069 } |
|
5070 } |
|
5071 break; |
|
5072 |
|
5073 case 0x8d: /* lea */ |
|
5074 ot = dflag + OT_WORD; |
|
5075 modrm = ldub_code(s->pc++); |
|
5076 mod = (modrm >> 6) & 3; |
|
5077 if (mod == 3) |
|
5078 goto illegal_op; |
|
5079 reg = ((modrm >> 3) & 7) | rex_r; |
|
5080 /* we must ensure that no segment is added */ |
|
5081 s->override = -1; |
|
5082 val = s->addseg; |
|
5083 s->addseg = 0; |
|
5084 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
5085 s->addseg = val; |
|
5086 gen_op_mov_reg_A0(ot - OT_WORD, reg); |
|
5087 break; |
|
5088 |
|
5089 case 0xa0: /* mov EAX, Ov */ |
|
5090 case 0xa1: |
|
5091 case 0xa2: /* mov Ov, EAX */ |
|
5092 case 0xa3: |
|
5093 { |
|
5094 target_ulong offset_addr; |
|
5095 |
|
5096 if ((b & 1) == 0) |
|
5097 ot = OT_BYTE; |
|
5098 else |
|
5099 ot = dflag + OT_WORD; |
|
5100 #ifdef TARGET_X86_64 |
|
5101 if (s->aflag == 2) { |
|
5102 offset_addr = ldq_code(s->pc); |
|
5103 s->pc += 8; |
|
5104 gen_op_movq_A0_im(offset_addr); |
|
5105 } else |
|
5106 #endif |
|
5107 { |
|
5108 if (s->aflag) { |
|
5109 offset_addr = insn_get(s, OT_LONG); |
|
5110 } else { |
|
5111 offset_addr = insn_get(s, OT_WORD); |
|
5112 } |
|
5113 gen_op_movl_A0_im(offset_addr); |
|
5114 } |
|
5115 gen_add_A0_ds_seg(s); |
|
5116 if ((b & 2) == 0) { |
|
5117 gen_op_ld_T0_A0(ot + s->mem_index); |
|
5118 gen_op_mov_reg_T0(ot, R_EAX); |
|
5119 } else { |
|
5120 gen_op_mov_TN_reg(ot, 0, R_EAX); |
|
5121 gen_op_st_T0_A0(ot + s->mem_index); |
|
5122 } |
|
5123 } |
|
5124 break; |
|
5125 case 0xd7: /* xlat */ |
|
5126 #ifdef TARGET_X86_64 |
|
5127 if (s->aflag == 2) { |
|
5128 gen_op_movq_A0_reg(R_EBX); |
|
5129 gen_op_mov_TN_reg(OT_QUAD, 0, R_EAX); |
|
5130 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xff); |
|
5131 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_T[0]); |
|
5132 } else |
|
5133 #endif |
|
5134 { |
|
5135 gen_op_movl_A0_reg(R_EBX); |
|
5136 gen_op_mov_TN_reg(OT_LONG, 0, R_EAX); |
|
5137 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xff); |
|
5138 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_T[0]); |
|
5139 if (s->aflag == 0) |
|
5140 gen_op_andl_A0_ffff(); |
|
5141 else |
|
5142 tcg_gen_andi_tl(cpu_A0, cpu_A0, 0xffffffff); |
|
5143 } |
|
5144 gen_add_A0_ds_seg(s); |
|
5145 gen_op_ldu_T0_A0(OT_BYTE + s->mem_index); |
|
5146 gen_op_mov_reg_T0(OT_BYTE, R_EAX); |
|
5147 break; |
|
5148 case 0xb0 ... 0xb7: /* mov R, Ib */ |
|
5149 val = insn_get(s, OT_BYTE); |
|
5150 gen_op_movl_T0_im(val); |
|
5151 gen_op_mov_reg_T0(OT_BYTE, (b & 7) | REX_B(s)); |
|
5152 break; |
|
5153 case 0xb8 ... 0xbf: /* mov R, Iv */ |
|
5154 #ifdef TARGET_X86_64 |
|
5155 if (dflag == 2) { |
|
5156 uint64_t tmp; |
|
5157 /* 64 bit case */ |
|
5158 tmp = ldq_code(s->pc); |
|
5159 s->pc += 8; |
|
5160 reg = (b & 7) | REX_B(s); |
|
5161 gen_movtl_T0_im(tmp); |
|
5162 gen_op_mov_reg_T0(OT_QUAD, reg); |
|
5163 } else |
|
5164 #endif |
|
5165 { |
|
5166 ot = dflag ? OT_LONG : OT_WORD; |
|
5167 val = insn_get(s, ot); |
|
5168 reg = (b & 7) | REX_B(s); |
|
5169 gen_op_movl_T0_im(val); |
|
5170 gen_op_mov_reg_T0(ot, reg); |
|
5171 } |
|
5172 break; |
|
5173 |
|
5174 case 0x91 ... 0x97: /* xchg R, EAX */ |
|
5175 ot = dflag + OT_WORD; |
|
5176 reg = (b & 7) | REX_B(s); |
|
5177 rm = R_EAX; |
|
5178 goto do_xchg_reg; |
|
5179 case 0x86: |
|
5180 case 0x87: /* xchg Ev, Gv */ |
|
5181 if ((b & 1) == 0) |
|
5182 ot = OT_BYTE; |
|
5183 else |
|
5184 ot = dflag + OT_WORD; |
|
5185 modrm = ldub_code(s->pc++); |
|
5186 reg = ((modrm >> 3) & 7) | rex_r; |
|
5187 mod = (modrm >> 6) & 3; |
|
5188 if (mod == 3) { |
|
5189 rm = (modrm & 7) | REX_B(s); |
|
5190 do_xchg_reg: |
|
5191 gen_op_mov_TN_reg(ot, 0, reg); |
|
5192 gen_op_mov_TN_reg(ot, 1, rm); |
|
5193 gen_op_mov_reg_T0(ot, rm); |
|
5194 gen_op_mov_reg_T1(ot, reg); |
|
5195 } else { |
|
5196 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
5197 gen_op_mov_TN_reg(ot, 0, reg); |
|
5198 /* for xchg, lock is implicit */ |
|
5199 if (!(prefixes & PREFIX_LOCK)) |
|
5200 gen_helper_lock(); |
|
5201 gen_op_ld_T1_A0(ot + s->mem_index); |
|
5202 gen_op_st_T0_A0(ot + s->mem_index); |
|
5203 if (!(prefixes & PREFIX_LOCK)) |
|
5204 gen_helper_unlock(); |
|
5205 gen_op_mov_reg_T1(ot, reg); |
|
5206 } |
|
5207 break; |
|
5208 case 0xc4: /* les Gv */ |
|
5209 if (CODE64(s)) |
|
5210 goto illegal_op; |
|
5211 op = R_ES; |
|
5212 goto do_lxx; |
|
5213 case 0xc5: /* lds Gv */ |
|
5214 if (CODE64(s)) |
|
5215 goto illegal_op; |
|
5216 op = R_DS; |
|
5217 goto do_lxx; |
|
5218 case 0x1b2: /* lss Gv */ |
|
5219 op = R_SS; |
|
5220 goto do_lxx; |
|
5221 case 0x1b4: /* lfs Gv */ |
|
5222 op = R_FS; |
|
5223 goto do_lxx; |
|
5224 case 0x1b5: /* lgs Gv */ |
|
5225 op = R_GS; |
|
5226 do_lxx: |
|
5227 ot = dflag ? OT_LONG : OT_WORD; |
|
5228 modrm = ldub_code(s->pc++); |
|
5229 reg = ((modrm >> 3) & 7) | rex_r; |
|
5230 mod = (modrm >> 6) & 3; |
|
5231 if (mod == 3) |
|
5232 goto illegal_op; |
|
5233 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
5234 gen_op_ld_T1_A0(ot + s->mem_index); |
|
5235 gen_add_A0_im(s, 1 << (ot - OT_WORD + 1)); |
|
5236 /* load the segment first to handle exceptions properly */ |
|
5237 gen_op_ldu_T0_A0(OT_WORD + s->mem_index); |
|
5238 gen_movl_seg_T0(s, op, pc_start - s->cs_base); |
|
5239 /* then put the data */ |
|
5240 gen_op_mov_reg_T1(ot, reg); |
|
5241 if (s->is_jmp) { |
|
5242 gen_jmp_im(s->pc - s->cs_base); |
|
5243 gen_eob(s); |
|
5244 } |
|
5245 break; |
|
5246 |
|
5247 /************************/ |
|
5248 /* shifts */ |
|
5249 case 0xc0: |
|
5250 case 0xc1: |
|
5251 /* shift Ev,Ib */ |
|
5252 shift = 2; |
|
5253 grp2: |
|
5254 { |
|
5255 if ((b & 1) == 0) |
|
5256 ot = OT_BYTE; |
|
5257 else |
|
5258 ot = dflag + OT_WORD; |
|
5259 |
|
5260 modrm = ldub_code(s->pc++); |
|
5261 mod = (modrm >> 6) & 3; |
|
5262 op = (modrm >> 3) & 7; |
|
5263 |
|
5264 if (mod != 3) { |
|
5265 if (shift == 2) { |
|
5266 s->rip_offset = 1; |
|
5267 } |
|
5268 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
5269 opreg = OR_TMP0; |
|
5270 } else { |
|
5271 opreg = (modrm & 7) | REX_B(s); |
|
5272 } |
|
5273 |
|
5274 /* simpler op */ |
|
5275 if (shift == 0) { |
|
5276 gen_shift(s, op, ot, opreg, OR_ECX); |
|
5277 } else { |
|
5278 if (shift == 2) { |
|
5279 shift = ldub_code(s->pc++); |
|
5280 } |
|
5281 gen_shifti(s, op, ot, opreg, shift); |
|
5282 } |
|
5283 } |
|
5284 break; |
|
5285 case 0xd0: |
|
5286 case 0xd1: |
|
5287 /* shift Ev,1 */ |
|
5288 shift = 1; |
|
5289 goto grp2; |
|
5290 case 0xd2: |
|
5291 case 0xd3: |
|
5292 /* shift Ev,cl */ |
|
5293 shift = 0; |
|
5294 goto grp2; |
|
5295 |
|
5296 case 0x1a4: /* shld imm */ |
|
5297 op = 0; |
|
5298 shift = 1; |
|
5299 goto do_shiftd; |
|
5300 case 0x1a5: /* shld cl */ |
|
5301 op = 0; |
|
5302 shift = 0; |
|
5303 goto do_shiftd; |
|
5304 case 0x1ac: /* shrd imm */ |
|
5305 op = 1; |
|
5306 shift = 1; |
|
5307 goto do_shiftd; |
|
5308 case 0x1ad: /* shrd cl */ |
|
5309 op = 1; |
|
5310 shift = 0; |
|
5311 do_shiftd: |
|
5312 ot = dflag + OT_WORD; |
|
5313 modrm = ldub_code(s->pc++); |
|
5314 mod = (modrm >> 6) & 3; |
|
5315 rm = (modrm & 7) | REX_B(s); |
|
5316 reg = ((modrm >> 3) & 7) | rex_r; |
|
5317 if (mod != 3) { |
|
5318 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
5319 opreg = OR_TMP0; |
|
5320 } else { |
|
5321 opreg = rm; |
|
5322 } |
|
5323 gen_op_mov_TN_reg(ot, 1, reg); |
|
5324 |
|
5325 if (shift) { |
|
5326 val = ldub_code(s->pc++); |
|
5327 tcg_gen_movi_tl(cpu_T3, val); |
|
5328 } else { |
|
5329 tcg_gen_ld_tl(cpu_T3, cpu_env, offsetof(CPUState, regs[R_ECX])); |
|
5330 } |
|
5331 gen_shiftd_rm_T1_T3(s, ot, opreg, op); |
|
5332 break; |
|
5333 |
|
5334 /************************/ |
|
5335 /* floats */ |
|
5336 case 0xd8 ... 0xdf: |
|
5337 if (s->flags & (HF_EM_MASK | HF_TS_MASK)) { |
|
5338 /* if CR0.EM or CR0.TS are set, generate an FPU exception */ |
|
5339 /* XXX: what to do if illegal op ? */ |
|
5340 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base); |
|
5341 break; |
|
5342 } |
|
5343 modrm = ldub_code(s->pc++); |
|
5344 mod = (modrm >> 6) & 3; |
|
5345 rm = modrm & 7; |
|
5346 op = ((b & 7) << 3) | ((modrm >> 3) & 7); |
|
5347 if (mod != 3) { |
|
5348 /* memory op */ |
|
5349 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
5350 switch(op) { |
|
5351 case 0x00 ... 0x07: /* fxxxs */ |
|
5352 case 0x10 ... 0x17: /* fixxxl */ |
|
5353 case 0x20 ... 0x27: /* fxxxl */ |
|
5354 case 0x30 ... 0x37: /* fixxx */ |
|
5355 { |
|
5356 int op1; |
|
5357 op1 = op & 7; |
|
5358 |
|
5359 switch(op >> 4) { |
|
5360 case 0: |
|
5361 gen_op_ld_T0_A0(OT_LONG + s->mem_index); |
|
5362 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); |
|
5363 gen_helper_flds_FT0(cpu_tmp2_i32); |
|
5364 break; |
|
5365 case 1: |
|
5366 gen_op_ld_T0_A0(OT_LONG + s->mem_index); |
|
5367 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); |
|
5368 gen_helper_fildl_FT0(cpu_tmp2_i32); |
|
5369 break; |
|
5370 case 2: |
|
5371 tcg_gen_qemu_ld64(cpu_tmp1_i64, cpu_A0, |
|
5372 (s->mem_index >> 2) - 1); |
|
5373 gen_helper_fldl_FT0(cpu_tmp1_i64); |
|
5374 break; |
|
5375 case 3: |
|
5376 default: |
|
5377 gen_op_lds_T0_A0(OT_WORD + s->mem_index); |
|
5378 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); |
|
5379 gen_helper_fildl_FT0(cpu_tmp2_i32); |
|
5380 break; |
|
5381 } |
|
5382 |
|
5383 gen_helper_fp_arith_ST0_FT0(op1); |
|
5384 if (op1 == 3) { |
|
5385 /* fcomp needs pop */ |
|
5386 gen_helper_fpop(); |
|
5387 } |
|
5388 } |
|
5389 break; |
|
5390 case 0x08: /* flds */ |
|
5391 case 0x0a: /* fsts */ |
|
5392 case 0x0b: /* fstps */ |
|
5393 case 0x18 ... 0x1b: /* fildl, fisttpl, fistl, fistpl */ |
|
5394 case 0x28 ... 0x2b: /* fldl, fisttpll, fstl, fstpl */ |
|
5395 case 0x38 ... 0x3b: /* filds, fisttps, fists, fistps */ |
|
5396 switch(op & 7) { |
|
5397 case 0: |
|
5398 switch(op >> 4) { |
|
5399 case 0: |
|
5400 gen_op_ld_T0_A0(OT_LONG + s->mem_index); |
|
5401 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); |
|
5402 gen_helper_flds_ST0(cpu_tmp2_i32); |
|
5403 break; |
|
5404 case 1: |
|
5405 gen_op_ld_T0_A0(OT_LONG + s->mem_index); |
|
5406 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); |
|
5407 gen_helper_fildl_ST0(cpu_tmp2_i32); |
|
5408 break; |
|
5409 case 2: |
|
5410 tcg_gen_qemu_ld64(cpu_tmp1_i64, cpu_A0, |
|
5411 (s->mem_index >> 2) - 1); |
|
5412 gen_helper_fldl_ST0(cpu_tmp1_i64); |
|
5413 break; |
|
5414 case 3: |
|
5415 default: |
|
5416 gen_op_lds_T0_A0(OT_WORD + s->mem_index); |
|
5417 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); |
|
5418 gen_helper_fildl_ST0(cpu_tmp2_i32); |
|
5419 break; |
|
5420 } |
|
5421 break; |
|
5422 case 1: |
|
5423 /* XXX: the corresponding CPUID bit must be tested ! */ |
|
5424 switch(op >> 4) { |
|
5425 case 1: |
|
5426 gen_helper_fisttl_ST0(cpu_tmp2_i32); |
|
5427 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32); |
|
5428 gen_op_st_T0_A0(OT_LONG + s->mem_index); |
|
5429 break; |
|
5430 case 2: |
|
5431 gen_helper_fisttll_ST0(cpu_tmp1_i64); |
|
5432 tcg_gen_qemu_st64(cpu_tmp1_i64, cpu_A0, |
|
5433 (s->mem_index >> 2) - 1); |
|
5434 break; |
|
5435 case 3: |
|
5436 default: |
|
5437 gen_helper_fistt_ST0(cpu_tmp2_i32); |
|
5438 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32); |
|
5439 gen_op_st_T0_A0(OT_WORD + s->mem_index); |
|
5440 break; |
|
5441 } |
|
5442 gen_helper_fpop(); |
|
5443 break; |
|
5444 default: |
|
5445 switch(op >> 4) { |
|
5446 case 0: |
|
5447 gen_helper_fsts_ST0(cpu_tmp2_i32); |
|
5448 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32); |
|
5449 gen_op_st_T0_A0(OT_LONG + s->mem_index); |
|
5450 break; |
|
5451 case 1: |
|
5452 gen_helper_fistl_ST0(cpu_tmp2_i32); |
|
5453 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32); |
|
5454 gen_op_st_T0_A0(OT_LONG + s->mem_index); |
|
5455 break; |
|
5456 case 2: |
|
5457 gen_helper_fstl_ST0(cpu_tmp1_i64); |
|
5458 tcg_gen_qemu_st64(cpu_tmp1_i64, cpu_A0, |
|
5459 (s->mem_index >> 2) - 1); |
|
5460 break; |
|
5461 case 3: |
|
5462 default: |
|
5463 gen_helper_fist_ST0(cpu_tmp2_i32); |
|
5464 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32); |
|
5465 gen_op_st_T0_A0(OT_WORD + s->mem_index); |
|
5466 break; |
|
5467 } |
|
5468 if ((op & 7) == 3) |
|
5469 gen_helper_fpop(); |
|
5470 break; |
|
5471 } |
|
5472 break; |
|
5473 case 0x0c: /* fldenv mem */ |
|
5474 if (s->cc_op != CC_OP_DYNAMIC) |
|
5475 gen_op_set_cc_op(s->cc_op); |
|
5476 gen_jmp_im(pc_start - s->cs_base); |
|
5477 gen_helper_fldenv( |
|
5478 cpu_A0, tcg_const_i32(s->dflag)); |
|
5479 break; |
|
5480 case 0x0d: /* fldcw mem */ |
|
5481 gen_op_ld_T0_A0(OT_WORD + s->mem_index); |
|
5482 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); |
|
5483 gen_helper_fldcw(cpu_tmp2_i32); |
|
5484 break; |
|
5485 case 0x0e: /* fnstenv mem */ |
|
5486 if (s->cc_op != CC_OP_DYNAMIC) |
|
5487 gen_op_set_cc_op(s->cc_op); |
|
5488 gen_jmp_im(pc_start - s->cs_base); |
|
5489 gen_helper_fstenv(cpu_A0, tcg_const_i32(s->dflag)); |
|
5490 break; |
|
5491 case 0x0f: /* fnstcw mem */ |
|
5492 gen_helper_fnstcw(cpu_tmp2_i32); |
|
5493 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32); |
|
5494 gen_op_st_T0_A0(OT_WORD + s->mem_index); |
|
5495 break; |
|
5496 case 0x1d: /* fldt mem */ |
|
5497 if (s->cc_op != CC_OP_DYNAMIC) |
|
5498 gen_op_set_cc_op(s->cc_op); |
|
5499 gen_jmp_im(pc_start - s->cs_base); |
|
5500 gen_helper_fldt_ST0(cpu_A0); |
|
5501 break; |
|
5502 case 0x1f: /* fstpt mem */ |
|
5503 if (s->cc_op != CC_OP_DYNAMIC) |
|
5504 gen_op_set_cc_op(s->cc_op); |
|
5505 gen_jmp_im(pc_start - s->cs_base); |
|
5506 gen_helper_fstt_ST0(cpu_A0); |
|
5507 gen_helper_fpop(); |
|
5508 break; |
|
5509 case 0x2c: /* frstor mem */ |
|
5510 if (s->cc_op != CC_OP_DYNAMIC) |
|
5511 gen_op_set_cc_op(s->cc_op); |
|
5512 gen_jmp_im(pc_start - s->cs_base); |
|
5513 gen_helper_frstor(cpu_A0, tcg_const_i32(s->dflag)); |
|
5514 break; |
|
5515 case 0x2e: /* fnsave mem */ |
|
5516 if (s->cc_op != CC_OP_DYNAMIC) |
|
5517 gen_op_set_cc_op(s->cc_op); |
|
5518 gen_jmp_im(pc_start - s->cs_base); |
|
5519 gen_helper_fsave(cpu_A0, tcg_const_i32(s->dflag)); |
|
5520 break; |
|
5521 case 0x2f: /* fnstsw mem */ |
|
5522 gen_helper_fnstsw(cpu_tmp2_i32); |
|
5523 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32); |
|
5524 gen_op_st_T0_A0(OT_WORD + s->mem_index); |
|
5525 break; |
|
5526 case 0x3c: /* fbld */ |
|
5527 if (s->cc_op != CC_OP_DYNAMIC) |
|
5528 gen_op_set_cc_op(s->cc_op); |
|
5529 gen_jmp_im(pc_start - s->cs_base); |
|
5530 gen_helper_fbld_ST0(cpu_A0); |
|
5531 break; |
|
5532 case 0x3e: /* fbstp */ |
|
5533 if (s->cc_op != CC_OP_DYNAMIC) |
|
5534 gen_op_set_cc_op(s->cc_op); |
|
5535 gen_jmp_im(pc_start - s->cs_base); |
|
5536 gen_helper_fbst_ST0(cpu_A0); |
|
5537 gen_helper_fpop(); |
|
5538 break; |
|
5539 case 0x3d: /* fildll */ |
|
5540 tcg_gen_qemu_ld64(cpu_tmp1_i64, cpu_A0, |
|
5541 (s->mem_index >> 2) - 1); |
|
5542 gen_helper_fildll_ST0(cpu_tmp1_i64); |
|
5543 break; |
|
5544 case 0x3f: /* fistpll */ |
|
5545 gen_helper_fistll_ST0(cpu_tmp1_i64); |
|
5546 tcg_gen_qemu_st64(cpu_tmp1_i64, cpu_A0, |
|
5547 (s->mem_index >> 2) - 1); |
|
5548 gen_helper_fpop(); |
|
5549 break; |
|
5550 default: |
|
5551 goto illegal_op; |
|
5552 } |
|
5553 } else { |
|
5554 /* register float ops */ |
|
5555 opreg = rm; |
|
5556 |
|
5557 switch(op) { |
|
5558 case 0x08: /* fld sti */ |
|
5559 gen_helper_fpush(); |
|
5560 gen_helper_fmov_ST0_STN(tcg_const_i32((opreg + 1) & 7)); |
|
5561 break; |
|
5562 case 0x09: /* fxchg sti */ |
|
5563 case 0x29: /* fxchg4 sti, undocumented op */ |
|
5564 case 0x39: /* fxchg7 sti, undocumented op */ |
|
5565 gen_helper_fxchg_ST0_STN(tcg_const_i32(opreg)); |
|
5566 break; |
|
5567 case 0x0a: /* grp d9/2 */ |
|
5568 switch(rm) { |
|
5569 case 0: /* fnop */ |
|
5570 /* check exceptions (FreeBSD FPU probe) */ |
|
5571 if (s->cc_op != CC_OP_DYNAMIC) |
|
5572 gen_op_set_cc_op(s->cc_op); |
|
5573 gen_jmp_im(pc_start - s->cs_base); |
|
5574 gen_helper_fwait(); |
|
5575 break; |
|
5576 default: |
|
5577 goto illegal_op; |
|
5578 } |
|
5579 break; |
|
5580 case 0x0c: /* grp d9/4 */ |
|
5581 switch(rm) { |
|
5582 case 0: /* fchs */ |
|
5583 gen_helper_fchs_ST0(); |
|
5584 break; |
|
5585 case 1: /* fabs */ |
|
5586 gen_helper_fabs_ST0(); |
|
5587 break; |
|
5588 case 4: /* ftst */ |
|
5589 gen_helper_fldz_FT0(); |
|
5590 gen_helper_fcom_ST0_FT0(); |
|
5591 break; |
|
5592 case 5: /* fxam */ |
|
5593 gen_helper_fxam_ST0(); |
|
5594 break; |
|
5595 default: |
|
5596 goto illegal_op; |
|
5597 } |
|
5598 break; |
|
5599 case 0x0d: /* grp d9/5 */ |
|
5600 { |
|
5601 switch(rm) { |
|
5602 case 0: |
|
5603 gen_helper_fpush(); |
|
5604 gen_helper_fld1_ST0(); |
|
5605 break; |
|
5606 case 1: |
|
5607 gen_helper_fpush(); |
|
5608 gen_helper_fldl2t_ST0(); |
|
5609 break; |
|
5610 case 2: |
|
5611 gen_helper_fpush(); |
|
5612 gen_helper_fldl2e_ST0(); |
|
5613 break; |
|
5614 case 3: |
|
5615 gen_helper_fpush(); |
|
5616 gen_helper_fldpi_ST0(); |
|
5617 break; |
|
5618 case 4: |
|
5619 gen_helper_fpush(); |
|
5620 gen_helper_fldlg2_ST0(); |
|
5621 break; |
|
5622 case 5: |
|
5623 gen_helper_fpush(); |
|
5624 gen_helper_fldln2_ST0(); |
|
5625 break; |
|
5626 case 6: |
|
5627 gen_helper_fpush(); |
|
5628 gen_helper_fldz_ST0(); |
|
5629 break; |
|
5630 default: |
|
5631 goto illegal_op; |
|
5632 } |
|
5633 } |
|
5634 break; |
|
5635 case 0x0e: /* grp d9/6 */ |
|
5636 switch(rm) { |
|
5637 case 0: /* f2xm1 */ |
|
5638 gen_helper_f2xm1(); |
|
5639 break; |
|
5640 case 1: /* fyl2x */ |
|
5641 gen_helper_fyl2x(); |
|
5642 break; |
|
5643 case 2: /* fptan */ |
|
5644 gen_helper_fptan(); |
|
5645 break; |
|
5646 case 3: /* fpatan */ |
|
5647 gen_helper_fpatan(); |
|
5648 break; |
|
5649 case 4: /* fxtract */ |
|
5650 gen_helper_fxtract(); |
|
5651 break; |
|
5652 case 5: /* fprem1 */ |
|
5653 gen_helper_fprem1(); |
|
5654 break; |
|
5655 case 6: /* fdecstp */ |
|
5656 gen_helper_fdecstp(); |
|
5657 break; |
|
5658 default: |
|
5659 case 7: /* fincstp */ |
|
5660 gen_helper_fincstp(); |
|
5661 break; |
|
5662 } |
|
5663 break; |
|
5664 case 0x0f: /* grp d9/7 */ |
|
5665 switch(rm) { |
|
5666 case 0: /* fprem */ |
|
5667 gen_helper_fprem(); |
|
5668 break; |
|
5669 case 1: /* fyl2xp1 */ |
|
5670 gen_helper_fyl2xp1(); |
|
5671 break; |
|
5672 case 2: /* fsqrt */ |
|
5673 gen_helper_fsqrt(); |
|
5674 break; |
|
5675 case 3: /* fsincos */ |
|
5676 gen_helper_fsincos(); |
|
5677 break; |
|
5678 case 5: /* fscale */ |
|
5679 gen_helper_fscale(); |
|
5680 break; |
|
5681 case 4: /* frndint */ |
|
5682 gen_helper_frndint(); |
|
5683 break; |
|
5684 case 6: /* fsin */ |
|
5685 gen_helper_fsin(); |
|
5686 break; |
|
5687 default: |
|
5688 case 7: /* fcos */ |
|
5689 gen_helper_fcos(); |
|
5690 break; |
|
5691 } |
|
5692 break; |
|
5693 case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */ |
|
5694 case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */ |
|
5695 case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */ |
|
5696 { |
|
5697 int op1; |
|
5698 |
|
5699 op1 = op & 7; |
|
5700 if (op >= 0x20) { |
|
5701 gen_helper_fp_arith_STN_ST0(op1, opreg); |
|
5702 if (op >= 0x30) |
|
5703 gen_helper_fpop(); |
|
5704 } else { |
|
5705 gen_helper_fmov_FT0_STN(tcg_const_i32(opreg)); |
|
5706 gen_helper_fp_arith_ST0_FT0(op1); |
|
5707 } |
|
5708 } |
|
5709 break; |
|
5710 case 0x02: /* fcom */ |
|
5711 case 0x22: /* fcom2, undocumented op */ |
|
5712 gen_helper_fmov_FT0_STN(tcg_const_i32(opreg)); |
|
5713 gen_helper_fcom_ST0_FT0(); |
|
5714 break; |
|
5715 case 0x03: /* fcomp */ |
|
5716 case 0x23: /* fcomp3, undocumented op */ |
|
5717 case 0x32: /* fcomp5, undocumented op */ |
|
5718 gen_helper_fmov_FT0_STN(tcg_const_i32(opreg)); |
|
5719 gen_helper_fcom_ST0_FT0(); |
|
5720 gen_helper_fpop(); |
|
5721 break; |
|
5722 case 0x15: /* da/5 */ |
|
5723 switch(rm) { |
|
5724 case 1: /* fucompp */ |
|
5725 gen_helper_fmov_FT0_STN(tcg_const_i32(1)); |
|
5726 gen_helper_fucom_ST0_FT0(); |
|
5727 gen_helper_fpop(); |
|
5728 gen_helper_fpop(); |
|
5729 break; |
|
5730 default: |
|
5731 goto illegal_op; |
|
5732 } |
|
5733 break; |
|
5734 case 0x1c: |
|
5735 switch(rm) { |
|
5736 case 0: /* feni (287 only, just do nop here) */ |
|
5737 break; |
|
5738 case 1: /* fdisi (287 only, just do nop here) */ |
|
5739 break; |
|
5740 case 2: /* fclex */ |
|
5741 gen_helper_fclex(); |
|
5742 break; |
|
5743 case 3: /* fninit */ |
|
5744 gen_helper_fninit(); |
|
5745 break; |
|
5746 case 4: /* fsetpm (287 only, just do nop here) */ |
|
5747 break; |
|
5748 default: |
|
5749 goto illegal_op; |
|
5750 } |
|
5751 break; |
|
5752 case 0x1d: /* fucomi */ |
|
5753 if (s->cc_op != CC_OP_DYNAMIC) |
|
5754 gen_op_set_cc_op(s->cc_op); |
|
5755 gen_helper_fmov_FT0_STN(tcg_const_i32(opreg)); |
|
5756 gen_helper_fucomi_ST0_FT0(); |
|
5757 s->cc_op = CC_OP_EFLAGS; |
|
5758 break; |
|
5759 case 0x1e: /* fcomi */ |
|
5760 if (s->cc_op != CC_OP_DYNAMIC) |
|
5761 gen_op_set_cc_op(s->cc_op); |
|
5762 gen_helper_fmov_FT0_STN(tcg_const_i32(opreg)); |
|
5763 gen_helper_fcomi_ST0_FT0(); |
|
5764 s->cc_op = CC_OP_EFLAGS; |
|
5765 break; |
|
5766 case 0x28: /* ffree sti */ |
|
5767 gen_helper_ffree_STN(tcg_const_i32(opreg)); |
|
5768 break; |
|
5769 case 0x2a: /* fst sti */ |
|
5770 gen_helper_fmov_STN_ST0(tcg_const_i32(opreg)); |
|
5771 break; |
|
5772 case 0x2b: /* fstp sti */ |
|
5773 case 0x0b: /* fstp1 sti, undocumented op */ |
|
5774 case 0x3a: /* fstp8 sti, undocumented op */ |
|
5775 case 0x3b: /* fstp9 sti, undocumented op */ |
|
5776 gen_helper_fmov_STN_ST0(tcg_const_i32(opreg)); |
|
5777 gen_helper_fpop(); |
|
5778 break; |
|
5779 case 0x2c: /* fucom st(i) */ |
|
5780 gen_helper_fmov_FT0_STN(tcg_const_i32(opreg)); |
|
5781 gen_helper_fucom_ST0_FT0(); |
|
5782 break; |
|
5783 case 0x2d: /* fucomp st(i) */ |
|
5784 gen_helper_fmov_FT0_STN(tcg_const_i32(opreg)); |
|
5785 gen_helper_fucom_ST0_FT0(); |
|
5786 gen_helper_fpop(); |
|
5787 break; |
|
5788 case 0x33: /* de/3 */ |
|
5789 switch(rm) { |
|
5790 case 1: /* fcompp */ |
|
5791 gen_helper_fmov_FT0_STN(tcg_const_i32(1)); |
|
5792 gen_helper_fcom_ST0_FT0(); |
|
5793 gen_helper_fpop(); |
|
5794 gen_helper_fpop(); |
|
5795 break; |
|
5796 default: |
|
5797 goto illegal_op; |
|
5798 } |
|
5799 break; |
|
5800 case 0x38: /* ffreep sti, undocumented op */ |
|
5801 gen_helper_ffree_STN(tcg_const_i32(opreg)); |
|
5802 gen_helper_fpop(); |
|
5803 break; |
|
5804 case 0x3c: /* df/4 */ |
|
5805 switch(rm) { |
|
5806 case 0: |
|
5807 gen_helper_fnstsw(cpu_tmp2_i32); |
|
5808 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32); |
|
5809 gen_op_mov_reg_T0(OT_WORD, R_EAX); |
|
5810 break; |
|
5811 default: |
|
5812 goto illegal_op; |
|
5813 } |
|
5814 break; |
|
5815 case 0x3d: /* fucomip */ |
|
5816 if (s->cc_op != CC_OP_DYNAMIC) |
|
5817 gen_op_set_cc_op(s->cc_op); |
|
5818 gen_helper_fmov_FT0_STN(tcg_const_i32(opreg)); |
|
5819 gen_helper_fucomi_ST0_FT0(); |
|
5820 gen_helper_fpop(); |
|
5821 s->cc_op = CC_OP_EFLAGS; |
|
5822 break; |
|
5823 case 0x3e: /* fcomip */ |
|
5824 if (s->cc_op != CC_OP_DYNAMIC) |
|
5825 gen_op_set_cc_op(s->cc_op); |
|
5826 gen_helper_fmov_FT0_STN(tcg_const_i32(opreg)); |
|
5827 gen_helper_fcomi_ST0_FT0(); |
|
5828 gen_helper_fpop(); |
|
5829 s->cc_op = CC_OP_EFLAGS; |
|
5830 break; |
|
5831 case 0x10 ... 0x13: /* fcmovxx */ |
|
5832 case 0x18 ... 0x1b: |
|
5833 { |
|
5834 int op1, l1; |
|
5835 static const uint8_t fcmov_cc[8] = { |
|
5836 (JCC_B << 1), |
|
5837 (JCC_Z << 1), |
|
5838 (JCC_BE << 1), |
|
5839 (JCC_P << 1), |
|
5840 }; |
|
5841 op1 = fcmov_cc[op & 3] | (((op >> 3) & 1) ^ 1); |
|
5842 l1 = gen_new_label(); |
|
5843 gen_jcc1(s, s->cc_op, op1, l1); |
|
5844 gen_helper_fmov_ST0_STN(tcg_const_i32(opreg)); |
|
5845 gen_set_label(l1); |
|
5846 } |
|
5847 break; |
|
5848 default: |
|
5849 goto illegal_op; |
|
5850 } |
|
5851 } |
|
5852 break; |
|
5853 /************************/ |
|
5854 /* string ops */ |
|
5855 |
|
5856 case 0xa4: /* movsS */ |
|
5857 case 0xa5: |
|
5858 if ((b & 1) == 0) |
|
5859 ot = OT_BYTE; |
|
5860 else |
|
5861 ot = dflag + OT_WORD; |
|
5862 |
|
5863 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) { |
|
5864 gen_repz_movs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base); |
|
5865 } else { |
|
5866 gen_movs(s, ot); |
|
5867 } |
|
5868 break; |
|
5869 |
|
5870 case 0xaa: /* stosS */ |
|
5871 case 0xab: |
|
5872 if ((b & 1) == 0) |
|
5873 ot = OT_BYTE; |
|
5874 else |
|
5875 ot = dflag + OT_WORD; |
|
5876 |
|
5877 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) { |
|
5878 gen_repz_stos(s, ot, pc_start - s->cs_base, s->pc - s->cs_base); |
|
5879 } else { |
|
5880 gen_stos(s, ot); |
|
5881 } |
|
5882 break; |
|
5883 case 0xac: /* lodsS */ |
|
5884 case 0xad: |
|
5885 if ((b & 1) == 0) |
|
5886 ot = OT_BYTE; |
|
5887 else |
|
5888 ot = dflag + OT_WORD; |
|
5889 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) { |
|
5890 gen_repz_lods(s, ot, pc_start - s->cs_base, s->pc - s->cs_base); |
|
5891 } else { |
|
5892 gen_lods(s, ot); |
|
5893 } |
|
5894 break; |
|
5895 case 0xae: /* scasS */ |
|
5896 case 0xaf: |
|
5897 if ((b & 1) == 0) |
|
5898 ot = OT_BYTE; |
|
5899 else |
|
5900 ot = dflag + OT_WORD; |
|
5901 if (prefixes & PREFIX_REPNZ) { |
|
5902 gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1); |
|
5903 } else if (prefixes & PREFIX_REPZ) { |
|
5904 gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0); |
|
5905 } else { |
|
5906 gen_scas(s, ot); |
|
5907 s->cc_op = CC_OP_SUBB + ot; |
|
5908 } |
|
5909 break; |
|
5910 |
|
5911 case 0xa6: /* cmpsS */ |
|
5912 case 0xa7: |
|
5913 if ((b & 1) == 0) |
|
5914 ot = OT_BYTE; |
|
5915 else |
|
5916 ot = dflag + OT_WORD; |
|
5917 if (prefixes & PREFIX_REPNZ) { |
|
5918 gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1); |
|
5919 } else if (prefixes & PREFIX_REPZ) { |
|
5920 gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0); |
|
5921 } else { |
|
5922 gen_cmps(s, ot); |
|
5923 s->cc_op = CC_OP_SUBB + ot; |
|
5924 } |
|
5925 break; |
|
5926 case 0x6c: /* insS */ |
|
5927 case 0x6d: |
|
5928 if ((b & 1) == 0) |
|
5929 ot = OT_BYTE; |
|
5930 else |
|
5931 ot = dflag ? OT_LONG : OT_WORD; |
|
5932 gen_op_mov_TN_reg(OT_WORD, 0, R_EDX); |
|
5933 gen_op_andl_T0_ffff(); |
|
5934 gen_check_io(s, ot, pc_start - s->cs_base, |
|
5935 SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes) | 4); |
|
5936 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) { |
|
5937 gen_repz_ins(s, ot, pc_start - s->cs_base, s->pc - s->cs_base); |
|
5938 } else { |
|
5939 gen_ins(s, ot); |
|
5940 if (use_icount) { |
|
5941 gen_jmp(s, s->pc - s->cs_base); |
|
5942 } |
|
5943 } |
|
5944 break; |
|
5945 case 0x6e: /* outsS */ |
|
5946 case 0x6f: |
|
5947 if ((b & 1) == 0) |
|
5948 ot = OT_BYTE; |
|
5949 else |
|
5950 ot = dflag ? OT_LONG : OT_WORD; |
|
5951 gen_op_mov_TN_reg(OT_WORD, 0, R_EDX); |
|
5952 gen_op_andl_T0_ffff(); |
|
5953 gen_check_io(s, ot, pc_start - s->cs_base, |
|
5954 svm_is_rep(prefixes) | 4); |
|
5955 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) { |
|
5956 gen_repz_outs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base); |
|
5957 } else { |
|
5958 gen_outs(s, ot); |
|
5959 if (use_icount) { |
|
5960 gen_jmp(s, s->pc - s->cs_base); |
|
5961 } |
|
5962 } |
|
5963 break; |
|
5964 |
|
5965 /************************/ |
|
5966 /* port I/O */ |
|
5967 |
|
5968 case 0xe4: |
|
5969 case 0xe5: |
|
5970 if ((b & 1) == 0) |
|
5971 ot = OT_BYTE; |
|
5972 else |
|
5973 ot = dflag ? OT_LONG : OT_WORD; |
|
5974 val = ldub_code(s->pc++); |
|
5975 gen_op_movl_T0_im(val); |
|
5976 gen_check_io(s, ot, pc_start - s->cs_base, |
|
5977 SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes)); |
|
5978 if (use_icount) |
|
5979 gen_io_start(); |
|
5980 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); |
|
5981 gen_helper_in_func(ot, cpu_T[1], cpu_tmp2_i32); |
|
5982 gen_op_mov_reg_T1(ot, R_EAX); |
|
5983 if (use_icount) { |
|
5984 gen_io_end(); |
|
5985 gen_jmp(s, s->pc - s->cs_base); |
|
5986 } |
|
5987 break; |
|
5988 case 0xe6: |
|
5989 case 0xe7: |
|
5990 if ((b & 1) == 0) |
|
5991 ot = OT_BYTE; |
|
5992 else |
|
5993 ot = dflag ? OT_LONG : OT_WORD; |
|
5994 val = ldub_code(s->pc++); |
|
5995 gen_op_movl_T0_im(val); |
|
5996 gen_check_io(s, ot, pc_start - s->cs_base, |
|
5997 svm_is_rep(prefixes)); |
|
5998 gen_op_mov_TN_reg(ot, 1, R_EAX); |
|
5999 |
|
6000 if (use_icount) |
|
6001 gen_io_start(); |
|
6002 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); |
|
6003 tcg_gen_andi_i32(cpu_tmp2_i32, cpu_tmp2_i32, 0xffff); |
|
6004 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T[1]); |
|
6005 gen_helper_out_func(ot, cpu_tmp2_i32, cpu_tmp3_i32); |
|
6006 if (use_icount) { |
|
6007 gen_io_end(); |
|
6008 gen_jmp(s, s->pc - s->cs_base); |
|
6009 } |
|
6010 break; |
|
6011 case 0xec: |
|
6012 case 0xed: |
|
6013 if ((b & 1) == 0) |
|
6014 ot = OT_BYTE; |
|
6015 else |
|
6016 ot = dflag ? OT_LONG : OT_WORD; |
|
6017 gen_op_mov_TN_reg(OT_WORD, 0, R_EDX); |
|
6018 gen_op_andl_T0_ffff(); |
|
6019 gen_check_io(s, ot, pc_start - s->cs_base, |
|
6020 SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes)); |
|
6021 if (use_icount) |
|
6022 gen_io_start(); |
|
6023 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); |
|
6024 gen_helper_in_func(ot, cpu_T[1], cpu_tmp2_i32); |
|
6025 gen_op_mov_reg_T1(ot, R_EAX); |
|
6026 if (use_icount) { |
|
6027 gen_io_end(); |
|
6028 gen_jmp(s, s->pc - s->cs_base); |
|
6029 } |
|
6030 break; |
|
6031 case 0xee: |
|
6032 case 0xef: |
|
6033 if ((b & 1) == 0) |
|
6034 ot = OT_BYTE; |
|
6035 else |
|
6036 ot = dflag ? OT_LONG : OT_WORD; |
|
6037 gen_op_mov_TN_reg(OT_WORD, 0, R_EDX); |
|
6038 gen_op_andl_T0_ffff(); |
|
6039 gen_check_io(s, ot, pc_start - s->cs_base, |
|
6040 svm_is_rep(prefixes)); |
|
6041 gen_op_mov_TN_reg(ot, 1, R_EAX); |
|
6042 |
|
6043 if (use_icount) |
|
6044 gen_io_start(); |
|
6045 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); |
|
6046 tcg_gen_andi_i32(cpu_tmp2_i32, cpu_tmp2_i32, 0xffff); |
|
6047 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T[1]); |
|
6048 gen_helper_out_func(ot, cpu_tmp2_i32, cpu_tmp3_i32); |
|
6049 if (use_icount) { |
|
6050 gen_io_end(); |
|
6051 gen_jmp(s, s->pc - s->cs_base); |
|
6052 } |
|
6053 break; |
|
6054 |
|
6055 /************************/ |
|
6056 /* control */ |
|
6057 case 0xc2: /* ret im */ |
|
6058 val = ldsw_code(s->pc); |
|
6059 s->pc += 2; |
|
6060 gen_pop_T0(s); |
|
6061 if (CODE64(s) && s->dflag) |
|
6062 s->dflag = 2; |
|
6063 gen_stack_update(s, val + (2 << s->dflag)); |
|
6064 if (s->dflag == 0) |
|
6065 gen_op_andl_T0_ffff(); |
|
6066 gen_op_jmp_T0(); |
|
6067 gen_eob(s); |
|
6068 break; |
|
6069 case 0xc3: /* ret */ |
|
6070 gen_pop_T0(s); |
|
6071 gen_pop_update(s); |
|
6072 if (s->dflag == 0) |
|
6073 gen_op_andl_T0_ffff(); |
|
6074 gen_op_jmp_T0(); |
|
6075 gen_eob(s); |
|
6076 break; |
|
6077 case 0xca: /* lret im */ |
|
6078 val = ldsw_code(s->pc); |
|
6079 s->pc += 2; |
|
6080 do_lret: |
|
6081 if (s->pe && !s->vm86) { |
|
6082 if (s->cc_op != CC_OP_DYNAMIC) |
|
6083 gen_op_set_cc_op(s->cc_op); |
|
6084 gen_jmp_im(pc_start - s->cs_base); |
|
6085 gen_helper_lret_protected(tcg_const_i32(s->dflag), |
|
6086 tcg_const_i32(val)); |
|
6087 } else { |
|
6088 gen_stack_A0(s); |
|
6089 /* pop offset */ |
|
6090 gen_op_ld_T0_A0(1 + s->dflag + s->mem_index); |
|
6091 if (s->dflag == 0) |
|
6092 gen_op_andl_T0_ffff(); |
|
6093 /* NOTE: keeping EIP updated is not a problem in case of |
|
6094 exception */ |
|
6095 gen_op_jmp_T0(); |
|
6096 /* pop selector */ |
|
6097 gen_op_addl_A0_im(2 << s->dflag); |
|
6098 gen_op_ld_T0_A0(1 + s->dflag + s->mem_index); |
|
6099 gen_op_movl_seg_T0_vm(R_CS); |
|
6100 /* add stack offset */ |
|
6101 gen_stack_update(s, val + (4 << s->dflag)); |
|
6102 } |
|
6103 gen_eob(s); |
|
6104 break; |
|
6105 case 0xcb: /* lret */ |
|
6106 val = 0; |
|
6107 goto do_lret; |
|
6108 case 0xcf: /* iret */ |
|
6109 gen_svm_check_intercept(s, pc_start, SVM_EXIT_IRET); |
|
6110 if (!s->pe) { |
|
6111 /* real mode */ |
|
6112 gen_helper_iret_real(tcg_const_i32(s->dflag)); |
|
6113 s->cc_op = CC_OP_EFLAGS; |
|
6114 } else if (s->vm86) { |
|
6115 if (s->iopl != 3) { |
|
6116 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
|
6117 } else { |
|
6118 gen_helper_iret_real(tcg_const_i32(s->dflag)); |
|
6119 s->cc_op = CC_OP_EFLAGS; |
|
6120 } |
|
6121 } else { |
|
6122 if (s->cc_op != CC_OP_DYNAMIC) |
|
6123 gen_op_set_cc_op(s->cc_op); |
|
6124 gen_jmp_im(pc_start - s->cs_base); |
|
6125 gen_helper_iret_protected(tcg_const_i32(s->dflag), |
|
6126 tcg_const_i32(s->pc - s->cs_base)); |
|
6127 s->cc_op = CC_OP_EFLAGS; |
|
6128 } |
|
6129 gen_eob(s); |
|
6130 break; |
|
6131 case 0xe8: /* call im */ |
|
6132 { |
|
6133 if (dflag) |
|
6134 tval = (int32_t)insn_get(s, OT_LONG); |
|
6135 else |
|
6136 tval = (int16_t)insn_get(s, OT_WORD); |
|
6137 next_eip = s->pc - s->cs_base; |
|
6138 tval += next_eip; |
|
6139 if (s->dflag == 0) |
|
6140 tval &= 0xffff; |
|
6141 gen_movtl_T0_im(next_eip); |
|
6142 gen_push_T0(s); |
|
6143 gen_jmp(s, tval); |
|
6144 } |
|
6145 break; |
|
6146 case 0x9a: /* lcall im */ |
|
6147 { |
|
6148 unsigned int selector, offset; |
|
6149 |
|
6150 if (CODE64(s)) |
|
6151 goto illegal_op; |
|
6152 ot = dflag ? OT_LONG : OT_WORD; |
|
6153 offset = insn_get(s, ot); |
|
6154 selector = insn_get(s, OT_WORD); |
|
6155 |
|
6156 gen_op_movl_T0_im(selector); |
|
6157 gen_op_movl_T1_imu(offset); |
|
6158 } |
|
6159 goto do_lcall; |
|
6160 case 0xe9: /* jmp im */ |
|
6161 if (dflag) |
|
6162 tval = (int32_t)insn_get(s, OT_LONG); |
|
6163 else |
|
6164 tval = (int16_t)insn_get(s, OT_WORD); |
|
6165 tval += s->pc - s->cs_base; |
|
6166 if (s->dflag == 0) |
|
6167 tval &= 0xffff; |
|
6168 else if(!CODE64(s)) |
|
6169 tval &= 0xffffffff; |
|
6170 gen_jmp(s, tval); |
|
6171 break; |
|
6172 case 0xea: /* ljmp im */ |
|
6173 { |
|
6174 unsigned int selector, offset; |
|
6175 |
|
6176 if (CODE64(s)) |
|
6177 goto illegal_op; |
|
6178 ot = dflag ? OT_LONG : OT_WORD; |
|
6179 offset = insn_get(s, ot); |
|
6180 selector = insn_get(s, OT_WORD); |
|
6181 |
|
6182 gen_op_movl_T0_im(selector); |
|
6183 gen_op_movl_T1_imu(offset); |
|
6184 } |
|
6185 goto do_ljmp; |
|
6186 case 0xeb: /* jmp Jb */ |
|
6187 tval = (int8_t)insn_get(s, OT_BYTE); |
|
6188 tval += s->pc - s->cs_base; |
|
6189 if (s->dflag == 0) |
|
6190 tval &= 0xffff; |
|
6191 gen_jmp(s, tval); |
|
6192 break; |
|
6193 case 0x70 ... 0x7f: /* jcc Jb */ |
|
6194 tval = (int8_t)insn_get(s, OT_BYTE); |
|
6195 goto do_jcc; |
|
6196 case 0x180 ... 0x18f: /* jcc Jv */ |
|
6197 if (dflag) { |
|
6198 tval = (int32_t)insn_get(s, OT_LONG); |
|
6199 } else { |
|
6200 tval = (int16_t)insn_get(s, OT_WORD); |
|
6201 } |
|
6202 do_jcc: |
|
6203 next_eip = s->pc - s->cs_base; |
|
6204 tval += next_eip; |
|
6205 if (s->dflag == 0) |
|
6206 tval &= 0xffff; |
|
6207 gen_jcc(s, b, tval, next_eip); |
|
6208 break; |
|
6209 |
|
6210 case 0x190 ... 0x19f: /* setcc Gv */ |
|
6211 modrm = ldub_code(s->pc++); |
|
6212 gen_setcc(s, b); |
|
6213 gen_ldst_modrm(s, modrm, OT_BYTE, OR_TMP0, 1); |
|
6214 break; |
|
6215 case 0x140 ... 0x14f: /* cmov Gv, Ev */ |
|
6216 { |
|
6217 int l1; |
|
6218 TCGv t0; |
|
6219 |
|
6220 ot = dflag + OT_WORD; |
|
6221 modrm = ldub_code(s->pc++); |
|
6222 reg = ((modrm >> 3) & 7) | rex_r; |
|
6223 mod = (modrm >> 6) & 3; |
|
6224 t0 = tcg_temp_local_new(); |
|
6225 if (mod != 3) { |
|
6226 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
6227 gen_op_ld_v(ot + s->mem_index, t0, cpu_A0); |
|
6228 } else { |
|
6229 rm = (modrm & 7) | REX_B(s); |
|
6230 gen_op_mov_v_reg(ot, t0, rm); |
|
6231 } |
|
6232 #ifdef TARGET_X86_64 |
|
6233 if (ot == OT_LONG) { |
|
6234 /* XXX: specific Intel behaviour ? */ |
|
6235 l1 = gen_new_label(); |
|
6236 gen_jcc1(s, s->cc_op, b ^ 1, l1); |
|
6237 tcg_gen_st32_tl(t0, cpu_env, offsetof(CPUState, regs[reg]) + REG_L_OFFSET); |
|
6238 gen_set_label(l1); |
|
6239 tcg_gen_movi_tl(cpu_tmp0, 0); |
|
6240 tcg_gen_st32_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg]) + REG_LH_OFFSET); |
|
6241 } else |
|
6242 #endif |
|
6243 { |
|
6244 l1 = gen_new_label(); |
|
6245 gen_jcc1(s, s->cc_op, b ^ 1, l1); |
|
6246 gen_op_mov_reg_v(ot, reg, t0); |
|
6247 gen_set_label(l1); |
|
6248 } |
|
6249 tcg_temp_free(t0); |
|
6250 } |
|
6251 break; |
|
6252 |
|
6253 /************************/ |
|
6254 /* flags */ |
|
6255 case 0x9c: /* pushf */ |
|
6256 gen_svm_check_intercept(s, pc_start, SVM_EXIT_PUSHF); |
|
6257 if (s->vm86 && s->iopl != 3) { |
|
6258 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
|
6259 } else { |
|
6260 if (s->cc_op != CC_OP_DYNAMIC) |
|
6261 gen_op_set_cc_op(s->cc_op); |
|
6262 gen_helper_read_eflags(cpu_T[0]); |
|
6263 gen_push_T0(s); |
|
6264 } |
|
6265 break; |
|
6266 case 0x9d: /* popf */ |
|
6267 gen_svm_check_intercept(s, pc_start, SVM_EXIT_POPF); |
|
6268 if (s->vm86 && s->iopl != 3) { |
|
6269 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
|
6270 } else { |
|
6271 gen_pop_T0(s); |
|
6272 if (s->cpl == 0) { |
|
6273 if (s->dflag) { |
|
6274 gen_helper_write_eflags(cpu_T[0], |
|
6275 tcg_const_i32((TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK | IOPL_MASK))); |
|
6276 } else { |
|
6277 gen_helper_write_eflags(cpu_T[0], |
|
6278 tcg_const_i32((TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK | IOPL_MASK) & 0xffff)); |
|
6279 } |
|
6280 } else { |
|
6281 if (s->cpl <= s->iopl) { |
|
6282 if (s->dflag) { |
|
6283 gen_helper_write_eflags(cpu_T[0], |
|
6284 tcg_const_i32((TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK))); |
|
6285 } else { |
|
6286 gen_helper_write_eflags(cpu_T[0], |
|
6287 tcg_const_i32((TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK) & 0xffff)); |
|
6288 } |
|
6289 } else { |
|
6290 if (s->dflag) { |
|
6291 gen_helper_write_eflags(cpu_T[0], |
|
6292 tcg_const_i32((TF_MASK | AC_MASK | ID_MASK | NT_MASK))); |
|
6293 } else { |
|
6294 gen_helper_write_eflags(cpu_T[0], |
|
6295 tcg_const_i32((TF_MASK | AC_MASK | ID_MASK | NT_MASK) & 0xffff)); |
|
6296 } |
|
6297 } |
|
6298 } |
|
6299 gen_pop_update(s); |
|
6300 s->cc_op = CC_OP_EFLAGS; |
|
6301 /* abort translation because TF flag may change */ |
|
6302 gen_jmp_im(s->pc - s->cs_base); |
|
6303 gen_eob(s); |
|
6304 } |
|
6305 break; |
|
6306 case 0x9e: /* sahf */ |
|
6307 if (CODE64(s) && !(s->cpuid_ext3_features & CPUID_EXT3_LAHF_LM)) |
|
6308 goto illegal_op; |
|
6309 gen_op_mov_TN_reg(OT_BYTE, 0, R_AH); |
|
6310 if (s->cc_op != CC_OP_DYNAMIC) |
|
6311 gen_op_set_cc_op(s->cc_op); |
|
6312 gen_compute_eflags(cpu_cc_src); |
|
6313 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, CC_O); |
|
6314 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], CC_S | CC_Z | CC_A | CC_P | CC_C); |
|
6315 tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, cpu_T[0]); |
|
6316 s->cc_op = CC_OP_EFLAGS; |
|
6317 break; |
|
6318 case 0x9f: /* lahf */ |
|
6319 if (CODE64(s) && !(s->cpuid_ext3_features & CPUID_EXT3_LAHF_LM)) |
|
6320 goto illegal_op; |
|
6321 if (s->cc_op != CC_OP_DYNAMIC) |
|
6322 gen_op_set_cc_op(s->cc_op); |
|
6323 gen_compute_eflags(cpu_T[0]); |
|
6324 /* Note: gen_compute_eflags() only gives the condition codes */ |
|
6325 tcg_gen_ori_tl(cpu_T[0], cpu_T[0], 0x02); |
|
6326 gen_op_mov_reg_T0(OT_BYTE, R_AH); |
|
6327 break; |
|
6328 case 0xf5: /* cmc */ |
|
6329 if (s->cc_op != CC_OP_DYNAMIC) |
|
6330 gen_op_set_cc_op(s->cc_op); |
|
6331 gen_compute_eflags(cpu_cc_src); |
|
6332 tcg_gen_xori_tl(cpu_cc_src, cpu_cc_src, CC_C); |
|
6333 s->cc_op = CC_OP_EFLAGS; |
|
6334 break; |
|
6335 case 0xf8: /* clc */ |
|
6336 if (s->cc_op != CC_OP_DYNAMIC) |
|
6337 gen_op_set_cc_op(s->cc_op); |
|
6338 gen_compute_eflags(cpu_cc_src); |
|
6339 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~CC_C); |
|
6340 s->cc_op = CC_OP_EFLAGS; |
|
6341 break; |
|
6342 case 0xf9: /* stc */ |
|
6343 if (s->cc_op != CC_OP_DYNAMIC) |
|
6344 gen_op_set_cc_op(s->cc_op); |
|
6345 gen_compute_eflags(cpu_cc_src); |
|
6346 tcg_gen_ori_tl(cpu_cc_src, cpu_cc_src, CC_C); |
|
6347 s->cc_op = CC_OP_EFLAGS; |
|
6348 break; |
|
6349 case 0xfc: /* cld */ |
|
6350 tcg_gen_movi_i32(cpu_tmp2_i32, 1); |
|
6351 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, offsetof(CPUState, df)); |
|
6352 break; |
|
6353 case 0xfd: /* std */ |
|
6354 tcg_gen_movi_i32(cpu_tmp2_i32, -1); |
|
6355 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, offsetof(CPUState, df)); |
|
6356 break; |
|
6357 |
|
6358 /************************/ |
|
6359 /* bit operations */ |
|
6360 case 0x1ba: /* bt/bts/btr/btc Gv, im */ |
|
6361 ot = dflag + OT_WORD; |
|
6362 modrm = ldub_code(s->pc++); |
|
6363 op = (modrm >> 3) & 7; |
|
6364 mod = (modrm >> 6) & 3; |
|
6365 rm = (modrm & 7) | REX_B(s); |
|
6366 if (mod != 3) { |
|
6367 s->rip_offset = 1; |
|
6368 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
6369 gen_op_ld_T0_A0(ot + s->mem_index); |
|
6370 } else { |
|
6371 gen_op_mov_TN_reg(ot, 0, rm); |
|
6372 } |
|
6373 /* load shift */ |
|
6374 val = ldub_code(s->pc++); |
|
6375 gen_op_movl_T1_im(val); |
|
6376 if (op < 4) |
|
6377 goto illegal_op; |
|
6378 op -= 4; |
|
6379 goto bt_op; |
|
6380 case 0x1a3: /* bt Gv, Ev */ |
|
6381 op = 0; |
|
6382 goto do_btx; |
|
6383 case 0x1ab: /* bts */ |
|
6384 op = 1; |
|
6385 goto do_btx; |
|
6386 case 0x1b3: /* btr */ |
|
6387 op = 2; |
|
6388 goto do_btx; |
|
6389 case 0x1bb: /* btc */ |
|
6390 op = 3; |
|
6391 do_btx: |
|
6392 ot = dflag + OT_WORD; |
|
6393 modrm = ldub_code(s->pc++); |
|
6394 reg = ((modrm >> 3) & 7) | rex_r; |
|
6395 mod = (modrm >> 6) & 3; |
|
6396 rm = (modrm & 7) | REX_B(s); |
|
6397 gen_op_mov_TN_reg(OT_LONG, 1, reg); |
|
6398 if (mod != 3) { |
|
6399 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
6400 /* specific case: we need to add a displacement */ |
|
6401 gen_exts(ot, cpu_T[1]); |
|
6402 tcg_gen_sari_tl(cpu_tmp0, cpu_T[1], 3 + ot); |
|
6403 tcg_gen_shli_tl(cpu_tmp0, cpu_tmp0, ot); |
|
6404 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0); |
|
6405 gen_op_ld_T0_A0(ot + s->mem_index); |
|
6406 } else { |
|
6407 gen_op_mov_TN_reg(ot, 0, rm); |
|
6408 } |
|
6409 bt_op: |
|
6410 tcg_gen_andi_tl(cpu_T[1], cpu_T[1], (1 << (3 + ot)) - 1); |
|
6411 switch(op) { |
|
6412 case 0: |
|
6413 tcg_gen_shr_tl(cpu_cc_src, cpu_T[0], cpu_T[1]); |
|
6414 tcg_gen_movi_tl(cpu_cc_dst, 0); |
|
6415 break; |
|
6416 case 1: |
|
6417 tcg_gen_shr_tl(cpu_tmp4, cpu_T[0], cpu_T[1]); |
|
6418 tcg_gen_movi_tl(cpu_tmp0, 1); |
|
6419 tcg_gen_shl_tl(cpu_tmp0, cpu_tmp0, cpu_T[1]); |
|
6420 tcg_gen_or_tl(cpu_T[0], cpu_T[0], cpu_tmp0); |
|
6421 break; |
|
6422 case 2: |
|
6423 tcg_gen_shr_tl(cpu_tmp4, cpu_T[0], cpu_T[1]); |
|
6424 tcg_gen_movi_tl(cpu_tmp0, 1); |
|
6425 tcg_gen_shl_tl(cpu_tmp0, cpu_tmp0, cpu_T[1]); |
|
6426 tcg_gen_not_tl(cpu_tmp0, cpu_tmp0); |
|
6427 tcg_gen_and_tl(cpu_T[0], cpu_T[0], cpu_tmp0); |
|
6428 break; |
|
6429 default: |
|
6430 case 3: |
|
6431 tcg_gen_shr_tl(cpu_tmp4, cpu_T[0], cpu_T[1]); |
|
6432 tcg_gen_movi_tl(cpu_tmp0, 1); |
|
6433 tcg_gen_shl_tl(cpu_tmp0, cpu_tmp0, cpu_T[1]); |
|
6434 tcg_gen_xor_tl(cpu_T[0], cpu_T[0], cpu_tmp0); |
|
6435 break; |
|
6436 } |
|
6437 s->cc_op = CC_OP_SARB + ot; |
|
6438 if (op != 0) { |
|
6439 if (mod != 3) |
|
6440 gen_op_st_T0_A0(ot + s->mem_index); |
|
6441 else |
|
6442 gen_op_mov_reg_T0(ot, rm); |
|
6443 tcg_gen_mov_tl(cpu_cc_src, cpu_tmp4); |
|
6444 tcg_gen_movi_tl(cpu_cc_dst, 0); |
|
6445 } |
|
6446 break; |
|
6447 case 0x1bc: /* bsf */ |
|
6448 case 0x1bd: /* bsr */ |
|
6449 { |
|
6450 int label1; |
|
6451 TCGv t0; |
|
6452 |
|
6453 ot = dflag + OT_WORD; |
|
6454 modrm = ldub_code(s->pc++); |
|
6455 reg = ((modrm >> 3) & 7) | rex_r; |
|
6456 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0); |
|
6457 gen_extu(ot, cpu_T[0]); |
|
6458 label1 = gen_new_label(); |
|
6459 tcg_gen_movi_tl(cpu_cc_dst, 0); |
|
6460 t0 = tcg_temp_local_new(); |
|
6461 tcg_gen_mov_tl(t0, cpu_T[0]); |
|
6462 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, label1); |
|
6463 if (b & 1) { |
|
6464 gen_helper_bsr(cpu_T[0], t0); |
|
6465 } else { |
|
6466 gen_helper_bsf(cpu_T[0], t0); |
|
6467 } |
|
6468 gen_op_mov_reg_T0(ot, reg); |
|
6469 tcg_gen_movi_tl(cpu_cc_dst, 1); |
|
6470 gen_set_label(label1); |
|
6471 tcg_gen_discard_tl(cpu_cc_src); |
|
6472 s->cc_op = CC_OP_LOGICB + ot; |
|
6473 tcg_temp_free(t0); |
|
6474 } |
|
6475 break; |
|
6476 /************************/ |
|
6477 /* bcd */ |
|
6478 case 0x27: /* daa */ |
|
6479 if (CODE64(s)) |
|
6480 goto illegal_op; |
|
6481 if (s->cc_op != CC_OP_DYNAMIC) |
|
6482 gen_op_set_cc_op(s->cc_op); |
|
6483 gen_helper_daa(); |
|
6484 s->cc_op = CC_OP_EFLAGS; |
|
6485 break; |
|
6486 case 0x2f: /* das */ |
|
6487 if (CODE64(s)) |
|
6488 goto illegal_op; |
|
6489 if (s->cc_op != CC_OP_DYNAMIC) |
|
6490 gen_op_set_cc_op(s->cc_op); |
|
6491 gen_helper_das(); |
|
6492 s->cc_op = CC_OP_EFLAGS; |
|
6493 break; |
|
6494 case 0x37: /* aaa */ |
|
6495 if (CODE64(s)) |
|
6496 goto illegal_op; |
|
6497 if (s->cc_op != CC_OP_DYNAMIC) |
|
6498 gen_op_set_cc_op(s->cc_op); |
|
6499 gen_helper_aaa(); |
|
6500 s->cc_op = CC_OP_EFLAGS; |
|
6501 break; |
|
6502 case 0x3f: /* aas */ |
|
6503 if (CODE64(s)) |
|
6504 goto illegal_op; |
|
6505 if (s->cc_op != CC_OP_DYNAMIC) |
|
6506 gen_op_set_cc_op(s->cc_op); |
|
6507 gen_helper_aas(); |
|
6508 s->cc_op = CC_OP_EFLAGS; |
|
6509 break; |
|
6510 case 0xd4: /* aam */ |
|
6511 if (CODE64(s)) |
|
6512 goto illegal_op; |
|
6513 val = ldub_code(s->pc++); |
|
6514 if (val == 0) { |
|
6515 gen_exception(s, EXCP00_DIVZ, pc_start - s->cs_base); |
|
6516 } else { |
|
6517 gen_helper_aam(tcg_const_i32(val)); |
|
6518 s->cc_op = CC_OP_LOGICB; |
|
6519 } |
|
6520 break; |
|
6521 case 0xd5: /* aad */ |
|
6522 if (CODE64(s)) |
|
6523 goto illegal_op; |
|
6524 val = ldub_code(s->pc++); |
|
6525 gen_helper_aad(tcg_const_i32(val)); |
|
6526 s->cc_op = CC_OP_LOGICB; |
|
6527 break; |
|
6528 /************************/ |
|
6529 /* misc */ |
|
6530 case 0x90: /* nop */ |
|
6531 /* XXX: xchg + rex handling */ |
|
6532 /* XXX: correct lock test for all insn */ |
|
6533 if (prefixes & PREFIX_LOCK) |
|
6534 goto illegal_op; |
|
6535 if (prefixes & PREFIX_REPZ) { |
|
6536 gen_svm_check_intercept(s, pc_start, SVM_EXIT_PAUSE); |
|
6537 } |
|
6538 break; |
|
6539 case 0x9b: /* fwait */ |
|
6540 if ((s->flags & (HF_MP_MASK | HF_TS_MASK)) == |
|
6541 (HF_MP_MASK | HF_TS_MASK)) { |
|
6542 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base); |
|
6543 } else { |
|
6544 if (s->cc_op != CC_OP_DYNAMIC) |
|
6545 gen_op_set_cc_op(s->cc_op); |
|
6546 gen_jmp_im(pc_start - s->cs_base); |
|
6547 gen_helper_fwait(); |
|
6548 } |
|
6549 break; |
|
6550 case 0xcc: /* int3 */ |
|
6551 gen_interrupt(s, EXCP03_INT3, pc_start - s->cs_base, s->pc - s->cs_base); |
|
6552 break; |
|
6553 case 0xcd: /* int N */ |
|
6554 val = ldub_code(s->pc++); |
|
6555 if (s->vm86 && s->iopl != 3) { |
|
6556 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
|
6557 } else { |
|
6558 gen_interrupt(s, val, pc_start - s->cs_base, s->pc - s->cs_base); |
|
6559 } |
|
6560 break; |
|
6561 case 0xce: /* into */ |
|
6562 if (CODE64(s)) |
|
6563 goto illegal_op; |
|
6564 if (s->cc_op != CC_OP_DYNAMIC) |
|
6565 gen_op_set_cc_op(s->cc_op); |
|
6566 gen_jmp_im(pc_start - s->cs_base); |
|
6567 gen_helper_into(tcg_const_i32(s->pc - pc_start)); |
|
6568 break; |
|
6569 #ifdef WANT_ICEBP |
|
6570 case 0xf1: /* icebp (undocumented, exits to external debugger) */ |
|
6571 gen_svm_check_intercept(s, pc_start, SVM_EXIT_ICEBP); |
|
6572 #if 1 |
|
6573 gen_debug(s, pc_start - s->cs_base); |
|
6574 #else |
|
6575 /* start debug */ |
|
6576 tb_flush(cpu_single_env); |
|
6577 cpu_set_log(CPU_LOG_INT | CPU_LOG_TB_IN_ASM); |
|
6578 #endif |
|
6579 break; |
|
6580 #endif |
|
6581 case 0xfa: /* cli */ |
|
6582 if (!s->vm86) { |
|
6583 if (s->cpl <= s->iopl) { |
|
6584 gen_helper_cli(); |
|
6585 } else { |
|
6586 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
|
6587 } |
|
6588 } else { |
|
6589 if (s->iopl == 3) { |
|
6590 gen_helper_cli(); |
|
6591 } else { |
|
6592 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
|
6593 } |
|
6594 } |
|
6595 break; |
|
6596 case 0xfb: /* sti */ |
|
6597 if (!s->vm86) { |
|
6598 if (s->cpl <= s->iopl) { |
|
6599 gen_sti: |
|
6600 gen_helper_sti(); |
|
6601 /* interruptions are enabled only the first insn after sti */ |
|
6602 /* If several instructions disable interrupts, only the |
|
6603 _first_ does it */ |
|
6604 if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK)) |
|
6605 gen_helper_set_inhibit_irq(); |
|
6606 /* give a chance to handle pending irqs */ |
|
6607 gen_jmp_im(s->pc - s->cs_base); |
|
6608 gen_eob(s); |
|
6609 } else { |
|
6610 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
|
6611 } |
|
6612 } else { |
|
6613 if (s->iopl == 3) { |
|
6614 goto gen_sti; |
|
6615 } else { |
|
6616 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
|
6617 } |
|
6618 } |
|
6619 break; |
|
6620 case 0x62: /* bound */ |
|
6621 if (CODE64(s)) |
|
6622 goto illegal_op; |
|
6623 ot = dflag ? OT_LONG : OT_WORD; |
|
6624 modrm = ldub_code(s->pc++); |
|
6625 reg = (modrm >> 3) & 7; |
|
6626 mod = (modrm >> 6) & 3; |
|
6627 if (mod == 3) |
|
6628 goto illegal_op; |
|
6629 gen_op_mov_TN_reg(ot, 0, reg); |
|
6630 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
6631 gen_jmp_im(pc_start - s->cs_base); |
|
6632 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); |
|
6633 if (ot == OT_WORD) |
|
6634 gen_helper_boundw(cpu_A0, cpu_tmp2_i32); |
|
6635 else |
|
6636 gen_helper_boundl(cpu_A0, cpu_tmp2_i32); |
|
6637 break; |
|
6638 case 0x1c8 ... 0x1cf: /* bswap reg */ |
|
6639 reg = (b & 7) | REX_B(s); |
|
6640 #ifdef TARGET_X86_64 |
|
6641 if (dflag == 2) { |
|
6642 gen_op_mov_TN_reg(OT_QUAD, 0, reg); |
|
6643 tcg_gen_bswap_i64(cpu_T[0], cpu_T[0]); |
|
6644 gen_op_mov_reg_T0(OT_QUAD, reg); |
|
6645 } else |
|
6646 { |
|
6647 TCGv_i32 tmp0; |
|
6648 gen_op_mov_TN_reg(OT_LONG, 0, reg); |
|
6649 |
|
6650 tmp0 = tcg_temp_new_i32(); |
|
6651 tcg_gen_trunc_i64_i32(tmp0, cpu_T[0]); |
|
6652 tcg_gen_bswap_i32(tmp0, tmp0); |
|
6653 tcg_gen_extu_i32_i64(cpu_T[0], tmp0); |
|
6654 gen_op_mov_reg_T0(OT_LONG, reg); |
|
6655 } |
|
6656 #else |
|
6657 { |
|
6658 gen_op_mov_TN_reg(OT_LONG, 0, reg); |
|
6659 tcg_gen_bswap_i32(cpu_T[0], cpu_T[0]); |
|
6660 gen_op_mov_reg_T0(OT_LONG, reg); |
|
6661 } |
|
6662 #endif |
|
6663 break; |
|
6664 case 0xd6: /* salc */ |
|
6665 if (CODE64(s)) |
|
6666 goto illegal_op; |
|
6667 if (s->cc_op != CC_OP_DYNAMIC) |
|
6668 gen_op_set_cc_op(s->cc_op); |
|
6669 gen_compute_eflags_c(cpu_T[0]); |
|
6670 tcg_gen_neg_tl(cpu_T[0], cpu_T[0]); |
|
6671 gen_op_mov_reg_T0(OT_BYTE, R_EAX); |
|
6672 break; |
|
6673 case 0xe0: /* loopnz */ |
|
6674 case 0xe1: /* loopz */ |
|
6675 case 0xe2: /* loop */ |
|
6676 case 0xe3: /* jecxz */ |
|
6677 { |
|
6678 int l1, l2, l3; |
|
6679 |
|
6680 tval = (int8_t)insn_get(s, OT_BYTE); |
|
6681 next_eip = s->pc - s->cs_base; |
|
6682 tval += next_eip; |
|
6683 if (s->dflag == 0) |
|
6684 tval &= 0xffff; |
|
6685 |
|
6686 l1 = gen_new_label(); |
|
6687 l2 = gen_new_label(); |
|
6688 l3 = gen_new_label(); |
|
6689 b &= 3; |
|
6690 switch(b) { |
|
6691 case 0: /* loopnz */ |
|
6692 case 1: /* loopz */ |
|
6693 if (s->cc_op != CC_OP_DYNAMIC) |
|
6694 gen_op_set_cc_op(s->cc_op); |
|
6695 gen_op_add_reg_im(s->aflag, R_ECX, -1); |
|
6696 gen_op_jz_ecx(s->aflag, l3); |
|
6697 gen_compute_eflags(cpu_tmp0); |
|
6698 tcg_gen_andi_tl(cpu_tmp0, cpu_tmp0, CC_Z); |
|
6699 if (b == 0) { |
|
6700 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_tmp0, 0, l1); |
|
6701 } else { |
|
6702 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_tmp0, 0, l1); |
|
6703 } |
|
6704 break; |
|
6705 case 2: /* loop */ |
|
6706 gen_op_add_reg_im(s->aflag, R_ECX, -1); |
|
6707 gen_op_jnz_ecx(s->aflag, l1); |
|
6708 break; |
|
6709 default: |
|
6710 case 3: /* jcxz */ |
|
6711 gen_op_jz_ecx(s->aflag, l1); |
|
6712 break; |
|
6713 } |
|
6714 |
|
6715 gen_set_label(l3); |
|
6716 gen_jmp_im(next_eip); |
|
6717 tcg_gen_br(l2); |
|
6718 |
|
6719 gen_set_label(l1); |
|
6720 gen_jmp_im(tval); |
|
6721 gen_set_label(l2); |
|
6722 gen_eob(s); |
|
6723 } |
|
6724 break; |
|
6725 case 0x130: /* wrmsr */ |
|
6726 case 0x132: /* rdmsr */ |
|
6727 if (s->cpl != 0) { |
|
6728 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
|
6729 } else { |
|
6730 if (s->cc_op != CC_OP_DYNAMIC) |
|
6731 gen_op_set_cc_op(s->cc_op); |
|
6732 gen_jmp_im(pc_start - s->cs_base); |
|
6733 if (b & 2) { |
|
6734 gen_helper_rdmsr(); |
|
6735 } else { |
|
6736 gen_helper_wrmsr(); |
|
6737 } |
|
6738 } |
|
6739 break; |
|
6740 case 0x131: /* rdtsc */ |
|
6741 if (s->cc_op != CC_OP_DYNAMIC) |
|
6742 gen_op_set_cc_op(s->cc_op); |
|
6743 gen_jmp_im(pc_start - s->cs_base); |
|
6744 if (use_icount) |
|
6745 gen_io_start(); |
|
6746 gen_helper_rdtsc(); |
|
6747 if (use_icount) { |
|
6748 gen_io_end(); |
|
6749 gen_jmp(s, s->pc - s->cs_base); |
|
6750 } |
|
6751 break; |
|
6752 case 0x133: /* rdpmc */ |
|
6753 if (s->cc_op != CC_OP_DYNAMIC) |
|
6754 gen_op_set_cc_op(s->cc_op); |
|
6755 gen_jmp_im(pc_start - s->cs_base); |
|
6756 gen_helper_rdpmc(); |
|
6757 break; |
|
6758 case 0x134: /* sysenter */ |
|
6759 /* For Intel SYSENTER is valid on 64-bit */ |
|
6760 if (CODE64(s) && cpu_single_env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1) |
|
6761 goto illegal_op; |
|
6762 if (!s->pe) { |
|
6763 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
|
6764 } else { |
|
6765 if (s->cc_op != CC_OP_DYNAMIC) { |
|
6766 gen_op_set_cc_op(s->cc_op); |
|
6767 s->cc_op = CC_OP_DYNAMIC; |
|
6768 } |
|
6769 gen_jmp_im(pc_start - s->cs_base); |
|
6770 gen_helper_sysenter(); |
|
6771 gen_eob(s); |
|
6772 } |
|
6773 break; |
|
6774 case 0x135: /* sysexit */ |
|
6775 /* For Intel SYSEXIT is valid on 64-bit */ |
|
6776 if (CODE64(s) && cpu_single_env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1) |
|
6777 goto illegal_op; |
|
6778 if (!s->pe) { |
|
6779 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
|
6780 } else { |
|
6781 if (s->cc_op != CC_OP_DYNAMIC) { |
|
6782 gen_op_set_cc_op(s->cc_op); |
|
6783 s->cc_op = CC_OP_DYNAMIC; |
|
6784 } |
|
6785 gen_jmp_im(pc_start - s->cs_base); |
|
6786 gen_helper_sysexit(tcg_const_i32(dflag)); |
|
6787 gen_eob(s); |
|
6788 } |
|
6789 break; |
|
6790 #ifdef TARGET_X86_64 |
|
6791 case 0x105: /* syscall */ |
|
6792 /* XXX: is it usable in real mode ? */ |
|
6793 if (s->cc_op != CC_OP_DYNAMIC) { |
|
6794 gen_op_set_cc_op(s->cc_op); |
|
6795 s->cc_op = CC_OP_DYNAMIC; |
|
6796 } |
|
6797 gen_jmp_im(pc_start - s->cs_base); |
|
6798 gen_helper_syscall(tcg_const_i32(s->pc - pc_start)); |
|
6799 gen_eob(s); |
|
6800 break; |
|
6801 case 0x107: /* sysret */ |
|
6802 if (!s->pe) { |
|
6803 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
|
6804 } else { |
|
6805 if (s->cc_op != CC_OP_DYNAMIC) { |
|
6806 gen_op_set_cc_op(s->cc_op); |
|
6807 s->cc_op = CC_OP_DYNAMIC; |
|
6808 } |
|
6809 gen_jmp_im(pc_start - s->cs_base); |
|
6810 gen_helper_sysret(tcg_const_i32(s->dflag)); |
|
6811 /* condition codes are modified only in long mode */ |
|
6812 if (s->lma) |
|
6813 s->cc_op = CC_OP_EFLAGS; |
|
6814 gen_eob(s); |
|
6815 } |
|
6816 break; |
|
6817 #endif |
|
6818 case 0x1a2: /* cpuid */ |
|
6819 if (s->cc_op != CC_OP_DYNAMIC) |
|
6820 gen_op_set_cc_op(s->cc_op); |
|
6821 gen_jmp_im(pc_start - s->cs_base); |
|
6822 gen_helper_cpuid(); |
|
6823 break; |
|
6824 case 0xf4: /* hlt */ |
|
6825 if (s->cpl != 0) { |
|
6826 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
|
6827 } else { |
|
6828 if (s->cc_op != CC_OP_DYNAMIC) |
|
6829 gen_op_set_cc_op(s->cc_op); |
|
6830 gen_jmp_im(pc_start - s->cs_base); |
|
6831 gen_helper_hlt(tcg_const_i32(s->pc - pc_start)); |
|
6832 s->is_jmp = 3; |
|
6833 } |
|
6834 break; |
|
6835 case 0x100: |
|
6836 modrm = ldub_code(s->pc++); |
|
6837 mod = (modrm >> 6) & 3; |
|
6838 op = (modrm >> 3) & 7; |
|
6839 switch(op) { |
|
6840 case 0: /* sldt */ |
|
6841 if (!s->pe || s->vm86) |
|
6842 goto illegal_op; |
|
6843 gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_READ); |
|
6844 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,ldt.selector)); |
|
6845 ot = OT_WORD; |
|
6846 if (mod == 3) |
|
6847 ot += s->dflag; |
|
6848 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1); |
|
6849 break; |
|
6850 case 2: /* lldt */ |
|
6851 if (!s->pe || s->vm86) |
|
6852 goto illegal_op; |
|
6853 if (s->cpl != 0) { |
|
6854 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
|
6855 } else { |
|
6856 gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_WRITE); |
|
6857 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0); |
|
6858 gen_jmp_im(pc_start - s->cs_base); |
|
6859 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); |
|
6860 gen_helper_lldt(cpu_tmp2_i32); |
|
6861 } |
|
6862 break; |
|
6863 case 1: /* str */ |
|
6864 if (!s->pe || s->vm86) |
|
6865 goto illegal_op; |
|
6866 gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_READ); |
|
6867 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,tr.selector)); |
|
6868 ot = OT_WORD; |
|
6869 if (mod == 3) |
|
6870 ot += s->dflag; |
|
6871 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1); |
|
6872 break; |
|
6873 case 3: /* ltr */ |
|
6874 if (!s->pe || s->vm86) |
|
6875 goto illegal_op; |
|
6876 if (s->cpl != 0) { |
|
6877 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
|
6878 } else { |
|
6879 gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_WRITE); |
|
6880 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0); |
|
6881 gen_jmp_im(pc_start - s->cs_base); |
|
6882 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); |
|
6883 gen_helper_ltr(cpu_tmp2_i32); |
|
6884 } |
|
6885 break; |
|
6886 case 4: /* verr */ |
|
6887 case 5: /* verw */ |
|
6888 if (!s->pe || s->vm86) |
|
6889 goto illegal_op; |
|
6890 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0); |
|
6891 if (s->cc_op != CC_OP_DYNAMIC) |
|
6892 gen_op_set_cc_op(s->cc_op); |
|
6893 if (op == 4) |
|
6894 gen_helper_verr(cpu_T[0]); |
|
6895 else |
|
6896 gen_helper_verw(cpu_T[0]); |
|
6897 s->cc_op = CC_OP_EFLAGS; |
|
6898 break; |
|
6899 default: |
|
6900 goto illegal_op; |
|
6901 } |
|
6902 break; |
|
6903 case 0x101: |
|
6904 modrm = ldub_code(s->pc++); |
|
6905 mod = (modrm >> 6) & 3; |
|
6906 op = (modrm >> 3) & 7; |
|
6907 rm = modrm & 7; |
|
6908 switch(op) { |
|
6909 case 0: /* sgdt */ |
|
6910 if (mod == 3) |
|
6911 goto illegal_op; |
|
6912 gen_svm_check_intercept(s, pc_start, SVM_EXIT_GDTR_READ); |
|
6913 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
6914 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, gdt.limit)); |
|
6915 gen_op_st_T0_A0(OT_WORD + s->mem_index); |
|
6916 gen_add_A0_im(s, 2); |
|
6917 tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, gdt.base)); |
|
6918 if (!s->dflag) |
|
6919 gen_op_andl_T0_im(0xffffff); |
|
6920 gen_op_st_T0_A0(CODE64(s) + OT_LONG + s->mem_index); |
|
6921 break; |
|
6922 case 1: |
|
6923 if (mod == 3) { |
|
6924 switch (rm) { |
|
6925 case 0: /* monitor */ |
|
6926 if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) || |
|
6927 s->cpl != 0) |
|
6928 goto illegal_op; |
|
6929 if (s->cc_op != CC_OP_DYNAMIC) |
|
6930 gen_op_set_cc_op(s->cc_op); |
|
6931 gen_jmp_im(pc_start - s->cs_base); |
|
6932 #ifdef TARGET_X86_64 |
|
6933 if (s->aflag == 2) { |
|
6934 gen_op_movq_A0_reg(R_EAX); |
|
6935 } else |
|
6936 #endif |
|
6937 { |
|
6938 gen_op_movl_A0_reg(R_EAX); |
|
6939 if (s->aflag == 0) |
|
6940 gen_op_andl_A0_ffff(); |
|
6941 } |
|
6942 gen_add_A0_ds_seg(s); |
|
6943 gen_helper_monitor(cpu_A0); |
|
6944 break; |
|
6945 case 1: /* mwait */ |
|
6946 if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) || |
|
6947 s->cpl != 0) |
|
6948 goto illegal_op; |
|
6949 if (s->cc_op != CC_OP_DYNAMIC) { |
|
6950 gen_op_set_cc_op(s->cc_op); |
|
6951 s->cc_op = CC_OP_DYNAMIC; |
|
6952 } |
|
6953 gen_jmp_im(pc_start - s->cs_base); |
|
6954 gen_helper_mwait(tcg_const_i32(s->pc - pc_start)); |
|
6955 gen_eob(s); |
|
6956 break; |
|
6957 default: |
|
6958 goto illegal_op; |
|
6959 } |
|
6960 } else { /* sidt */ |
|
6961 gen_svm_check_intercept(s, pc_start, SVM_EXIT_IDTR_READ); |
|
6962 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
6963 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, idt.limit)); |
|
6964 gen_op_st_T0_A0(OT_WORD + s->mem_index); |
|
6965 gen_add_A0_im(s, 2); |
|
6966 tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, idt.base)); |
|
6967 if (!s->dflag) |
|
6968 gen_op_andl_T0_im(0xffffff); |
|
6969 gen_op_st_T0_A0(CODE64(s) + OT_LONG + s->mem_index); |
|
6970 } |
|
6971 break; |
|
6972 case 2: /* lgdt */ |
|
6973 case 3: /* lidt */ |
|
6974 if (mod == 3) { |
|
6975 if (s->cc_op != CC_OP_DYNAMIC) |
|
6976 gen_op_set_cc_op(s->cc_op); |
|
6977 gen_jmp_im(pc_start - s->cs_base); |
|
6978 switch(rm) { |
|
6979 case 0: /* VMRUN */ |
|
6980 if (!(s->flags & HF_SVME_MASK) || !s->pe) |
|
6981 goto illegal_op; |
|
6982 if (s->cpl != 0) { |
|
6983 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
|
6984 break; |
|
6985 } else { |
|
6986 gen_helper_vmrun(tcg_const_i32(s->aflag), |
|
6987 tcg_const_i32(s->pc - pc_start)); |
|
6988 tcg_gen_exit_tb(0); |
|
6989 s->is_jmp = 3; |
|
6990 } |
|
6991 break; |
|
6992 case 1: /* VMMCALL */ |
|
6993 if (!(s->flags & HF_SVME_MASK)) |
|
6994 goto illegal_op; |
|
6995 gen_helper_vmmcall(); |
|
6996 break; |
|
6997 case 2: /* VMLOAD */ |
|
6998 if (!(s->flags & HF_SVME_MASK) || !s->pe) |
|
6999 goto illegal_op; |
|
7000 if (s->cpl != 0) { |
|
7001 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
|
7002 break; |
|
7003 } else { |
|
7004 gen_helper_vmload(tcg_const_i32(s->aflag)); |
|
7005 } |
|
7006 break; |
|
7007 case 3: /* VMSAVE */ |
|
7008 if (!(s->flags & HF_SVME_MASK) || !s->pe) |
|
7009 goto illegal_op; |
|
7010 if (s->cpl != 0) { |
|
7011 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
|
7012 break; |
|
7013 } else { |
|
7014 gen_helper_vmsave(tcg_const_i32(s->aflag)); |
|
7015 } |
|
7016 break; |
|
7017 case 4: /* STGI */ |
|
7018 if ((!(s->flags & HF_SVME_MASK) && |
|
7019 !(s->cpuid_ext3_features & CPUID_EXT3_SKINIT)) || |
|
7020 !s->pe) |
|
7021 goto illegal_op; |
|
7022 if (s->cpl != 0) { |
|
7023 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
|
7024 break; |
|
7025 } else { |
|
7026 gen_helper_stgi(); |
|
7027 } |
|
7028 break; |
|
7029 case 5: /* CLGI */ |
|
7030 if (!(s->flags & HF_SVME_MASK) || !s->pe) |
|
7031 goto illegal_op; |
|
7032 if (s->cpl != 0) { |
|
7033 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
|
7034 break; |
|
7035 } else { |
|
7036 gen_helper_clgi(); |
|
7037 } |
|
7038 break; |
|
7039 case 6: /* SKINIT */ |
|
7040 if ((!(s->flags & HF_SVME_MASK) && |
|
7041 !(s->cpuid_ext3_features & CPUID_EXT3_SKINIT)) || |
|
7042 !s->pe) |
|
7043 goto illegal_op; |
|
7044 gen_helper_skinit(); |
|
7045 break; |
|
7046 case 7: /* INVLPGA */ |
|
7047 if (!(s->flags & HF_SVME_MASK) || !s->pe) |
|
7048 goto illegal_op; |
|
7049 if (s->cpl != 0) { |
|
7050 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
|
7051 break; |
|
7052 } else { |
|
7053 gen_helper_invlpga(tcg_const_i32(s->aflag)); |
|
7054 } |
|
7055 break; |
|
7056 default: |
|
7057 goto illegal_op; |
|
7058 } |
|
7059 } else if (s->cpl != 0) { |
|
7060 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
|
7061 } else { |
|
7062 gen_svm_check_intercept(s, pc_start, |
|
7063 op==2 ? SVM_EXIT_GDTR_WRITE : SVM_EXIT_IDTR_WRITE); |
|
7064 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
7065 gen_op_ld_T1_A0(OT_WORD + s->mem_index); |
|
7066 gen_add_A0_im(s, 2); |
|
7067 gen_op_ld_T0_A0(CODE64(s) + OT_LONG + s->mem_index); |
|
7068 if (!s->dflag) |
|
7069 gen_op_andl_T0_im(0xffffff); |
|
7070 if (op == 2) { |
|
7071 tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,gdt.base)); |
|
7072 tcg_gen_st32_tl(cpu_T[1], cpu_env, offsetof(CPUX86State,gdt.limit)); |
|
7073 } else { |
|
7074 tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,idt.base)); |
|
7075 tcg_gen_st32_tl(cpu_T[1], cpu_env, offsetof(CPUX86State,idt.limit)); |
|
7076 } |
|
7077 } |
|
7078 break; |
|
7079 case 4: /* smsw */ |
|
7080 gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_CR0); |
|
7081 #if defined TARGET_X86_64 && defined WORDS_BIGENDIAN |
|
7082 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,cr[0]) + 4); |
|
7083 #else |
|
7084 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,cr[0])); |
|
7085 #endif |
|
7086 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 1); |
|
7087 break; |
|
7088 case 6: /* lmsw */ |
|
7089 if (s->cpl != 0) { |
|
7090 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
|
7091 } else { |
|
7092 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0); |
|
7093 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0); |
|
7094 gen_helper_lmsw(cpu_T[0]); |
|
7095 gen_jmp_im(s->pc - s->cs_base); |
|
7096 gen_eob(s); |
|
7097 } |
|
7098 break; |
|
7099 case 7: /* invlpg */ |
|
7100 if (s->cpl != 0) { |
|
7101 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
|
7102 } else { |
|
7103 if (mod == 3) { |
|
7104 #ifdef TARGET_X86_64 |
|
7105 if (CODE64(s) && rm == 0) { |
|
7106 /* swapgs */ |
|
7107 tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,segs[R_GS].base)); |
|
7108 tcg_gen_ld_tl(cpu_T[1], cpu_env, offsetof(CPUX86State,kernelgsbase)); |
|
7109 tcg_gen_st_tl(cpu_T[1], cpu_env, offsetof(CPUX86State,segs[R_GS].base)); |
|
7110 tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,kernelgsbase)); |
|
7111 } else |
|
7112 #endif |
|
7113 { |
|
7114 goto illegal_op; |
|
7115 } |
|
7116 } else { |
|
7117 if (s->cc_op != CC_OP_DYNAMIC) |
|
7118 gen_op_set_cc_op(s->cc_op); |
|
7119 gen_jmp_im(pc_start - s->cs_base); |
|
7120 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
7121 gen_helper_invlpg(cpu_A0); |
|
7122 gen_jmp_im(s->pc - s->cs_base); |
|
7123 gen_eob(s); |
|
7124 } |
|
7125 } |
|
7126 break; |
|
7127 default: |
|
7128 goto illegal_op; |
|
7129 } |
|
7130 break; |
|
7131 case 0x108: /* invd */ |
|
7132 case 0x109: /* wbinvd */ |
|
7133 if (s->cpl != 0) { |
|
7134 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
|
7135 } else { |
|
7136 gen_svm_check_intercept(s, pc_start, (b & 2) ? SVM_EXIT_INVD : SVM_EXIT_WBINVD); |
|
7137 /* nothing to do */ |
|
7138 } |
|
7139 break; |
|
7140 case 0x63: /* arpl or movslS (x86_64) */ |
|
7141 #ifdef TARGET_X86_64 |
|
7142 if (CODE64(s)) { |
|
7143 int d_ot; |
|
7144 /* d_ot is the size of destination */ |
|
7145 d_ot = dflag + OT_WORD; |
|
7146 |
|
7147 modrm = ldub_code(s->pc++); |
|
7148 reg = ((modrm >> 3) & 7) | rex_r; |
|
7149 mod = (modrm >> 6) & 3; |
|
7150 rm = (modrm & 7) | REX_B(s); |
|
7151 |
|
7152 if (mod == 3) { |
|
7153 gen_op_mov_TN_reg(OT_LONG, 0, rm); |
|
7154 /* sign extend */ |
|
7155 if (d_ot == OT_QUAD) |
|
7156 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); |
|
7157 gen_op_mov_reg_T0(d_ot, reg); |
|
7158 } else { |
|
7159 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
7160 if (d_ot == OT_QUAD) { |
|
7161 gen_op_lds_T0_A0(OT_LONG + s->mem_index); |
|
7162 } else { |
|
7163 gen_op_ld_T0_A0(OT_LONG + s->mem_index); |
|
7164 } |
|
7165 gen_op_mov_reg_T0(d_ot, reg); |
|
7166 } |
|
7167 } else |
|
7168 #endif |
|
7169 { |
|
7170 int label1; |
|
7171 TCGv t0, t1, t2; |
|
7172 |
|
7173 if (!s->pe || s->vm86) |
|
7174 goto illegal_op; |
|
7175 t0 = tcg_temp_local_new(); |
|
7176 t1 = tcg_temp_local_new(); |
|
7177 t2 = tcg_temp_local_new(); |
|
7178 ot = OT_WORD; |
|
7179 modrm = ldub_code(s->pc++); |
|
7180 reg = (modrm >> 3) & 7; |
|
7181 mod = (modrm >> 6) & 3; |
|
7182 rm = modrm & 7; |
|
7183 if (mod != 3) { |
|
7184 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
7185 gen_op_ld_v(ot + s->mem_index, t0, cpu_A0); |
|
7186 } else { |
|
7187 gen_op_mov_v_reg(ot, t0, rm); |
|
7188 } |
|
7189 gen_op_mov_v_reg(ot, t1, reg); |
|
7190 tcg_gen_andi_tl(cpu_tmp0, t0, 3); |
|
7191 tcg_gen_andi_tl(t1, t1, 3); |
|
7192 tcg_gen_movi_tl(t2, 0); |
|
7193 label1 = gen_new_label(); |
|
7194 tcg_gen_brcond_tl(TCG_COND_GE, cpu_tmp0, t1, label1); |
|
7195 tcg_gen_andi_tl(t0, t0, ~3); |
|
7196 tcg_gen_or_tl(t0, t0, t1); |
|
7197 tcg_gen_movi_tl(t2, CC_Z); |
|
7198 gen_set_label(label1); |
|
7199 if (mod != 3) { |
|
7200 gen_op_st_v(ot + s->mem_index, t0, cpu_A0); |
|
7201 } else { |
|
7202 gen_op_mov_reg_v(ot, rm, t0); |
|
7203 } |
|
7204 if (s->cc_op != CC_OP_DYNAMIC) |
|
7205 gen_op_set_cc_op(s->cc_op); |
|
7206 gen_compute_eflags(cpu_cc_src); |
|
7207 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~CC_Z); |
|
7208 tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, t2); |
|
7209 s->cc_op = CC_OP_EFLAGS; |
|
7210 tcg_temp_free(t0); |
|
7211 tcg_temp_free(t1); |
|
7212 tcg_temp_free(t2); |
|
7213 } |
|
7214 break; |
|
7215 case 0x102: /* lar */ |
|
7216 case 0x103: /* lsl */ |
|
7217 { |
|
7218 int label1; |
|
7219 TCGv t0; |
|
7220 if (!s->pe || s->vm86) |
|
7221 goto illegal_op; |
|
7222 ot = dflag ? OT_LONG : OT_WORD; |
|
7223 modrm = ldub_code(s->pc++); |
|
7224 reg = ((modrm >> 3) & 7) | rex_r; |
|
7225 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0); |
|
7226 t0 = tcg_temp_local_new(); |
|
7227 if (s->cc_op != CC_OP_DYNAMIC) |
|
7228 gen_op_set_cc_op(s->cc_op); |
|
7229 if (b == 0x102) |
|
7230 gen_helper_lar(t0, cpu_T[0]); |
|
7231 else |
|
7232 gen_helper_lsl(t0, cpu_T[0]); |
|
7233 tcg_gen_andi_tl(cpu_tmp0, cpu_cc_src, CC_Z); |
|
7234 label1 = gen_new_label(); |
|
7235 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_tmp0, 0, label1); |
|
7236 gen_op_mov_reg_v(ot, reg, t0); |
|
7237 gen_set_label(label1); |
|
7238 s->cc_op = CC_OP_EFLAGS; |
|
7239 tcg_temp_free(t0); |
|
7240 } |
|
7241 break; |
|
7242 case 0x118: |
|
7243 modrm = ldub_code(s->pc++); |
|
7244 mod = (modrm >> 6) & 3; |
|
7245 op = (modrm >> 3) & 7; |
|
7246 switch(op) { |
|
7247 case 0: /* prefetchnta */ |
|
7248 case 1: /* prefetchnt0 */ |
|
7249 case 2: /* prefetchnt0 */ |
|
7250 case 3: /* prefetchnt0 */ |
|
7251 if (mod == 3) |
|
7252 goto illegal_op; |
|
7253 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
7254 /* nothing more to do */ |
|
7255 break; |
|
7256 default: /* nop (multi byte) */ |
|
7257 gen_nop_modrm(s, modrm); |
|
7258 break; |
|
7259 } |
|
7260 break; |
|
7261 case 0x119 ... 0x11f: /* nop (multi byte) */ |
|
7262 modrm = ldub_code(s->pc++); |
|
7263 gen_nop_modrm(s, modrm); |
|
7264 break; |
|
7265 case 0x120: /* mov reg, crN */ |
|
7266 case 0x122: /* mov crN, reg */ |
|
7267 if (s->cpl != 0) { |
|
7268 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
|
7269 } else { |
|
7270 modrm = ldub_code(s->pc++); |
|
7271 if ((modrm & 0xc0) != 0xc0) |
|
7272 goto illegal_op; |
|
7273 rm = (modrm & 7) | REX_B(s); |
|
7274 reg = ((modrm >> 3) & 7) | rex_r; |
|
7275 if (CODE64(s)) |
|
7276 ot = OT_QUAD; |
|
7277 else |
|
7278 ot = OT_LONG; |
|
7279 switch(reg) { |
|
7280 case 0: |
|
7281 case 2: |
|
7282 case 3: |
|
7283 case 4: |
|
7284 case 8: |
|
7285 if (s->cc_op != CC_OP_DYNAMIC) |
|
7286 gen_op_set_cc_op(s->cc_op); |
|
7287 gen_jmp_im(pc_start - s->cs_base); |
|
7288 if (b & 2) { |
|
7289 gen_op_mov_TN_reg(ot, 0, rm); |
|
7290 gen_helper_write_crN(tcg_const_i32(reg), cpu_T[0]); |
|
7291 gen_jmp_im(s->pc - s->cs_base); |
|
7292 gen_eob(s); |
|
7293 } else { |
|
7294 gen_helper_read_crN(cpu_T[0], tcg_const_i32(reg)); |
|
7295 gen_op_mov_reg_T0(ot, rm); |
|
7296 } |
|
7297 break; |
|
7298 default: |
|
7299 goto illegal_op; |
|
7300 } |
|
7301 } |
|
7302 break; |
|
7303 case 0x121: /* mov reg, drN */ |
|
7304 case 0x123: /* mov drN, reg */ |
|
7305 if (s->cpl != 0) { |
|
7306 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
|
7307 } else { |
|
7308 modrm = ldub_code(s->pc++); |
|
7309 if ((modrm & 0xc0) != 0xc0) |
|
7310 goto illegal_op; |
|
7311 rm = (modrm & 7) | REX_B(s); |
|
7312 reg = ((modrm >> 3) & 7) | rex_r; |
|
7313 if (CODE64(s)) |
|
7314 ot = OT_QUAD; |
|
7315 else |
|
7316 ot = OT_LONG; |
|
7317 /* XXX: do it dynamically with CR4.DE bit */ |
|
7318 if (reg == 4 || reg == 5 || reg >= 8) |
|
7319 goto illegal_op; |
|
7320 if (b & 2) { |
|
7321 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_DR0 + reg); |
|
7322 gen_op_mov_TN_reg(ot, 0, rm); |
|
7323 gen_helper_movl_drN_T0(tcg_const_i32(reg), cpu_T[0]); |
|
7324 gen_jmp_im(s->pc - s->cs_base); |
|
7325 gen_eob(s); |
|
7326 } else { |
|
7327 gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_DR0 + reg); |
|
7328 tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,dr[reg])); |
|
7329 gen_op_mov_reg_T0(ot, rm); |
|
7330 } |
|
7331 } |
|
7332 break; |
|
7333 case 0x106: /* clts */ |
|
7334 if (s->cpl != 0) { |
|
7335 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
|
7336 } else { |
|
7337 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0); |
|
7338 gen_helper_clts(); |
|
7339 /* abort block because static cpu state changed */ |
|
7340 gen_jmp_im(s->pc - s->cs_base); |
|
7341 gen_eob(s); |
|
7342 } |
|
7343 break; |
|
7344 /* MMX/3DNow!/SSE/SSE2/SSE3/SSSE3/SSE4 support */ |
|
7345 case 0x1c3: /* MOVNTI reg, mem */ |
|
7346 if (!(s->cpuid_features & CPUID_SSE2)) |
|
7347 goto illegal_op; |
|
7348 ot = s->dflag == 2 ? OT_QUAD : OT_LONG; |
|
7349 modrm = ldub_code(s->pc++); |
|
7350 mod = (modrm >> 6) & 3; |
|
7351 if (mod == 3) |
|
7352 goto illegal_op; |
|
7353 reg = ((modrm >> 3) & 7) | rex_r; |
|
7354 /* generate a generic store */ |
|
7355 gen_ldst_modrm(s, modrm, ot, reg, 1); |
|
7356 break; |
|
7357 case 0x1ae: |
|
7358 modrm = ldub_code(s->pc++); |
|
7359 mod = (modrm >> 6) & 3; |
|
7360 op = (modrm >> 3) & 7; |
|
7361 switch(op) { |
|
7362 case 0: /* fxsave */ |
|
7363 if (mod == 3 || !(s->cpuid_features & CPUID_FXSR) || |
|
7364 (s->flags & HF_EM_MASK)) |
|
7365 goto illegal_op; |
|
7366 if (s->flags & HF_TS_MASK) { |
|
7367 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base); |
|
7368 break; |
|
7369 } |
|
7370 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
7371 if (s->cc_op != CC_OP_DYNAMIC) |
|
7372 gen_op_set_cc_op(s->cc_op); |
|
7373 gen_jmp_im(pc_start - s->cs_base); |
|
7374 gen_helper_fxsave(cpu_A0, tcg_const_i32((s->dflag == 2))); |
|
7375 break; |
|
7376 case 1: /* fxrstor */ |
|
7377 if (mod == 3 || !(s->cpuid_features & CPUID_FXSR) || |
|
7378 (s->flags & HF_EM_MASK)) |
|
7379 goto illegal_op; |
|
7380 if (s->flags & HF_TS_MASK) { |
|
7381 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base); |
|
7382 break; |
|
7383 } |
|
7384 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
7385 if (s->cc_op != CC_OP_DYNAMIC) |
|
7386 gen_op_set_cc_op(s->cc_op); |
|
7387 gen_jmp_im(pc_start - s->cs_base); |
|
7388 gen_helper_fxrstor(cpu_A0, tcg_const_i32((s->dflag == 2))); |
|
7389 break; |
|
7390 case 2: /* ldmxcsr */ |
|
7391 case 3: /* stmxcsr */ |
|
7392 if (s->flags & HF_TS_MASK) { |
|
7393 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base); |
|
7394 break; |
|
7395 } |
|
7396 if ((s->flags & HF_EM_MASK) || !(s->flags & HF_OSFXSR_MASK) || |
|
7397 mod == 3) |
|
7398 goto illegal_op; |
|
7399 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
7400 if (op == 2) { |
|
7401 gen_op_ld_T0_A0(OT_LONG + s->mem_index); |
|
7402 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, mxcsr)); |
|
7403 } else { |
|
7404 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, mxcsr)); |
|
7405 gen_op_st_T0_A0(OT_LONG + s->mem_index); |
|
7406 } |
|
7407 break; |
|
7408 case 5: /* lfence */ |
|
7409 case 6: /* mfence */ |
|
7410 if ((modrm & 0xc7) != 0xc0 || !(s->cpuid_features & CPUID_SSE)) |
|
7411 goto illegal_op; |
|
7412 break; |
|
7413 case 7: /* sfence / clflush */ |
|
7414 if ((modrm & 0xc7) == 0xc0) { |
|
7415 /* sfence */ |
|
7416 /* XXX: also check for cpuid_ext2_features & CPUID_EXT2_EMMX */ |
|
7417 if (!(s->cpuid_features & CPUID_SSE)) |
|
7418 goto illegal_op; |
|
7419 } else { |
|
7420 /* clflush */ |
|
7421 if (!(s->cpuid_features & CPUID_CLFLUSH)) |
|
7422 goto illegal_op; |
|
7423 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
7424 } |
|
7425 break; |
|
7426 default: |
|
7427 goto illegal_op; |
|
7428 } |
|
7429 break; |
|
7430 case 0x10d: /* 3DNow! prefetch(w) */ |
|
7431 modrm = ldub_code(s->pc++); |
|
7432 mod = (modrm >> 6) & 3; |
|
7433 if (mod == 3) |
|
7434 goto illegal_op; |
|
7435 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
7436 /* ignore for now */ |
|
7437 break; |
|
7438 case 0x1aa: /* rsm */ |
|
7439 gen_svm_check_intercept(s, pc_start, SVM_EXIT_RSM); |
|
7440 if (!(s->flags & HF_SMM_MASK)) |
|
7441 goto illegal_op; |
|
7442 if (s->cc_op != CC_OP_DYNAMIC) { |
|
7443 gen_op_set_cc_op(s->cc_op); |
|
7444 s->cc_op = CC_OP_DYNAMIC; |
|
7445 } |
|
7446 gen_jmp_im(s->pc - s->cs_base); |
|
7447 gen_helper_rsm(); |
|
7448 gen_eob(s); |
|
7449 break; |
|
7450 case 0x1b8: /* SSE4.2 popcnt */ |
|
7451 if ((prefixes & (PREFIX_REPZ | PREFIX_LOCK | PREFIX_REPNZ)) != |
|
7452 PREFIX_REPZ) |
|
7453 goto illegal_op; |
|
7454 if (!(s->cpuid_ext_features & CPUID_EXT_POPCNT)) |
|
7455 goto illegal_op; |
|
7456 |
|
7457 modrm = ldub_code(s->pc++); |
|
7458 reg = ((modrm >> 3) & 7); |
|
7459 |
|
7460 if (s->prefix & PREFIX_DATA) |
|
7461 ot = OT_WORD; |
|
7462 else if (s->dflag != 2) |
|
7463 ot = OT_LONG; |
|
7464 else |
|
7465 ot = OT_QUAD; |
|
7466 |
|
7467 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0); |
|
7468 gen_helper_popcnt(cpu_T[0], cpu_T[0], tcg_const_i32(ot)); |
|
7469 gen_op_mov_reg_T0(ot, reg); |
|
7470 |
|
7471 s->cc_op = CC_OP_EFLAGS; |
|
7472 break; |
|
7473 case 0x10e ... 0x10f: |
|
7474 /* 3DNow! instructions, ignore prefixes */ |
|
7475 s->prefix &= ~(PREFIX_REPZ | PREFIX_REPNZ | PREFIX_DATA); |
|
7476 case 0x110 ... 0x117: |
|
7477 case 0x128 ... 0x12f: |
|
7478 case 0x138 ... 0x13a: |
|
7479 case 0x150 ... 0x177: |
|
7480 case 0x17c ... 0x17f: |
|
7481 case 0x1c2: |
|
7482 case 0x1c4 ... 0x1c6: |
|
7483 case 0x1d0 ... 0x1fe: |
|
7484 gen_sse(s, b, pc_start, rex_r); |
|
7485 break; |
|
7486 default: |
|
7487 goto illegal_op; |
|
7488 } |
|
7489 /* lock generation */ |
|
7490 if (s->prefix & PREFIX_LOCK) |
|
7491 gen_helper_unlock(); |
|
7492 return s->pc; |
|
7493 illegal_op: |
|
7494 if (s->prefix & PREFIX_LOCK) |
|
7495 gen_helper_unlock(); |
|
7496 /* XXX: ensure that no lock was generated */ |
|
7497 gen_exception(s, EXCP06_ILLOP, pc_start - s->cs_base); |
|
7498 return s->pc; |
|
7499 } |
|
7500 |
|
7501 void optimize_flags_init(void) |
|
7502 { |
|
7503 #if TCG_TARGET_REG_BITS == 32 |
|
7504 assert(sizeof(CCTable) == (1 << 3)); |
|
7505 #else |
|
7506 assert(sizeof(CCTable) == (1 << 4)); |
|
7507 #endif |
|
7508 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env"); |
|
7509 cpu_cc_op = tcg_global_mem_new_i32(TCG_AREG0, |
|
7510 offsetof(CPUState, cc_op), "cc_op"); |
|
7511 cpu_cc_src = tcg_global_mem_new(TCG_AREG0, offsetof(CPUState, cc_src), |
|
7512 "cc_src"); |
|
7513 cpu_cc_dst = tcg_global_mem_new(TCG_AREG0, offsetof(CPUState, cc_dst), |
|
7514 "cc_dst"); |
|
7515 cpu_cc_tmp = tcg_global_mem_new(TCG_AREG0, offsetof(CPUState, cc_tmp), |
|
7516 "cc_tmp"); |
|
7517 |
|
7518 /* register helpers */ |
|
7519 #define GEN_HELPER 2 |
|
7520 #include "helper.h" |
|
7521 } |
|
7522 |
|
7523 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for |
|
7524 basic block 'tb'. If search_pc is TRUE, also generate PC |
|
7525 information for each intermediate instruction. */ |
|
7526 static inline void gen_intermediate_code_internal(CPUState *env, |
|
7527 TranslationBlock *tb, |
|
7528 int search_pc) |
|
7529 { |
|
7530 DisasContext dc1, *dc = &dc1; |
|
7531 target_ulong pc_ptr; |
|
7532 uint16_t *gen_opc_end; |
|
7533 CPUBreakpoint *bp; |
|
7534 int j, lj, cflags; |
|
7535 uint64_t flags; |
|
7536 target_ulong pc_start; |
|
7537 target_ulong cs_base; |
|
7538 int num_insns; |
|
7539 int max_insns; |
|
7540 |
|
7541 /* generate intermediate code */ |
|
7542 pc_start = tb->pc; |
|
7543 cs_base = tb->cs_base; |
|
7544 flags = tb->flags; |
|
7545 cflags = tb->cflags; |
|
7546 |
|
7547 dc->pe = (flags >> HF_PE_SHIFT) & 1; |
|
7548 dc->code32 = (flags >> HF_CS32_SHIFT) & 1; |
|
7549 dc->ss32 = (flags >> HF_SS32_SHIFT) & 1; |
|
7550 dc->addseg = (flags >> HF_ADDSEG_SHIFT) & 1; |
|
7551 dc->f_st = 0; |
|
7552 dc->vm86 = (flags >> VM_SHIFT) & 1; |
|
7553 dc->cpl = (flags >> HF_CPL_SHIFT) & 3; |
|
7554 dc->iopl = (flags >> IOPL_SHIFT) & 3; |
|
7555 dc->tf = (flags >> TF_SHIFT) & 1; |
|
7556 dc->singlestep_enabled = env->singlestep_enabled; |
|
7557 dc->cc_op = CC_OP_DYNAMIC; |
|
7558 dc->cs_base = cs_base; |
|
7559 dc->tb = tb; |
|
7560 dc->popl_esp_hack = 0; |
|
7561 /* select memory access functions */ |
|
7562 dc->mem_index = 0; |
|
7563 if (flags & HF_SOFTMMU_MASK) { |
|
7564 if (dc->cpl == 3) |
|
7565 dc->mem_index = 2 * 4; |
|
7566 else |
|
7567 dc->mem_index = 1 * 4; |
|
7568 } |
|
7569 dc->cpuid_features = env->cpuid_features; |
|
7570 dc->cpuid_ext_features = env->cpuid_ext_features; |
|
7571 dc->cpuid_ext2_features = env->cpuid_ext2_features; |
|
7572 dc->cpuid_ext3_features = env->cpuid_ext3_features; |
|
7573 #ifdef TARGET_X86_64 |
|
7574 dc->lma = (flags >> HF_LMA_SHIFT) & 1; |
|
7575 dc->code64 = (flags >> HF_CS64_SHIFT) & 1; |
|
7576 #endif |
|
7577 dc->flags = flags; |
|
7578 dc->jmp_opt = !(dc->tf || env->singlestep_enabled || |
|
7579 (flags & HF_INHIBIT_IRQ_MASK) |
|
7580 #ifndef CONFIG_SOFTMMU |
|
7581 || (flags & HF_SOFTMMU_MASK) |
|
7582 #endif |
|
7583 ); |
|
7584 #if 0 |
|
7585 /* check addseg logic */ |
|
7586 if (!dc->addseg && (dc->vm86 || !dc->pe || !dc->code32)) |
|
7587 printf("ERROR addseg\n"); |
|
7588 #endif |
|
7589 |
|
7590 cpu_T[0] = tcg_temp_new(); |
|
7591 cpu_T[1] = tcg_temp_new(); |
|
7592 cpu_A0 = tcg_temp_new(); |
|
7593 cpu_T3 = tcg_temp_new(); |
|
7594 |
|
7595 cpu_tmp0 = tcg_temp_new(); |
|
7596 cpu_tmp1_i64 = tcg_temp_new_i64(); |
|
7597 cpu_tmp2_i32 = tcg_temp_new_i32(); |
|
7598 cpu_tmp3_i32 = tcg_temp_new_i32(); |
|
7599 cpu_tmp4 = tcg_temp_new(); |
|
7600 cpu_tmp5 = tcg_temp_new(); |
|
7601 cpu_tmp6 = tcg_temp_new(); |
|
7602 cpu_ptr0 = tcg_temp_new_ptr(); |
|
7603 cpu_ptr1 = tcg_temp_new_ptr(); |
|
7604 |
|
7605 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; |
|
7606 |
|
7607 dc->is_jmp = DISAS_NEXT; |
|
7608 pc_ptr = pc_start; |
|
7609 lj = -1; |
|
7610 num_insns = 0; |
|
7611 max_insns = tb->cflags & CF_COUNT_MASK; |
|
7612 if (max_insns == 0) |
|
7613 max_insns = CF_COUNT_MASK; |
|
7614 |
|
7615 gen_icount_start(); |
|
7616 for(;;) { |
|
7617 if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) { |
|
7618 TAILQ_FOREACH(bp, &env->breakpoints, entry) { |
|
7619 if (bp->pc == pc_ptr) { |
|
7620 gen_debug(dc, pc_ptr - dc->cs_base); |
|
7621 break; |
|
7622 } |
|
7623 } |
|
7624 } |
|
7625 if (search_pc) { |
|
7626 j = gen_opc_ptr - gen_opc_buf; |
|
7627 if (lj < j) { |
|
7628 lj++; |
|
7629 while (lj < j) |
|
7630 gen_opc_instr_start[lj++] = 0; |
|
7631 } |
|
7632 gen_opc_pc[lj] = pc_ptr; |
|
7633 gen_opc_cc_op[lj] = dc->cc_op; |
|
7634 gen_opc_instr_start[lj] = 1; |
|
7635 gen_opc_icount[lj] = num_insns; |
|
7636 } |
|
7637 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) |
|
7638 gen_io_start(); |
|
7639 |
|
7640 pc_ptr = disas_insn(dc, pc_ptr); |
|
7641 num_insns++; |
|
7642 /* stop translation if indicated */ |
|
7643 if (dc->is_jmp) |
|
7644 break; |
|
7645 /* if single step mode, we generate only one instruction and |
|
7646 generate an exception */ |
|
7647 /* if irq were inhibited with HF_INHIBIT_IRQ_MASK, we clear |
|
7648 the flag and abort the translation to give the irqs a |
|
7649 change to be happen */ |
|
7650 if (dc->tf || dc->singlestep_enabled || |
|
7651 (flags & HF_INHIBIT_IRQ_MASK)) { |
|
7652 gen_jmp_im(pc_ptr - dc->cs_base); |
|
7653 gen_eob(dc); |
|
7654 break; |
|
7655 } |
|
7656 /* if too long translation, stop generation too */ |
|
7657 if (gen_opc_ptr >= gen_opc_end || |
|
7658 (pc_ptr - pc_start) >= (TARGET_PAGE_SIZE - 32) || |
|
7659 num_insns >= max_insns) { |
|
7660 gen_jmp_im(pc_ptr - dc->cs_base); |
|
7661 gen_eob(dc); |
|
7662 break; |
|
7663 } |
|
7664 } |
|
7665 if (tb->cflags & CF_LAST_IO) |
|
7666 gen_io_end(); |
|
7667 gen_icount_end(tb, num_insns); |
|
7668 *gen_opc_ptr = INDEX_op_end; |
|
7669 /* we don't forget to fill the last values */ |
|
7670 if (search_pc) { |
|
7671 j = gen_opc_ptr - gen_opc_buf; |
|
7672 lj++; |
|
7673 while (lj <= j) |
|
7674 gen_opc_instr_start[lj++] = 0; |
|
7675 } |
|
7676 |
|
7677 #ifdef DEBUG_DISAS |
|
7678 if (loglevel & CPU_LOG_TB_CPU) { |
|
7679 cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP); |
|
7680 } |
|
7681 if (loglevel & CPU_LOG_TB_IN_ASM) { |
|
7682 int disas_flags; |
|
7683 fprintf(logfile, "----------------\n"); |
|
7684 fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start)); |
|
7685 #ifdef TARGET_X86_64 |
|
7686 if (dc->code64) |
|
7687 disas_flags = 2; |
|
7688 else |
|
7689 #endif |
|
7690 disas_flags = !dc->code32; |
|
7691 target_disas(logfile, pc_start, pc_ptr - pc_start, disas_flags); |
|
7692 fprintf(logfile, "\n"); |
|
7693 } |
|
7694 #endif |
|
7695 |
|
7696 if (!search_pc) { |
|
7697 tb->size = pc_ptr - pc_start; |
|
7698 tb->icount = num_insns; |
|
7699 } |
|
7700 } |
|
7701 |
|
7702 void gen_intermediate_code(CPUState *env, TranslationBlock *tb) |
|
7703 { |
|
7704 gen_intermediate_code_internal(env, tb, 0); |
|
7705 } |
|
7706 |
|
7707 void gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb) |
|
7708 { |
|
7709 gen_intermediate_code_internal(env, tb, 1); |
|
7710 } |
|
7711 |
|
7712 void gen_pc_load(CPUState *env, TranslationBlock *tb, |
|
7713 unsigned long searched_pc, int pc_pos, void *puc) |
|
7714 { |
|
7715 int cc_op; |
|
7716 #ifdef DEBUG_DISAS |
|
7717 if (loglevel & CPU_LOG_TB_OP) { |
|
7718 int i; |
|
7719 fprintf(logfile, "RESTORE:\n"); |
|
7720 for(i = 0;i <= pc_pos; i++) { |
|
7721 if (gen_opc_instr_start[i]) { |
|
7722 fprintf(logfile, "0x%04x: " TARGET_FMT_lx "\n", i, gen_opc_pc[i]); |
|
7723 } |
|
7724 } |
|
7725 fprintf(logfile, "spc=0x%08lx pc_pos=0x%x eip=" TARGET_FMT_lx " cs_base=%x\n", |
|
7726 searched_pc, pc_pos, gen_opc_pc[pc_pos] - tb->cs_base, |
|
7727 (uint32_t)tb->cs_base); |
|
7728 } |
|
7729 #endif |
|
7730 env->eip = gen_opc_pc[pc_pos] - tb->cs_base; |
|
7731 cc_op = gen_opc_cc_op[pc_pos]; |
|
7732 if (cc_op != CC_OP_DYNAMIC) |
|
7733 env->cc_op = cc_op; |
|
7734 } |