]> git.proxmox.com Git - qemu.git/blob - translate-i386.c
added minimal segment support
[qemu.git] / translate-i386.c
1 /*
2 * i386 translation
3 *
4 * Copyright (c) 2003 Fabrice Bellard
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program 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
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20 #include <stdarg.h>
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <inttypes.h>
25 #include <assert.h>
26
27 #define DEBUG_DISAS
28
29 #define IN_OP_I386
30 #include "cpu-i386.h"
31
32 /* dump all code */
33 #ifdef DEBUG_DISAS
34 #include "dis-asm.h"
35 #endif
36
37 #ifndef offsetof
38 #define offsetof(type, field) ((size_t) &((type *)0)->field)
39 #endif
40
41 static uint8_t *gen_code_ptr;
42 int __op_param1, __op_param2, __op_param3;
43
44 extern FILE *logfile;
45 extern int loglevel;
46
47 /* supress that */
48 static void error(const char *fmt, ...)
49 {
50 va_list ap;
51
52 va_start(ap, fmt);
53 fprintf(stderr, "\n");
54 vfprintf(stderr, fmt, ap);
55 fprintf(stderr, "\n");
56 va_end(ap);
57 exit(1);
58 }
59
60 #define PREFIX_REPZ 1
61 #define PREFIX_REPNZ 2
62 #define PREFIX_LOCK 4
63 #define PREFIX_CS 8
64 #define PREFIX_SS 0x10
65 #define PREFIX_DS 0x20
66 #define PREFIX_ES 0x40
67 #define PREFIX_FS 0x80
68 #define PREFIX_GS 0x100
69 #define PREFIX_DATA 0x200
70 #define PREFIX_ADR 0x400
71 #define PREFIX_FWAIT 0x800
72
73 typedef struct DisasContext {
74 /* current insn context */
75 int prefix;
76 int aflag, dflag;
77 uint8_t *pc; /* current pc */
78 int is_jmp; /* 1 = means jump (stop translation), 2 means CPU
79 static state change (stop translation) */
80 /* current block context */
81 int code32; /* 32 bit code segment */
82 int cc_op; /* current CC operation */
83 int addseg; /* non zero if either DS/ES/SS have a non zero base */
84 int f_st; /* currently unused */
85 } DisasContext;
86
87 /* i386 arith/logic operations */
88 enum {
89 OP_ADDL,
90 OP_ORL,
91 OP_ADCL,
92 OP_SBBL,
93 OP_ANDL,
94 OP_SUBL,
95 OP_XORL,
96 OP_CMPL,
97 };
98
99 /* i386 shift ops */
100 enum {
101 OP_ROL,
102 OP_ROR,
103 OP_RCL,
104 OP_RCR,
105 OP_SHL,
106 OP_SHR,
107 OP_SHL1, /* undocumented */
108 OP_SAR = 7,
109 };
110
111 #include "op-i386.h"
112
113 /* operand size */
114 enum {
115 OT_BYTE = 0,
116 OT_WORD,
117 OT_LONG,
118 OT_QUAD,
119 };
120
121 enum {
122 /* I386 int registers */
123 OR_EAX, /* MUST be even numbered */
124 OR_ECX,
125 OR_EDX,
126 OR_EBX,
127 OR_ESP,
128 OR_EBP,
129 OR_ESI,
130 OR_EDI,
131 OR_TMP0, /* temporary operand register */
132 OR_TMP1,
133 OR_A0, /* temporary register used when doing address evaluation */
134 OR_ZERO, /* fixed zero register */
135 NB_OREGS,
136 };
137
138 typedef void (GenOpFunc)(void);
139 typedef void (GenOpFunc1)(long);
140 typedef void (GenOpFunc2)(long, long);
141
142 static GenOpFunc *gen_op_mov_reg_T0[3][8] = {
143 [OT_BYTE] = {
144 gen_op_movb_EAX_T0,
145 gen_op_movb_ECX_T0,
146 gen_op_movb_EDX_T0,
147 gen_op_movb_EBX_T0,
148 gen_op_movh_EAX_T0,
149 gen_op_movh_ECX_T0,
150 gen_op_movh_EDX_T0,
151 gen_op_movh_EBX_T0,
152 },
153 [OT_WORD] = {
154 gen_op_movw_EAX_T0,
155 gen_op_movw_ECX_T0,
156 gen_op_movw_EDX_T0,
157 gen_op_movw_EBX_T0,
158 gen_op_movw_ESP_T0,
159 gen_op_movw_EBP_T0,
160 gen_op_movw_ESI_T0,
161 gen_op_movw_EDI_T0,
162 },
163 [OT_LONG] = {
164 gen_op_movl_EAX_T0,
165 gen_op_movl_ECX_T0,
166 gen_op_movl_EDX_T0,
167 gen_op_movl_EBX_T0,
168 gen_op_movl_ESP_T0,
169 gen_op_movl_EBP_T0,
170 gen_op_movl_ESI_T0,
171 gen_op_movl_EDI_T0,
172 },
173 };
174
175 static GenOpFunc *gen_op_mov_reg_T1[3][8] = {
176 [OT_BYTE] = {
177 gen_op_movb_EAX_T1,
178 gen_op_movb_ECX_T1,
179 gen_op_movb_EDX_T1,
180 gen_op_movb_EBX_T1,
181 gen_op_movh_EAX_T1,
182 gen_op_movh_ECX_T1,
183 gen_op_movh_EDX_T1,
184 gen_op_movh_EBX_T1,
185 },
186 [OT_WORD] = {
187 gen_op_movw_EAX_T1,
188 gen_op_movw_ECX_T1,
189 gen_op_movw_EDX_T1,
190 gen_op_movw_EBX_T1,
191 gen_op_movw_ESP_T1,
192 gen_op_movw_EBP_T1,
193 gen_op_movw_ESI_T1,
194 gen_op_movw_EDI_T1,
195 },
196 [OT_LONG] = {
197 gen_op_movl_EAX_T1,
198 gen_op_movl_ECX_T1,
199 gen_op_movl_EDX_T1,
200 gen_op_movl_EBX_T1,
201 gen_op_movl_ESP_T1,
202 gen_op_movl_EBP_T1,
203 gen_op_movl_ESI_T1,
204 gen_op_movl_EDI_T1,
205 },
206 };
207
208 static GenOpFunc *gen_op_mov_reg_A0[2][8] = {
209 [0] = {
210 gen_op_movw_EAX_A0,
211 gen_op_movw_ECX_A0,
212 gen_op_movw_EDX_A0,
213 gen_op_movw_EBX_A0,
214 gen_op_movw_ESP_A0,
215 gen_op_movw_EBP_A0,
216 gen_op_movw_ESI_A0,
217 gen_op_movw_EDI_A0,
218 },
219 [1] = {
220 gen_op_movl_EAX_A0,
221 gen_op_movl_ECX_A0,
222 gen_op_movl_EDX_A0,
223 gen_op_movl_EBX_A0,
224 gen_op_movl_ESP_A0,
225 gen_op_movl_EBP_A0,
226 gen_op_movl_ESI_A0,
227 gen_op_movl_EDI_A0,
228 },
229 };
230
231 static GenOpFunc *gen_op_mov_TN_reg[3][2][8] =
232 {
233 [OT_BYTE] = {
234 {
235 gen_op_movl_T0_EAX,
236 gen_op_movl_T0_ECX,
237 gen_op_movl_T0_EDX,
238 gen_op_movl_T0_EBX,
239 gen_op_movh_T0_EAX,
240 gen_op_movh_T0_ECX,
241 gen_op_movh_T0_EDX,
242 gen_op_movh_T0_EBX,
243 },
244 {
245 gen_op_movl_T1_EAX,
246 gen_op_movl_T1_ECX,
247 gen_op_movl_T1_EDX,
248 gen_op_movl_T1_EBX,
249 gen_op_movh_T1_EAX,
250 gen_op_movh_T1_ECX,
251 gen_op_movh_T1_EDX,
252 gen_op_movh_T1_EBX,
253 },
254 },
255 [OT_WORD] = {
256 {
257 gen_op_movl_T0_EAX,
258 gen_op_movl_T0_ECX,
259 gen_op_movl_T0_EDX,
260 gen_op_movl_T0_EBX,
261 gen_op_movl_T0_ESP,
262 gen_op_movl_T0_EBP,
263 gen_op_movl_T0_ESI,
264 gen_op_movl_T0_EDI,
265 },
266 {
267 gen_op_movl_T1_EAX,
268 gen_op_movl_T1_ECX,
269 gen_op_movl_T1_EDX,
270 gen_op_movl_T1_EBX,
271 gen_op_movl_T1_ESP,
272 gen_op_movl_T1_EBP,
273 gen_op_movl_T1_ESI,
274 gen_op_movl_T1_EDI,
275 },
276 },
277 [OT_LONG] = {
278 {
279 gen_op_movl_T0_EAX,
280 gen_op_movl_T0_ECX,
281 gen_op_movl_T0_EDX,
282 gen_op_movl_T0_EBX,
283 gen_op_movl_T0_ESP,
284 gen_op_movl_T0_EBP,
285 gen_op_movl_T0_ESI,
286 gen_op_movl_T0_EDI,
287 },
288 {
289 gen_op_movl_T1_EAX,
290 gen_op_movl_T1_ECX,
291 gen_op_movl_T1_EDX,
292 gen_op_movl_T1_EBX,
293 gen_op_movl_T1_ESP,
294 gen_op_movl_T1_EBP,
295 gen_op_movl_T1_ESI,
296 gen_op_movl_T1_EDI,
297 },
298 },
299 };
300
301 static GenOpFunc *gen_op_movl_A0_reg[8] = {
302 gen_op_movl_A0_EAX,
303 gen_op_movl_A0_ECX,
304 gen_op_movl_A0_EDX,
305 gen_op_movl_A0_EBX,
306 gen_op_movl_A0_ESP,
307 gen_op_movl_A0_EBP,
308 gen_op_movl_A0_ESI,
309 gen_op_movl_A0_EDI,
310 };
311
312 static GenOpFunc *gen_op_addl_A0_reg_sN[4][8] = {
313 [0] = {
314 gen_op_addl_A0_EAX,
315 gen_op_addl_A0_ECX,
316 gen_op_addl_A0_EDX,
317 gen_op_addl_A0_EBX,
318 gen_op_addl_A0_ESP,
319 gen_op_addl_A0_EBP,
320 gen_op_addl_A0_ESI,
321 gen_op_addl_A0_EDI,
322 },
323 [1] = {
324 gen_op_addl_A0_EAX_s1,
325 gen_op_addl_A0_ECX_s1,
326 gen_op_addl_A0_EDX_s1,
327 gen_op_addl_A0_EBX_s1,
328 gen_op_addl_A0_ESP_s1,
329 gen_op_addl_A0_EBP_s1,
330 gen_op_addl_A0_ESI_s1,
331 gen_op_addl_A0_EDI_s1,
332 },
333 [2] = {
334 gen_op_addl_A0_EAX_s2,
335 gen_op_addl_A0_ECX_s2,
336 gen_op_addl_A0_EDX_s2,
337 gen_op_addl_A0_EBX_s2,
338 gen_op_addl_A0_ESP_s2,
339 gen_op_addl_A0_EBP_s2,
340 gen_op_addl_A0_ESI_s2,
341 gen_op_addl_A0_EDI_s2,
342 },
343 [3] = {
344 gen_op_addl_A0_EAX_s3,
345 gen_op_addl_A0_ECX_s3,
346 gen_op_addl_A0_EDX_s3,
347 gen_op_addl_A0_EBX_s3,
348 gen_op_addl_A0_ESP_s3,
349 gen_op_addl_A0_EBP_s3,
350 gen_op_addl_A0_ESI_s3,
351 gen_op_addl_A0_EDI_s3,
352 },
353 };
354
355 static GenOpFunc *gen_op_arith_T0_T1_cc[8] = {
356 gen_op_addl_T0_T1_cc,
357 gen_op_orl_T0_T1_cc,
358 NULL,
359 NULL,
360 gen_op_andl_T0_T1_cc,
361 gen_op_subl_T0_T1_cc,
362 gen_op_xorl_T0_T1_cc,
363 gen_op_cmpl_T0_T1_cc,
364 };
365
366 static GenOpFunc *gen_op_arithc_T0_T1_cc[3][2] = {
367 [OT_BYTE] = {
368 gen_op_adcb_T0_T1_cc,
369 gen_op_sbbb_T0_T1_cc,
370 },
371 [OT_WORD] = {
372 gen_op_adcw_T0_T1_cc,
373 gen_op_sbbw_T0_T1_cc,
374 },
375 [OT_LONG] = {
376 gen_op_adcl_T0_T1_cc,
377 gen_op_sbbl_T0_T1_cc,
378 },
379 };
380
381 static const int cc_op_arithb[8] = {
382 CC_OP_ADDB,
383 CC_OP_LOGICB,
384 CC_OP_ADDB,
385 CC_OP_SUBB,
386 CC_OP_LOGICB,
387 CC_OP_SUBB,
388 CC_OP_LOGICB,
389 CC_OP_SUBB,
390 };
391
392 static GenOpFunc *gen_op_shift_T0_T1_cc[3][8] = {
393 [OT_BYTE] = {
394 gen_op_rolb_T0_T1_cc,
395 gen_op_rorb_T0_T1_cc,
396 gen_op_rclb_T0_T1_cc,
397 gen_op_rcrb_T0_T1_cc,
398 gen_op_shlb_T0_T1_cc,
399 gen_op_shrb_T0_T1_cc,
400 gen_op_shlb_T0_T1_cc,
401 gen_op_sarb_T0_T1_cc,
402 },
403 [OT_WORD] = {
404 gen_op_rolw_T0_T1_cc,
405 gen_op_rorw_T0_T1_cc,
406 gen_op_rclw_T0_T1_cc,
407 gen_op_rcrw_T0_T1_cc,
408 gen_op_shlw_T0_T1_cc,
409 gen_op_shrw_T0_T1_cc,
410 gen_op_shlw_T0_T1_cc,
411 gen_op_sarw_T0_T1_cc,
412 },
413 [OT_LONG] = {
414 gen_op_roll_T0_T1_cc,
415 gen_op_rorl_T0_T1_cc,
416 gen_op_rcll_T0_T1_cc,
417 gen_op_rcrl_T0_T1_cc,
418 gen_op_shll_T0_T1_cc,
419 gen_op_shrl_T0_T1_cc,
420 gen_op_shll_T0_T1_cc,
421 gen_op_sarl_T0_T1_cc,
422 },
423 };
424
425 static GenOpFunc1 *gen_op_shiftd_T0_T1_im_cc[2][2] = {
426 [0] = {
427 gen_op_shldw_T0_T1_im_cc,
428 gen_op_shrdw_T0_T1_im_cc,
429 },
430 [1] = {
431 gen_op_shldl_T0_T1_im_cc,
432 gen_op_shrdl_T0_T1_im_cc,
433 },
434 };
435
436 static GenOpFunc *gen_op_shiftd_T0_T1_ECX_cc[2][2] = {
437 [0] = {
438 gen_op_shldw_T0_T1_ECX_cc,
439 gen_op_shrdw_T0_T1_ECX_cc,
440 },
441 [1] = {
442 gen_op_shldl_T0_T1_ECX_cc,
443 gen_op_shrdl_T0_T1_ECX_cc,
444 },
445 };
446
447 static GenOpFunc *gen_op_btx_T0_T1_cc[2][4] = {
448 [0] = {
449 gen_op_btw_T0_T1_cc,
450 gen_op_btsw_T0_T1_cc,
451 gen_op_btrw_T0_T1_cc,
452 gen_op_btcw_T0_T1_cc,
453 },
454 [1] = {
455 gen_op_btl_T0_T1_cc,
456 gen_op_btsl_T0_T1_cc,
457 gen_op_btrl_T0_T1_cc,
458 gen_op_btcl_T0_T1_cc,
459 },
460 };
461
462 static GenOpFunc *gen_op_bsx_T0_cc[2][2] = {
463 [0] = {
464 gen_op_bsfw_T0_cc,
465 gen_op_bsrw_T0_cc,
466 },
467 [1] = {
468 gen_op_bsfl_T0_cc,
469 gen_op_bsrl_T0_cc,
470 },
471 };
472
473 static GenOpFunc *gen_op_lds_T0_A0[3] = {
474 gen_op_ldsb_T0_A0,
475 gen_op_ldsw_T0_A0,
476 };
477
478 static GenOpFunc *gen_op_ldu_T0_A0[3] = {
479 gen_op_ldub_T0_A0,
480 gen_op_lduw_T0_A0,
481 };
482
483 /* sign does not matter */
484 static GenOpFunc *gen_op_ld_T0_A0[3] = {
485 gen_op_ldub_T0_A0,
486 gen_op_lduw_T0_A0,
487 gen_op_ldl_T0_A0,
488 };
489
490 static GenOpFunc *gen_op_ld_T1_A0[3] = {
491 gen_op_ldub_T1_A0,
492 gen_op_lduw_T1_A0,
493 gen_op_ldl_T1_A0,
494 };
495
496 static GenOpFunc *gen_op_st_T0_A0[3] = {
497 gen_op_stb_T0_A0,
498 gen_op_stw_T0_A0,
499 gen_op_stl_T0_A0,
500 };
501
502 static GenOpFunc *gen_op_movs[6] = {
503 gen_op_movsb,
504 gen_op_movsw,
505 gen_op_movsl,
506 gen_op_rep_movsb,
507 gen_op_rep_movsw,
508 gen_op_rep_movsl,
509 };
510
511 static GenOpFunc *gen_op_stos[6] = {
512 gen_op_stosb,
513 gen_op_stosw,
514 gen_op_stosl,
515 gen_op_rep_stosb,
516 gen_op_rep_stosw,
517 gen_op_rep_stosl,
518 };
519
520 static GenOpFunc *gen_op_lods[6] = {
521 gen_op_lodsb,
522 gen_op_lodsw,
523 gen_op_lodsl,
524 gen_op_rep_lodsb,
525 gen_op_rep_lodsw,
526 gen_op_rep_lodsl,
527 };
528
529 static GenOpFunc *gen_op_scas[9] = {
530 gen_op_scasb,
531 gen_op_scasw,
532 gen_op_scasl,
533 gen_op_repz_scasb,
534 gen_op_repz_scasw,
535 gen_op_repz_scasl,
536 gen_op_repnz_scasb,
537 gen_op_repnz_scasw,
538 gen_op_repnz_scasl,
539 };
540
541 static GenOpFunc *gen_op_cmps[9] = {
542 gen_op_cmpsb,
543 gen_op_cmpsw,
544 gen_op_cmpsl,
545 gen_op_repz_cmpsb,
546 gen_op_repz_cmpsw,
547 gen_op_repz_cmpsl,
548 gen_op_repnz_cmpsb,
549 gen_op_repnz_cmpsw,
550 gen_op_repnz_cmpsl,
551 };
552
553 static GenOpFunc *gen_op_ins[6] = {
554 gen_op_insb,
555 gen_op_insw,
556 gen_op_insl,
557 gen_op_rep_insb,
558 gen_op_rep_insw,
559 gen_op_rep_insl,
560 };
561
562
563 static GenOpFunc *gen_op_outs[6] = {
564 gen_op_outsb,
565 gen_op_outsw,
566 gen_op_outsl,
567 gen_op_rep_outsb,
568 gen_op_rep_outsw,
569 gen_op_rep_outsl,
570 };
571
572 static GenOpFunc *gen_op_in[3] = {
573 gen_op_inb_T0_T1,
574 gen_op_inw_T0_T1,
575 gen_op_inl_T0_T1,
576 };
577
578 static GenOpFunc *gen_op_out[3] = {
579 gen_op_outb_T0_T1,
580 gen_op_outw_T0_T1,
581 gen_op_outl_T0_T1,
582 };
583
584 enum {
585 JCC_O,
586 JCC_B,
587 JCC_Z,
588 JCC_BE,
589 JCC_S,
590 JCC_P,
591 JCC_L,
592 JCC_LE,
593 };
594
595 static GenOpFunc2 *gen_jcc_slow[8] = {
596 gen_op_jo_cc,
597 gen_op_jb_cc,
598 gen_op_jz_cc,
599 gen_op_jbe_cc,
600 gen_op_js_cc,
601 gen_op_jp_cc,
602 gen_op_jl_cc,
603 gen_op_jle_cc,
604 };
605
606 static GenOpFunc2 *gen_jcc_sub[3][8] = {
607 [OT_BYTE] = {
608 NULL,
609 gen_op_jb_subb,
610 gen_op_jz_subb,
611 gen_op_jbe_subb,
612 gen_op_js_subb,
613 NULL,
614 gen_op_jl_subb,
615 gen_op_jle_subb,
616 },
617 [OT_WORD] = {
618 NULL,
619 gen_op_jb_subw,
620 gen_op_jz_subw,
621 gen_op_jbe_subw,
622 gen_op_js_subw,
623 NULL,
624 gen_op_jl_subw,
625 gen_op_jle_subw,
626 },
627 [OT_LONG] = {
628 NULL,
629 gen_op_jb_subl,
630 gen_op_jz_subl,
631 gen_op_jbe_subl,
632 gen_op_js_subl,
633 NULL,
634 gen_op_jl_subl,
635 gen_op_jle_subl,
636 },
637 };
638
639 static GenOpFunc *gen_setcc_slow[8] = {
640 gen_op_seto_T0_cc,
641 gen_op_setb_T0_cc,
642 gen_op_setz_T0_cc,
643 gen_op_setbe_T0_cc,
644 gen_op_sets_T0_cc,
645 gen_op_setp_T0_cc,
646 gen_op_setl_T0_cc,
647 gen_op_setle_T0_cc,
648 };
649
650 static GenOpFunc *gen_setcc_sub[3][8] = {
651 [OT_BYTE] = {
652 NULL,
653 gen_op_setb_T0_subb,
654 gen_op_setz_T0_subb,
655 gen_op_setbe_T0_subb,
656 gen_op_sets_T0_subb,
657 NULL,
658 gen_op_setl_T0_subb,
659 gen_op_setle_T0_subb,
660 },
661 [OT_WORD] = {
662 NULL,
663 gen_op_setb_T0_subw,
664 gen_op_setz_T0_subw,
665 gen_op_setbe_T0_subw,
666 gen_op_sets_T0_subw,
667 NULL,
668 gen_op_setl_T0_subw,
669 gen_op_setle_T0_subw,
670 },
671 [OT_LONG] = {
672 NULL,
673 gen_op_setb_T0_subl,
674 gen_op_setz_T0_subl,
675 gen_op_setbe_T0_subl,
676 gen_op_sets_T0_subl,
677 NULL,
678 gen_op_setl_T0_subl,
679 gen_op_setle_T0_subl,
680 },
681 };
682
683 static GenOpFunc *gen_op_fp_arith_ST0_FT0[8] = {
684 gen_op_fadd_ST0_FT0,
685 gen_op_fmul_ST0_FT0,
686 gen_op_fcom_ST0_FT0,
687 gen_op_fcom_ST0_FT0,
688 gen_op_fsub_ST0_FT0,
689 gen_op_fsubr_ST0_FT0,
690 gen_op_fdiv_ST0_FT0,
691 gen_op_fdivr_ST0_FT0,
692 };
693
694 /* NOTE the exception in "r" op ordering */
695 static GenOpFunc1 *gen_op_fp_arith_STN_ST0[8] = {
696 gen_op_fadd_STN_ST0,
697 gen_op_fmul_STN_ST0,
698 NULL,
699 NULL,
700 gen_op_fsubr_STN_ST0,
701 gen_op_fsub_STN_ST0,
702 gen_op_fdivr_STN_ST0,
703 gen_op_fdiv_STN_ST0,
704 };
705
706 static void gen_op(DisasContext *s1, int op, int ot, int d, int s)
707 {
708 if (d != OR_TMP0)
709 gen_op_mov_TN_reg[ot][0][d]();
710 if (s != OR_TMP1)
711 gen_op_mov_TN_reg[ot][1][s]();
712 if (op == OP_ADCL || op == OP_SBBL) {
713 if (s1->cc_op != CC_OP_DYNAMIC)
714 gen_op_set_cc_op(s1->cc_op);
715 gen_op_arithc_T0_T1_cc[ot][op - OP_ADCL]();
716 s1->cc_op = CC_OP_DYNAMIC;
717 } else {
718 gen_op_arith_T0_T1_cc[op]();
719 s1->cc_op = cc_op_arithb[op] + ot;
720 }
721 if (d != OR_TMP0 && op != OP_CMPL)
722 gen_op_mov_reg_T0[ot][d]();
723 }
724
725 static void gen_opi(DisasContext *s1, int op, int ot, int d, int c)
726 {
727 gen_op_movl_T1_im(c);
728 gen_op(s1, op, ot, d, OR_TMP1);
729 }
730
731 static void gen_inc(DisasContext *s1, int ot, int d, int c)
732 {
733 if (d != OR_TMP0)
734 gen_op_mov_TN_reg[ot][0][d]();
735 if (s1->cc_op != CC_OP_DYNAMIC)
736 gen_op_set_cc_op(s1->cc_op);
737 if (c > 0) {
738 gen_op_incl_T0_cc();
739 s1->cc_op = CC_OP_INCB + ot;
740 } else {
741 gen_op_decl_T0_cc();
742 s1->cc_op = CC_OP_DECB + ot;
743 }
744 if (d != OR_TMP0)
745 gen_op_mov_reg_T0[ot][d]();
746 }
747
748 static void gen_shift(DisasContext *s1, int op, int ot, int d, int s)
749 {
750 if (d != OR_TMP0)
751 gen_op_mov_TN_reg[ot][0][d]();
752 if (s != OR_TMP1)
753 gen_op_mov_TN_reg[ot][1][s]();
754 /* for zero counts, flags are not updated, so must do it dynamically */
755 if (s1->cc_op != CC_OP_DYNAMIC)
756 gen_op_set_cc_op(s1->cc_op);
757
758 gen_op_shift_T0_T1_cc[ot][op]();
759
760 if (d != OR_TMP0)
761 gen_op_mov_reg_T0[ot][d]();
762 s1->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
763 }
764
765 static void gen_shifti(DisasContext *s1, int op, int ot, int d, int c)
766 {
767 /* currently not optimized */
768 gen_op_movl_T1_im(c);
769 gen_shift(s1, op, ot, d, OR_TMP1);
770 }
771
772 static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ptr)
773 {
774 int havesib;
775 int base, disp;
776 int index;
777 int scale;
778 int opreg;
779 int mod, rm, code, override, must_add_seg;
780
781 /* XXX: add a generation time variable to tell if base == 0 in DS/ES/SS */
782 /* XXX: fix lea case */
783 override = -1;
784 must_add_seg = s->addseg;
785 if (s->prefix & (PREFIX_CS | PREFIX_SS | PREFIX_DS |
786 PREFIX_ES | PREFIX_FS | PREFIX_GS)) {
787 if (s->prefix & PREFIX_ES)
788 override = R_ES;
789 else if (s->prefix & PREFIX_CS)
790 override = R_CS;
791 else if (s->prefix & PREFIX_SS)
792 override = R_SS;
793 else if (s->prefix & PREFIX_DS)
794 override = R_DS;
795 else if (s->prefix & PREFIX_FS)
796 override = R_FS;
797 else
798 override = R_GS;
799 must_add_seg = 1;
800 }
801
802 mod = (modrm >> 6) & 3;
803 rm = modrm & 7;
804
805 if (s->aflag) {
806
807 havesib = 0;
808 base = rm;
809 index = 0;
810 scale = 0;
811
812 if (base == 4) {
813 havesib = 1;
814 code = ldub(s->pc++);
815 scale = (code >> 6) & 3;
816 index = (code >> 3) & 7;
817 base = code & 7;
818 }
819
820 switch (mod) {
821 case 0:
822 if (base == 5) {
823 base = -1;
824 disp = ldl(s->pc);
825 s->pc += 4;
826 } else {
827 disp = 0;
828 }
829 break;
830 case 1:
831 disp = (int8_t)ldub(s->pc++);
832 break;
833 default:
834 case 2:
835 disp = ldl(s->pc);
836 s->pc += 4;
837 break;
838 }
839
840 if (base >= 0) {
841 gen_op_movl_A0_reg[base]();
842 if (disp != 0)
843 gen_op_addl_A0_im(disp);
844 } else {
845 gen_op_movl_A0_im(disp);
846 }
847 if (havesib && (index != 4 || scale != 0)) {
848 gen_op_addl_A0_reg_sN[scale][index]();
849 }
850 if (must_add_seg) {
851 if (override < 0) {
852 if (base == R_EBP || base == R_ESP)
853 override = R_SS;
854 else
855 override = R_DS;
856 }
857 gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[override].base));
858 }
859 } else {
860 switch (mod) {
861 case 0:
862 if (rm == 6) {
863 disp = lduw(s->pc);
864 s->pc += 2;
865 gen_op_movl_A0_im(disp);
866 rm = 0; /* avoid SS override */
867 goto no_rm;
868 } else {
869 disp = 0;
870 }
871 break;
872 case 1:
873 disp = (int8_t)ldub(s->pc++);
874 break;
875 default:
876 case 2:
877 disp = lduw(s->pc);
878 s->pc += 2;
879 break;
880 }
881 switch(rm) {
882 case 0:
883 gen_op_movl_A0_reg[R_EBX]();
884 gen_op_addl_A0_reg_sN[0][R_ESI]();
885 break;
886 case 1:
887 gen_op_movl_A0_reg[R_EBX]();
888 gen_op_addl_A0_reg_sN[0][R_EDI]();
889 break;
890 case 2:
891 gen_op_movl_A0_reg[R_EBP]();
892 gen_op_addl_A0_reg_sN[0][R_ESI]();
893 break;
894 case 3:
895 gen_op_movl_A0_reg[R_EBP]();
896 gen_op_addl_A0_reg_sN[0][R_EDI]();
897 break;
898 case 4:
899 gen_op_movl_A0_reg[R_ESI]();
900 break;
901 case 5:
902 gen_op_movl_A0_reg[R_EDI]();
903 break;
904 case 6:
905 gen_op_movl_A0_reg[R_EBP]();
906 break;
907 default:
908 case 7:
909 gen_op_movl_A0_reg[R_EBX]();
910 break;
911 }
912 if (disp != 0)
913 gen_op_addl_A0_im(disp);
914 gen_op_andl_A0_ffff();
915 no_rm:
916 if (must_add_seg) {
917 if (override < 0) {
918 if (rm == 2 || rm == 3 || rm == 6)
919 override = R_SS;
920 else
921 override = R_DS;
922 }
923 gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[override].base));
924 }
925 }
926
927 opreg = OR_A0;
928 disp = 0;
929 *reg_ptr = opreg;
930 *offset_ptr = disp;
931 }
932
933 /* generate modrm memory load or store of 'reg'. TMP0 is used if reg !=
934 OR_TMP0 */
935 static void gen_ldst_modrm(DisasContext *s, int modrm, int ot, int reg, int is_store)
936 {
937 int mod, rm, opreg, disp;
938
939 mod = (modrm >> 6) & 3;
940 rm = modrm & 7;
941 if (mod == 3) {
942 if (is_store) {
943 if (reg != OR_TMP0)
944 gen_op_mov_TN_reg[ot][0][reg]();
945 gen_op_mov_reg_T0[ot][rm]();
946 } else {
947 gen_op_mov_TN_reg[ot][0][rm]();
948 if (reg != OR_TMP0)
949 gen_op_mov_reg_T0[ot][reg]();
950 }
951 } else {
952 gen_lea_modrm(s, modrm, &opreg, &disp);
953 if (is_store) {
954 if (reg != OR_TMP0)
955 gen_op_mov_TN_reg[ot][0][reg]();
956 gen_op_st_T0_A0[ot]();
957 } else {
958 gen_op_ld_T0_A0[ot]();
959 if (reg != OR_TMP0)
960 gen_op_mov_reg_T0[ot][reg]();
961 }
962 }
963 }
964
965 static inline uint32_t insn_get(DisasContext *s, int ot)
966 {
967 uint32_t ret;
968
969 switch(ot) {
970 case OT_BYTE:
971 ret = ldub(s->pc);
972 s->pc++;
973 break;
974 case OT_WORD:
975 ret = lduw(s->pc);
976 s->pc += 2;
977 break;
978 default:
979 case OT_LONG:
980 ret = ldl(s->pc);
981 s->pc += 4;
982 break;
983 }
984 return ret;
985 }
986
987 static void gen_jcc(DisasContext *s, int b, int val)
988 {
989 int inv, jcc_op;
990 GenOpFunc2 *func;
991
992 inv = b & 1;
993 jcc_op = (b >> 1) & 7;
994 switch(s->cc_op) {
995 /* we optimize the cmp/jcc case */
996 case CC_OP_SUBB:
997 case CC_OP_SUBW:
998 case CC_OP_SUBL:
999 func = gen_jcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
1000 if (!func)
1001 goto slow_jcc;
1002 break;
1003
1004 /* some jumps are easy to compute */
1005 case CC_OP_ADDB:
1006 case CC_OP_ADDW:
1007 case CC_OP_ADDL:
1008 case CC_OP_ADCB:
1009 case CC_OP_ADCW:
1010 case CC_OP_ADCL:
1011 case CC_OP_SBBB:
1012 case CC_OP_SBBW:
1013 case CC_OP_SBBL:
1014 case CC_OP_LOGICB:
1015 case CC_OP_LOGICW:
1016 case CC_OP_LOGICL:
1017 case CC_OP_INCB:
1018 case CC_OP_INCW:
1019 case CC_OP_INCL:
1020 case CC_OP_DECB:
1021 case CC_OP_DECW:
1022 case CC_OP_DECL:
1023 case CC_OP_SHLB:
1024 case CC_OP_SHLW:
1025 case CC_OP_SHLL:
1026 case CC_OP_SARB:
1027 case CC_OP_SARW:
1028 case CC_OP_SARL:
1029 switch(jcc_op) {
1030 case JCC_Z:
1031 func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1032 break;
1033 case JCC_S:
1034 func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1035 break;
1036 default:
1037 goto slow_jcc;
1038 }
1039 break;
1040 default:
1041 slow_jcc:
1042 if (s->cc_op != CC_OP_DYNAMIC)
1043 gen_op_set_cc_op(s->cc_op);
1044 func = gen_jcc_slow[jcc_op];
1045 break;
1046 }
1047 if (!inv) {
1048 func(val, (long)s->pc);
1049 } else {
1050 func((long)s->pc, val);
1051 }
1052 }
1053
1054 static void gen_setcc(DisasContext *s, int b)
1055 {
1056 int inv, jcc_op;
1057 GenOpFunc *func;
1058
1059 inv = b & 1;
1060 jcc_op = (b >> 1) & 7;
1061 switch(s->cc_op) {
1062 /* we optimize the cmp/jcc case */
1063 case CC_OP_SUBB:
1064 case CC_OP_SUBW:
1065 case CC_OP_SUBL:
1066 func = gen_setcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
1067 if (!func)
1068 goto slow_jcc;
1069 break;
1070
1071 /* some jumps are easy to compute */
1072 case CC_OP_ADDB:
1073 case CC_OP_ADDW:
1074 case CC_OP_ADDL:
1075 case CC_OP_LOGICB:
1076 case CC_OP_LOGICW:
1077 case CC_OP_LOGICL:
1078 case CC_OP_INCB:
1079 case CC_OP_INCW:
1080 case CC_OP_INCL:
1081 case CC_OP_DECB:
1082 case CC_OP_DECW:
1083 case CC_OP_DECL:
1084 case CC_OP_SHLB:
1085 case CC_OP_SHLW:
1086 case CC_OP_SHLL:
1087 switch(jcc_op) {
1088 case JCC_Z:
1089 func = gen_setcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1090 break;
1091 case JCC_S:
1092 func = gen_setcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1093 break;
1094 default:
1095 goto slow_jcc;
1096 }
1097 break;
1098 default:
1099 slow_jcc:
1100 if (s->cc_op != CC_OP_DYNAMIC)
1101 gen_op_set_cc_op(s->cc_op);
1102 func = gen_setcc_slow[jcc_op];
1103 break;
1104 }
1105 func();
1106 if (inv) {
1107 gen_op_xor_T0_1();
1108 }
1109 }
1110
1111 /* move T0 to seg_reg and compute if the CPU state may change */
1112 void gen_movl_seg_T0(DisasContext *s, int seg_reg)
1113 {
1114 gen_op_movl_seg_T0(seg_reg);
1115 if (!s->addseg && seg_reg < R_FS)
1116 s->is_jmp = 2; /* abort translation because the register may
1117 have a non zero base */
1118 }
1119
1120 /* return the next pc address. Return -1 if no insn found. *is_jmp_ptr
1121 is set to true if the instruction sets the PC (last instruction of
1122 a basic block) */
1123 long disas_insn(DisasContext *s, uint8_t *pc_start)
1124 {
1125 int b, prefixes, aflag, dflag;
1126 int shift, ot;
1127 int modrm, reg, rm, mod, reg_addr, op, opreg, offset_addr, val;
1128
1129 s->pc = pc_start;
1130 prefixes = 0;
1131 aflag = s->code32;
1132 dflag = s->code32;
1133 // cur_pc = s->pc; /* for insn generation */
1134 next_byte:
1135 b = ldub(s->pc);
1136 s->pc++;
1137 /* check prefixes */
1138 switch (b) {
1139 case 0xf3:
1140 prefixes |= PREFIX_REPZ;
1141 goto next_byte;
1142 case 0xf2:
1143 prefixes |= PREFIX_REPNZ;
1144 goto next_byte;
1145 case 0xf0:
1146 prefixes |= PREFIX_LOCK;
1147 goto next_byte;
1148 case 0x2e:
1149 prefixes |= PREFIX_CS;
1150 goto next_byte;
1151 case 0x36:
1152 prefixes |= PREFIX_SS;
1153 goto next_byte;
1154 case 0x3e:
1155 prefixes |= PREFIX_DS;
1156 goto next_byte;
1157 case 0x26:
1158 prefixes |= PREFIX_ES;
1159 goto next_byte;
1160 case 0x64:
1161 prefixes |= PREFIX_FS;
1162 goto next_byte;
1163 case 0x65:
1164 prefixes |= PREFIX_GS;
1165 goto next_byte;
1166 case 0x66:
1167 prefixes |= PREFIX_DATA;
1168 goto next_byte;
1169 case 0x67:
1170 prefixes |= PREFIX_ADR;
1171 goto next_byte;
1172 case 0x9b:
1173 prefixes |= PREFIX_FWAIT;
1174 goto next_byte;
1175 }
1176
1177 if (prefixes & PREFIX_DATA)
1178 dflag ^= 1;
1179 if (prefixes & PREFIX_ADR)
1180 aflag ^= 1;
1181
1182 s->prefix = prefixes;
1183 s->aflag = aflag;
1184 s->dflag = dflag;
1185
1186 /* now check op code */
1187 reswitch:
1188 switch(b) {
1189 case 0x0f:
1190 /**************************/
1191 /* extended op code */
1192 b = ldub(s->pc++) | 0x100;
1193 goto reswitch;
1194
1195 /**************************/
1196 /* arith & logic */
1197 case 0x00 ... 0x05:
1198 case 0x08 ... 0x0d:
1199 case 0x10 ... 0x15:
1200 case 0x18 ... 0x1d:
1201 case 0x20 ... 0x25:
1202 case 0x28 ... 0x2d:
1203 case 0x30 ... 0x35:
1204 case 0x38 ... 0x3d:
1205 {
1206 int op, f, val;
1207 op = (b >> 3) & 7;
1208 f = (b >> 1) & 3;
1209
1210 if ((b & 1) == 0)
1211 ot = OT_BYTE;
1212 else
1213 ot = dflag ? OT_LONG : OT_WORD;
1214
1215 switch(f) {
1216 case 0: /* OP Ev, Gv */
1217 modrm = ldub(s->pc++);
1218 reg = ((modrm >> 3) & 7) + OR_EAX;
1219 mod = (modrm >> 6) & 3;
1220 rm = modrm & 7;
1221 if (mod != 3) {
1222 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1223 gen_op_ld_T0_A0[ot]();
1224 opreg = OR_TMP0;
1225 } else {
1226 opreg = OR_EAX + rm;
1227 }
1228 gen_op(s, op, ot, opreg, reg);
1229 if (mod != 3 && op != 7) {
1230 gen_op_st_T0_A0[ot]();
1231 }
1232 break;
1233 case 1: /* OP Gv, Ev */
1234 modrm = ldub(s->pc++);
1235 mod = (modrm >> 6) & 3;
1236 reg = ((modrm >> 3) & 7) + OR_EAX;
1237 rm = modrm & 7;
1238 if (mod != 3) {
1239 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1240 gen_op_ld_T1_A0[ot]();
1241 opreg = OR_TMP1;
1242 } else {
1243 opreg = OR_EAX + rm;
1244 }
1245 gen_op(s, op, ot, reg, opreg);
1246 break;
1247 case 2: /* OP A, Iv */
1248 val = insn_get(s, ot);
1249 gen_opi(s, op, ot, OR_EAX, val);
1250 break;
1251 }
1252 }
1253 break;
1254
1255 case 0x80: /* GRP1 */
1256 case 0x81:
1257 case 0x83:
1258 {
1259 int val;
1260
1261 if ((b & 1) == 0)
1262 ot = OT_BYTE;
1263 else
1264 ot = dflag ? OT_LONG : OT_WORD;
1265
1266 modrm = ldub(s->pc++);
1267 mod = (modrm >> 6) & 3;
1268 rm = modrm & 7;
1269 op = (modrm >> 3) & 7;
1270
1271 if (mod != 3) {
1272 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1273 gen_op_ld_T0_A0[ot]();
1274 opreg = OR_TMP0;
1275 } else {
1276 opreg = rm + OR_EAX;
1277 }
1278
1279 switch(b) {
1280 default:
1281 case 0x80:
1282 case 0x81:
1283 val = insn_get(s, ot);
1284 break;
1285 case 0x83:
1286 val = (int8_t)insn_get(s, OT_BYTE);
1287 break;
1288 }
1289
1290 gen_opi(s, op, ot, opreg, val);
1291 if (op != 7 && mod != 3) {
1292 gen_op_st_T0_A0[ot]();
1293 }
1294 }
1295 break;
1296
1297 /**************************/
1298 /* inc, dec, and other misc arith */
1299 case 0x40 ... 0x47: /* inc Gv */
1300 ot = dflag ? OT_LONG : OT_WORD;
1301 gen_inc(s, ot, OR_EAX + (b & 7), 1);
1302 break;
1303 case 0x48 ... 0x4f: /* dec Gv */
1304 ot = dflag ? OT_LONG : OT_WORD;
1305 gen_inc(s, ot, OR_EAX + (b & 7), -1);
1306 break;
1307 case 0xf6: /* GRP3 */
1308 case 0xf7:
1309 if ((b & 1) == 0)
1310 ot = OT_BYTE;
1311 else
1312 ot = dflag ? OT_LONG : OT_WORD;
1313
1314 modrm = ldub(s->pc++);
1315 mod = (modrm >> 6) & 3;
1316 rm = modrm & 7;
1317 op = (modrm >> 3) & 7;
1318 if (mod != 3) {
1319 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1320 gen_op_ld_T0_A0[ot]();
1321 } else {
1322 gen_op_mov_TN_reg[ot][0][rm]();
1323 }
1324
1325 switch(op) {
1326 case 0: /* test */
1327 val = insn_get(s, ot);
1328 gen_op_movl_T1_im(val);
1329 gen_op_testl_T0_T1_cc();
1330 s->cc_op = CC_OP_LOGICB + ot;
1331 break;
1332 case 2: /* not */
1333 gen_op_notl_T0();
1334 if (mod != 3) {
1335 gen_op_st_T0_A0[ot]();
1336 } else {
1337 gen_op_mov_reg_T0[ot][rm]();
1338 }
1339 break;
1340 case 3: /* neg */
1341 gen_op_negl_T0_cc();
1342 if (mod != 3) {
1343 gen_op_st_T0_A0[ot]();
1344 } else {
1345 gen_op_mov_reg_T0[ot][rm]();
1346 }
1347 s->cc_op = CC_OP_SUBB + ot;
1348 break;
1349 case 4: /* mul */
1350 switch(ot) {
1351 case OT_BYTE:
1352 gen_op_mulb_AL_T0();
1353 break;
1354 case OT_WORD:
1355 gen_op_mulw_AX_T0();
1356 break;
1357 default:
1358 case OT_LONG:
1359 gen_op_mull_EAX_T0();
1360 break;
1361 }
1362 s->cc_op = CC_OP_MUL;
1363 break;
1364 case 5: /* imul */
1365 switch(ot) {
1366 case OT_BYTE:
1367 gen_op_imulb_AL_T0();
1368 break;
1369 case OT_WORD:
1370 gen_op_imulw_AX_T0();
1371 break;
1372 default:
1373 case OT_LONG:
1374 gen_op_imull_EAX_T0();
1375 break;
1376 }
1377 s->cc_op = CC_OP_MUL;
1378 break;
1379 case 6: /* div */
1380 switch(ot) {
1381 case OT_BYTE:
1382 gen_op_divb_AL_T0();
1383 break;
1384 case OT_WORD:
1385 gen_op_divw_AX_T0();
1386 break;
1387 default:
1388 case OT_LONG:
1389 gen_op_divl_EAX_T0();
1390 break;
1391 }
1392 break;
1393 case 7: /* idiv */
1394 switch(ot) {
1395 case OT_BYTE:
1396 gen_op_idivb_AL_T0();
1397 break;
1398 case OT_WORD:
1399 gen_op_idivw_AX_T0();
1400 break;
1401 default:
1402 case OT_LONG:
1403 gen_op_idivl_EAX_T0();
1404 break;
1405 }
1406 break;
1407 default:
1408 error("GRP3: bad instruction");
1409 return -1;
1410 }
1411 break;
1412
1413 case 0xfe: /* GRP4 */
1414 case 0xff: /* GRP5 */
1415 if ((b & 1) == 0)
1416 ot = OT_BYTE;
1417 else
1418 ot = dflag ? OT_LONG : OT_WORD;
1419
1420 modrm = ldub(s->pc++);
1421 mod = (modrm >> 6) & 3;
1422 rm = modrm & 7;
1423 op = (modrm >> 3) & 7;
1424 if (op >= 2 && b == 0xfe) {
1425 error("GRP4: bad instruction");
1426 return -1;
1427 }
1428 if (mod != 3) {
1429 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1430 gen_op_ld_T0_A0[ot]();
1431 } else {
1432 gen_op_mov_TN_reg[ot][0][rm]();
1433 }
1434
1435 switch(op) {
1436 case 0: /* inc Ev */
1437 gen_inc(s, ot, OR_TMP0, 1);
1438 if (mod != 3)
1439 gen_op_st_T0_A0[ot]();
1440 else
1441 gen_op_mov_reg_T0[ot][rm]();
1442 break;
1443 case 1: /* dec Ev */
1444 gen_inc(s, ot, OR_TMP0, -1);
1445 if (mod != 3)
1446 gen_op_st_T0_A0[ot]();
1447 else
1448 gen_op_mov_reg_T0[ot][rm]();
1449 break;
1450 case 2: /* call Ev */
1451 gen_op_movl_T1_im((long)s->pc);
1452 gen_op_pushl_T1();
1453 gen_op_jmp_T0();
1454 s->is_jmp = 1;
1455 break;
1456 case 4: /* jmp Ev */
1457 gen_op_jmp_T0();
1458 s->is_jmp = 1;
1459 break;
1460 case 6: /* push Ev */
1461 gen_op_pushl_T0();
1462 break;
1463 default:
1464 error("GRP5: bad instruction");
1465 return -1;
1466 }
1467 break;
1468
1469 case 0x84: /* test Ev, Gv */
1470 case 0x85:
1471 if ((b & 1) == 0)
1472 ot = OT_BYTE;
1473 else
1474 ot = dflag ? OT_LONG : OT_WORD;
1475
1476 modrm = ldub(s->pc++);
1477 mod = (modrm >> 6) & 3;
1478 rm = modrm & 7;
1479 reg = (modrm >> 3) & 7;
1480
1481 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1482 gen_op_mov_TN_reg[ot][1][reg + OR_EAX]();
1483 gen_op_testl_T0_T1_cc();
1484 s->cc_op = CC_OP_LOGICB + ot;
1485 break;
1486
1487 case 0xa8: /* test eAX, Iv */
1488 case 0xa9:
1489 if ((b & 1) == 0)
1490 ot = OT_BYTE;
1491 else
1492 ot = dflag ? OT_LONG : OT_WORD;
1493 val = insn_get(s, ot);
1494
1495 gen_op_mov_TN_reg[ot][0][OR_EAX]();
1496 gen_op_movl_T1_im(val);
1497 gen_op_testl_T0_T1_cc();
1498 s->cc_op = CC_OP_LOGICB + ot;
1499 break;
1500
1501 case 0x98: /* CWDE/CBW */
1502 if (dflag)
1503 gen_op_movswl_EAX_AX();
1504 else
1505 gen_op_movsbw_AX_AL();
1506 break;
1507 case 0x99: /* CDQ/CWD */
1508 if (dflag)
1509 gen_op_movslq_EDX_EAX();
1510 else
1511 gen_op_movswl_DX_AX();
1512 break;
1513 case 0x1af: /* imul Gv, Ev */
1514 case 0x69: /* imul Gv, Ev, I */
1515 case 0x6b:
1516 ot = dflag ? OT_LONG : OT_WORD;
1517 modrm = ldub(s->pc++);
1518 reg = ((modrm >> 3) & 7) + OR_EAX;
1519 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1520 if (b == 0x69) {
1521 val = insn_get(s, ot);
1522 gen_op_movl_T1_im(val);
1523 } else if (b == 0x6b) {
1524 val = insn_get(s, OT_BYTE);
1525 gen_op_movl_T1_im(val);
1526 } else {
1527 gen_op_mov_TN_reg[ot][1][reg]();
1528 }
1529
1530 if (ot == OT_LONG) {
1531 gen_op_imull_T0_T1();
1532 } else {
1533 gen_op_imulw_T0_T1();
1534 }
1535 gen_op_mov_reg_T0[ot][reg]();
1536 s->cc_op = CC_OP_MUL;
1537 break;
1538
1539 /**************************/
1540 /* push/pop */
1541 case 0x50 ... 0x57: /* push */
1542 gen_op_mov_TN_reg[OT_LONG][0][b & 7]();
1543 gen_op_pushl_T0();
1544 break;
1545 case 0x58 ... 0x5f: /* pop */
1546 gen_op_popl_T0();
1547 gen_op_mov_reg_T0[OT_LONG][b & 7]();
1548 break;
1549 case 0x60: /* pusha */
1550 if (s->dflag)
1551 gen_op_pushal();
1552 else
1553 gen_op_pushaw();
1554 break;
1555 case 0x61: /* popa */
1556 if (s->dflag)
1557 gen_op_popal();
1558 else
1559 gen_op_popaw();
1560 break;
1561 case 0x68: /* push Iv */
1562 case 0x6a:
1563 ot = dflag ? OT_LONG : OT_WORD;
1564 if (b == 0x68)
1565 val = insn_get(s, ot);
1566 else
1567 val = (int8_t)insn_get(s, OT_BYTE);
1568 gen_op_movl_T0_im(val);
1569 gen_op_pushl_T0();
1570 break;
1571 case 0x8f: /* pop Ev */
1572 ot = dflag ? OT_LONG : OT_WORD;
1573 modrm = ldub(s->pc++);
1574 gen_op_popl_T0();
1575 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
1576 break;
1577 case 0xc8: /* enter */
1578 {
1579 int level;
1580 val = lduw(s->pc);
1581 s->pc += 2;
1582 level = ldub(s->pc++);
1583 level &= 0x1f;
1584 gen_op_enterl(val, level);
1585 }
1586 break;
1587 case 0xc9: /* leave */
1588 gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
1589 gen_op_mov_reg_T0[OT_LONG][R_ESP]();
1590 gen_op_popl_T0();
1591 gen_op_mov_reg_T0[OT_LONG][R_EBP]();
1592 break;
1593 case 0x06: /* push es */
1594 case 0x0e: /* push cs */
1595 case 0x16: /* push ss */
1596 case 0x1e: /* push ds */
1597 gen_op_movl_T0_seg(b >> 3);
1598 gen_op_pushl_T0();
1599 break;
1600 case 0x1a0: /* push fs */
1601 case 0x1a8: /* push gs */
1602 gen_op_movl_T0_seg(((b >> 3) & 7) + R_FS);
1603 gen_op_pushl_T0();
1604 break;
1605 case 0x07: /* pop es */
1606 case 0x17: /* pop ss */
1607 case 0x1f: /* pop ds */
1608 gen_op_popl_T0();
1609 gen_movl_seg_T0(s, b >> 3);
1610 break;
1611 case 0x1a1: /* pop fs */
1612 case 0x1a9: /* pop gs */
1613 gen_op_popl_T0();
1614 gen_movl_seg_T0(s, ((b >> 3) & 7) + R_FS);
1615 break;
1616
1617 /**************************/
1618 /* mov */
1619 case 0x88:
1620 case 0x89: /* mov Gv, Ev */
1621 if ((b & 1) == 0)
1622 ot = OT_BYTE;
1623 else
1624 ot = dflag ? OT_LONG : OT_WORD;
1625 modrm = ldub(s->pc++);
1626 reg = (modrm >> 3) & 7;
1627
1628 /* generate a generic store */
1629 gen_ldst_modrm(s, modrm, ot, OR_EAX + reg, 1);
1630 break;
1631 case 0xc6:
1632 case 0xc7: /* mov Ev, Iv */
1633 if ((b & 1) == 0)
1634 ot = OT_BYTE;
1635 else
1636 ot = dflag ? OT_LONG : OT_WORD;
1637 modrm = ldub(s->pc++);
1638 mod = (modrm >> 6) & 3;
1639 if (mod != 3)
1640 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1641 val = insn_get(s, ot);
1642 gen_op_movl_T0_im(val);
1643 if (mod != 3)
1644 gen_op_st_T0_A0[ot]();
1645 else
1646 gen_op_mov_reg_T0[ot][modrm & 7]();
1647 break;
1648 case 0x8a:
1649 case 0x8b: /* mov Ev, Gv */
1650 if ((b & 1) == 0)
1651 ot = OT_BYTE;
1652 else
1653 ot = dflag ? OT_LONG : OT_WORD;
1654 modrm = ldub(s->pc++);
1655 reg = (modrm >> 3) & 7;
1656
1657 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1658 gen_op_mov_reg_T0[ot][reg]();
1659 break;
1660 case 0x8e: /* mov seg, Gv */
1661 ot = dflag ? OT_LONG : OT_WORD;
1662 modrm = ldub(s->pc++);
1663 reg = (modrm >> 3) & 7;
1664 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1665 if (reg >= 6)
1666 goto illegal_op;
1667 gen_movl_seg_T0(s, reg);
1668 break;
1669 case 0x8c: /* mov Gv, seg */
1670 ot = dflag ? OT_LONG : OT_WORD;
1671 modrm = ldub(s->pc++);
1672 reg = (modrm >> 3) & 7;
1673 if (reg >= 6)
1674 goto illegal_op;
1675 gen_op_movl_T0_seg(reg);
1676 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
1677 break;
1678
1679 case 0x1b6: /* movzbS Gv, Eb */
1680 case 0x1b7: /* movzwS Gv, Eb */
1681 case 0x1be: /* movsbS Gv, Eb */
1682 case 0x1bf: /* movswS Gv, Eb */
1683 {
1684 int d_ot;
1685 /* d_ot is the size of destination */
1686 d_ot = dflag + OT_WORD;
1687 /* ot is the size of source */
1688 ot = (b & 1) + OT_BYTE;
1689 modrm = ldub(s->pc++);
1690 reg = ((modrm >> 3) & 7) + OR_EAX;
1691 mod = (modrm >> 6) & 3;
1692 rm = modrm & 7;
1693
1694 if (mod == 3) {
1695 gen_op_mov_TN_reg[ot][0][rm]();
1696 switch(ot | (b & 8)) {
1697 case OT_BYTE:
1698 gen_op_movzbl_T0_T0();
1699 break;
1700 case OT_BYTE | 8:
1701 gen_op_movsbl_T0_T0();
1702 break;
1703 case OT_WORD:
1704 gen_op_movzwl_T0_T0();
1705 break;
1706 default:
1707 case OT_WORD | 8:
1708 gen_op_movswl_T0_T0();
1709 break;
1710 }
1711 gen_op_mov_reg_T0[d_ot][reg]();
1712 } else {
1713 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1714 if (b & 8) {
1715 gen_op_lds_T0_A0[ot]();
1716 } else {
1717 gen_op_ldu_T0_A0[ot]();
1718 }
1719 gen_op_mov_reg_T0[d_ot][reg]();
1720 }
1721 }
1722 break;
1723
1724 case 0x8d: /* lea */
1725 ot = dflag ? OT_LONG : OT_WORD;
1726 modrm = ldub(s->pc++);
1727 reg = (modrm >> 3) & 7;
1728 /* we must ensure that no segment is added */
1729 s->prefix &= ~(PREFIX_CS | PREFIX_SS | PREFIX_DS |
1730 PREFIX_ES | PREFIX_FS | PREFIX_GS);
1731 val = s->addseg;
1732 s->addseg = 0;
1733 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1734 s->addseg = val;
1735 gen_op_mov_reg_A0[ot - OT_WORD][reg]();
1736 break;
1737
1738 case 0xa0: /* mov EAX, Ov */
1739 case 0xa1:
1740 case 0xa2: /* mov Ov, EAX */
1741 case 0xa3:
1742 if ((b & 1) == 0)
1743 ot = OT_BYTE;
1744 else
1745 ot = dflag ? OT_LONG : OT_WORD;
1746 if (s->aflag)
1747 offset_addr = insn_get(s, OT_LONG);
1748 else
1749 offset_addr = insn_get(s, OT_WORD);
1750 gen_op_movl_A0_im(offset_addr);
1751 if ((b & 2) == 0) {
1752 gen_op_ld_T0_A0[ot]();
1753 gen_op_mov_reg_T0[ot][R_EAX]();
1754 } else {
1755 gen_op_mov_TN_reg[ot][0][R_EAX]();
1756 gen_op_st_T0_A0[ot]();
1757 }
1758 break;
1759
1760 case 0xb0 ... 0xb7: /* mov R, Ib */
1761 val = insn_get(s, OT_BYTE);
1762 gen_op_movl_T0_im(val);
1763 gen_op_mov_reg_T0[OT_BYTE][b & 7]();
1764 break;
1765 case 0xb8 ... 0xbf: /* mov R, Iv */
1766 ot = dflag ? OT_LONG : OT_WORD;
1767 val = insn_get(s, ot);
1768 reg = OR_EAX + (b & 7);
1769 gen_op_movl_T0_im(val);
1770 gen_op_mov_reg_T0[ot][reg]();
1771 break;
1772
1773 case 0x91 ... 0x97: /* xchg R, EAX */
1774 ot = dflag ? OT_LONG : OT_WORD;
1775 reg = b & 7;
1776 gen_op_mov_TN_reg[ot][0][reg]();
1777 gen_op_mov_TN_reg[ot][1][R_EAX]();
1778 gen_op_mov_reg_T0[ot][R_EAX]();
1779 gen_op_mov_reg_T1[ot][reg]();
1780 break;
1781 case 0x86:
1782 case 0x87: /* xchg Ev, Gv */
1783 if ((b & 1) == 0)
1784 ot = OT_BYTE;
1785 else
1786 ot = dflag ? OT_LONG : OT_WORD;
1787 modrm = ldub(s->pc++);
1788 reg = (modrm >> 3) & 7;
1789
1790 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1791 gen_op_mov_TN_reg[ot][0][reg]();
1792 gen_op_ld_T1_A0[ot]();
1793 gen_op_st_T0_A0[ot]();
1794 gen_op_mov_reg_T1[ot][reg]();
1795 break;
1796 case 0xc4: /* les Gv */
1797 op = R_ES;
1798 goto do_lxx;
1799 case 0xc5: /* lds Gv */
1800 op = R_DS;
1801 goto do_lxx;
1802 case 0x1b2: /* lss Gv */
1803 op = R_SS;
1804 goto do_lxx;
1805 case 0x1b4: /* lfs Gv */
1806 op = R_FS;
1807 goto do_lxx;
1808 case 0x1b5: /* lgs Gv */
1809 op = R_GS;
1810 do_lxx:
1811 ot = dflag ? OT_LONG : OT_WORD;
1812 modrm = ldub(s->pc++);
1813 reg = (modrm >> 3) & 7;
1814 mod = (modrm >> 6) & 3;
1815 if (mod == 3)
1816 goto illegal_op;
1817 gen_op_ld_T1_A0[ot]();
1818 op_addl_A0_im(1 << (ot - OT_WORD + 1));
1819 /* load the segment first to handle exceptions properly */
1820 gen_op_lduw_T0_A0();
1821 gen_movl_seg_T0(s, op);
1822 /* then put the data */
1823 gen_op_mov_reg_T1[ot][reg]();
1824 break;
1825
1826 /************************/
1827 /* shifts */
1828 case 0xc0:
1829 case 0xc1:
1830 /* shift Ev,Ib */
1831 shift = 2;
1832 grp2:
1833 {
1834 if ((b & 1) == 0)
1835 ot = OT_BYTE;
1836 else
1837 ot = dflag ? OT_LONG : OT_WORD;
1838
1839 modrm = ldub(s->pc++);
1840 mod = (modrm >> 6) & 3;
1841 rm = modrm & 7;
1842 op = (modrm >> 3) & 7;
1843
1844 if (mod != 3) {
1845 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1846 gen_op_ld_T0_A0[ot]();
1847 opreg = OR_TMP0;
1848 } else {
1849 opreg = rm + OR_EAX;
1850 }
1851
1852 /* simpler op */
1853 if (shift == 0) {
1854 gen_shift(s, op, ot, opreg, OR_ECX);
1855 } else {
1856 if (shift == 2) {
1857 shift = ldub(s->pc++);
1858 }
1859 gen_shifti(s, op, ot, opreg, shift);
1860 }
1861
1862 if (mod != 3) {
1863 gen_op_st_T0_A0[ot]();
1864 }
1865 }
1866 break;
1867 case 0xd0:
1868 case 0xd1:
1869 /* shift Ev,1 */
1870 shift = 1;
1871 goto grp2;
1872 case 0xd2:
1873 case 0xd3:
1874 /* shift Ev,cl */
1875 shift = 0;
1876 goto grp2;
1877
1878 case 0x1a4: /* shld imm */
1879 op = 0;
1880 shift = 1;
1881 goto do_shiftd;
1882 case 0x1a5: /* shld cl */
1883 op = 0;
1884 shift = 0;
1885 goto do_shiftd;
1886 case 0x1ac: /* shrd imm */
1887 op = 1;
1888 shift = 1;
1889 goto do_shiftd;
1890 case 0x1ad: /* shrd cl */
1891 op = 1;
1892 shift = 0;
1893 do_shiftd:
1894 ot = dflag ? OT_LONG : OT_WORD;
1895 modrm = ldub(s->pc++);
1896 mod = (modrm >> 6) & 3;
1897 rm = modrm & 7;
1898 reg = (modrm >> 3) & 7;
1899
1900 if (mod != 3) {
1901 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1902 gen_op_ld_T0_A0[ot]();
1903 } else {
1904 gen_op_mov_TN_reg[ot][0][rm]();
1905 }
1906 gen_op_mov_TN_reg[ot][1][reg]();
1907
1908 if (shift) {
1909 val = ldub(s->pc++);
1910 val &= 0x1f;
1911 if (val) {
1912 gen_op_shiftd_T0_T1_im_cc[ot - OT_WORD][op](val);
1913 if (op == 0 && ot != OT_WORD)
1914 s->cc_op = CC_OP_SHLB + ot;
1915 else
1916 s->cc_op = CC_OP_SARB + ot;
1917 }
1918 } else {
1919 if (s->cc_op != CC_OP_DYNAMIC)
1920 gen_op_set_cc_op(s->cc_op);
1921 gen_op_shiftd_T0_T1_ECX_cc[ot - OT_WORD][op]();
1922 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
1923 }
1924 if (mod != 3) {
1925 gen_op_st_T0_A0[ot]();
1926 } else {
1927 gen_op_mov_reg_T0[ot][rm]();
1928 }
1929 break;
1930
1931 /************************/
1932 /* floats */
1933 case 0xd8 ... 0xdf:
1934 modrm = ldub(s->pc++);
1935 mod = (modrm >> 6) & 3;
1936 rm = modrm & 7;
1937 op = ((b & 7) << 3) | ((modrm >> 3) & 7);
1938
1939 if (mod != 3) {
1940 /* memory op */
1941 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1942 switch(op) {
1943 case 0x00 ... 0x07: /* fxxxs */
1944 case 0x10 ... 0x17: /* fixxxl */
1945 case 0x20 ... 0x27: /* fxxxl */
1946 case 0x30 ... 0x37: /* fixxx */
1947 {
1948 int op1;
1949 op1 = op & 7;
1950
1951 switch(op >> 4) {
1952 case 0:
1953 gen_op_flds_FT0_A0();
1954 break;
1955 case 1:
1956 gen_op_fildl_FT0_A0();
1957 break;
1958 case 2:
1959 gen_op_fldl_FT0_A0();
1960 break;
1961 case 3:
1962 default:
1963 gen_op_fild_FT0_A0();
1964 break;
1965 }
1966
1967 gen_op_fp_arith_ST0_FT0[op1]();
1968 if (op1 == 3) {
1969 /* fcomp needs pop */
1970 gen_op_fpop();
1971 }
1972 }
1973 break;
1974 case 0x08: /* flds */
1975 case 0x0a: /* fsts */
1976 case 0x0b: /* fstps */
1977 case 0x18: /* fildl */
1978 case 0x1a: /* fistl */
1979 case 0x1b: /* fistpl */
1980 case 0x28: /* fldl */
1981 case 0x2a: /* fstl */
1982 case 0x2b: /* fstpl */
1983 case 0x38: /* filds */
1984 case 0x3a: /* fists */
1985 case 0x3b: /* fistps */
1986
1987 switch(op & 7) {
1988 case 0:
1989 gen_op_fpush();
1990 switch(op >> 4) {
1991 case 0:
1992 gen_op_flds_ST0_A0();
1993 break;
1994 case 1:
1995 gen_op_fildl_ST0_A0();
1996 break;
1997 case 2:
1998 gen_op_fldl_ST0_A0();
1999 break;
2000 case 3:
2001 default:
2002 gen_op_fild_ST0_A0();
2003 break;
2004 }
2005 break;
2006 default:
2007 switch(op >> 4) {
2008 case 0:
2009 gen_op_fsts_ST0_A0();
2010 break;
2011 case 1:
2012 gen_op_fistl_ST0_A0();
2013 break;
2014 case 2:
2015 gen_op_fstl_ST0_A0();
2016 break;
2017 case 3:
2018 default:
2019 gen_op_fist_ST0_A0();
2020 break;
2021 }
2022 if ((op & 7) == 3)
2023 gen_op_fpop();
2024 break;
2025 }
2026 break;
2027 case 0x0d: /* fldcw mem */
2028 gen_op_fldcw_A0();
2029 break;
2030 case 0x0f: /* fnstcw mem */
2031 gen_op_fnstcw_A0();
2032 break;
2033 case 0x1d: /* fldt mem */
2034 gen_op_fpush();
2035 gen_op_fldt_ST0_A0();
2036 break;
2037 case 0x1f: /* fstpt mem */
2038 gen_op_fstt_ST0_A0();
2039 gen_op_fpop();
2040 break;
2041 case 0x2f: /* fnstsw mem */
2042 gen_op_fnstsw_A0();
2043 break;
2044 case 0x3c: /* fbld */
2045 gen_op_fpush();
2046 gen_op_fbld_ST0_A0();
2047 break;
2048 case 0x3e: /* fbstp */
2049 gen_op_fbst_ST0_A0();
2050 gen_op_fpop();
2051 break;
2052 case 0x3d: /* fildll */
2053 gen_op_fpush();
2054 gen_op_fildll_ST0_A0();
2055 break;
2056 case 0x3f: /* fistpll */
2057 gen_op_fistll_ST0_A0();
2058 gen_op_fpop();
2059 break;
2060 default:
2061 error("unhandled FPm [op=0x%02x]\n", op);
2062 return -1;
2063 }
2064 } else {
2065 /* register float ops */
2066 opreg = rm;
2067
2068 switch(op) {
2069 case 0x08: /* fld sti */
2070 gen_op_fpush();
2071 gen_op_fmov_ST0_STN((opreg + 1) & 7);
2072 break;
2073 case 0x09: /* fxchg sti */
2074 gen_op_fxchg_ST0_STN(opreg);
2075 break;
2076 case 0x0a: /* grp d9/2 */
2077 switch(rm) {
2078 case 0: /* fnop */
2079 break;
2080 default:
2081 error("unhandled FP GRP d9/2\n");
2082 return -1;
2083 }
2084 break;
2085 case 0x0c: /* grp d9/4 */
2086 switch(rm) {
2087 case 0: /* fchs */
2088 gen_op_fchs_ST0();
2089 break;
2090 case 1: /* fabs */
2091 gen_op_fabs_ST0();
2092 break;
2093 case 4: /* ftst */
2094 gen_op_fldz_FT0();
2095 gen_op_fcom_ST0_FT0();
2096 break;
2097 case 5: /* fxam */
2098 gen_op_fxam_ST0();
2099 break;
2100 default:
2101 return -1;
2102 }
2103 break;
2104 case 0x0d: /* grp d9/5 */
2105 {
2106 switch(rm) {
2107 case 0:
2108 gen_op_fpush();
2109 gen_op_fld1_ST0();
2110 break;
2111 case 1:
2112 gen_op_fpush();
2113 gen_op_fldl2t_ST0();
2114 break;
2115 case 2:
2116 gen_op_fpush();
2117 gen_op_fldl2e_ST0();
2118 break;
2119 case 3:
2120 gen_op_fpush();
2121 gen_op_fldpi_ST0();
2122 break;
2123 case 4:
2124 gen_op_fpush();
2125 gen_op_fldlg2_ST0();
2126 break;
2127 case 5:
2128 gen_op_fpush();
2129 gen_op_fldln2_ST0();
2130 break;
2131 case 6:
2132 gen_op_fpush();
2133 gen_op_fldz_ST0();
2134 break;
2135 default:
2136 return -1;
2137 }
2138 }
2139 break;
2140 case 0x0e: /* grp d9/6 */
2141 switch(rm) {
2142 case 0: /* f2xm1 */
2143 gen_op_f2xm1();
2144 break;
2145 case 1: /* fyl2x */
2146 gen_op_fyl2x();
2147 break;
2148 case 2: /* fptan */
2149 gen_op_fptan();
2150 break;
2151 case 3: /* fpatan */
2152 gen_op_fpatan();
2153 break;
2154 case 4: /* fxtract */
2155 gen_op_fxtract();
2156 break;
2157 case 5: /* fprem1 */
2158 gen_op_fprem1();
2159 break;
2160 case 6: /* fdecstp */
2161 gen_op_fdecstp();
2162 break;
2163 default:
2164 case 7: /* fincstp */
2165 gen_op_fincstp();
2166 break;
2167 }
2168 break;
2169 case 0x0f: /* grp d9/7 */
2170 switch(rm) {
2171 case 0: /* fprem */
2172 gen_op_fprem();
2173 break;
2174 case 1: /* fyl2xp1 */
2175 gen_op_fyl2xp1();
2176 break;
2177 case 2: /* fsqrt */
2178 gen_op_fsqrt();
2179 break;
2180 case 3: /* fsincos */
2181 gen_op_fsincos();
2182 break;
2183 case 5: /* fscale */
2184 gen_op_fscale();
2185 break;
2186 case 4: /* frndint */
2187 gen_op_frndint();
2188 break;
2189 case 6: /* fsin */
2190 gen_op_fsin();
2191 break;
2192 default:
2193 case 7: /* fcos */
2194 gen_op_fcos();
2195 break;
2196 }
2197 break;
2198 case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
2199 case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
2200 case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
2201 {
2202 int op1;
2203
2204 op1 = op & 7;
2205 if (op >= 0x20) {
2206 gen_op_fp_arith_STN_ST0[op1](opreg);
2207 if (op >= 0x30)
2208 gen_op_fpop();
2209 } else {
2210 gen_op_fmov_FT0_STN(opreg);
2211 gen_op_fp_arith_ST0_FT0[op1]();
2212 }
2213 }
2214 break;
2215 case 0x02: /* fcom */
2216 gen_op_fmov_FT0_STN(opreg);
2217 gen_op_fcom_ST0_FT0();
2218 break;
2219 case 0x03: /* fcomp */
2220 gen_op_fmov_FT0_STN(opreg);
2221 gen_op_fcom_ST0_FT0();
2222 gen_op_fpop();
2223 break;
2224 case 0x15: /* da/5 */
2225 switch(rm) {
2226 case 1: /* fucompp */
2227 gen_op_fmov_FT0_STN(1);
2228 gen_op_fucom_ST0_FT0();
2229 gen_op_fpop();
2230 gen_op_fpop();
2231 break;
2232 default:
2233 return -1;
2234 }
2235 break;
2236 case 0x2a: /* fst sti */
2237 gen_op_fmov_STN_ST0(opreg);
2238 break;
2239 case 0x2b: /* fstp sti */
2240 gen_op_fmov_STN_ST0(opreg);
2241 gen_op_fpop();
2242 break;
2243 case 0x2c: /* fucom st(i) */
2244 gen_op_fmov_FT0_STN(opreg);
2245 gen_op_fucom_ST0_FT0();
2246 break;
2247 case 0x2d: /* fucomp st(i) */
2248 gen_op_fmov_FT0_STN(opreg);
2249 gen_op_fucom_ST0_FT0();
2250 gen_op_fpop();
2251 break;
2252 case 0x33: /* de/3 */
2253 switch(rm) {
2254 case 1: /* fcompp */
2255 gen_op_fmov_FT0_STN(1);
2256 gen_op_fcom_ST0_FT0();
2257 gen_op_fpop();
2258 gen_op_fpop();
2259 break;
2260 default:
2261 return -1;
2262 }
2263 break;
2264 case 0x3c: /* df/4 */
2265 switch(rm) {
2266 case 0:
2267 gen_op_fnstsw_EAX();
2268 break;
2269 default:
2270 error("unhandled FP %x df/4\n", rm);
2271 return -1;
2272 }
2273 break;
2274 default:
2275 error("unhandled FPr [op=0x%x]\n", op);
2276 return -1;
2277 }
2278 }
2279 break;
2280 /************************/
2281 /* string ops */
2282 case 0xa4: /* movsS */
2283 case 0xa5:
2284 if ((b & 1) == 0)
2285 ot = OT_BYTE;
2286 else
2287 ot = dflag ? OT_LONG : OT_WORD;
2288 if (prefixes & PREFIX_REPZ) {
2289 gen_op_movs[3 + ot]();
2290 } else {
2291 gen_op_movs[ot]();
2292 }
2293 break;
2294
2295 case 0xaa: /* stosS */
2296 case 0xab:
2297 if ((b & 1) == 0)
2298 ot = OT_BYTE;
2299 else
2300 ot = dflag ? OT_LONG : OT_WORD;
2301 if (prefixes & PREFIX_REPZ) {
2302 gen_op_stos[3 + ot]();
2303 } else {
2304 gen_op_stos[ot]();
2305 }
2306 break;
2307 case 0xac: /* lodsS */
2308 case 0xad:
2309 if ((b & 1) == 0)
2310 ot = OT_BYTE;
2311 else
2312 ot = dflag ? OT_LONG : OT_WORD;
2313 if (prefixes & PREFIX_REPZ) {
2314 gen_op_lods[3 + ot]();
2315 } else {
2316 gen_op_lods[ot]();
2317 }
2318 break;
2319 case 0xae: /* scasS */
2320 case 0xaf:
2321 if ((b & 1) == 0)
2322 ot = OT_BYTE;
2323 else
2324 ot = dflag ? OT_LONG : OT_WORD;
2325 if (prefixes & PREFIX_REPNZ) {
2326 if (s->cc_op != CC_OP_DYNAMIC)
2327 gen_op_set_cc_op(s->cc_op);
2328 gen_op_scas[6 + ot]();
2329 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2330 } else if (prefixes & PREFIX_REPZ) {
2331 if (s->cc_op != CC_OP_DYNAMIC)
2332 gen_op_set_cc_op(s->cc_op);
2333 gen_op_scas[3 + ot]();
2334 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2335 } else {
2336 gen_op_scas[ot]();
2337 s->cc_op = CC_OP_SUBB + ot;
2338 }
2339 break;
2340
2341 case 0xa6: /* cmpsS */
2342 case 0xa7:
2343 if ((b & 1) == 0)
2344 ot = OT_BYTE;
2345 else
2346 ot = dflag ? OT_LONG : OT_WORD;
2347 if (prefixes & PREFIX_REPNZ) {
2348 if (s->cc_op != CC_OP_DYNAMIC)
2349 gen_op_set_cc_op(s->cc_op);
2350 gen_op_cmps[6 + ot]();
2351 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2352 } else if (prefixes & PREFIX_REPZ) {
2353 if (s->cc_op != CC_OP_DYNAMIC)
2354 gen_op_set_cc_op(s->cc_op);
2355 gen_op_cmps[3 + ot]();
2356 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2357 } else {
2358 gen_op_cmps[ot]();
2359 s->cc_op = CC_OP_SUBB + ot;
2360 }
2361 break;
2362
2363 /************************/
2364 /* port I/O */
2365 case 0x6c: /* insS */
2366 case 0x6d:
2367 if ((b & 1) == 0)
2368 ot = OT_BYTE;
2369 else
2370 ot = dflag ? OT_LONG : OT_WORD;
2371 if (prefixes & PREFIX_REPZ) {
2372 gen_op_ins[3 + ot]();
2373 } else {
2374 gen_op_ins[ot]();
2375 }
2376 break;
2377 case 0x6e: /* outsS */
2378 case 0x6f:
2379 if ((b & 1) == 0)
2380 ot = OT_BYTE;
2381 else
2382 ot = dflag ? OT_LONG : OT_WORD;
2383 if (prefixes & PREFIX_REPZ) {
2384 gen_op_outs[3 + ot]();
2385 } else {
2386 gen_op_outs[ot]();
2387 }
2388 break;
2389 case 0xe4:
2390 case 0xe5:
2391 if ((b & 1) == 0)
2392 ot = OT_BYTE;
2393 else
2394 ot = dflag ? OT_LONG : OT_WORD;
2395 val = ldub(s->pc++);
2396 gen_op_movl_T0_im(val);
2397 gen_op_in[ot]();
2398 gen_op_mov_reg_T1[ot][R_EAX]();
2399 break;
2400 case 0xe6:
2401 case 0xe7:
2402 if ((b & 1) == 0)
2403 ot = OT_BYTE;
2404 else
2405 ot = dflag ? OT_LONG : OT_WORD;
2406 val = ldub(s->pc++);
2407 gen_op_movl_T0_im(val);
2408 gen_op_mov_TN_reg[ot][1][R_EAX]();
2409 gen_op_out[ot]();
2410 break;
2411 case 0xec:
2412 case 0xed:
2413 if ((b & 1) == 0)
2414 ot = OT_BYTE;
2415 else
2416 ot = dflag ? OT_LONG : OT_WORD;
2417 gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
2418 gen_op_in[ot]();
2419 gen_op_mov_reg_T1[ot][R_EAX]();
2420 break;
2421 case 0xee:
2422 case 0xef:
2423 if ((b & 1) == 0)
2424 ot = OT_BYTE;
2425 else
2426 ot = dflag ? OT_LONG : OT_WORD;
2427 gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
2428 gen_op_mov_TN_reg[ot][1][R_EAX]();
2429 gen_op_out[ot]();
2430 break;
2431
2432 /************************/
2433 /* control */
2434 case 0xc2: /* ret im */
2435 /* XXX: handle stack pop ? */
2436 val = ldsw(s->pc);
2437 s->pc += 2;
2438 gen_op_popl_T0();
2439 gen_op_addl_ESP_im(val);
2440 gen_op_jmp_T0();
2441 s->is_jmp = 1;
2442 break;
2443 case 0xc3: /* ret */
2444 gen_op_popl_T0();
2445 gen_op_jmp_T0();
2446 s->is_jmp = 1;
2447 break;
2448 case 0xe8: /* call */
2449 val = insn_get(s, OT_LONG);
2450 val += (long)s->pc;
2451 gen_op_movl_T1_im((long)s->pc);
2452 gen_op_pushl_T1();
2453 gen_op_jmp_im(val);
2454 s->is_jmp = 1;
2455 break;
2456 case 0xe9: /* jmp */
2457 val = insn_get(s, OT_LONG);
2458 val += (long)s->pc;
2459 gen_op_jmp_im(val);
2460 s->is_jmp = 1;
2461 break;
2462 case 0xeb: /* jmp Jb */
2463 val = (int8_t)insn_get(s, OT_BYTE);
2464 val += (long)s->pc;
2465 gen_op_jmp_im(val);
2466 s->is_jmp = 1;
2467 break;
2468 case 0x70 ... 0x7f: /* jcc Jb */
2469 val = (int8_t)insn_get(s, OT_BYTE);
2470 val += (long)s->pc;
2471 goto do_jcc;
2472 case 0x180 ... 0x18f: /* jcc Jv */
2473 if (dflag) {
2474 val = insn_get(s, OT_LONG);
2475 } else {
2476 val = (int16_t)insn_get(s, OT_WORD);
2477 }
2478 val += (long)s->pc; /* XXX: fix 16 bit wrap */
2479 do_jcc:
2480 gen_jcc(s, b, val);
2481 s->is_jmp = 1;
2482 break;
2483
2484 case 0x190 ... 0x19f:
2485 modrm = ldub(s->pc++);
2486 gen_setcc(s, b);
2487 gen_ldst_modrm(s, modrm, OT_BYTE, OR_TMP0, 1);
2488 break;
2489
2490 /************************/
2491 /* flags */
2492 case 0x9c: /* pushf */
2493 if (s->cc_op != CC_OP_DYNAMIC)
2494 gen_op_set_cc_op(s->cc_op);
2495 gen_op_movl_T0_eflags();
2496 gen_op_pushl_T0();
2497 break;
2498 case 0x9d: /* popf */
2499 gen_op_popl_T0();
2500 gen_op_movl_eflags_T0();
2501 s->cc_op = CC_OP_EFLAGS;
2502 break;
2503 case 0x9e: /* sahf */
2504 gen_op_mov_TN_reg[OT_BYTE][0][R_AH]();
2505 if (s->cc_op != CC_OP_DYNAMIC)
2506 gen_op_set_cc_op(s->cc_op);
2507 gen_op_movb_eflags_T0();
2508 s->cc_op = CC_OP_EFLAGS;
2509 break;
2510 case 0x9f: /* lahf */
2511 if (s->cc_op != CC_OP_DYNAMIC)
2512 gen_op_set_cc_op(s->cc_op);
2513 gen_op_movl_T0_eflags();
2514 gen_op_mov_reg_T0[OT_BYTE][R_AH]();
2515 break;
2516 case 0xf5: /* cmc */
2517 if (s->cc_op != CC_OP_DYNAMIC)
2518 gen_op_set_cc_op(s->cc_op);
2519 gen_op_cmc();
2520 s->cc_op = CC_OP_EFLAGS;
2521 break;
2522 case 0xf8: /* clc */
2523 if (s->cc_op != CC_OP_DYNAMIC)
2524 gen_op_set_cc_op(s->cc_op);
2525 gen_op_clc();
2526 s->cc_op = CC_OP_EFLAGS;
2527 break;
2528 case 0xf9: /* stc */
2529 if (s->cc_op != CC_OP_DYNAMIC)
2530 gen_op_set_cc_op(s->cc_op);
2531 gen_op_stc();
2532 s->cc_op = CC_OP_EFLAGS;
2533 break;
2534 case 0xfc: /* cld */
2535 gen_op_cld();
2536 break;
2537 case 0xfd: /* std */
2538 gen_op_std();
2539 break;
2540
2541 /************************/
2542 /* bit operations */
2543 case 0x1ba: /* bt/bts/btr/btc Gv, im */
2544 ot = dflag ? OT_LONG : OT_WORD;
2545 modrm = ldub(s->pc++);
2546 op = (modrm >> 3) & 7;
2547 mod = (modrm >> 6) & 3;
2548 rm = modrm & 7;
2549 if (mod != 3) {
2550 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2551 gen_op_ld_T0_A0[ot]();
2552 } else {
2553 gen_op_mov_TN_reg[ot][0][rm]();
2554 }
2555 /* load shift */
2556 val = ldub(s->pc++);
2557 gen_op_movl_T1_im(val);
2558 if (op < 4)
2559 return -1;
2560 op -= 4;
2561 gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
2562 s->cc_op = CC_OP_SARB + ot;
2563 if (op != 0) {
2564 if (mod != 3)
2565 gen_op_st_T0_A0[ot]();
2566 else
2567 gen_op_mov_reg_T0[ot][rm]();
2568 }
2569 break;
2570 case 0x1a3: /* bt Gv, Ev */
2571 op = 0;
2572 goto do_btx;
2573 case 0x1ab: /* bts */
2574 op = 1;
2575 goto do_btx;
2576 case 0x1b3: /* btr */
2577 op = 2;
2578 goto do_btx;
2579 case 0x1bb: /* btc */
2580 op = 3;
2581 do_btx:
2582 ot = dflag ? OT_LONG : OT_WORD;
2583 modrm = ldub(s->pc++);
2584 reg = (modrm >> 3) & 7;
2585 mod = (modrm >> 6) & 3;
2586 rm = modrm & 7;
2587 gen_op_mov_TN_reg[OT_LONG][1][reg]();
2588 if (mod != 3) {
2589 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2590 /* specific case: we need to add a displacement */
2591 if (ot == OT_WORD)
2592 gen_op_add_bitw_A0_T1();
2593 else
2594 gen_op_add_bitl_A0_T1();
2595 gen_op_ld_T0_A0[ot]();
2596 } else {
2597 gen_op_mov_TN_reg[ot][0][rm]();
2598 }
2599 gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
2600 s->cc_op = CC_OP_SARB + ot;
2601 if (op != 0) {
2602 if (mod != 3)
2603 gen_op_st_T0_A0[ot]();
2604 else
2605 gen_op_mov_reg_T0[ot][rm]();
2606 }
2607 break;
2608 case 0x1bc: /* bsf */
2609 case 0x1bd: /* bsr */
2610 ot = dflag ? OT_LONG : OT_WORD;
2611 modrm = ldub(s->pc++);
2612 reg = (modrm >> 3) & 7;
2613 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
2614 gen_op_bsx_T0_cc[ot - OT_WORD][b & 1]();
2615 /* NOTE: we always write back the result. Intel doc says it is
2616 undefined if T0 == 0 */
2617 gen_op_mov_reg_T0[ot][reg]();
2618 s->cc_op = CC_OP_LOGICB + ot;
2619 break;
2620 /************************/
2621 /* bcd */
2622 case 0x27: /* daa */
2623 if (s->cc_op != CC_OP_DYNAMIC)
2624 gen_op_set_cc_op(s->cc_op);
2625 gen_op_daa();
2626 s->cc_op = CC_OP_EFLAGS;
2627 break;
2628 case 0x2f: /* das */
2629 if (s->cc_op != CC_OP_DYNAMIC)
2630 gen_op_set_cc_op(s->cc_op);
2631 gen_op_das();
2632 s->cc_op = CC_OP_EFLAGS;
2633 break;
2634 case 0x37: /* aaa */
2635 if (s->cc_op != CC_OP_DYNAMIC)
2636 gen_op_set_cc_op(s->cc_op);
2637 gen_op_aaa();
2638 s->cc_op = CC_OP_EFLAGS;
2639 break;
2640 case 0x3f: /* aas */
2641 if (s->cc_op != CC_OP_DYNAMIC)
2642 gen_op_set_cc_op(s->cc_op);
2643 gen_op_aas();
2644 s->cc_op = CC_OP_EFLAGS;
2645 break;
2646 case 0xd4: /* aam */
2647 val = ldub(s->pc++);
2648 gen_op_aam(val);
2649 s->cc_op = CC_OP_LOGICB;
2650 break;
2651 case 0xd5: /* aad */
2652 val = ldub(s->pc++);
2653 gen_op_aad(val);
2654 s->cc_op = CC_OP_LOGICB;
2655 break;
2656 /************************/
2657 /* misc */
2658 case 0x90: /* nop */
2659 break;
2660 case 0xcc: /* int3 */
2661 gen_op_int3((long)pc_start);
2662 s->is_jmp = 1;
2663 break;
2664 case 0xcd: /* int N */
2665 val = ldub(s->pc++);
2666 /* XXX: currently we ignore the interrupt number */
2667 gen_op_int_im((long)pc_start);
2668 s->is_jmp = 1;
2669 break;
2670 case 0xce: /* into */
2671 if (s->cc_op != CC_OP_DYNAMIC)
2672 gen_op_set_cc_op(s->cc_op);
2673 gen_op_into((long)pc_start, (long)s->pc);
2674 s->is_jmp = 1;
2675 break;
2676 case 0x1c8 ... 0x1cf: /* bswap reg */
2677 reg = b & 7;
2678 gen_op_mov_TN_reg[OT_LONG][0][reg]();
2679 gen_op_bswapl_T0();
2680 gen_op_mov_reg_T0[OT_LONG][reg]();
2681 break;
2682 case 0xd6: /* salc */
2683 if (s->cc_op != CC_OP_DYNAMIC)
2684 gen_op_set_cc_op(s->cc_op);
2685 gen_op_salc();
2686 break;
2687 case 0x1a2: /* rdtsc */
2688 gen_op_rdtsc();
2689 break;
2690 #if 0
2691 case 0x1a2: /* cpuid */
2692 gen_insn0(OP_ASM);
2693 break;
2694 #endif
2695 default:
2696 error("unknown opcode 0x%x", b);
2697 return -1;
2698 }
2699 return (long)s->pc;
2700 illegal_op:
2701 error("illegal opcode pc=0x%08Lx", (long)pc_start);
2702 return -1;
2703 }
2704
2705 /* return the next pc */
2706 int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size,
2707 int *gen_code_size_ptr, uint8_t *pc_start,
2708 int flags)
2709 {
2710 DisasContext dc1, *dc = &dc1;
2711 uint8_t *gen_code_end, *pc_ptr;
2712 long ret;
2713 #ifdef DEBUG_DISAS
2714 struct disassemble_info disasm_info;
2715 #endif
2716 dc->code32 = (flags >> GEN_FLAG_CODE32_SHIFT) & 1;
2717 dc->addseg = (flags >> GEN_FLAG_ADDSEG_SHIFT) & 1;
2718 dc->f_st = (flags >> GEN_FLAG_ST_SHIFT) & 7;
2719 dc->cc_op = CC_OP_DYNAMIC;
2720 gen_code_ptr = gen_code_buf;
2721 gen_code_end = gen_code_buf + max_code_size - 4096;
2722 gen_start();
2723
2724 dc->is_jmp = 0;
2725 pc_ptr = pc_start;
2726 do {
2727 ret = disas_insn(dc, pc_ptr);
2728 if (ret == -1)
2729 error("unknown instruction at PC=0x%x B=%02x %02x",
2730 pc_ptr, pc_ptr[0], pc_ptr[1]);
2731 pc_ptr = (void *)ret;
2732 } while (!dc->is_jmp && gen_code_ptr < gen_code_end);
2733 /* we must store the eflags state if it is not already done */
2734 if (dc->cc_op != CC_OP_DYNAMIC)
2735 gen_op_set_cc_op(dc->cc_op);
2736 if (dc->is_jmp != 1) {
2737 /* we add an additionnal jmp to update the simulated PC */
2738 gen_op_jmp_im(ret);
2739 }
2740 gen_end();
2741 *gen_code_size_ptr = gen_code_ptr - gen_code_buf;
2742
2743 #ifdef DEBUG_DISAS
2744 if (loglevel) {
2745 uint8_t *pc;
2746 int count;
2747
2748 INIT_DISASSEMBLE_INFO(disasm_info, logfile, fprintf);
2749 #if 0
2750 disasm_info.flavour = bfd_get_flavour (abfd);
2751 disasm_info.arch = bfd_get_arch (abfd);
2752 disasm_info.mach = bfd_get_mach (abfd);
2753 #endif
2754 #ifdef WORDS_BIGENDIAN
2755 disasm_info.endian = BFD_ENDIAN_BIG;
2756 #else
2757 disasm_info.endian = BFD_ENDIAN_LITTLE;
2758 #endif
2759 fprintf(logfile, "IN:\n");
2760 disasm_info.buffer = pc_start;
2761 disasm_info.buffer_vma = (unsigned long)pc_start;
2762 disasm_info.buffer_length = pc_ptr - pc_start;
2763 pc = pc_start;
2764 while (pc < pc_ptr) {
2765 fprintf(logfile, "0x%08lx: ", (long)pc);
2766 count = print_insn_i386((unsigned long)pc, &disasm_info);
2767 fprintf(logfile, "\n");
2768 pc += count;
2769 }
2770 fprintf(logfile, "\n");
2771
2772 pc = gen_code_buf;
2773 disasm_info.buffer = pc;
2774 disasm_info.buffer_vma = (unsigned long)pc;
2775 disasm_info.buffer_length = *gen_code_size_ptr;
2776 fprintf(logfile, "OUT: [size=%d]\n", *gen_code_size_ptr);
2777 while (pc < gen_code_ptr) {
2778 fprintf(logfile, "0x%08lx: ", (long)pc);
2779 count = print_insn_i386((unsigned long)pc, &disasm_info);
2780 fprintf(logfile, "\n");
2781 pc += count;
2782 }
2783 fprintf(logfile, "\n");
2784 }
2785 #endif
2786 return 0;
2787 }
2788
2789 CPUX86State *cpu_x86_init(void)
2790 {
2791 CPUX86State *env;
2792 int i;
2793
2794 cpu_x86_tblocks_init();
2795
2796 env = malloc(sizeof(CPUX86State));
2797 if (!env)
2798 return NULL;
2799 memset(env, 0, sizeof(CPUX86State));
2800 /* basic FPU init */
2801 for(i = 0;i < 8; i++)
2802 env->fptags[i] = 1;
2803 env->fpuc = 0x37f;
2804 /* flags setup */
2805 env->cc_op = CC_OP_EFLAGS;
2806 env->df = 1;
2807 return env;
2808 }
2809
2810 void cpu_x86_close(CPUX86State *env)
2811 {
2812 free(env);
2813 }