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