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