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