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