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