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