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