]> git.proxmox.com Git - qemu.git/blob - translate-i386.c
added getrusage
[qemu.git] / translate-i386.c
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 "disas.h"
29
30 #define DEBUG_DISAS
31
32 #define IN_OP_I386
33 #include "cpu-i386.h"
34
35 /* XXX: move that elsewhere */
36 static uint16_t *gen_opc_ptr;
37 static uint32_t *gen_opparam_ptr;
38 int __op_param1, __op_param2, __op_param3;
39
40 #ifdef __i386__
41 static inline void flush_icache_range(unsigned long start, unsigned long stop)
42 {
43 }
44 #endif
45
46 #ifdef __s390__
47 static inline void flush_icache_range(unsigned long start, unsigned long stop)
48 {
49 }
50 #endif
51
52 #ifdef __ia64__
53 static inline void flush_icache_range(unsigned long start, unsigned long stop)
54 {
55 }
56 #endif
57
58 #ifdef __powerpc__
59
60 #define MIN_CACHE_LINE_SIZE 8 /* conservative value */
61
62 static void inline flush_icache_range(unsigned long start, unsigned long stop)
63 {
64 unsigned long p;
65
66 p = start & ~(MIN_CACHE_LINE_SIZE - 1);
67 stop = (stop + MIN_CACHE_LINE_SIZE - 1) & ~(MIN_CACHE_LINE_SIZE - 1);
68
69 for (p = start; p < stop; p += MIN_CACHE_LINE_SIZE) {
70 asm ("dcbst 0,%0;" : : "r"(p) : "memory");
71 }
72 asm ("sync");
73 for (p = start; p < stop; p += MIN_CACHE_LINE_SIZE) {
74 asm ("icbi 0,%0; sync;" : : "r"(p) : "memory");
75 }
76 asm ("sync");
77 asm ("isync");
78 }
79 #endif
80
81 #ifdef __alpha__
82 static inline void flush_icache_range(unsigned long start, unsigned long stop)
83 {
84 asm ("imb");
85 }
86 #endif
87
88 #ifdef __sparc__
89
90 static void inline flush_icache_range(unsigned long start, unsigned long stop)
91 {
92 unsigned long p;
93
94 p = start & ~(8UL - 1UL);
95 stop = (stop + (8UL - 1UL)) & ~(8UL - 1UL);
96
97 for (; p < stop; p += 8)
98 __asm__ __volatile__("flush\t%0" : : "r" (p));
99 }
100
101 #endif
102
103 extern FILE *logfile;
104 extern int loglevel;
105
106 #define PREFIX_REPZ 0x01
107 #define PREFIX_REPNZ 0x02
108 #define PREFIX_LOCK 0x04
109 #define PREFIX_DATA 0x08
110 #define PREFIX_ADR 0x10
111 #define PREFIX_FWAIT 0x20
112
113 typedef struct DisasContext {
114 /* current insn context */
115 int override; /* -1 if no override */
116 int prefix;
117 int aflag, dflag;
118 uint8_t *pc; /* pc = eip + cs_base */
119 int is_jmp; /* 1 = means jump (stop translation), 2 means CPU
120 static state change (stop translation) */
121 /* current block context */
122 uint8_t *cs_base; /* base of CS segment */
123 int code32; /* 32 bit code segment */
124 int ss32; /* 32 bit stack segment */
125 int cc_op; /* current CC operation */
126 int addseg; /* non zero if either DS/ES/SS have a non zero base */
127 int f_st; /* currently unused */
128 int vm86; /* vm86 mode */
129 int cpl;
130 int iopl;
131 int tf; /* TF cpu flag */
132 } DisasContext;
133
134 /* i386 arith/logic operations */
135 enum {
136 OP_ADDL,
137 OP_ORL,
138 OP_ADCL,
139 OP_SBBL,
140 OP_ANDL,
141 OP_SUBL,
142 OP_XORL,
143 OP_CMPL,
144 };
145
146 /* i386 shift ops */
147 enum {
148 OP_ROL,
149 OP_ROR,
150 OP_RCL,
151 OP_RCR,
152 OP_SHL,
153 OP_SHR,
154 OP_SHL1, /* undocumented */
155 OP_SAR = 7,
156 };
157
158 enum {
159 #define DEF(s, n) INDEX_op_ ## s,
160 #include "opc-i386.h"
161 #undef DEF
162 NB_OPS,
163 };
164
165 #include "op-i386.h"
166
167 /* operand size */
168 enum {
169 OT_BYTE = 0,
170 OT_WORD,
171 OT_LONG,
172 OT_QUAD,
173 };
174
175 enum {
176 /* I386 int registers */
177 OR_EAX, /* MUST be even numbered */
178 OR_ECX,
179 OR_EDX,
180 OR_EBX,
181 OR_ESP,
182 OR_EBP,
183 OR_ESI,
184 OR_EDI,
185 OR_TMP0, /* temporary operand register */
186 OR_TMP1,
187 OR_A0, /* temporary register used when doing address evaluation */
188 OR_ZERO, /* fixed zero register */
189 NB_OREGS,
190 };
191
192 typedef void (GenOpFunc)(void);
193 typedef void (GenOpFunc1)(long);
194 typedef void (GenOpFunc2)(long, long);
195
196 static GenOpFunc *gen_op_mov_reg_T0[3][8] = {
197 [OT_BYTE] = {
198 gen_op_movb_EAX_T0,
199 gen_op_movb_ECX_T0,
200 gen_op_movb_EDX_T0,
201 gen_op_movb_EBX_T0,
202 gen_op_movh_EAX_T0,
203 gen_op_movh_ECX_T0,
204 gen_op_movh_EDX_T0,
205 gen_op_movh_EBX_T0,
206 },
207 [OT_WORD] = {
208 gen_op_movw_EAX_T0,
209 gen_op_movw_ECX_T0,
210 gen_op_movw_EDX_T0,
211 gen_op_movw_EBX_T0,
212 gen_op_movw_ESP_T0,
213 gen_op_movw_EBP_T0,
214 gen_op_movw_ESI_T0,
215 gen_op_movw_EDI_T0,
216 },
217 [OT_LONG] = {
218 gen_op_movl_EAX_T0,
219 gen_op_movl_ECX_T0,
220 gen_op_movl_EDX_T0,
221 gen_op_movl_EBX_T0,
222 gen_op_movl_ESP_T0,
223 gen_op_movl_EBP_T0,
224 gen_op_movl_ESI_T0,
225 gen_op_movl_EDI_T0,
226 },
227 };
228
229 static GenOpFunc *gen_op_mov_reg_T1[3][8] = {
230 [OT_BYTE] = {
231 gen_op_movb_EAX_T1,
232 gen_op_movb_ECX_T1,
233 gen_op_movb_EDX_T1,
234 gen_op_movb_EBX_T1,
235 gen_op_movh_EAX_T1,
236 gen_op_movh_ECX_T1,
237 gen_op_movh_EDX_T1,
238 gen_op_movh_EBX_T1,
239 },
240 [OT_WORD] = {
241 gen_op_movw_EAX_T1,
242 gen_op_movw_ECX_T1,
243 gen_op_movw_EDX_T1,
244 gen_op_movw_EBX_T1,
245 gen_op_movw_ESP_T1,
246 gen_op_movw_EBP_T1,
247 gen_op_movw_ESI_T1,
248 gen_op_movw_EDI_T1,
249 },
250 [OT_LONG] = {
251 gen_op_movl_EAX_T1,
252 gen_op_movl_ECX_T1,
253 gen_op_movl_EDX_T1,
254 gen_op_movl_EBX_T1,
255 gen_op_movl_ESP_T1,
256 gen_op_movl_EBP_T1,
257 gen_op_movl_ESI_T1,
258 gen_op_movl_EDI_T1,
259 },
260 };
261
262 static GenOpFunc *gen_op_mov_reg_A0[2][8] = {
263 [0] = {
264 gen_op_movw_EAX_A0,
265 gen_op_movw_ECX_A0,
266 gen_op_movw_EDX_A0,
267 gen_op_movw_EBX_A0,
268 gen_op_movw_ESP_A0,
269 gen_op_movw_EBP_A0,
270 gen_op_movw_ESI_A0,
271 gen_op_movw_EDI_A0,
272 },
273 [1] = {
274 gen_op_movl_EAX_A0,
275 gen_op_movl_ECX_A0,
276 gen_op_movl_EDX_A0,
277 gen_op_movl_EBX_A0,
278 gen_op_movl_ESP_A0,
279 gen_op_movl_EBP_A0,
280 gen_op_movl_ESI_A0,
281 gen_op_movl_EDI_A0,
282 },
283 };
284
285 static GenOpFunc *gen_op_mov_TN_reg[3][2][8] =
286 {
287 [OT_BYTE] = {
288 {
289 gen_op_movl_T0_EAX,
290 gen_op_movl_T0_ECX,
291 gen_op_movl_T0_EDX,
292 gen_op_movl_T0_EBX,
293 gen_op_movh_T0_EAX,
294 gen_op_movh_T0_ECX,
295 gen_op_movh_T0_EDX,
296 gen_op_movh_T0_EBX,
297 },
298 {
299 gen_op_movl_T1_EAX,
300 gen_op_movl_T1_ECX,
301 gen_op_movl_T1_EDX,
302 gen_op_movl_T1_EBX,
303 gen_op_movh_T1_EAX,
304 gen_op_movh_T1_ECX,
305 gen_op_movh_T1_EDX,
306 gen_op_movh_T1_EBX,
307 },
308 },
309 [OT_WORD] = {
310 {
311 gen_op_movl_T0_EAX,
312 gen_op_movl_T0_ECX,
313 gen_op_movl_T0_EDX,
314 gen_op_movl_T0_EBX,
315 gen_op_movl_T0_ESP,
316 gen_op_movl_T0_EBP,
317 gen_op_movl_T0_ESI,
318 gen_op_movl_T0_EDI,
319 },
320 {
321 gen_op_movl_T1_EAX,
322 gen_op_movl_T1_ECX,
323 gen_op_movl_T1_EDX,
324 gen_op_movl_T1_EBX,
325 gen_op_movl_T1_ESP,
326 gen_op_movl_T1_EBP,
327 gen_op_movl_T1_ESI,
328 gen_op_movl_T1_EDI,
329 },
330 },
331 [OT_LONG] = {
332 {
333 gen_op_movl_T0_EAX,
334 gen_op_movl_T0_ECX,
335 gen_op_movl_T0_EDX,
336 gen_op_movl_T0_EBX,
337 gen_op_movl_T0_ESP,
338 gen_op_movl_T0_EBP,
339 gen_op_movl_T0_ESI,
340 gen_op_movl_T0_EDI,
341 },
342 {
343 gen_op_movl_T1_EAX,
344 gen_op_movl_T1_ECX,
345 gen_op_movl_T1_EDX,
346 gen_op_movl_T1_EBX,
347 gen_op_movl_T1_ESP,
348 gen_op_movl_T1_EBP,
349 gen_op_movl_T1_ESI,
350 gen_op_movl_T1_EDI,
351 },
352 },
353 };
354
355 static GenOpFunc *gen_op_movl_A0_reg[8] = {
356 gen_op_movl_A0_EAX,
357 gen_op_movl_A0_ECX,
358 gen_op_movl_A0_EDX,
359 gen_op_movl_A0_EBX,
360 gen_op_movl_A0_ESP,
361 gen_op_movl_A0_EBP,
362 gen_op_movl_A0_ESI,
363 gen_op_movl_A0_EDI,
364 };
365
366 static GenOpFunc *gen_op_addl_A0_reg_sN[4][8] = {
367 [0] = {
368 gen_op_addl_A0_EAX,
369 gen_op_addl_A0_ECX,
370 gen_op_addl_A0_EDX,
371 gen_op_addl_A0_EBX,
372 gen_op_addl_A0_ESP,
373 gen_op_addl_A0_EBP,
374 gen_op_addl_A0_ESI,
375 gen_op_addl_A0_EDI,
376 },
377 [1] = {
378 gen_op_addl_A0_EAX_s1,
379 gen_op_addl_A0_ECX_s1,
380 gen_op_addl_A0_EDX_s1,
381 gen_op_addl_A0_EBX_s1,
382 gen_op_addl_A0_ESP_s1,
383 gen_op_addl_A0_EBP_s1,
384 gen_op_addl_A0_ESI_s1,
385 gen_op_addl_A0_EDI_s1,
386 },
387 [2] = {
388 gen_op_addl_A0_EAX_s2,
389 gen_op_addl_A0_ECX_s2,
390 gen_op_addl_A0_EDX_s2,
391 gen_op_addl_A0_EBX_s2,
392 gen_op_addl_A0_ESP_s2,
393 gen_op_addl_A0_EBP_s2,
394 gen_op_addl_A0_ESI_s2,
395 gen_op_addl_A0_EDI_s2,
396 },
397 [3] = {
398 gen_op_addl_A0_EAX_s3,
399 gen_op_addl_A0_ECX_s3,
400 gen_op_addl_A0_EDX_s3,
401 gen_op_addl_A0_EBX_s3,
402 gen_op_addl_A0_ESP_s3,
403 gen_op_addl_A0_EBP_s3,
404 gen_op_addl_A0_ESI_s3,
405 gen_op_addl_A0_EDI_s3,
406 },
407 };
408
409 static GenOpFunc *gen_op_cmov_reg_T1_T0[2][8] = {
410 [0] = {
411 gen_op_cmovw_EAX_T1_T0,
412 gen_op_cmovw_ECX_T1_T0,
413 gen_op_cmovw_EDX_T1_T0,
414 gen_op_cmovw_EBX_T1_T0,
415 gen_op_cmovw_ESP_T1_T0,
416 gen_op_cmovw_EBP_T1_T0,
417 gen_op_cmovw_ESI_T1_T0,
418 gen_op_cmovw_EDI_T1_T0,
419 },
420 [1] = {
421 gen_op_cmovl_EAX_T1_T0,
422 gen_op_cmovl_ECX_T1_T0,
423 gen_op_cmovl_EDX_T1_T0,
424 gen_op_cmovl_EBX_T1_T0,
425 gen_op_cmovl_ESP_T1_T0,
426 gen_op_cmovl_EBP_T1_T0,
427 gen_op_cmovl_ESI_T1_T0,
428 gen_op_cmovl_EDI_T1_T0,
429 },
430 };
431
432 static GenOpFunc *gen_op_arith_T0_T1_cc[8] = {
433 gen_op_addl_T0_T1_cc,
434 gen_op_orl_T0_T1_cc,
435 NULL,
436 NULL,
437 gen_op_andl_T0_T1_cc,
438 gen_op_subl_T0_T1_cc,
439 gen_op_xorl_T0_T1_cc,
440 gen_op_cmpl_T0_T1_cc,
441 };
442
443 static GenOpFunc *gen_op_arithc_T0_T1_cc[3][2] = {
444 [OT_BYTE] = {
445 gen_op_adcb_T0_T1_cc,
446 gen_op_sbbb_T0_T1_cc,
447 },
448 [OT_WORD] = {
449 gen_op_adcw_T0_T1_cc,
450 gen_op_sbbw_T0_T1_cc,
451 },
452 [OT_LONG] = {
453 gen_op_adcl_T0_T1_cc,
454 gen_op_sbbl_T0_T1_cc,
455 },
456 };
457
458 static const int cc_op_arithb[8] = {
459 CC_OP_ADDB,
460 CC_OP_LOGICB,
461 CC_OP_ADDB,
462 CC_OP_SUBB,
463 CC_OP_LOGICB,
464 CC_OP_SUBB,
465 CC_OP_LOGICB,
466 CC_OP_SUBB,
467 };
468
469 static GenOpFunc *gen_op_cmpxchg_T0_T1_EAX_cc[3] = {
470 gen_op_cmpxchgb_T0_T1_EAX_cc,
471 gen_op_cmpxchgw_T0_T1_EAX_cc,
472 gen_op_cmpxchgl_T0_T1_EAX_cc,
473 };
474
475 static GenOpFunc *gen_op_shift_T0_T1_cc[3][8] = {
476 [OT_BYTE] = {
477 gen_op_rolb_T0_T1_cc,
478 gen_op_rorb_T0_T1_cc,
479 gen_op_rclb_T0_T1_cc,
480 gen_op_rcrb_T0_T1_cc,
481 gen_op_shlb_T0_T1_cc,
482 gen_op_shrb_T0_T1_cc,
483 gen_op_shlb_T0_T1_cc,
484 gen_op_sarb_T0_T1_cc,
485 },
486 [OT_WORD] = {
487 gen_op_rolw_T0_T1_cc,
488 gen_op_rorw_T0_T1_cc,
489 gen_op_rclw_T0_T1_cc,
490 gen_op_rcrw_T0_T1_cc,
491 gen_op_shlw_T0_T1_cc,
492 gen_op_shrw_T0_T1_cc,
493 gen_op_shlw_T0_T1_cc,
494 gen_op_sarw_T0_T1_cc,
495 },
496 [OT_LONG] = {
497 gen_op_roll_T0_T1_cc,
498 gen_op_rorl_T0_T1_cc,
499 gen_op_rcll_T0_T1_cc,
500 gen_op_rcrl_T0_T1_cc,
501 gen_op_shll_T0_T1_cc,
502 gen_op_shrl_T0_T1_cc,
503 gen_op_shll_T0_T1_cc,
504 gen_op_sarl_T0_T1_cc,
505 },
506 };
507
508 static GenOpFunc1 *gen_op_shiftd_T0_T1_im_cc[2][2] = {
509 [0] = {
510 gen_op_shldw_T0_T1_im_cc,
511 gen_op_shrdw_T0_T1_im_cc,
512 },
513 [1] = {
514 gen_op_shldl_T0_T1_im_cc,
515 gen_op_shrdl_T0_T1_im_cc,
516 },
517 };
518
519 static GenOpFunc *gen_op_shiftd_T0_T1_ECX_cc[2][2] = {
520 [0] = {
521 gen_op_shldw_T0_T1_ECX_cc,
522 gen_op_shrdw_T0_T1_ECX_cc,
523 },
524 [1] = {
525 gen_op_shldl_T0_T1_ECX_cc,
526 gen_op_shrdl_T0_T1_ECX_cc,
527 },
528 };
529
530 static GenOpFunc *gen_op_btx_T0_T1_cc[2][4] = {
531 [0] = {
532 gen_op_btw_T0_T1_cc,
533 gen_op_btsw_T0_T1_cc,
534 gen_op_btrw_T0_T1_cc,
535 gen_op_btcw_T0_T1_cc,
536 },
537 [1] = {
538 gen_op_btl_T0_T1_cc,
539 gen_op_btsl_T0_T1_cc,
540 gen_op_btrl_T0_T1_cc,
541 gen_op_btcl_T0_T1_cc,
542 },
543 };
544
545 static GenOpFunc *gen_op_bsx_T0_cc[2][2] = {
546 [0] = {
547 gen_op_bsfw_T0_cc,
548 gen_op_bsrw_T0_cc,
549 },
550 [1] = {
551 gen_op_bsfl_T0_cc,
552 gen_op_bsrl_T0_cc,
553 },
554 };
555
556 static GenOpFunc *gen_op_lds_T0_A0[3] = {
557 gen_op_ldsb_T0_A0,
558 gen_op_ldsw_T0_A0,
559 };
560
561 static GenOpFunc *gen_op_ldu_T0_A0[3] = {
562 gen_op_ldub_T0_A0,
563 gen_op_lduw_T0_A0,
564 };
565
566 /* sign does not matter */
567 static GenOpFunc *gen_op_ld_T0_A0[3] = {
568 gen_op_ldub_T0_A0,
569 gen_op_lduw_T0_A0,
570 gen_op_ldl_T0_A0,
571 };
572
573 static GenOpFunc *gen_op_ld_T1_A0[3] = {
574 gen_op_ldub_T1_A0,
575 gen_op_lduw_T1_A0,
576 gen_op_ldl_T1_A0,
577 };
578
579 static GenOpFunc *gen_op_st_T0_A0[3] = {
580 gen_op_stb_T0_A0,
581 gen_op_stw_T0_A0,
582 gen_op_stl_T0_A0,
583 };
584
585 /* the _a32 and _a16 string operations use A0 as the base register. */
586
587 #define STRINGOP(x) \
588 gen_op_ ## x ## b_fast, \
589 gen_op_ ## x ## w_fast, \
590 gen_op_ ## x ## l_fast, \
591 gen_op_ ## x ## b_a32, \
592 gen_op_ ## x ## w_a32, \
593 gen_op_ ## x ## l_a32, \
594 gen_op_ ## x ## b_a16, \
595 gen_op_ ## x ## w_a16, \
596 gen_op_ ## x ## l_a16,
597
598 static GenOpFunc *gen_op_movs[9 * 2] = {
599 STRINGOP(movs)
600 STRINGOP(rep_movs)
601 };
602
603 static GenOpFunc *gen_op_stos[9 * 2] = {
604 STRINGOP(stos)
605 STRINGOP(rep_stos)
606 };
607
608 static GenOpFunc *gen_op_lods[9 * 2] = {
609 STRINGOP(lods)
610 STRINGOP(rep_lods)
611 };
612
613 static GenOpFunc *gen_op_scas[9 * 3] = {
614 STRINGOP(scas)
615 STRINGOP(repz_scas)
616 STRINGOP(repnz_scas)
617 };
618
619 static GenOpFunc *gen_op_cmps[9 * 3] = {
620 STRINGOP(cmps)
621 STRINGOP(repz_cmps)
622 STRINGOP(repnz_cmps)
623 };
624
625 static GenOpFunc *gen_op_ins[9 * 2] = {
626 STRINGOP(ins)
627 STRINGOP(rep_ins)
628 };
629
630
631 static GenOpFunc *gen_op_outs[9 * 2] = {
632 STRINGOP(outs)
633 STRINGOP(rep_outs)
634 };
635
636
637 static inline void gen_string_ds(DisasContext *s, int ot, GenOpFunc **func)
638 {
639 int index, override;
640
641 override = s->override;
642 if (s->aflag) {
643 /* 32 bit address */
644 if (s->addseg && override < 0)
645 override = R_DS;
646 if (override >= 0) {
647 gen_op_movl_A0_seg(offsetof(CPUX86State,seg_cache[override].base));
648 index = 3 + ot;
649 } else {
650 index = ot;
651 }
652 } else {
653 if (override < 0)
654 override = R_DS;
655 gen_op_movl_A0_seg(offsetof(CPUX86State,seg_cache[override].base));
656 /* 16 address, always override */
657 index = 6 + ot;
658 }
659 func[index]();
660 }
661
662 static inline void gen_string_es(DisasContext *s, int ot, GenOpFunc **func)
663 {
664 int index;
665
666 if (s->aflag) {
667 if (s->addseg) {
668 index = 3 + ot;
669 } else {
670 index = ot;
671 }
672 } else {
673 index = 6 + ot;
674 }
675 func[index]();
676 }
677
678
679 static GenOpFunc *gen_op_in[3] = {
680 gen_op_inb_T0_T1,
681 gen_op_inw_T0_T1,
682 gen_op_inl_T0_T1,
683 };
684
685 static GenOpFunc *gen_op_out[3] = {
686 gen_op_outb_T0_T1,
687 gen_op_outw_T0_T1,
688 gen_op_outl_T0_T1,
689 };
690
691 enum {
692 JCC_O,
693 JCC_B,
694 JCC_Z,
695 JCC_BE,
696 JCC_S,
697 JCC_P,
698 JCC_L,
699 JCC_LE,
700 };
701
702 static GenOpFunc2 *gen_jcc_slow[8] = {
703 gen_op_jo_cc,
704 gen_op_jb_cc,
705 gen_op_jz_cc,
706 gen_op_jbe_cc,
707 gen_op_js_cc,
708 gen_op_jp_cc,
709 gen_op_jl_cc,
710 gen_op_jle_cc,
711 };
712
713 static GenOpFunc2 *gen_jcc_sub[3][8] = {
714 [OT_BYTE] = {
715 NULL,
716 gen_op_jb_subb,
717 gen_op_jz_subb,
718 gen_op_jbe_subb,
719 gen_op_js_subb,
720 NULL,
721 gen_op_jl_subb,
722 gen_op_jle_subb,
723 },
724 [OT_WORD] = {
725 NULL,
726 gen_op_jb_subw,
727 gen_op_jz_subw,
728 gen_op_jbe_subw,
729 gen_op_js_subw,
730 NULL,
731 gen_op_jl_subw,
732 gen_op_jle_subw,
733 },
734 [OT_LONG] = {
735 NULL,
736 gen_op_jb_subl,
737 gen_op_jz_subl,
738 gen_op_jbe_subl,
739 gen_op_js_subl,
740 NULL,
741 gen_op_jl_subl,
742 gen_op_jle_subl,
743 },
744 };
745 static GenOpFunc2 *gen_op_loop[2][4] = {
746 [0] = {
747 gen_op_loopnzw,
748 gen_op_loopzw,
749 gen_op_loopw,
750 gen_op_jecxzw,
751 },
752 [1] = {
753 gen_op_loopnzl,
754 gen_op_loopzl,
755 gen_op_loopl,
756 gen_op_jecxzl,
757 },
758 };
759
760 static GenOpFunc *gen_setcc_slow[8] = {
761 gen_op_seto_T0_cc,
762 gen_op_setb_T0_cc,
763 gen_op_setz_T0_cc,
764 gen_op_setbe_T0_cc,
765 gen_op_sets_T0_cc,
766 gen_op_setp_T0_cc,
767 gen_op_setl_T0_cc,
768 gen_op_setle_T0_cc,
769 };
770
771 static GenOpFunc *gen_setcc_sub[3][8] = {
772 [OT_BYTE] = {
773 NULL,
774 gen_op_setb_T0_subb,
775 gen_op_setz_T0_subb,
776 gen_op_setbe_T0_subb,
777 gen_op_sets_T0_subb,
778 NULL,
779 gen_op_setl_T0_subb,
780 gen_op_setle_T0_subb,
781 },
782 [OT_WORD] = {
783 NULL,
784 gen_op_setb_T0_subw,
785 gen_op_setz_T0_subw,
786 gen_op_setbe_T0_subw,
787 gen_op_sets_T0_subw,
788 NULL,
789 gen_op_setl_T0_subw,
790 gen_op_setle_T0_subw,
791 },
792 [OT_LONG] = {
793 NULL,
794 gen_op_setb_T0_subl,
795 gen_op_setz_T0_subl,
796 gen_op_setbe_T0_subl,
797 gen_op_sets_T0_subl,
798 NULL,
799 gen_op_setl_T0_subl,
800 gen_op_setle_T0_subl,
801 },
802 };
803
804 static GenOpFunc *gen_op_fp_arith_ST0_FT0[8] = {
805 gen_op_fadd_ST0_FT0,
806 gen_op_fmul_ST0_FT0,
807 gen_op_fcom_ST0_FT0,
808 gen_op_fcom_ST0_FT0,
809 gen_op_fsub_ST0_FT0,
810 gen_op_fsubr_ST0_FT0,
811 gen_op_fdiv_ST0_FT0,
812 gen_op_fdivr_ST0_FT0,
813 };
814
815 /* NOTE the exception in "r" op ordering */
816 static GenOpFunc1 *gen_op_fp_arith_STN_ST0[8] = {
817 gen_op_fadd_STN_ST0,
818 gen_op_fmul_STN_ST0,
819 NULL,
820 NULL,
821 gen_op_fsubr_STN_ST0,
822 gen_op_fsub_STN_ST0,
823 gen_op_fdivr_STN_ST0,
824 gen_op_fdiv_STN_ST0,
825 };
826
827 static void gen_op(DisasContext *s1, int op, int ot, int d, int s)
828 {
829 if (d != OR_TMP0)
830 gen_op_mov_TN_reg[ot][0][d]();
831 if (s != OR_TMP1)
832 gen_op_mov_TN_reg[ot][1][s]();
833 if (op == OP_ADCL || op == OP_SBBL) {
834 if (s1->cc_op != CC_OP_DYNAMIC)
835 gen_op_set_cc_op(s1->cc_op);
836 gen_op_arithc_T0_T1_cc[ot][op - OP_ADCL]();
837 s1->cc_op = CC_OP_DYNAMIC;
838 } else {
839 gen_op_arith_T0_T1_cc[op]();
840 s1->cc_op = cc_op_arithb[op] + ot;
841 }
842 if (d != OR_TMP0 && op != OP_CMPL)
843 gen_op_mov_reg_T0[ot][d]();
844 }
845
846 static void gen_opi(DisasContext *s1, int op, int ot, int d, int c)
847 {
848 gen_op_movl_T1_im(c);
849 gen_op(s1, op, ot, d, OR_TMP1);
850 }
851
852 static void gen_inc(DisasContext *s1, int ot, int d, int c)
853 {
854 if (d != OR_TMP0)
855 gen_op_mov_TN_reg[ot][0][d]();
856 if (s1->cc_op != CC_OP_DYNAMIC)
857 gen_op_set_cc_op(s1->cc_op);
858 if (c > 0) {
859 gen_op_incl_T0_cc();
860 s1->cc_op = CC_OP_INCB + ot;
861 } else {
862 gen_op_decl_T0_cc();
863 s1->cc_op = CC_OP_DECB + ot;
864 }
865 if (d != OR_TMP0)
866 gen_op_mov_reg_T0[ot][d]();
867 }
868
869 static void gen_shift(DisasContext *s1, int op, int ot, int d, int s)
870 {
871 if (d != OR_TMP0)
872 gen_op_mov_TN_reg[ot][0][d]();
873 if (s != OR_TMP1)
874 gen_op_mov_TN_reg[ot][1][s]();
875 /* for zero counts, flags are not updated, so must do it dynamically */
876 if (s1->cc_op != CC_OP_DYNAMIC)
877 gen_op_set_cc_op(s1->cc_op);
878
879 gen_op_shift_T0_T1_cc[ot][op]();
880
881 if (d != OR_TMP0)
882 gen_op_mov_reg_T0[ot][d]();
883 s1->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
884 }
885
886 static void gen_shifti(DisasContext *s1, int op, int ot, int d, int c)
887 {
888 /* currently not optimized */
889 gen_op_movl_T1_im(c);
890 gen_shift(s1, op, ot, d, OR_TMP1);
891 }
892
893 static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ptr)
894 {
895 int havesib;
896 int base, disp;
897 int index;
898 int scale;
899 int opreg;
900 int mod, rm, code, override, must_add_seg;
901
902 override = s->override;
903 must_add_seg = s->addseg;
904 if (override >= 0)
905 must_add_seg = 1;
906 mod = (modrm >> 6) & 3;
907 rm = modrm & 7;
908
909 if (s->aflag) {
910
911 havesib = 0;
912 base = rm;
913 index = 0;
914 scale = 0;
915
916 if (base == 4) {
917 havesib = 1;
918 code = ldub(s->pc++);
919 scale = (code >> 6) & 3;
920 index = (code >> 3) & 7;
921 base = code & 7;
922 }
923
924 switch (mod) {
925 case 0:
926 if (base == 5) {
927 base = -1;
928 disp = ldl(s->pc);
929 s->pc += 4;
930 } else {
931 disp = 0;
932 }
933 break;
934 case 1:
935 disp = (int8_t)ldub(s->pc++);
936 break;
937 default:
938 case 2:
939 disp = ldl(s->pc);
940 s->pc += 4;
941 break;
942 }
943
944 if (base >= 0) {
945 gen_op_movl_A0_reg[base]();
946 if (disp != 0)
947 gen_op_addl_A0_im(disp);
948 } else {
949 gen_op_movl_A0_im(disp);
950 }
951 if (havesib && (index != 4 || scale != 0)) {
952 gen_op_addl_A0_reg_sN[scale][index]();
953 }
954 if (must_add_seg) {
955 if (override < 0) {
956 if (base == R_EBP || base == R_ESP)
957 override = R_SS;
958 else
959 override = R_DS;
960 }
961 gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[override].base));
962 }
963 } else {
964 switch (mod) {
965 case 0:
966 if (rm == 6) {
967 disp = lduw(s->pc);
968 s->pc += 2;
969 gen_op_movl_A0_im(disp);
970 rm = 0; /* avoid SS override */
971 goto no_rm;
972 } else {
973 disp = 0;
974 }
975 break;
976 case 1:
977 disp = (int8_t)ldub(s->pc++);
978 break;
979 default:
980 case 2:
981 disp = lduw(s->pc);
982 s->pc += 2;
983 break;
984 }
985 switch(rm) {
986 case 0:
987 gen_op_movl_A0_reg[R_EBX]();
988 gen_op_addl_A0_reg_sN[0][R_ESI]();
989 break;
990 case 1:
991 gen_op_movl_A0_reg[R_EBX]();
992 gen_op_addl_A0_reg_sN[0][R_EDI]();
993 break;
994 case 2:
995 gen_op_movl_A0_reg[R_EBP]();
996 gen_op_addl_A0_reg_sN[0][R_ESI]();
997 break;
998 case 3:
999 gen_op_movl_A0_reg[R_EBP]();
1000 gen_op_addl_A0_reg_sN[0][R_EDI]();
1001 break;
1002 case 4:
1003 gen_op_movl_A0_reg[R_ESI]();
1004 break;
1005 case 5:
1006 gen_op_movl_A0_reg[R_EDI]();
1007 break;
1008 case 6:
1009 gen_op_movl_A0_reg[R_EBP]();
1010 break;
1011 default:
1012 case 7:
1013 gen_op_movl_A0_reg[R_EBX]();
1014 break;
1015 }
1016 if (disp != 0)
1017 gen_op_addl_A0_im(disp);
1018 gen_op_andl_A0_ffff();
1019 no_rm:
1020 if (must_add_seg) {
1021 if (override < 0) {
1022 if (rm == 2 || rm == 3 || rm == 6)
1023 override = R_SS;
1024 else
1025 override = R_DS;
1026 }
1027 gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[override].base));
1028 }
1029 }
1030
1031 opreg = OR_A0;
1032 disp = 0;
1033 *reg_ptr = opreg;
1034 *offset_ptr = disp;
1035 }
1036
1037 /* generate modrm memory load or store of 'reg'. TMP0 is used if reg !=
1038 OR_TMP0 */
1039 static void gen_ldst_modrm(DisasContext *s, int modrm, int ot, int reg, int is_store)
1040 {
1041 int mod, rm, opreg, disp;
1042
1043 mod = (modrm >> 6) & 3;
1044 rm = modrm & 7;
1045 if (mod == 3) {
1046 if (is_store) {
1047 if (reg != OR_TMP0)
1048 gen_op_mov_TN_reg[ot][0][reg]();
1049 gen_op_mov_reg_T0[ot][rm]();
1050 } else {
1051 gen_op_mov_TN_reg[ot][0][rm]();
1052 if (reg != OR_TMP0)
1053 gen_op_mov_reg_T0[ot][reg]();
1054 }
1055 } else {
1056 gen_lea_modrm(s, modrm, &opreg, &disp);
1057 if (is_store) {
1058 if (reg != OR_TMP0)
1059 gen_op_mov_TN_reg[ot][0][reg]();
1060 gen_op_st_T0_A0[ot]();
1061 } else {
1062 gen_op_ld_T0_A0[ot]();
1063 if (reg != OR_TMP0)
1064 gen_op_mov_reg_T0[ot][reg]();
1065 }
1066 }
1067 }
1068
1069 static inline uint32_t insn_get(DisasContext *s, int ot)
1070 {
1071 uint32_t ret;
1072
1073 switch(ot) {
1074 case OT_BYTE:
1075 ret = ldub(s->pc);
1076 s->pc++;
1077 break;
1078 case OT_WORD:
1079 ret = lduw(s->pc);
1080 s->pc += 2;
1081 break;
1082 default:
1083 case OT_LONG:
1084 ret = ldl(s->pc);
1085 s->pc += 4;
1086 break;
1087 }
1088 return ret;
1089 }
1090
1091 static inline void gen_jcc(DisasContext *s, int b, int val, int next_eip)
1092 {
1093 int inv, jcc_op;
1094 GenOpFunc2 *func;
1095
1096 inv = b & 1;
1097 jcc_op = (b >> 1) & 7;
1098 switch(s->cc_op) {
1099 /* we optimize the cmp/jcc case */
1100 case CC_OP_SUBB:
1101 case CC_OP_SUBW:
1102 case CC_OP_SUBL:
1103 func = gen_jcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
1104 if (!func)
1105 goto slow_jcc;
1106 break;
1107
1108 /* some jumps are easy to compute */
1109 case CC_OP_ADDB:
1110 case CC_OP_ADDW:
1111 case CC_OP_ADDL:
1112 case CC_OP_ADCB:
1113 case CC_OP_ADCW:
1114 case CC_OP_ADCL:
1115 case CC_OP_SBBB:
1116 case CC_OP_SBBW:
1117 case CC_OP_SBBL:
1118 case CC_OP_LOGICB:
1119 case CC_OP_LOGICW:
1120 case CC_OP_LOGICL:
1121 case CC_OP_INCB:
1122 case CC_OP_INCW:
1123 case CC_OP_INCL:
1124 case CC_OP_DECB:
1125 case CC_OP_DECW:
1126 case CC_OP_DECL:
1127 case CC_OP_SHLB:
1128 case CC_OP_SHLW:
1129 case CC_OP_SHLL:
1130 case CC_OP_SARB:
1131 case CC_OP_SARW:
1132 case CC_OP_SARL:
1133 switch(jcc_op) {
1134 case JCC_Z:
1135 func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1136 break;
1137 case JCC_S:
1138 func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1139 break;
1140 default:
1141 goto slow_jcc;
1142 }
1143 break;
1144 default:
1145 slow_jcc:
1146 if (s->cc_op != CC_OP_DYNAMIC)
1147 gen_op_set_cc_op(s->cc_op);
1148 func = gen_jcc_slow[jcc_op];
1149 break;
1150 }
1151 if (!inv) {
1152 func(val, next_eip);
1153 } else {
1154 func(next_eip, val);
1155 }
1156 }
1157
1158 static void gen_setcc(DisasContext *s, int b)
1159 {
1160 int inv, jcc_op;
1161 GenOpFunc *func;
1162
1163 inv = b & 1;
1164 jcc_op = (b >> 1) & 7;
1165 switch(s->cc_op) {
1166 /* we optimize the cmp/jcc case */
1167 case CC_OP_SUBB:
1168 case CC_OP_SUBW:
1169 case CC_OP_SUBL:
1170 func = gen_setcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
1171 if (!func)
1172 goto slow_jcc;
1173 break;
1174
1175 /* some jumps are easy to compute */
1176 case CC_OP_ADDB:
1177 case CC_OP_ADDW:
1178 case CC_OP_ADDL:
1179 case CC_OP_LOGICB:
1180 case CC_OP_LOGICW:
1181 case CC_OP_LOGICL:
1182 case CC_OP_INCB:
1183 case CC_OP_INCW:
1184 case CC_OP_INCL:
1185 case CC_OP_DECB:
1186 case CC_OP_DECW:
1187 case CC_OP_DECL:
1188 case CC_OP_SHLB:
1189 case CC_OP_SHLW:
1190 case CC_OP_SHLL:
1191 switch(jcc_op) {
1192 case JCC_Z:
1193 func = gen_setcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1194 break;
1195 case JCC_S:
1196 func = gen_setcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1197 break;
1198 default:
1199 goto slow_jcc;
1200 }
1201 break;
1202 default:
1203 slow_jcc:
1204 if (s->cc_op != CC_OP_DYNAMIC)
1205 gen_op_set_cc_op(s->cc_op);
1206 func = gen_setcc_slow[jcc_op];
1207 break;
1208 }
1209 func();
1210 if (inv) {
1211 gen_op_xor_T0_1();
1212 }
1213 }
1214
1215 /* move T0 to seg_reg and compute if the CPU state may change */
1216 static void gen_movl_seg_T0(DisasContext *s, int seg_reg)
1217 {
1218 gen_op_movl_seg_T0(seg_reg);
1219 if (!s->addseg && seg_reg < R_FS)
1220 s->is_jmp = 2; /* abort translation because the register may
1221 have a non zero base */
1222 }
1223
1224 /* generate a push. It depends on ss32, addseg and dflag */
1225 static void gen_push_T0(DisasContext *s)
1226 {
1227 if (s->ss32) {
1228 if (!s->addseg) {
1229 if (s->dflag)
1230 gen_op_pushl_T0();
1231 else
1232 gen_op_pushw_T0();
1233 } else {
1234 if (s->dflag)
1235 gen_op_pushl_ss32_T0();
1236 else
1237 gen_op_pushw_ss32_T0();
1238 }
1239 } else {
1240 if (s->dflag)
1241 gen_op_pushl_ss16_T0();
1242 else
1243 gen_op_pushw_ss16_T0();
1244 }
1245 }
1246
1247 /* two step pop is necessary for precise exceptions */
1248 static void gen_pop_T0(DisasContext *s)
1249 {
1250 if (s->ss32) {
1251 if (!s->addseg) {
1252 if (s->dflag)
1253 gen_op_popl_T0();
1254 else
1255 gen_op_popw_T0();
1256 } else {
1257 if (s->dflag)
1258 gen_op_popl_ss32_T0();
1259 else
1260 gen_op_popw_ss32_T0();
1261 }
1262 } else {
1263 if (s->dflag)
1264 gen_op_popl_ss16_T0();
1265 else
1266 gen_op_popw_ss16_T0();
1267 }
1268 }
1269
1270 static void gen_pop_update(DisasContext *s)
1271 {
1272 if (s->ss32) {
1273 if (s->dflag)
1274 gen_op_addl_ESP_4();
1275 else
1276 gen_op_addl_ESP_2();
1277 } else {
1278 if (s->dflag)
1279 gen_op_addw_ESP_4();
1280 else
1281 gen_op_addw_ESP_2();
1282 }
1283 }
1284
1285 /* NOTE: wrap around in 16 bit not fully handled */
1286 static void gen_pusha(DisasContext *s)
1287 {
1288 int i;
1289 gen_op_movl_A0_ESP();
1290 gen_op_addl_A0_im(-16 << s->dflag);
1291 if (!s->ss32)
1292 gen_op_andl_A0_ffff();
1293 gen_op_movl_T1_A0();
1294 if (s->addseg)
1295 gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[R_SS].base));
1296 for(i = 0;i < 8; i++) {
1297 gen_op_mov_TN_reg[OT_LONG][0][7 - i]();
1298 gen_op_st_T0_A0[OT_WORD + s->dflag]();
1299 gen_op_addl_A0_im(2 << s->dflag);
1300 }
1301 gen_op_mov_reg_T1[OT_WORD + s->dflag][R_ESP]();
1302 }
1303
1304 /* NOTE: wrap around in 16 bit not fully handled */
1305 static void gen_popa(DisasContext *s)
1306 {
1307 int i;
1308 gen_op_movl_A0_ESP();
1309 if (!s->ss32)
1310 gen_op_andl_A0_ffff();
1311 gen_op_movl_T1_A0();
1312 gen_op_addl_T1_im(16 << s->dflag);
1313 if (s->addseg)
1314 gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[R_SS].base));
1315 for(i = 0;i < 8; i++) {
1316 /* ESP is not reloaded */
1317 if (i != 3) {
1318 gen_op_ld_T0_A0[OT_WORD + s->dflag]();
1319 gen_op_mov_reg_T0[OT_WORD + s->dflag][7 - i]();
1320 }
1321 gen_op_addl_A0_im(2 << s->dflag);
1322 }
1323 gen_op_mov_reg_T1[OT_WORD + s->dflag][R_ESP]();
1324 }
1325
1326 /* NOTE: wrap around in 16 bit not fully handled */
1327 /* XXX: check this */
1328 static void gen_enter(DisasContext *s, int esp_addend, int level)
1329 {
1330 int ot, level1, addend, opsize;
1331
1332 ot = s->dflag + OT_WORD;
1333 level &= 0x1f;
1334 level1 = level;
1335 opsize = 2 << s->dflag;
1336
1337 gen_op_movl_A0_ESP();
1338 gen_op_addl_A0_im(-opsize);
1339 if (!s->ss32)
1340 gen_op_andl_A0_ffff();
1341 gen_op_movl_T1_A0();
1342 if (s->addseg)
1343 gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[R_SS].base));
1344 /* push bp */
1345 gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
1346 gen_op_st_T0_A0[ot]();
1347 if (level) {
1348 while (level--) {
1349 gen_op_addl_A0_im(-opsize);
1350 gen_op_addl_T0_im(-opsize);
1351 gen_op_st_T0_A0[ot]();
1352 }
1353 gen_op_addl_A0_im(-opsize);
1354 /* XXX: add st_T1_A0 ? */
1355 gen_op_movl_T0_T1();
1356 gen_op_st_T0_A0[ot]();
1357 }
1358 gen_op_mov_reg_T1[ot][R_EBP]();
1359 addend = -esp_addend;
1360 if (level1)
1361 addend -= opsize * (level1 + 1);
1362 gen_op_addl_T1_im(addend);
1363 gen_op_mov_reg_T1[ot][R_ESP]();
1364 }
1365
1366 static void gen_exception(DisasContext *s, int trapno, unsigned int cur_eip)
1367 {
1368 if (s->cc_op != CC_OP_DYNAMIC)
1369 gen_op_set_cc_op(s->cc_op);
1370 gen_op_jmp_im(cur_eip);
1371 gen_op_raise_exception(trapno);
1372 s->is_jmp = 1;
1373 }
1374
1375 /* return the next pc address. Return -1 if no insn found. *is_jmp_ptr
1376 is set to true if the instruction sets the PC (last instruction of
1377 a basic block) */
1378 long disas_insn(DisasContext *s, uint8_t *pc_start)
1379 {
1380 int b, prefixes, aflag, dflag;
1381 int shift, ot;
1382 int modrm, reg, rm, mod, reg_addr, op, opreg, offset_addr, val;
1383 unsigned int next_eip;
1384
1385 s->pc = pc_start;
1386 prefixes = 0;
1387 aflag = s->code32;
1388 dflag = s->code32;
1389 s->override = -1;
1390 next_byte:
1391 b = ldub(s->pc);
1392 s->pc++;
1393 /* check prefixes */
1394 switch (b) {
1395 case 0xf3:
1396 prefixes |= PREFIX_REPZ;
1397 goto next_byte;
1398 case 0xf2:
1399 prefixes |= PREFIX_REPNZ;
1400 goto next_byte;
1401 case 0xf0:
1402 prefixes |= PREFIX_LOCK;
1403 goto next_byte;
1404 case 0x2e:
1405 s->override = R_CS;
1406 goto next_byte;
1407 case 0x36:
1408 s->override = R_SS;
1409 goto next_byte;
1410 case 0x3e:
1411 s->override = R_DS;
1412 goto next_byte;
1413 case 0x26:
1414 s->override = R_ES;
1415 goto next_byte;
1416 case 0x64:
1417 s->override = R_FS;
1418 goto next_byte;
1419 case 0x65:
1420 s->override = R_GS;
1421 goto next_byte;
1422 case 0x66:
1423 prefixes |= PREFIX_DATA;
1424 goto next_byte;
1425 case 0x67:
1426 prefixes |= PREFIX_ADR;
1427 goto next_byte;
1428 case 0x9b:
1429 prefixes |= PREFIX_FWAIT;
1430 goto next_byte;
1431 }
1432
1433 if (prefixes & PREFIX_DATA)
1434 dflag ^= 1;
1435 if (prefixes & PREFIX_ADR)
1436 aflag ^= 1;
1437
1438 s->prefix = prefixes;
1439 s->aflag = aflag;
1440 s->dflag = dflag;
1441
1442 /* lock generation */
1443 if (prefixes & PREFIX_LOCK)
1444 gen_op_lock();
1445
1446 /* now check op code */
1447 reswitch:
1448 switch(b) {
1449 case 0x0f:
1450 /**************************/
1451 /* extended op code */
1452 b = ldub(s->pc++) | 0x100;
1453 goto reswitch;
1454
1455 /**************************/
1456 /* arith & logic */
1457 case 0x00 ... 0x05:
1458 case 0x08 ... 0x0d:
1459 case 0x10 ... 0x15:
1460 case 0x18 ... 0x1d:
1461 case 0x20 ... 0x25:
1462 case 0x28 ... 0x2d:
1463 case 0x30 ... 0x35:
1464 case 0x38 ... 0x3d:
1465 {
1466 int op, f, val;
1467 op = (b >> 3) & 7;
1468 f = (b >> 1) & 3;
1469
1470 if ((b & 1) == 0)
1471 ot = OT_BYTE;
1472 else
1473 ot = dflag ? OT_LONG : OT_WORD;
1474
1475 switch(f) {
1476 case 0: /* OP Ev, Gv */
1477 modrm = ldub(s->pc++);
1478 reg = ((modrm >> 3) & 7) + OR_EAX;
1479 mod = (modrm >> 6) & 3;
1480 rm = modrm & 7;
1481 if (mod != 3) {
1482 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1483 gen_op_ld_T0_A0[ot]();
1484 opreg = OR_TMP0;
1485 } else {
1486 opreg = OR_EAX + rm;
1487 }
1488 gen_op(s, op, ot, opreg, reg);
1489 if (mod != 3 && op != 7) {
1490 gen_op_st_T0_A0[ot]();
1491 }
1492 break;
1493 case 1: /* OP Gv, Ev */
1494 modrm = ldub(s->pc++);
1495 mod = (modrm >> 6) & 3;
1496 reg = ((modrm >> 3) & 7) + OR_EAX;
1497 rm = modrm & 7;
1498 if (mod != 3) {
1499 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1500 gen_op_ld_T1_A0[ot]();
1501 opreg = OR_TMP1;
1502 } else {
1503 opreg = OR_EAX + rm;
1504 }
1505 gen_op(s, op, ot, reg, opreg);
1506 break;
1507 case 2: /* OP A, Iv */
1508 val = insn_get(s, ot);
1509 gen_opi(s, op, ot, OR_EAX, val);
1510 break;
1511 }
1512 }
1513 break;
1514
1515 case 0x80: /* GRP1 */
1516 case 0x81:
1517 case 0x83:
1518 {
1519 int val;
1520
1521 if ((b & 1) == 0)
1522 ot = OT_BYTE;
1523 else
1524 ot = dflag ? OT_LONG : OT_WORD;
1525
1526 modrm = ldub(s->pc++);
1527 mod = (modrm >> 6) & 3;
1528 rm = modrm & 7;
1529 op = (modrm >> 3) & 7;
1530
1531 if (mod != 3) {
1532 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1533 gen_op_ld_T0_A0[ot]();
1534 opreg = OR_TMP0;
1535 } else {
1536 opreg = rm + OR_EAX;
1537 }
1538
1539 switch(b) {
1540 default:
1541 case 0x80:
1542 case 0x81:
1543 val = insn_get(s, ot);
1544 break;
1545 case 0x83:
1546 val = (int8_t)insn_get(s, OT_BYTE);
1547 break;
1548 }
1549
1550 gen_opi(s, op, ot, opreg, val);
1551 if (op != 7 && mod != 3) {
1552 gen_op_st_T0_A0[ot]();
1553 }
1554 }
1555 break;
1556
1557 /**************************/
1558 /* inc, dec, and other misc arith */
1559 case 0x40 ... 0x47: /* inc Gv */
1560 ot = dflag ? OT_LONG : OT_WORD;
1561 gen_inc(s, ot, OR_EAX + (b & 7), 1);
1562 break;
1563 case 0x48 ... 0x4f: /* dec Gv */
1564 ot = dflag ? OT_LONG : OT_WORD;
1565 gen_inc(s, ot, OR_EAX + (b & 7), -1);
1566 break;
1567 case 0xf6: /* GRP3 */
1568 case 0xf7:
1569 if ((b & 1) == 0)
1570 ot = OT_BYTE;
1571 else
1572 ot = dflag ? OT_LONG : OT_WORD;
1573
1574 modrm = ldub(s->pc++);
1575 mod = (modrm >> 6) & 3;
1576 rm = modrm & 7;
1577 op = (modrm >> 3) & 7;
1578 if (mod != 3) {
1579 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1580 gen_op_ld_T0_A0[ot]();
1581 } else {
1582 gen_op_mov_TN_reg[ot][0][rm]();
1583 }
1584
1585 switch(op) {
1586 case 0: /* test */
1587 val = insn_get(s, ot);
1588 gen_op_movl_T1_im(val);
1589 gen_op_testl_T0_T1_cc();
1590 s->cc_op = CC_OP_LOGICB + ot;
1591 break;
1592 case 2: /* not */
1593 gen_op_notl_T0();
1594 if (mod != 3) {
1595 gen_op_st_T0_A0[ot]();
1596 } else {
1597 gen_op_mov_reg_T0[ot][rm]();
1598 }
1599 break;
1600 case 3: /* neg */
1601 gen_op_negl_T0_cc();
1602 if (mod != 3) {
1603 gen_op_st_T0_A0[ot]();
1604 } else {
1605 gen_op_mov_reg_T0[ot][rm]();
1606 }
1607 s->cc_op = CC_OP_SUBB + ot;
1608 break;
1609 case 4: /* mul */
1610 switch(ot) {
1611 case OT_BYTE:
1612 gen_op_mulb_AL_T0();
1613 break;
1614 case OT_WORD:
1615 gen_op_mulw_AX_T0();
1616 break;
1617 default:
1618 case OT_LONG:
1619 gen_op_mull_EAX_T0();
1620 break;
1621 }
1622 s->cc_op = CC_OP_MUL;
1623 break;
1624 case 5: /* imul */
1625 switch(ot) {
1626 case OT_BYTE:
1627 gen_op_imulb_AL_T0();
1628 break;
1629 case OT_WORD:
1630 gen_op_imulw_AX_T0();
1631 break;
1632 default:
1633 case OT_LONG:
1634 gen_op_imull_EAX_T0();
1635 break;
1636 }
1637 s->cc_op = CC_OP_MUL;
1638 break;
1639 case 6: /* div */
1640 switch(ot) {
1641 case OT_BYTE:
1642 gen_op_divb_AL_T0();
1643 break;
1644 case OT_WORD:
1645 gen_op_divw_AX_T0();
1646 break;
1647 default:
1648 case OT_LONG:
1649 gen_op_divl_EAX_T0();
1650 break;
1651 }
1652 break;
1653 case 7: /* idiv */
1654 switch(ot) {
1655 case OT_BYTE:
1656 gen_op_idivb_AL_T0();
1657 break;
1658 case OT_WORD:
1659 gen_op_idivw_AX_T0();
1660 break;
1661 default:
1662 case OT_LONG:
1663 gen_op_idivl_EAX_T0();
1664 break;
1665 }
1666 break;
1667 default:
1668 goto illegal_op;
1669 }
1670 break;
1671
1672 case 0xfe: /* GRP4 */
1673 case 0xff: /* GRP5 */
1674 if ((b & 1) == 0)
1675 ot = OT_BYTE;
1676 else
1677 ot = dflag ? OT_LONG : OT_WORD;
1678
1679 modrm = ldub(s->pc++);
1680 mod = (modrm >> 6) & 3;
1681 rm = modrm & 7;
1682 op = (modrm >> 3) & 7;
1683 if (op >= 2 && b == 0xfe) {
1684 goto illegal_op;
1685 }
1686 if (mod != 3) {
1687 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1688 if (op != 3 && op != 5)
1689 gen_op_ld_T0_A0[ot]();
1690 } else {
1691 gen_op_mov_TN_reg[ot][0][rm]();
1692 }
1693
1694 switch(op) {
1695 case 0: /* inc Ev */
1696 gen_inc(s, ot, OR_TMP0, 1);
1697 if (mod != 3)
1698 gen_op_st_T0_A0[ot]();
1699 else
1700 gen_op_mov_reg_T0[ot][rm]();
1701 break;
1702 case 1: /* dec Ev */
1703 gen_inc(s, ot, OR_TMP0, -1);
1704 if (mod != 3)
1705 gen_op_st_T0_A0[ot]();
1706 else
1707 gen_op_mov_reg_T0[ot][rm]();
1708 break;
1709 case 2: /* call Ev */
1710 /* XXX: optimize if memory (no and is necessary) */
1711 if (s->dflag == 0)
1712 gen_op_andl_T0_ffff();
1713 gen_op_jmp_T0();
1714 next_eip = s->pc - s->cs_base;
1715 gen_op_movl_T0_im(next_eip);
1716 gen_push_T0(s);
1717 s->is_jmp = 1;
1718 break;
1719 case 3: /* lcall Ev */
1720 /* push return segment + offset */
1721 gen_op_movl_T0_seg(R_CS);
1722 gen_push_T0(s);
1723 next_eip = s->pc - s->cs_base;
1724 gen_op_movl_T0_im(next_eip);
1725 gen_push_T0(s);
1726
1727 gen_op_ld_T1_A0[ot]();
1728 gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
1729 gen_op_lduw_T0_A0();
1730 gen_movl_seg_T0(s, R_CS);
1731 gen_op_movl_T0_T1();
1732 gen_op_jmp_T0();
1733 s->is_jmp = 1;
1734 break;
1735 case 4: /* jmp Ev */
1736 if (s->dflag == 0)
1737 gen_op_andl_T0_ffff();
1738 gen_op_jmp_T0();
1739 s->is_jmp = 1;
1740 break;
1741 case 5: /* ljmp Ev */
1742 gen_op_ld_T1_A0[ot]();
1743 gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
1744 gen_op_lduw_T0_A0();
1745 gen_movl_seg_T0(s, R_CS);
1746 gen_op_movl_T0_T1();
1747 gen_op_jmp_T0();
1748 s->is_jmp = 1;
1749 break;
1750 case 6: /* push Ev */
1751 gen_push_T0(s);
1752 break;
1753 default:
1754 goto illegal_op;
1755 }
1756 break;
1757
1758 case 0x84: /* test Ev, Gv */
1759 case 0x85:
1760 if ((b & 1) == 0)
1761 ot = OT_BYTE;
1762 else
1763 ot = dflag ? OT_LONG : OT_WORD;
1764
1765 modrm = ldub(s->pc++);
1766 mod = (modrm >> 6) & 3;
1767 rm = modrm & 7;
1768 reg = (modrm >> 3) & 7;
1769
1770 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1771 gen_op_mov_TN_reg[ot][1][reg + OR_EAX]();
1772 gen_op_testl_T0_T1_cc();
1773 s->cc_op = CC_OP_LOGICB + ot;
1774 break;
1775
1776 case 0xa8: /* test eAX, Iv */
1777 case 0xa9:
1778 if ((b & 1) == 0)
1779 ot = OT_BYTE;
1780 else
1781 ot = dflag ? OT_LONG : OT_WORD;
1782 val = insn_get(s, ot);
1783
1784 gen_op_mov_TN_reg[ot][0][OR_EAX]();
1785 gen_op_movl_T1_im(val);
1786 gen_op_testl_T0_T1_cc();
1787 s->cc_op = CC_OP_LOGICB + ot;
1788 break;
1789
1790 case 0x98: /* CWDE/CBW */
1791 if (dflag)
1792 gen_op_movswl_EAX_AX();
1793 else
1794 gen_op_movsbw_AX_AL();
1795 break;
1796 case 0x99: /* CDQ/CWD */
1797 if (dflag)
1798 gen_op_movslq_EDX_EAX();
1799 else
1800 gen_op_movswl_DX_AX();
1801 break;
1802 case 0x1af: /* imul Gv, Ev */
1803 case 0x69: /* imul Gv, Ev, I */
1804 case 0x6b:
1805 ot = dflag ? OT_LONG : OT_WORD;
1806 modrm = ldub(s->pc++);
1807 reg = ((modrm >> 3) & 7) + OR_EAX;
1808 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1809 if (b == 0x69) {
1810 val = insn_get(s, ot);
1811 gen_op_movl_T1_im(val);
1812 } else if (b == 0x6b) {
1813 val = insn_get(s, OT_BYTE);
1814 gen_op_movl_T1_im(val);
1815 } else {
1816 gen_op_mov_TN_reg[ot][1][reg]();
1817 }
1818
1819 if (ot == OT_LONG) {
1820 gen_op_imull_T0_T1();
1821 } else {
1822 gen_op_imulw_T0_T1();
1823 }
1824 gen_op_mov_reg_T0[ot][reg]();
1825 s->cc_op = CC_OP_MUL;
1826 break;
1827 case 0x1c0:
1828 case 0x1c1: /* xadd Ev, Gv */
1829 if ((b & 1) == 0)
1830 ot = OT_BYTE;
1831 else
1832 ot = dflag ? OT_LONG : OT_WORD;
1833 modrm = ldub(s->pc++);
1834 reg = (modrm >> 3) & 7;
1835 mod = (modrm >> 6) & 3;
1836 if (mod == 3) {
1837 rm = modrm & 7;
1838 gen_op_mov_TN_reg[ot][0][reg]();
1839 gen_op_mov_TN_reg[ot][1][rm]();
1840 gen_op_addl_T0_T1_cc();
1841 gen_op_mov_reg_T0[ot][rm]();
1842 gen_op_mov_reg_T1[ot][reg]();
1843 } else {
1844 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1845 gen_op_mov_TN_reg[ot][0][reg]();
1846 gen_op_ld_T1_A0[ot]();
1847 gen_op_addl_T0_T1_cc();
1848 gen_op_st_T0_A0[ot]();
1849 gen_op_mov_reg_T1[ot][reg]();
1850 }
1851 s->cc_op = CC_OP_ADDB + ot;
1852 break;
1853 case 0x1b0:
1854 case 0x1b1: /* cmpxchg Ev, Gv */
1855 if ((b & 1) == 0)
1856 ot = OT_BYTE;
1857 else
1858 ot = dflag ? OT_LONG : OT_WORD;
1859 modrm = ldub(s->pc++);
1860 reg = (modrm >> 3) & 7;
1861 mod = (modrm >> 6) & 3;
1862 gen_op_mov_TN_reg[ot][1][reg]();
1863 if (mod == 3) {
1864 rm = modrm & 7;
1865 gen_op_mov_TN_reg[ot][0][rm]();
1866 gen_op_cmpxchg_T0_T1_EAX_cc[ot]();
1867 gen_op_mov_reg_T0[ot][rm]();
1868 } else {
1869 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1870 gen_op_ld_T0_A0[ot]();
1871 gen_op_cmpxchg_T0_T1_EAX_cc[ot]();
1872 gen_op_st_T0_A0[ot]();
1873 }
1874 s->cc_op = CC_OP_SUBB + ot;
1875 break;
1876 case 0x1c7: /* cmpxchg8b */
1877 modrm = ldub(s->pc++);
1878 mod = (modrm >> 6) & 3;
1879 if (mod == 3)
1880 goto illegal_op;
1881 if (s->cc_op != CC_OP_DYNAMIC)
1882 gen_op_set_cc_op(s->cc_op);
1883 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1884 gen_op_cmpxchg8b();
1885 s->cc_op = CC_OP_EFLAGS;
1886 break;
1887
1888 /**************************/
1889 /* push/pop */
1890 case 0x50 ... 0x57: /* push */
1891 gen_op_mov_TN_reg[OT_LONG][0][b & 7]();
1892 gen_push_T0(s);
1893 break;
1894 case 0x58 ... 0x5f: /* pop */
1895 ot = dflag ? OT_LONG : OT_WORD;
1896 gen_pop_T0(s);
1897 gen_op_mov_reg_T0[ot][b & 7]();
1898 gen_pop_update(s);
1899 break;
1900 case 0x60: /* pusha */
1901 gen_pusha(s);
1902 break;
1903 case 0x61: /* popa */
1904 gen_popa(s);
1905 break;
1906 case 0x68: /* push Iv */
1907 case 0x6a:
1908 ot = dflag ? OT_LONG : OT_WORD;
1909 if (b == 0x68)
1910 val = insn_get(s, ot);
1911 else
1912 val = (int8_t)insn_get(s, OT_BYTE);
1913 gen_op_movl_T0_im(val);
1914 gen_push_T0(s);
1915 break;
1916 case 0x8f: /* pop Ev */
1917 ot = dflag ? OT_LONG : OT_WORD;
1918 modrm = ldub(s->pc++);
1919 gen_pop_T0(s);
1920 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
1921 gen_pop_update(s);
1922 break;
1923 case 0xc8: /* enter */
1924 {
1925 int level;
1926 val = lduw(s->pc);
1927 s->pc += 2;
1928 level = ldub(s->pc++);
1929 gen_enter(s, val, level);
1930 }
1931 break;
1932 case 0xc9: /* leave */
1933 /* XXX: exception not precise (ESP is update before potential exception) */
1934 if (s->ss32) {
1935 gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
1936 gen_op_mov_reg_T0[OT_LONG][R_ESP]();
1937 } else {
1938 gen_op_mov_TN_reg[OT_WORD][0][R_EBP]();
1939 gen_op_mov_reg_T0[OT_WORD][R_ESP]();
1940 }
1941 gen_pop_T0(s);
1942 ot = dflag ? OT_LONG : OT_WORD;
1943 gen_op_mov_reg_T0[ot][R_EBP]();
1944 gen_pop_update(s);
1945 break;
1946 case 0x06: /* push es */
1947 case 0x0e: /* push cs */
1948 case 0x16: /* push ss */
1949 case 0x1e: /* push ds */
1950 gen_op_movl_T0_seg(b >> 3);
1951 gen_push_T0(s);
1952 break;
1953 case 0x1a0: /* push fs */
1954 case 0x1a8: /* push gs */
1955 gen_op_movl_T0_seg((b >> 3) & 7);
1956 gen_push_T0(s);
1957 break;
1958 case 0x07: /* pop es */
1959 case 0x17: /* pop ss */
1960 case 0x1f: /* pop ds */
1961 gen_pop_T0(s);
1962 gen_movl_seg_T0(s, b >> 3);
1963 gen_pop_update(s);
1964 break;
1965 case 0x1a1: /* pop fs */
1966 case 0x1a9: /* pop gs */
1967 gen_pop_T0(s);
1968 gen_movl_seg_T0(s, (b >> 3) & 7);
1969 gen_pop_update(s);
1970 break;
1971
1972 /**************************/
1973 /* mov */
1974 case 0x88:
1975 case 0x89: /* mov Gv, Ev */
1976 if ((b & 1) == 0)
1977 ot = OT_BYTE;
1978 else
1979 ot = dflag ? OT_LONG : OT_WORD;
1980 modrm = ldub(s->pc++);
1981 reg = (modrm >> 3) & 7;
1982
1983 /* generate a generic store */
1984 gen_ldst_modrm(s, modrm, ot, OR_EAX + reg, 1);
1985 break;
1986 case 0xc6:
1987 case 0xc7: /* mov Ev, Iv */
1988 if ((b & 1) == 0)
1989 ot = OT_BYTE;
1990 else
1991 ot = dflag ? OT_LONG : OT_WORD;
1992 modrm = ldub(s->pc++);
1993 mod = (modrm >> 6) & 3;
1994 if (mod != 3)
1995 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1996 val = insn_get(s, ot);
1997 gen_op_movl_T0_im(val);
1998 if (mod != 3)
1999 gen_op_st_T0_A0[ot]();
2000 else
2001 gen_op_mov_reg_T0[ot][modrm & 7]();
2002 break;
2003 case 0x8a:
2004 case 0x8b: /* mov Ev, Gv */
2005 if ((b & 1) == 0)
2006 ot = OT_BYTE;
2007 else
2008 ot = dflag ? OT_LONG : OT_WORD;
2009 modrm = ldub(s->pc++);
2010 reg = (modrm >> 3) & 7;
2011
2012 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
2013 gen_op_mov_reg_T0[ot][reg]();
2014 break;
2015 case 0x8e: /* mov seg, Gv */
2016 ot = dflag ? OT_LONG : OT_WORD;
2017 modrm = ldub(s->pc++);
2018 reg = (modrm >> 3) & 7;
2019 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
2020 if (reg >= 6 || reg == R_CS)
2021 goto illegal_op;
2022 gen_movl_seg_T0(s, reg);
2023 break;
2024 case 0x8c: /* mov Gv, seg */
2025 ot = dflag ? OT_LONG : OT_WORD;
2026 modrm = ldub(s->pc++);
2027 reg = (modrm >> 3) & 7;
2028 if (reg >= 6)
2029 goto illegal_op;
2030 gen_op_movl_T0_seg(reg);
2031 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
2032 break;
2033
2034 case 0x1b6: /* movzbS Gv, Eb */
2035 case 0x1b7: /* movzwS Gv, Eb */
2036 case 0x1be: /* movsbS Gv, Eb */
2037 case 0x1bf: /* movswS Gv, Eb */
2038 {
2039 int d_ot;
2040 /* d_ot is the size of destination */
2041 d_ot = dflag + OT_WORD;
2042 /* ot is the size of source */
2043 ot = (b & 1) + OT_BYTE;
2044 modrm = ldub(s->pc++);
2045 reg = ((modrm >> 3) & 7) + OR_EAX;
2046 mod = (modrm >> 6) & 3;
2047 rm = modrm & 7;
2048
2049 if (mod == 3) {
2050 gen_op_mov_TN_reg[ot][0][rm]();
2051 switch(ot | (b & 8)) {
2052 case OT_BYTE:
2053 gen_op_movzbl_T0_T0();
2054 break;
2055 case OT_BYTE | 8:
2056 gen_op_movsbl_T0_T0();
2057 break;
2058 case OT_WORD:
2059 gen_op_movzwl_T0_T0();
2060 break;
2061 default:
2062 case OT_WORD | 8:
2063 gen_op_movswl_T0_T0();
2064 break;
2065 }
2066 gen_op_mov_reg_T0[d_ot][reg]();
2067 } else {
2068 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2069 if (b & 8) {
2070 gen_op_lds_T0_A0[ot]();
2071 } else {
2072 gen_op_ldu_T0_A0[ot]();
2073 }
2074 gen_op_mov_reg_T0[d_ot][reg]();
2075 }
2076 }
2077 break;
2078
2079 case 0x8d: /* lea */
2080 ot = dflag ? OT_LONG : OT_WORD;
2081 modrm = ldub(s->pc++);
2082 reg = (modrm >> 3) & 7;
2083 /* we must ensure that no segment is added */
2084 s->override = -1;
2085 val = s->addseg;
2086 s->addseg = 0;
2087 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2088 s->addseg = val;
2089 gen_op_mov_reg_A0[ot - OT_WORD][reg]();
2090 break;
2091
2092 case 0xa0: /* mov EAX, Ov */
2093 case 0xa1:
2094 case 0xa2: /* mov Ov, EAX */
2095 case 0xa3:
2096 if ((b & 1) == 0)
2097 ot = OT_BYTE;
2098 else
2099 ot = dflag ? OT_LONG : OT_WORD;
2100 if (s->aflag)
2101 offset_addr = insn_get(s, OT_LONG);
2102 else
2103 offset_addr = insn_get(s, OT_WORD);
2104 gen_op_movl_A0_im(offset_addr);
2105 /* handle override */
2106 {
2107 int override, must_add_seg;
2108 must_add_seg = s->addseg;
2109 if (s->override >= 0) {
2110 override = s->override;
2111 must_add_seg = 1;
2112 } else {
2113 override = R_DS;
2114 }
2115 if (must_add_seg) {
2116 gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[override].base));
2117 }
2118 }
2119 if ((b & 2) == 0) {
2120 gen_op_ld_T0_A0[ot]();
2121 gen_op_mov_reg_T0[ot][R_EAX]();
2122 } else {
2123 gen_op_mov_TN_reg[ot][0][R_EAX]();
2124 gen_op_st_T0_A0[ot]();
2125 }
2126 break;
2127 case 0xd7: /* xlat */
2128 gen_op_movl_A0_reg[R_EBX]();
2129 gen_op_addl_A0_AL();
2130 if (s->aflag == 0)
2131 gen_op_andl_A0_ffff();
2132 /* handle override */
2133 {
2134 int override, must_add_seg;
2135 must_add_seg = s->addseg;
2136 override = R_DS;
2137 if (s->override >= 0) {
2138 override = s->override;
2139 must_add_seg = 1;
2140 } else {
2141 override = R_DS;
2142 }
2143 if (must_add_seg) {
2144 gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[override].base));
2145 }
2146 }
2147 gen_op_ldub_T0_A0();
2148 gen_op_mov_reg_T0[OT_BYTE][R_EAX]();
2149 break;
2150 case 0xb0 ... 0xb7: /* mov R, Ib */
2151 val = insn_get(s, OT_BYTE);
2152 gen_op_movl_T0_im(val);
2153 gen_op_mov_reg_T0[OT_BYTE][b & 7]();
2154 break;
2155 case 0xb8 ... 0xbf: /* mov R, Iv */
2156 ot = dflag ? OT_LONG : OT_WORD;
2157 val = insn_get(s, ot);
2158 reg = OR_EAX + (b & 7);
2159 gen_op_movl_T0_im(val);
2160 gen_op_mov_reg_T0[ot][reg]();
2161 break;
2162
2163 case 0x91 ... 0x97: /* xchg R, EAX */
2164 ot = dflag ? OT_LONG : OT_WORD;
2165 reg = b & 7;
2166 rm = R_EAX;
2167 goto do_xchg_reg;
2168 case 0x86:
2169 case 0x87: /* xchg Ev, Gv */
2170 if ((b & 1) == 0)
2171 ot = OT_BYTE;
2172 else
2173 ot = dflag ? OT_LONG : OT_WORD;
2174 modrm = ldub(s->pc++);
2175 reg = (modrm >> 3) & 7;
2176 mod = (modrm >> 6) & 3;
2177 if (mod == 3) {
2178 rm = modrm & 7;
2179 do_xchg_reg:
2180 gen_op_mov_TN_reg[ot][0][reg]();
2181 gen_op_mov_TN_reg[ot][1][rm]();
2182 gen_op_mov_reg_T0[ot][rm]();
2183 gen_op_mov_reg_T1[ot][reg]();
2184 } else {
2185 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2186 gen_op_mov_TN_reg[ot][0][reg]();
2187 /* for xchg, lock is implicit */
2188 if (!(prefixes & PREFIX_LOCK))
2189 gen_op_lock();
2190 gen_op_ld_T1_A0[ot]();
2191 gen_op_st_T0_A0[ot]();
2192 if (!(prefixes & PREFIX_LOCK))
2193 gen_op_unlock();
2194 gen_op_mov_reg_T1[ot][reg]();
2195 }
2196 break;
2197 case 0xc4: /* les Gv */
2198 op = R_ES;
2199 goto do_lxx;
2200 case 0xc5: /* lds Gv */
2201 op = R_DS;
2202 goto do_lxx;
2203 case 0x1b2: /* lss Gv */
2204 op = R_SS;
2205 goto do_lxx;
2206 case 0x1b4: /* lfs Gv */
2207 op = R_FS;
2208 goto do_lxx;
2209 case 0x1b5: /* lgs Gv */
2210 op = R_GS;
2211 do_lxx:
2212 ot = dflag ? OT_LONG : OT_WORD;
2213 modrm = ldub(s->pc++);
2214 reg = (modrm >> 3) & 7;
2215 mod = (modrm >> 6) & 3;
2216 if (mod == 3)
2217 goto illegal_op;
2218 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2219 gen_op_ld_T1_A0[ot]();
2220 gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
2221 /* load the segment first to handle exceptions properly */
2222 gen_op_lduw_T0_A0();
2223 gen_movl_seg_T0(s, op);
2224 /* then put the data */
2225 gen_op_mov_reg_T1[ot][reg]();
2226 break;
2227
2228 /************************/
2229 /* shifts */
2230 case 0xc0:
2231 case 0xc1:
2232 /* shift Ev,Ib */
2233 shift = 2;
2234 grp2:
2235 {
2236 if ((b & 1) == 0)
2237 ot = OT_BYTE;
2238 else
2239 ot = dflag ? OT_LONG : OT_WORD;
2240
2241 modrm = ldub(s->pc++);
2242 mod = (modrm >> 6) & 3;
2243 rm = modrm & 7;
2244 op = (modrm >> 3) & 7;
2245
2246 if (mod != 3) {
2247 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2248 gen_op_ld_T0_A0[ot]();
2249 opreg = OR_TMP0;
2250 } else {
2251 opreg = rm + OR_EAX;
2252 }
2253
2254 /* simpler op */
2255 if (shift == 0) {
2256 gen_shift(s, op, ot, opreg, OR_ECX);
2257 } else {
2258 if (shift == 2) {
2259 shift = ldub(s->pc++);
2260 }
2261 gen_shifti(s, op, ot, opreg, shift);
2262 }
2263
2264 if (mod != 3) {
2265 gen_op_st_T0_A0[ot]();
2266 }
2267 }
2268 break;
2269 case 0xd0:
2270 case 0xd1:
2271 /* shift Ev,1 */
2272 shift = 1;
2273 goto grp2;
2274 case 0xd2:
2275 case 0xd3:
2276 /* shift Ev,cl */
2277 shift = 0;
2278 goto grp2;
2279
2280 case 0x1a4: /* shld imm */
2281 op = 0;
2282 shift = 1;
2283 goto do_shiftd;
2284 case 0x1a5: /* shld cl */
2285 op = 0;
2286 shift = 0;
2287 goto do_shiftd;
2288 case 0x1ac: /* shrd imm */
2289 op = 1;
2290 shift = 1;
2291 goto do_shiftd;
2292 case 0x1ad: /* shrd cl */
2293 op = 1;
2294 shift = 0;
2295 do_shiftd:
2296 ot = dflag ? OT_LONG : OT_WORD;
2297 modrm = ldub(s->pc++);
2298 mod = (modrm >> 6) & 3;
2299 rm = modrm & 7;
2300 reg = (modrm >> 3) & 7;
2301
2302 if (mod != 3) {
2303 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2304 gen_op_ld_T0_A0[ot]();
2305 } else {
2306 gen_op_mov_TN_reg[ot][0][rm]();
2307 }
2308 gen_op_mov_TN_reg[ot][1][reg]();
2309
2310 if (shift) {
2311 val = ldub(s->pc++);
2312 val &= 0x1f;
2313 if (val) {
2314 gen_op_shiftd_T0_T1_im_cc[ot - OT_WORD][op](val);
2315 if (op == 0 && ot != OT_WORD)
2316 s->cc_op = CC_OP_SHLB + ot;
2317 else
2318 s->cc_op = CC_OP_SARB + ot;
2319 }
2320 } else {
2321 if (s->cc_op != CC_OP_DYNAMIC)
2322 gen_op_set_cc_op(s->cc_op);
2323 gen_op_shiftd_T0_T1_ECX_cc[ot - OT_WORD][op]();
2324 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2325 }
2326 if (mod != 3) {
2327 gen_op_st_T0_A0[ot]();
2328 } else {
2329 gen_op_mov_reg_T0[ot][rm]();
2330 }
2331 break;
2332
2333 /************************/
2334 /* floats */
2335 case 0xd8 ... 0xdf:
2336 modrm = ldub(s->pc++);
2337 mod = (modrm >> 6) & 3;
2338 rm = modrm & 7;
2339 op = ((b & 7) << 3) | ((modrm >> 3) & 7);
2340
2341 if (mod != 3) {
2342 /* memory op */
2343 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2344 switch(op) {
2345 case 0x00 ... 0x07: /* fxxxs */
2346 case 0x10 ... 0x17: /* fixxxl */
2347 case 0x20 ... 0x27: /* fxxxl */
2348 case 0x30 ... 0x37: /* fixxx */
2349 {
2350 int op1;
2351 op1 = op & 7;
2352
2353 switch(op >> 4) {
2354 case 0:
2355 gen_op_flds_FT0_A0();
2356 break;
2357 case 1:
2358 gen_op_fildl_FT0_A0();
2359 break;
2360 case 2:
2361 gen_op_fldl_FT0_A0();
2362 break;
2363 case 3:
2364 default:
2365 gen_op_fild_FT0_A0();
2366 break;
2367 }
2368
2369 gen_op_fp_arith_ST0_FT0[op1]();
2370 if (op1 == 3) {
2371 /* fcomp needs pop */
2372 gen_op_fpop();
2373 }
2374 }
2375 break;
2376 case 0x08: /* flds */
2377 case 0x0a: /* fsts */
2378 case 0x0b: /* fstps */
2379 case 0x18: /* fildl */
2380 case 0x1a: /* fistl */
2381 case 0x1b: /* fistpl */
2382 case 0x28: /* fldl */
2383 case 0x2a: /* fstl */
2384 case 0x2b: /* fstpl */
2385 case 0x38: /* filds */
2386 case 0x3a: /* fists */
2387 case 0x3b: /* fistps */
2388
2389 switch(op & 7) {
2390 case 0:
2391 gen_op_fpush();
2392 switch(op >> 4) {
2393 case 0:
2394 gen_op_flds_ST0_A0();
2395 break;
2396 case 1:
2397 gen_op_fildl_ST0_A0();
2398 break;
2399 case 2:
2400 gen_op_fldl_ST0_A0();
2401 break;
2402 case 3:
2403 default:
2404 gen_op_fild_ST0_A0();
2405 break;
2406 }
2407 break;
2408 default:
2409 switch(op >> 4) {
2410 case 0:
2411 gen_op_fsts_ST0_A0();
2412 break;
2413 case 1:
2414 gen_op_fistl_ST0_A0();
2415 break;
2416 case 2:
2417 gen_op_fstl_ST0_A0();
2418 break;
2419 case 3:
2420 default:
2421 gen_op_fist_ST0_A0();
2422 break;
2423 }
2424 if ((op & 7) == 3)
2425 gen_op_fpop();
2426 break;
2427 }
2428 break;
2429 case 0x0d: /* fldcw mem */
2430 gen_op_fldcw_A0();
2431 break;
2432 case 0x0f: /* fnstcw mem */
2433 gen_op_fnstcw_A0();
2434 break;
2435 case 0x1d: /* fldt mem */
2436 gen_op_fpush();
2437 gen_op_fldt_ST0_A0();
2438 break;
2439 case 0x1f: /* fstpt mem */
2440 gen_op_fstt_ST0_A0();
2441 gen_op_fpop();
2442 break;
2443 case 0x2f: /* fnstsw mem */
2444 gen_op_fnstsw_A0();
2445 break;
2446 case 0x3c: /* fbld */
2447 gen_op_fpush();
2448 gen_op_fbld_ST0_A0();
2449 break;
2450 case 0x3e: /* fbstp */
2451 gen_op_fbst_ST0_A0();
2452 gen_op_fpop();
2453 break;
2454 case 0x3d: /* fildll */
2455 gen_op_fpush();
2456 gen_op_fildll_ST0_A0();
2457 break;
2458 case 0x3f: /* fistpll */
2459 gen_op_fistll_ST0_A0();
2460 gen_op_fpop();
2461 break;
2462 default:
2463 goto illegal_op;
2464 }
2465 } else {
2466 /* register float ops */
2467 opreg = rm;
2468
2469 switch(op) {
2470 case 0x08: /* fld sti */
2471 gen_op_fpush();
2472 gen_op_fmov_ST0_STN((opreg + 1) & 7);
2473 break;
2474 case 0x09: /* fxchg sti */
2475 gen_op_fxchg_ST0_STN(opreg);
2476 break;
2477 case 0x0a: /* grp d9/2 */
2478 switch(rm) {
2479 case 0: /* fnop */
2480 break;
2481 default:
2482 goto illegal_op;
2483 }
2484 break;
2485 case 0x0c: /* grp d9/4 */
2486 switch(rm) {
2487 case 0: /* fchs */
2488 gen_op_fchs_ST0();
2489 break;
2490 case 1: /* fabs */
2491 gen_op_fabs_ST0();
2492 break;
2493 case 4: /* ftst */
2494 gen_op_fldz_FT0();
2495 gen_op_fcom_ST0_FT0();
2496 break;
2497 case 5: /* fxam */
2498 gen_op_fxam_ST0();
2499 break;
2500 default:
2501 goto illegal_op;
2502 }
2503 break;
2504 case 0x0d: /* grp d9/5 */
2505 {
2506 switch(rm) {
2507 case 0:
2508 gen_op_fpush();
2509 gen_op_fld1_ST0();
2510 break;
2511 case 1:
2512 gen_op_fpush();
2513 gen_op_fldl2t_ST0();
2514 break;
2515 case 2:
2516 gen_op_fpush();
2517 gen_op_fldl2e_ST0();
2518 break;
2519 case 3:
2520 gen_op_fpush();
2521 gen_op_fldpi_ST0();
2522 break;
2523 case 4:
2524 gen_op_fpush();
2525 gen_op_fldlg2_ST0();
2526 break;
2527 case 5:
2528 gen_op_fpush();
2529 gen_op_fldln2_ST0();
2530 break;
2531 case 6:
2532 gen_op_fpush();
2533 gen_op_fldz_ST0();
2534 break;
2535 default:
2536 goto illegal_op;
2537 }
2538 }
2539 break;
2540 case 0x0e: /* grp d9/6 */
2541 switch(rm) {
2542 case 0: /* f2xm1 */
2543 gen_op_f2xm1();
2544 break;
2545 case 1: /* fyl2x */
2546 gen_op_fyl2x();
2547 break;
2548 case 2: /* fptan */
2549 gen_op_fptan();
2550 break;
2551 case 3: /* fpatan */
2552 gen_op_fpatan();
2553 break;
2554 case 4: /* fxtract */
2555 gen_op_fxtract();
2556 break;
2557 case 5: /* fprem1 */
2558 gen_op_fprem1();
2559 break;
2560 case 6: /* fdecstp */
2561 gen_op_fdecstp();
2562 break;
2563 default:
2564 case 7: /* fincstp */
2565 gen_op_fincstp();
2566 break;
2567 }
2568 break;
2569 case 0x0f: /* grp d9/7 */
2570 switch(rm) {
2571 case 0: /* fprem */
2572 gen_op_fprem();
2573 break;
2574 case 1: /* fyl2xp1 */
2575 gen_op_fyl2xp1();
2576 break;
2577 case 2: /* fsqrt */
2578 gen_op_fsqrt();
2579 break;
2580 case 3: /* fsincos */
2581 gen_op_fsincos();
2582 break;
2583 case 5: /* fscale */
2584 gen_op_fscale();
2585 break;
2586 case 4: /* frndint */
2587 gen_op_frndint();
2588 break;
2589 case 6: /* fsin */
2590 gen_op_fsin();
2591 break;
2592 default:
2593 case 7: /* fcos */
2594 gen_op_fcos();
2595 break;
2596 }
2597 break;
2598 case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
2599 case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
2600 case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
2601 {
2602 int op1;
2603
2604 op1 = op & 7;
2605 if (op >= 0x20) {
2606 gen_op_fp_arith_STN_ST0[op1](opreg);
2607 if (op >= 0x30)
2608 gen_op_fpop();
2609 } else {
2610 gen_op_fmov_FT0_STN(opreg);
2611 gen_op_fp_arith_ST0_FT0[op1]();
2612 }
2613 }
2614 break;
2615 case 0x02: /* fcom */
2616 gen_op_fmov_FT0_STN(opreg);
2617 gen_op_fcom_ST0_FT0();
2618 break;
2619 case 0x03: /* fcomp */
2620 gen_op_fmov_FT0_STN(opreg);
2621 gen_op_fcom_ST0_FT0();
2622 gen_op_fpop();
2623 break;
2624 case 0x15: /* da/5 */
2625 switch(rm) {
2626 case 1: /* fucompp */
2627 gen_op_fmov_FT0_STN(1);
2628 gen_op_fucom_ST0_FT0();
2629 gen_op_fpop();
2630 gen_op_fpop();
2631 break;
2632 default:
2633 goto illegal_op;
2634 }
2635 break;
2636 case 0x1c:
2637 switch(rm) {
2638 case 2: /* fclex */
2639 gen_op_fclex();
2640 break;
2641 case 3: /* fninit */
2642 gen_op_fninit();
2643 break;
2644 default:
2645 goto illegal_op;
2646 }
2647 break;
2648 case 0x2a: /* fst sti */
2649 gen_op_fmov_STN_ST0(opreg);
2650 break;
2651 case 0x2b: /* fstp sti */
2652 gen_op_fmov_STN_ST0(opreg);
2653 gen_op_fpop();
2654 break;
2655 case 0x2c: /* fucom st(i) */
2656 gen_op_fmov_FT0_STN(opreg);
2657 gen_op_fucom_ST0_FT0();
2658 break;
2659 case 0x2d: /* fucomp st(i) */
2660 gen_op_fmov_FT0_STN(opreg);
2661 gen_op_fucom_ST0_FT0();
2662 gen_op_fpop();
2663 break;
2664 case 0x33: /* de/3 */
2665 switch(rm) {
2666 case 1: /* fcompp */
2667 gen_op_fmov_FT0_STN(1);
2668 gen_op_fcom_ST0_FT0();
2669 gen_op_fpop();
2670 gen_op_fpop();
2671 break;
2672 default:
2673 goto illegal_op;
2674 }
2675 break;
2676 case 0x3c: /* df/4 */
2677 switch(rm) {
2678 case 0:
2679 gen_op_fnstsw_EAX();
2680 break;
2681 default:
2682 goto illegal_op;
2683 }
2684 break;
2685 default:
2686 goto illegal_op;
2687 }
2688 }
2689 break;
2690 /************************/
2691 /* string ops */
2692
2693 case 0xa4: /* movsS */
2694 case 0xa5:
2695 if ((b & 1) == 0)
2696 ot = OT_BYTE;
2697 else
2698 ot = dflag ? OT_LONG : OT_WORD;
2699
2700 if (prefixes & PREFIX_REPZ) {
2701 gen_string_ds(s, ot, gen_op_movs + 9);
2702 } else {
2703 gen_string_ds(s, ot, gen_op_movs);
2704 }
2705 break;
2706
2707 case 0xaa: /* stosS */
2708 case 0xab:
2709 if ((b & 1) == 0)
2710 ot = OT_BYTE;
2711 else
2712 ot = dflag ? OT_LONG : OT_WORD;
2713
2714 if (prefixes & PREFIX_REPZ) {
2715 gen_string_es(s, ot, gen_op_stos + 9);
2716 } else {
2717 gen_string_es(s, ot, gen_op_stos);
2718 }
2719 break;
2720 case 0xac: /* lodsS */
2721 case 0xad:
2722 if ((b & 1) == 0)
2723 ot = OT_BYTE;
2724 else
2725 ot = dflag ? OT_LONG : OT_WORD;
2726 if (prefixes & PREFIX_REPZ) {
2727 gen_string_ds(s, ot, gen_op_lods + 9);
2728 } else {
2729 gen_string_ds(s, ot, gen_op_lods);
2730 }
2731 break;
2732 case 0xae: /* scasS */
2733 case 0xaf:
2734 if ((b & 1) == 0)
2735 ot = OT_BYTE;
2736 else
2737 ot = dflag ? OT_LONG : OT_WORD;
2738 if (prefixes & PREFIX_REPNZ) {
2739 if (s->cc_op != CC_OP_DYNAMIC)
2740 gen_op_set_cc_op(s->cc_op);
2741 gen_string_es(s, ot, gen_op_scas + 9 * 2);
2742 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2743 } else if (prefixes & PREFIX_REPZ) {
2744 if (s->cc_op != CC_OP_DYNAMIC)
2745 gen_op_set_cc_op(s->cc_op);
2746 gen_string_es(s, ot, gen_op_scas + 9);
2747 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2748 } else {
2749 gen_string_es(s, ot, gen_op_scas);
2750 s->cc_op = CC_OP_SUBB + ot;
2751 }
2752 break;
2753
2754 case 0xa6: /* cmpsS */
2755 case 0xa7:
2756 if ((b & 1) == 0)
2757 ot = OT_BYTE;
2758 else
2759 ot = dflag ? OT_LONG : OT_WORD;
2760 if (prefixes & PREFIX_REPNZ) {
2761 if (s->cc_op != CC_OP_DYNAMIC)
2762 gen_op_set_cc_op(s->cc_op);
2763 gen_string_ds(s, ot, gen_op_cmps + 9 * 2);
2764 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2765 } else if (prefixes & PREFIX_REPZ) {
2766 if (s->cc_op != CC_OP_DYNAMIC)
2767 gen_op_set_cc_op(s->cc_op);
2768 gen_string_ds(s, ot, gen_op_cmps + 9);
2769 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2770 } else {
2771 gen_string_ds(s, ot, gen_op_cmps);
2772 s->cc_op = CC_OP_SUBB + ot;
2773 }
2774 break;
2775 case 0x6c: /* insS */
2776 case 0x6d:
2777 if (s->cpl > s->iopl || s->vm86) {
2778 /* NOTE: even for (E)CX = 0 the exception is raised */
2779 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
2780 } else {
2781 if ((b & 1) == 0)
2782 ot = OT_BYTE;
2783 else
2784 ot = dflag ? OT_LONG : OT_WORD;
2785 if (prefixes & PREFIX_REPZ) {
2786 gen_string_es(s, ot, gen_op_ins + 9);
2787 } else {
2788 gen_string_es(s, ot, gen_op_ins);
2789 }
2790 }
2791 break;
2792 case 0x6e: /* outsS */
2793 case 0x6f:
2794 if (s->cpl > s->iopl || s->vm86) {
2795 /* NOTE: even for (E)CX = 0 the exception is raised */
2796 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
2797 } else {
2798 if ((b & 1) == 0)
2799 ot = OT_BYTE;
2800 else
2801 ot = dflag ? OT_LONG : OT_WORD;
2802 if (prefixes & PREFIX_REPZ) {
2803 gen_string_ds(s, ot, gen_op_outs + 9);
2804 } else {
2805 gen_string_ds(s, ot, gen_op_outs);
2806 }
2807 }
2808 break;
2809
2810 /************************/
2811 /* port I/O */
2812 case 0xe4:
2813 case 0xe5:
2814 if (s->cpl > s->iopl || s->vm86) {
2815 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
2816 } else {
2817 if ((b & 1) == 0)
2818 ot = OT_BYTE;
2819 else
2820 ot = dflag ? OT_LONG : OT_WORD;
2821 val = ldub(s->pc++);
2822 gen_op_movl_T0_im(val);
2823 gen_op_in[ot]();
2824 gen_op_mov_reg_T1[ot][R_EAX]();
2825 }
2826 break;
2827 case 0xe6:
2828 case 0xe7:
2829 if (s->cpl > s->iopl || s->vm86) {
2830 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
2831 } else {
2832 if ((b & 1) == 0)
2833 ot = OT_BYTE;
2834 else
2835 ot = dflag ? OT_LONG : OT_WORD;
2836 val = ldub(s->pc++);
2837 gen_op_movl_T0_im(val);
2838 gen_op_mov_TN_reg[ot][1][R_EAX]();
2839 gen_op_out[ot]();
2840 }
2841 break;
2842 case 0xec:
2843 case 0xed:
2844 if (s->cpl > s->iopl || s->vm86) {
2845 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
2846 } else {
2847 if ((b & 1) == 0)
2848 ot = OT_BYTE;
2849 else
2850 ot = dflag ? OT_LONG : OT_WORD;
2851 gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
2852 gen_op_in[ot]();
2853 gen_op_mov_reg_T1[ot][R_EAX]();
2854 }
2855 break;
2856 case 0xee:
2857 case 0xef:
2858 if (s->cpl > s->iopl || s->vm86) {
2859 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
2860 } else {
2861 if ((b & 1) == 0)
2862 ot = OT_BYTE;
2863 else
2864 ot = dflag ? OT_LONG : OT_WORD;
2865 gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
2866 gen_op_mov_TN_reg[ot][1][R_EAX]();
2867 gen_op_out[ot]();
2868 }
2869 break;
2870
2871 /************************/
2872 /* control */
2873 case 0xc2: /* ret im */
2874 val = ldsw(s->pc);
2875 s->pc += 2;
2876 gen_pop_T0(s);
2877 if (s->ss32)
2878 gen_op_addl_ESP_im(val + (2 << s->dflag));
2879 else
2880 gen_op_addw_ESP_im(val + (2 << s->dflag));
2881 if (s->dflag == 0)
2882 gen_op_andl_T0_ffff();
2883 gen_op_jmp_T0();
2884 s->is_jmp = 1;
2885 break;
2886 case 0xc3: /* ret */
2887 gen_pop_T0(s);
2888 gen_pop_update(s);
2889 if (s->dflag == 0)
2890 gen_op_andl_T0_ffff();
2891 gen_op_jmp_T0();
2892 s->is_jmp = 1;
2893 break;
2894 case 0xca: /* lret im */
2895 /* XXX: not restartable */
2896 val = ldsw(s->pc);
2897 s->pc += 2;
2898 /* pop offset */
2899 gen_pop_T0(s);
2900 if (s->dflag == 0)
2901 gen_op_andl_T0_ffff();
2902 gen_op_jmp_T0();
2903 gen_pop_update(s);
2904 /* pop selector */
2905 gen_pop_T0(s);
2906 gen_movl_seg_T0(s, R_CS);
2907 gen_pop_update(s);
2908 /* add stack offset */
2909 if (s->ss32)
2910 gen_op_addl_ESP_im(val);
2911 else
2912 gen_op_addw_ESP_im(val);
2913 s->is_jmp = 1;
2914 break;
2915 case 0xcb: /* lret */
2916 /* XXX: not restartable */
2917 /* pop offset */
2918 gen_pop_T0(s);
2919 if (s->dflag == 0)
2920 gen_op_andl_T0_ffff();
2921 gen_op_jmp_T0();
2922 gen_pop_update(s);
2923 /* pop selector */
2924 gen_pop_T0(s);
2925 gen_movl_seg_T0(s, R_CS);
2926 gen_pop_update(s);
2927 s->is_jmp = 1;
2928 break;
2929 case 0xcf: /* iret */
2930 if (s->vm86 && s->iopl != 3) {
2931 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
2932 } else {
2933 /* XXX: not restartable */
2934 /* pop offset */
2935 gen_pop_T0(s);
2936 if (s->dflag == 0)
2937 gen_op_andl_T0_ffff();
2938 gen_op_jmp_T0();
2939 gen_pop_update(s);
2940 /* pop selector */
2941 gen_pop_T0(s);
2942 gen_movl_seg_T0(s, R_CS);
2943 gen_pop_update(s);
2944 /* pop eflags */
2945 gen_pop_T0(s);
2946 if (s->dflag) {
2947 gen_op_movl_eflags_T0();
2948 } else {
2949 gen_op_movw_eflags_T0();
2950 }
2951 gen_pop_update(s);
2952 s->cc_op = CC_OP_EFLAGS;
2953 }
2954 s->is_jmp = 1;
2955 break;
2956 case 0xe8: /* call im */
2957 {
2958 unsigned int next_eip;
2959 ot = dflag ? OT_LONG : OT_WORD;
2960 val = insn_get(s, ot);
2961 next_eip = s->pc - s->cs_base;
2962 val += next_eip;
2963 if (s->dflag == 0)
2964 val &= 0xffff;
2965 gen_op_movl_T0_im(next_eip);
2966 gen_push_T0(s);
2967 gen_op_jmp_im(val);
2968 s->is_jmp = 1;
2969 }
2970 break;
2971 case 0x9a: /* lcall im */
2972 {
2973 unsigned int selector, offset;
2974
2975 ot = dflag ? OT_LONG : OT_WORD;
2976 offset = insn_get(s, ot);
2977 selector = insn_get(s, OT_WORD);
2978
2979 /* push return segment + offset */
2980 gen_op_movl_T0_seg(R_CS);
2981 gen_push_T0(s);
2982 next_eip = s->pc - s->cs_base;
2983 gen_op_movl_T0_im(next_eip);
2984 gen_push_T0(s);
2985
2986 /* change cs and pc */
2987 gen_op_movl_T0_im(selector);
2988 gen_movl_seg_T0(s, R_CS);
2989 gen_op_jmp_im((unsigned long)offset);
2990 s->is_jmp = 1;
2991 }
2992 break;
2993 case 0xe9: /* jmp */
2994 ot = dflag ? OT_LONG : OT_WORD;
2995 val = insn_get(s, ot);
2996 val += s->pc - s->cs_base;
2997 if (s->dflag == 0)
2998 val = val & 0xffff;
2999 gen_op_jmp_im(val);
3000 s->is_jmp = 1;
3001 break;
3002 case 0xea: /* ljmp im */
3003 {
3004 unsigned int selector, offset;
3005
3006 ot = dflag ? OT_LONG : OT_WORD;
3007 offset = insn_get(s, ot);
3008 selector = insn_get(s, OT_WORD);
3009
3010 /* change cs and pc */
3011 gen_op_movl_T0_im(selector);
3012 gen_movl_seg_T0(s, R_CS);
3013 gen_op_jmp_im((unsigned long)offset);
3014 s->is_jmp = 1;
3015 }
3016 break;
3017 case 0xeb: /* jmp Jb */
3018 val = (int8_t)insn_get(s, OT_BYTE);
3019 val += s->pc - s->cs_base;
3020 if (s->dflag == 0)
3021 val = val & 0xffff;
3022 gen_op_jmp_im(val);
3023 s->is_jmp = 1;
3024 break;
3025 case 0x70 ... 0x7f: /* jcc Jb */
3026 val = (int8_t)insn_get(s, OT_BYTE);
3027 goto do_jcc;
3028 case 0x180 ... 0x18f: /* jcc Jv */
3029 if (dflag) {
3030 val = insn_get(s, OT_LONG);
3031 } else {
3032 val = (int16_t)insn_get(s, OT_WORD);
3033 }
3034 do_jcc:
3035 next_eip = s->pc - s->cs_base;
3036 val += next_eip;
3037 if (s->dflag == 0)
3038 val &= 0xffff;
3039 gen_jcc(s, b, val, next_eip);
3040 s->is_jmp = 1;
3041 break;
3042
3043 case 0x190 ... 0x19f: /* setcc Gv */
3044 modrm = ldub(s->pc++);
3045 gen_setcc(s, b);
3046 gen_ldst_modrm(s, modrm, OT_BYTE, OR_TMP0, 1);
3047 break;
3048 case 0x140 ... 0x14f: /* cmov Gv, Ev */
3049 ot = dflag ? OT_LONG : OT_WORD;
3050 modrm = ldub(s->pc++);
3051 reg = (modrm >> 3) & 7;
3052 mod = (modrm >> 6) & 3;
3053 gen_setcc(s, b);
3054 if (mod != 3) {
3055 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3056 gen_op_ld_T1_A0[ot]();
3057 } else {
3058 rm = modrm & 7;
3059 gen_op_mov_TN_reg[ot][1][rm]();
3060 }
3061 gen_op_cmov_reg_T1_T0[ot - OT_WORD][reg]();
3062 break;
3063
3064 /************************/
3065 /* flags */
3066 case 0x9c: /* pushf */
3067 if (s->vm86 && s->iopl != 3) {
3068 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3069 } else {
3070 if (s->cc_op != CC_OP_DYNAMIC)
3071 gen_op_set_cc_op(s->cc_op);
3072 gen_op_movl_T0_eflags();
3073 gen_push_T0(s);
3074 }
3075 break;
3076 case 0x9d: /* popf */
3077 if (s->vm86 && s->iopl != 3) {
3078 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3079 } else {
3080 gen_pop_T0(s);
3081 if (s->dflag) {
3082 gen_op_movl_eflags_T0();
3083 } else {
3084 gen_op_movw_eflags_T0();
3085 }
3086 gen_pop_update(s);
3087 s->cc_op = CC_OP_EFLAGS;
3088 s->is_jmp = 2; /* abort translation because TF flag may change */
3089 }
3090 break;
3091 case 0x9e: /* sahf */
3092 gen_op_mov_TN_reg[OT_BYTE][0][R_AH]();
3093 if (s->cc_op != CC_OP_DYNAMIC)
3094 gen_op_set_cc_op(s->cc_op);
3095 gen_op_movb_eflags_T0();
3096 s->cc_op = CC_OP_EFLAGS;
3097 break;
3098 case 0x9f: /* lahf */
3099 if (s->cc_op != CC_OP_DYNAMIC)
3100 gen_op_set_cc_op(s->cc_op);
3101 gen_op_movl_T0_eflags();
3102 gen_op_mov_reg_T0[OT_BYTE][R_AH]();
3103 break;
3104 case 0xf5: /* cmc */
3105 if (s->cc_op != CC_OP_DYNAMIC)
3106 gen_op_set_cc_op(s->cc_op);
3107 gen_op_cmc();
3108 s->cc_op = CC_OP_EFLAGS;
3109 break;
3110 case 0xf8: /* clc */
3111 if (s->cc_op != CC_OP_DYNAMIC)
3112 gen_op_set_cc_op(s->cc_op);
3113 gen_op_clc();
3114 s->cc_op = CC_OP_EFLAGS;
3115 break;
3116 case 0xf9: /* stc */
3117 if (s->cc_op != CC_OP_DYNAMIC)
3118 gen_op_set_cc_op(s->cc_op);
3119 gen_op_stc();
3120 s->cc_op = CC_OP_EFLAGS;
3121 break;
3122 case 0xfc: /* cld */
3123 gen_op_cld();
3124 break;
3125 case 0xfd: /* std */
3126 gen_op_std();
3127 break;
3128
3129 /************************/
3130 /* bit operations */
3131 case 0x1ba: /* bt/bts/btr/btc Gv, im */
3132 ot = dflag ? OT_LONG : OT_WORD;
3133 modrm = ldub(s->pc++);
3134 op = (modrm >> 3) & 7;
3135 mod = (modrm >> 6) & 3;
3136 rm = modrm & 7;
3137 if (mod != 3) {
3138 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3139 gen_op_ld_T0_A0[ot]();
3140 } else {
3141 gen_op_mov_TN_reg[ot][0][rm]();
3142 }
3143 /* load shift */
3144 val = ldub(s->pc++);
3145 gen_op_movl_T1_im(val);
3146 if (op < 4)
3147 goto illegal_op;
3148 op -= 4;
3149 gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
3150 s->cc_op = CC_OP_SARB + ot;
3151 if (op != 0) {
3152 if (mod != 3)
3153 gen_op_st_T0_A0[ot]();
3154 else
3155 gen_op_mov_reg_T0[ot][rm]();
3156 }
3157 break;
3158 case 0x1a3: /* bt Gv, Ev */
3159 op = 0;
3160 goto do_btx;
3161 case 0x1ab: /* bts */
3162 op = 1;
3163 goto do_btx;
3164 case 0x1b3: /* btr */
3165 op = 2;
3166 goto do_btx;
3167 case 0x1bb: /* btc */
3168 op = 3;
3169 do_btx:
3170 ot = dflag ? OT_LONG : OT_WORD;
3171 modrm = ldub(s->pc++);
3172 reg = (modrm >> 3) & 7;
3173 mod = (modrm >> 6) & 3;
3174 rm = modrm & 7;
3175 gen_op_mov_TN_reg[OT_LONG][1][reg]();
3176 if (mod != 3) {
3177 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3178 /* specific case: we need to add a displacement */
3179 if (ot == OT_WORD)
3180 gen_op_add_bitw_A0_T1();
3181 else
3182 gen_op_add_bitl_A0_T1();
3183 gen_op_ld_T0_A0[ot]();
3184 } else {
3185 gen_op_mov_TN_reg[ot][0][rm]();
3186 }
3187 gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
3188 s->cc_op = CC_OP_SARB + ot;
3189 if (op != 0) {
3190 if (mod != 3)
3191 gen_op_st_T0_A0[ot]();
3192 else
3193 gen_op_mov_reg_T0[ot][rm]();
3194 }
3195 break;
3196 case 0x1bc: /* bsf */
3197 case 0x1bd: /* bsr */
3198 ot = dflag ? OT_LONG : OT_WORD;
3199 modrm = ldub(s->pc++);
3200 reg = (modrm >> 3) & 7;
3201 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
3202 gen_op_bsx_T0_cc[ot - OT_WORD][b & 1]();
3203 /* NOTE: we always write back the result. Intel doc says it is
3204 undefined if T0 == 0 */
3205 gen_op_mov_reg_T0[ot][reg]();
3206 s->cc_op = CC_OP_LOGICB + ot;
3207 break;
3208 /************************/
3209 /* bcd */
3210 case 0x27: /* daa */
3211 if (s->cc_op != CC_OP_DYNAMIC)
3212 gen_op_set_cc_op(s->cc_op);
3213 gen_op_daa();
3214 s->cc_op = CC_OP_EFLAGS;
3215 break;
3216 case 0x2f: /* das */
3217 if (s->cc_op != CC_OP_DYNAMIC)
3218 gen_op_set_cc_op(s->cc_op);
3219 gen_op_das();
3220 s->cc_op = CC_OP_EFLAGS;
3221 break;
3222 case 0x37: /* aaa */
3223 if (s->cc_op != CC_OP_DYNAMIC)
3224 gen_op_set_cc_op(s->cc_op);
3225 gen_op_aaa();
3226 s->cc_op = CC_OP_EFLAGS;
3227 break;
3228 case 0x3f: /* aas */
3229 if (s->cc_op != CC_OP_DYNAMIC)
3230 gen_op_set_cc_op(s->cc_op);
3231 gen_op_aas();
3232 s->cc_op = CC_OP_EFLAGS;
3233 break;
3234 case 0xd4: /* aam */
3235 val = ldub(s->pc++);
3236 gen_op_aam(val);
3237 s->cc_op = CC_OP_LOGICB;
3238 break;
3239 case 0xd5: /* aad */
3240 val = ldub(s->pc++);
3241 gen_op_aad(val);
3242 s->cc_op = CC_OP_LOGICB;
3243 break;
3244 /************************/
3245 /* misc */
3246 case 0x90: /* nop */
3247 break;
3248 case 0xcc: /* int3 */
3249 gen_exception(s, EXCP03_INT3, s->pc - s->cs_base);
3250 break;
3251 case 0xcd: /* int N */
3252 val = ldub(s->pc++);
3253 if (s->cc_op != CC_OP_DYNAMIC)
3254 gen_op_set_cc_op(s->cc_op);
3255 gen_op_int_im(val, pc_start - s->cs_base);
3256 s->is_jmp = 1;
3257 break;
3258 case 0xce: /* into */
3259 if (s->cc_op != CC_OP_DYNAMIC)
3260 gen_op_set_cc_op(s->cc_op);
3261 gen_op_into(s->pc - s->cs_base);
3262 break;
3263 case 0xfa: /* cli */
3264 if (!s->vm86) {
3265 if (s->cpl <= s->iopl) {
3266 gen_op_cli();
3267 } else {
3268 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3269 }
3270 } else {
3271 if (s->iopl == 3) {
3272 gen_op_cli();
3273 } else {
3274 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3275 }
3276 }
3277 break;
3278 case 0xfb: /* sti */
3279 if (!s->vm86) {
3280 if (s->cpl <= s->iopl) {
3281 gen_op_sti();
3282 } else {
3283 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3284 }
3285 } else {
3286 if (s->iopl == 3) {
3287 gen_op_sti();
3288 } else {
3289 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3290 }
3291 }
3292 break;
3293 case 0x62: /* bound */
3294 ot = dflag ? OT_LONG : OT_WORD;
3295 modrm = ldub(s->pc++);
3296 reg = (modrm >> 3) & 7;
3297 mod = (modrm >> 6) & 3;
3298 if (mod == 3)
3299 goto illegal_op;
3300 gen_op_mov_reg_T0[ot][reg]();
3301 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3302 if (ot == OT_WORD)
3303 gen_op_boundw();
3304 else
3305 gen_op_boundl();
3306 break;
3307 case 0x1c8 ... 0x1cf: /* bswap reg */
3308 reg = b & 7;
3309 gen_op_mov_TN_reg[OT_LONG][0][reg]();
3310 gen_op_bswapl_T0();
3311 gen_op_mov_reg_T0[OT_LONG][reg]();
3312 break;
3313 case 0xd6: /* salc */
3314 if (s->cc_op != CC_OP_DYNAMIC)
3315 gen_op_set_cc_op(s->cc_op);
3316 gen_op_salc();
3317 break;
3318 case 0xe0: /* loopnz */
3319 case 0xe1: /* loopz */
3320 if (s->cc_op != CC_OP_DYNAMIC)
3321 gen_op_set_cc_op(s->cc_op);
3322 /* FALL THRU */
3323 case 0xe2: /* loop */
3324 case 0xe3: /* jecxz */
3325 val = (int8_t)insn_get(s, OT_BYTE);
3326 next_eip = s->pc - s->cs_base;
3327 val += next_eip;
3328 if (s->dflag == 0)
3329 val &= 0xffff;
3330 gen_op_loop[s->aflag][b & 3](val, next_eip);
3331 s->is_jmp = 1;
3332 break;
3333 case 0x131: /* rdtsc */
3334 gen_op_rdtsc();
3335 break;
3336 case 0x1a2: /* cpuid */
3337 gen_op_cpuid();
3338 break;
3339 case 0xf4: /* hlt */
3340 /* XXX: if cpl == 0, then should do something else */
3341 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3342 break;
3343 case 0x102: /* lar */
3344 case 0x103: /* lsl */
3345 if (s->vm86)
3346 goto illegal_op;
3347 ot = dflag ? OT_LONG : OT_WORD;
3348 modrm = ldub(s->pc++);
3349 reg = (modrm >> 3) & 7;
3350 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
3351 gen_op_mov_TN_reg[ot][1][reg]();
3352 if (s->cc_op != CC_OP_DYNAMIC)
3353 gen_op_set_cc_op(s->cc_op);
3354 if (b == 0x102)
3355 gen_op_lar();
3356 else
3357 gen_op_lsl();
3358 s->cc_op = CC_OP_EFLAGS;
3359 gen_op_mov_reg_T1[ot][reg]();
3360 break;
3361 default:
3362 goto illegal_op;
3363 }
3364 /* lock generation */
3365 if (s->prefix & PREFIX_LOCK)
3366 gen_op_unlock();
3367 return (long)s->pc;
3368 illegal_op:
3369 /* XXX: ensure that no lock was generated */
3370 return -1;
3371 }
3372
3373 #define CC_OSZAPC (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C)
3374 #define CC_OSZAP (CC_O | CC_S | CC_Z | CC_A | CC_P)
3375
3376 /* flags read by an operation */
3377 static uint16_t opc_read_flags[NB_OPS] = {
3378 [INDEX_op_aas] = CC_A,
3379 [INDEX_op_aaa] = CC_A,
3380 [INDEX_op_das] = CC_A | CC_C,
3381 [INDEX_op_daa] = CC_A | CC_C,
3382
3383 [INDEX_op_adcb_T0_T1_cc] = CC_C,
3384 [INDEX_op_adcw_T0_T1_cc] = CC_C,
3385 [INDEX_op_adcl_T0_T1_cc] = CC_C,
3386 [INDEX_op_sbbb_T0_T1_cc] = CC_C,
3387 [INDEX_op_sbbw_T0_T1_cc] = CC_C,
3388 [INDEX_op_sbbl_T0_T1_cc] = CC_C,
3389
3390 /* subtle: due to the incl/decl implementation, C is used */
3391 [INDEX_op_incl_T0_cc] = CC_C,
3392 [INDEX_op_decl_T0_cc] = CC_C,
3393
3394 [INDEX_op_into] = CC_O,
3395
3396 [INDEX_op_jo_cc] = CC_O,
3397 [INDEX_op_jb_cc] = CC_C,
3398 [INDEX_op_jz_cc] = CC_Z,
3399 [INDEX_op_jbe_cc] = CC_Z | CC_C,
3400 [INDEX_op_js_cc] = CC_S,
3401 [INDEX_op_jp_cc] = CC_P,
3402 [INDEX_op_jl_cc] = CC_O | CC_S,
3403 [INDEX_op_jle_cc] = CC_O | CC_S | CC_Z,
3404
3405 [INDEX_op_jb_subb] = CC_C,
3406 [INDEX_op_jb_subw] = CC_C,
3407 [INDEX_op_jb_subl] = CC_C,
3408
3409 [INDEX_op_jz_subb] = CC_Z,
3410 [INDEX_op_jz_subw] = CC_Z,
3411 [INDEX_op_jz_subl] = CC_Z,
3412
3413 [INDEX_op_jbe_subb] = CC_Z | CC_C,
3414 [INDEX_op_jbe_subw] = CC_Z | CC_C,
3415 [INDEX_op_jbe_subl] = CC_Z | CC_C,
3416
3417 [INDEX_op_js_subb] = CC_S,
3418 [INDEX_op_js_subw] = CC_S,
3419 [INDEX_op_js_subl] = CC_S,
3420
3421 [INDEX_op_jl_subb] = CC_O | CC_S,
3422 [INDEX_op_jl_subw] = CC_O | CC_S,
3423 [INDEX_op_jl_subl] = CC_O | CC_S,
3424
3425 [INDEX_op_jle_subb] = CC_O | CC_S | CC_Z,
3426 [INDEX_op_jle_subw] = CC_O | CC_S | CC_Z,
3427 [INDEX_op_jle_subl] = CC_O | CC_S | CC_Z,
3428
3429 [INDEX_op_loopnzw] = CC_Z,
3430 [INDEX_op_loopnzl] = CC_Z,
3431 [INDEX_op_loopzw] = CC_Z,
3432 [INDEX_op_loopzl] = CC_Z,
3433
3434 [INDEX_op_seto_T0_cc] = CC_O,
3435 [INDEX_op_setb_T0_cc] = CC_C,
3436 [INDEX_op_setz_T0_cc] = CC_Z,
3437 [INDEX_op_setbe_T0_cc] = CC_Z | CC_C,
3438 [INDEX_op_sets_T0_cc] = CC_S,
3439 [INDEX_op_setp_T0_cc] = CC_P,
3440 [INDEX_op_setl_T0_cc] = CC_O | CC_S,
3441 [INDEX_op_setle_T0_cc] = CC_O | CC_S | CC_Z,
3442
3443 [INDEX_op_setb_T0_subb] = CC_C,
3444 [INDEX_op_setb_T0_subw] = CC_C,
3445 [INDEX_op_setb_T0_subl] = CC_C,
3446
3447 [INDEX_op_setz_T0_subb] = CC_Z,
3448 [INDEX_op_setz_T0_subw] = CC_Z,
3449 [INDEX_op_setz_T0_subl] = CC_Z,
3450
3451 [INDEX_op_setbe_T0_subb] = CC_Z | CC_C,
3452 [INDEX_op_setbe_T0_subw] = CC_Z | CC_C,
3453 [INDEX_op_setbe_T0_subl] = CC_Z | CC_C,
3454
3455 [INDEX_op_sets_T0_subb] = CC_S,
3456 [INDEX_op_sets_T0_subw] = CC_S,
3457 [INDEX_op_sets_T0_subl] = CC_S,
3458
3459 [INDEX_op_setl_T0_subb] = CC_O | CC_S,
3460 [INDEX_op_setl_T0_subw] = CC_O | CC_S,
3461 [INDEX_op_setl_T0_subl] = CC_O | CC_S,
3462
3463 [INDEX_op_setle_T0_subb] = CC_O | CC_S | CC_Z,
3464 [INDEX_op_setle_T0_subw] = CC_O | CC_S | CC_Z,
3465 [INDEX_op_setle_T0_subl] = CC_O | CC_S | CC_Z,
3466
3467 [INDEX_op_movl_T0_eflags] = CC_OSZAPC,
3468 [INDEX_op_cmc] = CC_C,
3469 [INDEX_op_salc] = CC_C,
3470
3471 [INDEX_op_rclb_T0_T1_cc] = CC_C,
3472 [INDEX_op_rclw_T0_T1_cc] = CC_C,
3473 [INDEX_op_rcll_T0_T1_cc] = CC_C,
3474 [INDEX_op_rcrb_T0_T1_cc] = CC_C,
3475 [INDEX_op_rcrw_T0_T1_cc] = CC_C,
3476 [INDEX_op_rcrl_T0_T1_cc] = CC_C,
3477 };
3478
3479 /* flags written by an operation */
3480 static uint16_t opc_write_flags[NB_OPS] = {
3481 [INDEX_op_addl_T0_T1_cc] = CC_OSZAPC,
3482 [INDEX_op_orl_T0_T1_cc] = CC_OSZAPC,
3483 [INDEX_op_adcb_T0_T1_cc] = CC_OSZAPC,
3484 [INDEX_op_adcw_T0_T1_cc] = CC_OSZAPC,
3485 [INDEX_op_adcl_T0_T1_cc] = CC_OSZAPC,
3486 [INDEX_op_sbbb_T0_T1_cc] = CC_OSZAPC,
3487 [INDEX_op_sbbw_T0_T1_cc] = CC_OSZAPC,
3488 [INDEX_op_sbbl_T0_T1_cc] = CC_OSZAPC,
3489 [INDEX_op_andl_T0_T1_cc] = CC_OSZAPC,
3490 [INDEX_op_subl_T0_T1_cc] = CC_OSZAPC,
3491 [INDEX_op_xorl_T0_T1_cc] = CC_OSZAPC,
3492 [INDEX_op_cmpl_T0_T1_cc] = CC_OSZAPC,
3493 [INDEX_op_negl_T0_cc] = CC_OSZAPC,
3494 /* subtle: due to the incl/decl implementation, C is used */
3495 [INDEX_op_incl_T0_cc] = CC_OSZAPC,
3496 [INDEX_op_decl_T0_cc] = CC_OSZAPC,
3497 [INDEX_op_testl_T0_T1_cc] = CC_OSZAPC,
3498
3499 [INDEX_op_mulb_AL_T0] = CC_OSZAPC,
3500 [INDEX_op_imulb_AL_T0] = CC_OSZAPC,
3501 [INDEX_op_mulw_AX_T0] = CC_OSZAPC,
3502 [INDEX_op_imulw_AX_T0] = CC_OSZAPC,
3503 [INDEX_op_mull_EAX_T0] = CC_OSZAPC,
3504 [INDEX_op_imull_EAX_T0] = CC_OSZAPC,
3505 [INDEX_op_imulw_T0_T1] = CC_OSZAPC,
3506 [INDEX_op_imull_T0_T1] = CC_OSZAPC,
3507
3508 /* bcd */
3509 [INDEX_op_aam] = CC_OSZAPC,
3510 [INDEX_op_aad] = CC_OSZAPC,
3511 [INDEX_op_aas] = CC_OSZAPC,
3512 [INDEX_op_aaa] = CC_OSZAPC,
3513 [INDEX_op_das] = CC_OSZAPC,
3514 [INDEX_op_daa] = CC_OSZAPC,
3515
3516 [INDEX_op_movb_eflags_T0] = CC_S | CC_Z | CC_A | CC_P | CC_C,
3517 [INDEX_op_movw_eflags_T0] = CC_OSZAPC,
3518 [INDEX_op_movl_eflags_T0] = CC_OSZAPC,
3519 [INDEX_op_clc] = CC_C,
3520 [INDEX_op_stc] = CC_C,
3521 [INDEX_op_cmc] = CC_C,
3522
3523 [INDEX_op_rolb_T0_T1_cc] = CC_O | CC_C,
3524 [INDEX_op_rolw_T0_T1_cc] = CC_O | CC_C,
3525 [INDEX_op_roll_T0_T1_cc] = CC_O | CC_C,
3526 [INDEX_op_rorb_T0_T1_cc] = CC_O | CC_C,
3527 [INDEX_op_rorw_T0_T1_cc] = CC_O | CC_C,
3528 [INDEX_op_rorl_T0_T1_cc] = CC_O | CC_C,
3529
3530 [INDEX_op_rclb_T0_T1_cc] = CC_O | CC_C,
3531 [INDEX_op_rclw_T0_T1_cc] = CC_O | CC_C,
3532 [INDEX_op_rcll_T0_T1_cc] = CC_O | CC_C,
3533 [INDEX_op_rcrb_T0_T1_cc] = CC_O | CC_C,
3534 [INDEX_op_rcrw_T0_T1_cc] = CC_O | CC_C,
3535 [INDEX_op_rcrl_T0_T1_cc] = CC_O | CC_C,
3536
3537 [INDEX_op_shlb_T0_T1_cc] = CC_OSZAPC,
3538 [INDEX_op_shlw_T0_T1_cc] = CC_OSZAPC,
3539 [INDEX_op_shll_T0_T1_cc] = CC_OSZAPC,
3540
3541 [INDEX_op_shrb_T0_T1_cc] = CC_OSZAPC,
3542 [INDEX_op_shrw_T0_T1_cc] = CC_OSZAPC,
3543 [INDEX_op_shrl_T0_T1_cc] = CC_OSZAPC,
3544
3545 [INDEX_op_sarb_T0_T1_cc] = CC_OSZAPC,
3546 [INDEX_op_sarw_T0_T1_cc] = CC_OSZAPC,
3547 [INDEX_op_sarl_T0_T1_cc] = CC_OSZAPC,
3548
3549 [INDEX_op_shldw_T0_T1_ECX_cc] = CC_OSZAPC,
3550 [INDEX_op_shldl_T0_T1_ECX_cc] = CC_OSZAPC,
3551 [INDEX_op_shldw_T0_T1_im_cc] = CC_OSZAPC,
3552 [INDEX_op_shldl_T0_T1_im_cc] = CC_OSZAPC,
3553
3554 [INDEX_op_shrdw_T0_T1_ECX_cc] = CC_OSZAPC,
3555 [INDEX_op_shrdl_T0_T1_ECX_cc] = CC_OSZAPC,
3556 [INDEX_op_shrdw_T0_T1_im_cc] = CC_OSZAPC,
3557 [INDEX_op_shrdl_T0_T1_im_cc] = CC_OSZAPC,
3558
3559 [INDEX_op_btw_T0_T1_cc] = CC_OSZAPC,
3560 [INDEX_op_btl_T0_T1_cc] = CC_OSZAPC,
3561 [INDEX_op_btsw_T0_T1_cc] = CC_OSZAPC,
3562 [INDEX_op_btsl_T0_T1_cc] = CC_OSZAPC,
3563 [INDEX_op_btrw_T0_T1_cc] = CC_OSZAPC,
3564 [INDEX_op_btrl_T0_T1_cc] = CC_OSZAPC,
3565 [INDEX_op_btcw_T0_T1_cc] = CC_OSZAPC,
3566 [INDEX_op_btcl_T0_T1_cc] = CC_OSZAPC,
3567
3568 [INDEX_op_bsfw_T0_cc] = CC_OSZAPC,
3569 [INDEX_op_bsfl_T0_cc] = CC_OSZAPC,
3570 [INDEX_op_bsrw_T0_cc] = CC_OSZAPC,
3571 [INDEX_op_bsrl_T0_cc] = CC_OSZAPC,
3572
3573 #undef STRINGOP
3574 #define STRINGOP(x) \
3575 [INDEX_op_ ## x ## b_fast] = CC_OSZAPC, \
3576 [INDEX_op_ ## x ## w_fast] = CC_OSZAPC, \
3577 [INDEX_op_ ## x ## l_fast] = CC_OSZAPC, \
3578 [INDEX_op_ ## x ## b_a32] = CC_OSZAPC, \
3579 [INDEX_op_ ## x ## w_a32] = CC_OSZAPC, \
3580 [INDEX_op_ ## x ## l_a32] = CC_OSZAPC, \
3581 [INDEX_op_ ## x ## b_a16] = CC_OSZAPC, \
3582 [INDEX_op_ ## x ## w_a16] = CC_OSZAPC, \
3583 [INDEX_op_ ## x ## l_a16] = CC_OSZAPC,
3584
3585 STRINGOP(scas)
3586 STRINGOP(repz_scas)
3587 STRINGOP(repnz_scas)
3588 STRINGOP(cmps)
3589 STRINGOP(repz_cmps)
3590 STRINGOP(repnz_cmps)
3591
3592 [INDEX_op_cmpxchgb_T0_T1_EAX_cc] = CC_OSZAPC,
3593 [INDEX_op_cmpxchgw_T0_T1_EAX_cc] = CC_OSZAPC,
3594 [INDEX_op_cmpxchgl_T0_T1_EAX_cc] = CC_OSZAPC,
3595
3596 [INDEX_op_cmpxchg8b] = CC_Z,
3597 [INDEX_op_lar] = CC_Z,
3598 [INDEX_op_lsl] = CC_Z,
3599 };
3600
3601 /* simpler form of an operation if no flags need to be generated */
3602 static uint16_t opc_simpler[NB_OPS] = {
3603 [INDEX_op_addl_T0_T1_cc] = INDEX_op_addl_T0_T1,
3604 [INDEX_op_orl_T0_T1_cc] = INDEX_op_orl_T0_T1,
3605 [INDEX_op_andl_T0_T1_cc] = INDEX_op_andl_T0_T1,
3606 [INDEX_op_subl_T0_T1_cc] = INDEX_op_subl_T0_T1,
3607 [INDEX_op_xorl_T0_T1_cc] = INDEX_op_xorl_T0_T1,
3608 [INDEX_op_negl_T0_cc] = INDEX_op_negl_T0,
3609 [INDEX_op_incl_T0_cc] = INDEX_op_incl_T0,
3610 [INDEX_op_decl_T0_cc] = INDEX_op_decl_T0,
3611
3612 [INDEX_op_rolb_T0_T1_cc] = INDEX_op_rolb_T0_T1,
3613 [INDEX_op_rolw_T0_T1_cc] = INDEX_op_rolw_T0_T1,
3614 [INDEX_op_roll_T0_T1_cc] = INDEX_op_roll_T0_T1,
3615
3616 [INDEX_op_rorb_T0_T1_cc] = INDEX_op_rorb_T0_T1,
3617 [INDEX_op_rorw_T0_T1_cc] = INDEX_op_rorw_T0_T1,
3618 [INDEX_op_rorl_T0_T1_cc] = INDEX_op_rorl_T0_T1,
3619
3620 [INDEX_op_shlb_T0_T1_cc] = INDEX_op_shlb_T0_T1,
3621 [INDEX_op_shlw_T0_T1_cc] = INDEX_op_shlw_T0_T1,
3622 [INDEX_op_shll_T0_T1_cc] = INDEX_op_shll_T0_T1,
3623
3624 [INDEX_op_shrb_T0_T1_cc] = INDEX_op_shrb_T0_T1,
3625 [INDEX_op_shrw_T0_T1_cc] = INDEX_op_shrw_T0_T1,
3626 [INDEX_op_shrl_T0_T1_cc] = INDEX_op_shrl_T0_T1,
3627
3628 [INDEX_op_sarb_T0_T1_cc] = INDEX_op_sarb_T0_T1,
3629 [INDEX_op_sarw_T0_T1_cc] = INDEX_op_sarw_T0_T1,
3630 [INDEX_op_sarl_T0_T1_cc] = INDEX_op_sarl_T0_T1,
3631 };
3632
3633 static void optimize_flags_init(void)
3634 {
3635 int i;
3636 /* put default values in arrays */
3637 for(i = 0; i < NB_OPS; i++) {
3638 if (opc_simpler[i] == 0)
3639 opc_simpler[i] = i;
3640 }
3641 }
3642
3643 /* CPU flags computation optimization: we move backward thru the
3644 generated code to see which flags are needed. The operation is
3645 modified if suitable */
3646 static void optimize_flags(uint16_t *opc_buf, int opc_buf_len)
3647 {
3648 uint16_t *opc_ptr;
3649 int live_flags, write_flags, op;
3650
3651 opc_ptr = opc_buf + opc_buf_len;
3652 /* live_flags contains the flags needed by the next instructions
3653 in the code. At the end of the bloc, we consider that all the
3654 flags are live. */
3655 live_flags = CC_OSZAPC;
3656 while (opc_ptr > opc_buf) {
3657 op = *--opc_ptr;
3658 /* if none of the flags written by the instruction is used,
3659 then we can try to find a simpler instruction */
3660 write_flags = opc_write_flags[op];
3661 if ((live_flags & write_flags) == 0) {
3662 *opc_ptr = opc_simpler[op];
3663 }
3664 /* compute the live flags before the instruction */
3665 live_flags &= ~write_flags;
3666 live_flags |= opc_read_flags[op];
3667 }
3668 }
3669
3670
3671 #ifdef DEBUG_DISAS
3672 static const char *op_str[] = {
3673 #define DEF(s, n) #s,
3674 #include "opc-i386.h"
3675 #undef DEF
3676 };
3677
3678 static uint8_t op_nb_args[] = {
3679 #define DEF(s, n) n,
3680 #include "opc-i386.h"
3681 #undef DEF
3682 };
3683
3684 static void dump_ops(const uint16_t *opc_buf, const uint32_t *opparam_buf)
3685 {
3686 const uint16_t *opc_ptr;
3687 const uint32_t *opparam_ptr;
3688 int c, n, i;
3689
3690 opc_ptr = opc_buf;
3691 opparam_ptr = opparam_buf;
3692 for(;;) {
3693 c = *opc_ptr++;
3694 n = op_nb_args[c];
3695 fprintf(logfile, "0x%04x: %s",
3696 (int)(opc_ptr - opc_buf - 1), op_str[c]);
3697 for(i = 0; i < n; i++) {
3698 fprintf(logfile, " 0x%x", opparam_ptr[i]);
3699 }
3700 fprintf(logfile, "\n");
3701 if (c == INDEX_op_end)
3702 break;
3703 opparam_ptr += n;
3704 }
3705 }
3706
3707 #endif
3708
3709 /* XXX: make this buffer thread safe */
3710 /* XXX: make safe guess about sizes */
3711 #define MAX_OP_PER_INSTR 32
3712 #define OPC_BUF_SIZE 512
3713 #define OPC_MAX_SIZE (OPC_BUF_SIZE - MAX_OP_PER_INSTR)
3714
3715 #define OPPARAM_BUF_SIZE (OPC_BUF_SIZE * 3)
3716
3717 static uint16_t gen_opc_buf[OPC_BUF_SIZE];
3718 static uint32_t gen_opparam_buf[OPPARAM_BUF_SIZE];
3719
3720 /* return non zero if the very first instruction is invalid so that
3721 the virtual CPU can trigger an exception.
3722
3723 '*code_size_ptr' contains the target code size including the
3724 instruction which triggered an exception, except in case of invalid
3725 illegal opcode. It must never exceed one target page.
3726
3727 '*gen_code_size_ptr' contains the size of the generated code (host
3728 code).
3729 */
3730 int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size,
3731 int *gen_code_size_ptr,
3732 uint8_t *pc_start, uint8_t *cs_base, int flags,
3733 int *code_size_ptr)
3734 {
3735 DisasContext dc1, *dc = &dc1;
3736 uint8_t *pc_ptr;
3737 uint16_t *gen_opc_end;
3738 int gen_code_size;
3739 long ret;
3740
3741 /* generate intermediate code */
3742
3743 dc->code32 = (flags >> GEN_FLAG_CODE32_SHIFT) & 1;
3744 dc->ss32 = (flags >> GEN_FLAG_SS32_SHIFT) & 1;
3745 dc->addseg = (flags >> GEN_FLAG_ADDSEG_SHIFT) & 1;
3746 dc->f_st = (flags >> GEN_FLAG_ST_SHIFT) & 7;
3747 dc->vm86 = (flags >> GEN_FLAG_VM_SHIFT) & 1;
3748 dc->cpl = (flags >> GEN_FLAG_CPL_SHIFT) & 3;
3749 dc->iopl = (flags >> GEN_FLAG_IOPL_SHIFT) & 3;
3750 dc->tf = (flags >> GEN_FLAG_TF_SHIFT) & 1;
3751 dc->cc_op = CC_OP_DYNAMIC;
3752 dc->cs_base = cs_base;
3753
3754 gen_opc_ptr = gen_opc_buf;
3755 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
3756 gen_opparam_ptr = gen_opparam_buf;
3757
3758 dc->is_jmp = 0;
3759 pc_ptr = pc_start;
3760 do {
3761 ret = disas_insn(dc, pc_ptr);
3762 if (ret == -1) {
3763 /* we trigger an illegal instruction operation only if it
3764 is the first instruction. Otherwise, we simply stop
3765 generating the code just before it */
3766 if (pc_ptr == pc_start)
3767 return -1;
3768 else
3769 break;
3770 }
3771 pc_ptr = (void *)ret;
3772 /* if single step mode, we generate only one instruction and
3773 generate an exception */
3774 if (dc->tf)
3775 break;
3776 } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
3777 (pc_ptr - pc_start) < (TARGET_PAGE_SIZE - 32));
3778 /* we must store the eflags state if it is not already done */
3779 if (dc->cc_op != CC_OP_DYNAMIC)
3780 gen_op_set_cc_op(dc->cc_op);
3781 if (dc->is_jmp != 1) {
3782 /* we add an additionnal jmp to update the simulated PC */
3783 gen_op_jmp_im(ret - (unsigned long)dc->cs_base);
3784 }
3785 if (dc->tf) {
3786 gen_op_raise_exception(EXCP01_SSTP);
3787 }
3788
3789 *gen_opc_ptr = INDEX_op_end;
3790
3791 #ifdef DEBUG_DISAS
3792 if (loglevel) {
3793 fprintf(logfile, "----------------\n");
3794 fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
3795 disas(logfile, pc_start, pc_ptr - pc_start,
3796 dc->code32 ? DISAS_I386_I386 : DISAS_I386_I8086);
3797 fprintf(logfile, "\n");
3798
3799 fprintf(logfile, "OP:\n");
3800 dump_ops(gen_opc_buf, gen_opparam_buf);
3801 fprintf(logfile, "\n");
3802 }
3803 #endif
3804
3805 /* optimize flag computations */
3806 optimize_flags(gen_opc_buf, gen_opc_ptr - gen_opc_buf);
3807
3808 #ifdef DEBUG_DISAS
3809 if (loglevel) {
3810 fprintf(logfile, "AFTER FLAGS OPT:\n");
3811 dump_ops(gen_opc_buf, gen_opparam_buf);
3812 fprintf(logfile, "\n");
3813 }
3814 #endif
3815
3816 /* generate machine code */
3817 gen_code_size = dyngen_code(gen_code_buf, gen_opc_buf, gen_opparam_buf);
3818 flush_icache_range((unsigned long)gen_code_buf, (unsigned long)(gen_code_buf + gen_code_size));
3819 *gen_code_size_ptr = gen_code_size;
3820 *code_size_ptr = pc_ptr - pc_start;
3821 #ifdef DEBUG_DISAS
3822 if (loglevel) {
3823 fprintf(logfile, "OUT: [size=%d]\n", *gen_code_size_ptr);
3824 disas(logfile, gen_code_buf, *gen_code_size_ptr, DISAS_TARGET);
3825 fprintf(logfile, "\n");
3826 fflush(logfile);
3827 }
3828 #endif
3829 return 0;
3830 }
3831
3832 CPUX86State *cpu_x86_init(void)
3833 {
3834 CPUX86State *env;
3835 int i;
3836 static int inited;
3837
3838 cpu_x86_tblocks_init();
3839
3840 env = malloc(sizeof(CPUX86State));
3841 if (!env)
3842 return NULL;
3843 memset(env, 0, sizeof(CPUX86State));
3844 /* basic FPU init */
3845 for(i = 0;i < 8; i++)
3846 env->fptags[i] = 1;
3847 env->fpuc = 0x37f;
3848 /* flags setup : we activate the IRQs by default as in user mode */
3849 env->eflags = 0x2 | IF_MASK;
3850
3851 /* init various static tables */
3852 if (!inited) {
3853 inited = 1;
3854 optimize_flags_init();
3855 page_init();
3856 }
3857 return env;
3858 }
3859
3860 void cpu_x86_close(CPUX86State *env)
3861 {
3862 free(env);
3863 }
3864
3865 static const char *cc_op_str[] = {
3866 "DYNAMIC",
3867 "EFLAGS",
3868 "MUL",
3869 "ADDB",
3870 "ADDW",
3871 "ADDL",
3872 "ADCB",
3873 "ADCW",
3874 "ADCL",
3875 "SUBB",
3876 "SUBW",
3877 "SUBL",
3878 "SBBB",
3879 "SBBW",
3880 "SBBL",
3881 "LOGICB",
3882 "LOGICW",
3883 "LOGICL",
3884 "INCB",
3885 "INCW",
3886 "INCL",
3887 "DECB",
3888 "DECW",
3889 "DECL",
3890 "SHLB",
3891 "SHLW",
3892 "SHLL",
3893 "SARB",
3894 "SARW",
3895 "SARL",
3896 };
3897
3898 void cpu_x86_dump_state(CPUX86State *env, FILE *f, int flags)
3899 {
3900 int eflags;
3901 char cc_op_name[32];
3902
3903 eflags = env->eflags;
3904 fprintf(f, "EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n"
3905 "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n"
3906 "EIP=%08x EFL=%08x [%c%c%c%c%c%c%c]\n",
3907 env->regs[R_EAX], env->regs[R_EBX], env->regs[R_ECX], env->regs[R_EDX],
3908 env->regs[R_ESI], env->regs[R_EDI], env->regs[R_EBP], env->regs[R_ESP],
3909 env->eip, eflags,
3910 eflags & DF_MASK ? 'D' : '-',
3911 eflags & CC_O ? 'O' : '-',
3912 eflags & CC_S ? 'S' : '-',
3913 eflags & CC_Z ? 'Z' : '-',
3914 eflags & CC_A ? 'A' : '-',
3915 eflags & CC_P ? 'P' : '-',
3916 eflags & CC_C ? 'C' : '-');
3917 fprintf(f, "CS=%04x SS=%04x DS=%04x ES=%04x FS=%04x GS=%04x\n",
3918 env->segs[R_CS],
3919 env->segs[R_SS],
3920 env->segs[R_DS],
3921 env->segs[R_ES],
3922 env->segs[R_FS],
3923 env->segs[R_GS]);
3924 if (flags & X86_DUMP_CCOP) {
3925 if ((unsigned)env->cc_op < CC_OP_NB)
3926 strcpy(cc_op_name, cc_op_str[env->cc_op]);
3927 else
3928 snprintf(cc_op_name, sizeof(cc_op_name), "[%d]", env->cc_op);
3929 fprintf(f, "CCS=%08x CCD=%08x CCO=%-8s\n",
3930 env->cc_src, env->cc_dst, cc_op_name);
3931 }
3932 if (flags & X86_DUMP_FPU) {
3933 fprintf(f, "ST0=%f ST1=%f ST2=%f ST3=%f\n",
3934 (double)env->fpregs[0],
3935 (double)env->fpregs[1],
3936 (double)env->fpregs[2],
3937 (double)env->fpregs[3]);
3938 fprintf(f, "ST4=%f ST5=%f ST6=%f ST7=%f\n",
3939 (double)env->fpregs[4],
3940 (double)env->fpregs[5],
3941 (double)env->fpregs[7],
3942 (double)env->fpregs[8]);
3943 }
3944 }