]> git.proxmox.com Git - qemu.git/blame - translate-i386.c
distribution patches
[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;
2086
2087 case 0xb0 ... 0xb7: /* mov R, Ib */
2088 val = insn_get(s, OT_BYTE);
ba1c6e37 2089 gen_op_movl_T0_im(val);
367e86e8
FB
2090 gen_op_mov_reg_T0[OT_BYTE][b & 7]();
2091 break;
2092 case 0xb8 ... 0xbf: /* mov R, Iv */
2093 ot = dflag ? OT_LONG : OT_WORD;
2094 val = insn_get(s, ot);
2095 reg = OR_EAX + (b & 7);
ba1c6e37 2096 gen_op_movl_T0_im(val);
367e86e8
FB
2097 gen_op_mov_reg_T0[ot][reg]();
2098 break;
2099
2100 case 0x91 ... 0x97: /* xchg R, EAX */
2101 ot = dflag ? OT_LONG : OT_WORD;
2102 reg = b & 7;
1a9353d2
FB
2103 rm = R_EAX;
2104 goto do_xchg_reg;
367e86e8
FB
2105 case 0x86:
2106 case 0x87: /* xchg Ev, Gv */
2107 if ((b & 1) == 0)
2108 ot = OT_BYTE;
2109 else
2110 ot = dflag ? OT_LONG : OT_WORD;
2111 modrm = ldub(s->pc++);
2112 reg = (modrm >> 3) & 7;
1a9353d2
FB
2113 mod = (modrm >> 6) & 3;
2114 if (mod == 3) {
2115 rm = modrm & 7;
2116 do_xchg_reg:
2117 gen_op_mov_TN_reg[ot][0][reg]();
2118 gen_op_mov_TN_reg[ot][1][rm]();
2119 gen_op_mov_reg_T0[ot][rm]();
2120 gen_op_mov_reg_T1[ot][reg]();
2121 } else {
2122 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2123 gen_op_mov_TN_reg[ot][0][reg]();
2124 gen_op_ld_T1_A0[ot]();
2125 gen_op_st_T0_A0[ot]();
2126 gen_op_mov_reg_T1[ot][reg]();
2127 }
367e86e8 2128 break;
6dbad63e
FB
2129 case 0xc4: /* les Gv */
2130 op = R_ES;
2131 goto do_lxx;
2132 case 0xc5: /* lds Gv */
2133 op = R_DS;
2134 goto do_lxx;
2135 case 0x1b2: /* lss Gv */
2136 op = R_SS;
2137 goto do_lxx;
2138 case 0x1b4: /* lfs Gv */
2139 op = R_FS;
2140 goto do_lxx;
2141 case 0x1b5: /* lgs Gv */
2142 op = R_GS;
2143 do_lxx:
2144 ot = dflag ? OT_LONG : OT_WORD;
2145 modrm = ldub(s->pc++);
2146 reg = (modrm >> 3) & 7;
2147 mod = (modrm >> 6) & 3;
2148 if (mod == 3)
2149 goto illegal_op;
2150 gen_op_ld_T1_A0[ot]();
dc99065b 2151 gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
6dbad63e
FB
2152 /* load the segment first to handle exceptions properly */
2153 gen_op_lduw_T0_A0();
2154 gen_movl_seg_T0(s, op);
2155 /* then put the data */
2156 gen_op_mov_reg_T1[ot][reg]();
2157 break;
367e86e8
FB
2158
2159 /************************/
2160 /* shifts */
2161 case 0xc0:
2162 case 0xc1:
2163 /* shift Ev,Ib */
2164 shift = 2;
2165 grp2:
2166 {
2167 if ((b & 1) == 0)
2168 ot = OT_BYTE;
2169 else
2170 ot = dflag ? OT_LONG : OT_WORD;
2171
2172 modrm = ldub(s->pc++);
2173 mod = (modrm >> 6) & 3;
2174 rm = modrm & 7;
2175 op = (modrm >> 3) & 7;
2176
2177 if (mod != 3) {
2178 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2179 gen_op_ld_T0_A0[ot]();
2180 opreg = OR_TMP0;
2181 } else {
2182 opreg = rm + OR_EAX;
2183 }
2184
2185 /* simpler op */
2186 if (shift == 0) {
2187 gen_shift(s, op, ot, opreg, OR_ECX);
2188 } else {
2189 if (shift == 2) {
2190 shift = ldub(s->pc++);
2191 }
2192 gen_shifti(s, op, ot, opreg, shift);
2193 }
2194
2195 if (mod != 3) {
2196 gen_op_st_T0_A0[ot]();
2197 }
2198 }
2199 break;
2200 case 0xd0:
2201 case 0xd1:
2202 /* shift Ev,1 */
2203 shift = 1;
2204 goto grp2;
2205 case 0xd2:
2206 case 0xd3:
2207 /* shift Ev,cl */
2208 shift = 0;
2209 goto grp2;
2210
d57c4e01
FB
2211 case 0x1a4: /* shld imm */
2212 op = 0;
2213 shift = 1;
2214 goto do_shiftd;
2215 case 0x1a5: /* shld cl */
2216 op = 0;
2217 shift = 0;
2218 goto do_shiftd;
2219 case 0x1ac: /* shrd imm */
2220 op = 1;
2221 shift = 1;
2222 goto do_shiftd;
2223 case 0x1ad: /* shrd cl */
2224 op = 1;
2225 shift = 0;
2226 do_shiftd:
2227 ot = dflag ? OT_LONG : OT_WORD;
2228 modrm = ldub(s->pc++);
2229 mod = (modrm >> 6) & 3;
2230 rm = modrm & 7;
2231 reg = (modrm >> 3) & 7;
2232
2233 if (mod != 3) {
2234 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2235 gen_op_ld_T0_A0[ot]();
2236 } else {
2237 gen_op_mov_TN_reg[ot][0][rm]();
2238 }
2239 gen_op_mov_TN_reg[ot][1][reg]();
2240
2241 if (shift) {
2242 val = ldub(s->pc++);
2243 val &= 0x1f;
2244 if (val) {
2245 gen_op_shiftd_T0_T1_im_cc[ot - OT_WORD][op](val);
2246 if (op == 0 && ot != OT_WORD)
2247 s->cc_op = CC_OP_SHLB + ot;
2248 else
2249 s->cc_op = CC_OP_SARB + ot;
2250 }
2251 } else {
2252 if (s->cc_op != CC_OP_DYNAMIC)
2253 gen_op_set_cc_op(s->cc_op);
2254 gen_op_shiftd_T0_T1_ECX_cc[ot - OT_WORD][op]();
2255 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2256 }
2257 if (mod != 3) {
2258 gen_op_st_T0_A0[ot]();
2259 } else {
2260 gen_op_mov_reg_T0[ot][rm]();
2261 }
2262 break;
2263
367e86e8
FB
2264 /************************/
2265 /* floats */
367e86e8
FB
2266 case 0xd8 ... 0xdf:
2267 modrm = ldub(s->pc++);
2268 mod = (modrm >> 6) & 3;
2269 rm = modrm & 7;
2270 op = ((b & 7) << 3) | ((modrm >> 3) & 7);
2271
2272 if (mod != 3) {
2273 /* memory op */
2274 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2275 switch(op) {
2276 case 0x00 ... 0x07: /* fxxxs */
2277 case 0x10 ... 0x17: /* fixxxl */
2278 case 0x20 ... 0x27: /* fxxxl */
2279 case 0x30 ... 0x37: /* fixxx */
2280 {
927f621e
FB
2281 int op1;
2282 op1 = op & 7;
367e86e8
FB
2283
2284 switch(op >> 4) {
2285 case 0:
927f621e 2286 gen_op_flds_FT0_A0();
367e86e8
FB
2287 break;
2288 case 1:
927f621e 2289 gen_op_fildl_FT0_A0();
367e86e8
FB
2290 break;
2291 case 2:
927f621e 2292 gen_op_fldl_FT0_A0();
367e86e8
FB
2293 break;
2294 case 3:
2295 default:
927f621e 2296 gen_op_fild_FT0_A0();
367e86e8
FB
2297 break;
2298 }
2299
927f621e
FB
2300 gen_op_fp_arith_ST0_FT0[op1]();
2301 if (op1 == 3) {
367e86e8 2302 /* fcomp needs pop */
927f621e 2303 gen_op_fpop();
367e86e8
FB
2304 }
2305 }
2306 break;
2307 case 0x08: /* flds */
2308 case 0x0a: /* fsts */
2309 case 0x0b: /* fstps */
2310 case 0x18: /* fildl */
2311 case 0x1a: /* fistl */
2312 case 0x1b: /* fistpl */
2313 case 0x28: /* fldl */
2314 case 0x2a: /* fstl */
2315 case 0x2b: /* fstpl */
2316 case 0x38: /* filds */
2317 case 0x3a: /* fists */
2318 case 0x3b: /* fistps */
2319
367e86e8
FB
2320 switch(op & 7) {
2321 case 0:
927f621e
FB
2322 gen_op_fpush();
2323 switch(op >> 4) {
2324 case 0:
2325 gen_op_flds_ST0_A0();
2326 break;
2327 case 1:
2328 gen_op_fildl_ST0_A0();
2329 break;
2330 case 2:
2331 gen_op_fldl_ST0_A0();
2332 break;
2333 case 3:
2334 default:
2335 gen_op_fild_ST0_A0();
2336 break;
367e86e8
FB
2337 }
2338 break;
2339 default:
927f621e
FB
2340 switch(op >> 4) {
2341 case 0:
2342 gen_op_fsts_ST0_A0();
2343 break;
2344 case 1:
2345 gen_op_fistl_ST0_A0();
2346 break;
2347 case 2:
2348 gen_op_fstl_ST0_A0();
2349 break;
2350 case 3:
2351 default:
2352 gen_op_fist_ST0_A0();
2353 break;
367e86e8
FB
2354 }
2355 if ((op & 7) == 3)
927f621e 2356 gen_op_fpop();
367e86e8
FB
2357 break;
2358 }
2359 break;
4b74fe1f
FB
2360 case 0x0d: /* fldcw mem */
2361 gen_op_fldcw_A0();
2362 break;
2363 case 0x0f: /* fnstcw mem */
2364 gen_op_fnstcw_A0();
2365 break;
77f8dd5a
FB
2366 case 0x1d: /* fldt mem */
2367 gen_op_fpush();
2368 gen_op_fldt_ST0_A0();
2369 break;
2370 case 0x1f: /* fstpt mem */
2371 gen_op_fstt_ST0_A0();
2372 gen_op_fpop();
2373 break;
367e86e8 2374 case 0x2f: /* fnstsw mem */
4b74fe1f 2375 gen_op_fnstsw_A0();
367e86e8 2376 break;
367e86e8 2377 case 0x3c: /* fbld */
77f8dd5a 2378 gen_op_fpush();
1017ebe9 2379 gen_op_fbld_ST0_A0();
77f8dd5a 2380 break;
367e86e8 2381 case 0x3e: /* fbstp */
77f8dd5a
FB
2382 gen_op_fbst_ST0_A0();
2383 gen_op_fpop();
2384 break;
367e86e8 2385 case 0x3d: /* fildll */
927f621e
FB
2386 gen_op_fpush();
2387 gen_op_fildll_ST0_A0();
367e86e8
FB
2388 break;
2389 case 0x3f: /* fistpll */
927f621e
FB
2390 gen_op_fistll_ST0_A0();
2391 gen_op_fpop();
367e86e8
FB
2392 break;
2393 default:
1a9353d2 2394 goto illegal_op;
367e86e8
FB
2395 }
2396 } else {
2397 /* register float ops */
927f621e 2398 opreg = rm;
367e86e8
FB
2399
2400 switch(op) {
2401 case 0x08: /* fld sti */
927f621e
FB
2402 gen_op_fpush();
2403 gen_op_fmov_ST0_STN((opreg + 1) & 7);
367e86e8
FB
2404 break;
2405 case 0x09: /* fxchg sti */
77f8dd5a 2406 gen_op_fxchg_ST0_STN(opreg);
367e86e8
FB
2407 break;
2408 case 0x0a: /* grp d9/2 */
2409 switch(rm) {
2410 case 0: /* fnop */
367e86e8
FB
2411 break;
2412 default:
1a9353d2 2413 goto illegal_op;
367e86e8
FB
2414 }
2415 break;
2416 case 0x0c: /* grp d9/4 */
2417 switch(rm) {
2418 case 0: /* fchs */
927f621e 2419 gen_op_fchs_ST0();
367e86e8
FB
2420 break;
2421 case 1: /* fabs */
927f621e 2422 gen_op_fabs_ST0();
367e86e8
FB
2423 break;
2424 case 4: /* ftst */
927f621e
FB
2425 gen_op_fldz_FT0();
2426 gen_op_fcom_ST0_FT0();
367e86e8
FB
2427 break;
2428 case 5: /* fxam */
927f621e 2429 gen_op_fxam_ST0();
367e86e8
FB
2430 break;
2431 default:
1a9353d2 2432 goto illegal_op;
367e86e8
FB
2433 }
2434 break;
2435 case 0x0d: /* grp d9/5 */
2436 {
927f621e
FB
2437 switch(rm) {
2438 case 0:
77f8dd5a 2439 gen_op_fpush();
927f621e
FB
2440 gen_op_fld1_ST0();
2441 break;
2442 case 1:
77f8dd5a
FB
2443 gen_op_fpush();
2444 gen_op_fldl2t_ST0();
927f621e
FB
2445 break;
2446 case 2:
77f8dd5a
FB
2447 gen_op_fpush();
2448 gen_op_fldl2e_ST0();
927f621e
FB
2449 break;
2450 case 3:
77f8dd5a 2451 gen_op_fpush();
927f621e
FB
2452 gen_op_fldpi_ST0();
2453 break;
2454 case 4:
77f8dd5a 2455 gen_op_fpush();
927f621e
FB
2456 gen_op_fldlg2_ST0();
2457 break;
2458 case 5:
77f8dd5a 2459 gen_op_fpush();
927f621e
FB
2460 gen_op_fldln2_ST0();
2461 break;
2462 case 6:
77f8dd5a 2463 gen_op_fpush();
927f621e
FB
2464 gen_op_fldz_ST0();
2465 break;
2466 default:
1a9353d2 2467 goto illegal_op;
367e86e8 2468 }
367e86e8
FB
2469 }
2470 break;
2471 case 0x0e: /* grp d9/6 */
2472 switch(rm) {
2473 case 0: /* f2xm1 */
927f621e 2474 gen_op_f2xm1();
367e86e8
FB
2475 break;
2476 case 1: /* fyl2x */
927f621e 2477 gen_op_fyl2x();
367e86e8
FB
2478 break;
2479 case 2: /* fptan */
927f621e 2480 gen_op_fptan();
367e86e8
FB
2481 break;
2482 case 3: /* fpatan */
927f621e 2483 gen_op_fpatan();
367e86e8
FB
2484 break;
2485 case 4: /* fxtract */
927f621e 2486 gen_op_fxtract();
367e86e8
FB
2487 break;
2488 case 5: /* fprem1 */
927f621e 2489 gen_op_fprem1();
367e86e8
FB
2490 break;
2491 case 6: /* fdecstp */
927f621e 2492 gen_op_fdecstp();
367e86e8
FB
2493 break;
2494 default:
927f621e
FB
2495 case 7: /* fincstp */
2496 gen_op_fincstp();
367e86e8
FB
2497 break;
2498 }
2499 break;
2500 case 0x0f: /* grp d9/7 */
2501 switch(rm) {
2502 case 0: /* fprem */
927f621e 2503 gen_op_fprem();
367e86e8
FB
2504 break;
2505 case 1: /* fyl2xp1 */
927f621e
FB
2506 gen_op_fyl2xp1();
2507 break;
2508 case 2: /* fsqrt */
2509 gen_op_fsqrt();
367e86e8
FB
2510 break;
2511 case 3: /* fsincos */
927f621e 2512 gen_op_fsincos();
367e86e8
FB
2513 break;
2514 case 5: /* fscale */
927f621e 2515 gen_op_fscale();
367e86e8 2516 break;
367e86e8 2517 case 4: /* frndint */
927f621e
FB
2518 gen_op_frndint();
2519 break;
367e86e8 2520 case 6: /* fsin */
927f621e
FB
2521 gen_op_fsin();
2522 break;
367e86e8
FB
2523 default:
2524 case 7: /* fcos */
927f621e 2525 gen_op_fcos();
367e86e8
FB
2526 break;
2527 }
2528 break;
2529 case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
2530 case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
2531 case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
2532 {
927f621e 2533 int op1;
367e86e8 2534
927f621e 2535 op1 = op & 7;
367e86e8 2536 if (op >= 0x20) {
927f621e 2537 gen_op_fp_arith_STN_ST0[op1](opreg);
77f8dd5a
FB
2538 if (op >= 0x30)
2539 gen_op_fpop();
367e86e8 2540 } else {
927f621e
FB
2541 gen_op_fmov_FT0_STN(opreg);
2542 gen_op_fp_arith_ST0_FT0[op1]();
367e86e8 2543 }
367e86e8
FB
2544 }
2545 break;
2546 case 0x02: /* fcom */
927f621e
FB
2547 gen_op_fmov_FT0_STN(opreg);
2548 gen_op_fcom_ST0_FT0();
367e86e8
FB
2549 break;
2550 case 0x03: /* fcomp */
927f621e
FB
2551 gen_op_fmov_FT0_STN(opreg);
2552 gen_op_fcom_ST0_FT0();
2553 gen_op_fpop();
367e86e8
FB
2554 break;
2555 case 0x15: /* da/5 */
2556 switch(rm) {
2557 case 1: /* fucompp */
927f621e 2558 gen_op_fmov_FT0_STN(1);
77f8dd5a 2559 gen_op_fucom_ST0_FT0();
927f621e
FB
2560 gen_op_fpop();
2561 gen_op_fpop();
367e86e8
FB
2562 break;
2563 default:
1a9353d2
FB
2564 goto illegal_op;
2565 }
2566 break;
2567 case 0x1c:
2568 switch(rm) {
2569 case 2: /* fclex */
2570 gen_op_fclex();
2571 break;
2572 case 3: /* fninit */
2573 gen_op_fninit();
2574 break;
2575 default:
2576 goto illegal_op;
367e86e8
FB
2577 }
2578 break;
2579 case 0x2a: /* fst sti */
927f621e 2580 gen_op_fmov_STN_ST0(opreg);
367e86e8
FB
2581 break;
2582 case 0x2b: /* fstp sti */
927f621e
FB
2583 gen_op_fmov_STN_ST0(opreg);
2584 gen_op_fpop();
367e86e8 2585 break;
77f8dd5a
FB
2586 case 0x2c: /* fucom st(i) */
2587 gen_op_fmov_FT0_STN(opreg);
2588 gen_op_fucom_ST0_FT0();
2589 break;
2590 case 0x2d: /* fucomp st(i) */
2591 gen_op_fmov_FT0_STN(opreg);
2592 gen_op_fucom_ST0_FT0();
2593 gen_op_fpop();
2594 break;
367e86e8
FB
2595 case 0x33: /* de/3 */
2596 switch(rm) {
2597 case 1: /* fcompp */
927f621e
FB
2598 gen_op_fmov_FT0_STN(1);
2599 gen_op_fcom_ST0_FT0();
2600 gen_op_fpop();
2601 gen_op_fpop();
367e86e8
FB
2602 break;
2603 default:
1a9353d2 2604 goto illegal_op;
367e86e8
FB
2605 }
2606 break;
2607 case 0x3c: /* df/4 */
2608 switch(rm) {
2609 case 0:
77f8dd5a 2610 gen_op_fnstsw_EAX();
367e86e8
FB
2611 break;
2612 default:
1a9353d2 2613 goto illegal_op;
367e86e8
FB
2614 }
2615 break;
2616 default:
1a9353d2 2617 goto illegal_op;
367e86e8
FB
2618 }
2619 }
2620 break;
367e86e8
FB
2621 /************************/
2622 /* string ops */
2623 case 0xa4: /* movsS */
2624 case 0xa5:
2625 if ((b & 1) == 0)
2626 ot = OT_BYTE;
2627 else
2628 ot = dflag ? OT_LONG : OT_WORD;
2629 if (prefixes & PREFIX_REPZ) {
2630 gen_op_movs[3 + ot]();
2631 } else {
2632 gen_op_movs[ot]();
2633 }
2634 break;
2635
2636 case 0xaa: /* stosS */
2637 case 0xab:
2638 if ((b & 1) == 0)
2639 ot = OT_BYTE;
2640 else
2641 ot = dflag ? OT_LONG : OT_WORD;
2642 if (prefixes & PREFIX_REPZ) {
2643 gen_op_stos[3 + ot]();
2644 } else {
2645 gen_op_stos[ot]();
2646 }
2647 break;
2648 case 0xac: /* lodsS */
2649 case 0xad:
2650 if ((b & 1) == 0)
2651 ot = OT_BYTE;
2652 else
2653 ot = dflag ? OT_LONG : OT_WORD;
2654 if (prefixes & PREFIX_REPZ) {
2655 gen_op_lods[3 + ot]();
2656 } else {
2657 gen_op_lods[ot]();
2658 }
2659 break;
2660 case 0xae: /* scasS */
2661 case 0xaf:
2662 if ((b & 1) == 0)
2663 ot = OT_BYTE;
2664 else
2665 ot = dflag ? OT_LONG : OT_WORD;
2666 if (prefixes & PREFIX_REPNZ) {
4b74fe1f
FB
2667 if (s->cc_op != CC_OP_DYNAMIC)
2668 gen_op_set_cc_op(s->cc_op);
367e86e8 2669 gen_op_scas[6 + ot]();
4b74fe1f 2670 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
367e86e8 2671 } else if (prefixes & PREFIX_REPZ) {
4b74fe1f
FB
2672 if (s->cc_op != CC_OP_DYNAMIC)
2673 gen_op_set_cc_op(s->cc_op);
367e86e8 2674 gen_op_scas[3 + ot]();
4b74fe1f 2675 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
367e86e8
FB
2676 } else {
2677 gen_op_scas[ot]();
4b74fe1f 2678 s->cc_op = CC_OP_SUBB + ot;
367e86e8
FB
2679 }
2680 break;
2681
2682 case 0xa6: /* cmpsS */
2683 case 0xa7:
2684 if ((b & 1) == 0)
2685 ot = OT_BYTE;
2686 else
2687 ot = dflag ? OT_LONG : OT_WORD;
2688 if (prefixes & PREFIX_REPNZ) {
4b74fe1f
FB
2689 if (s->cc_op != CC_OP_DYNAMIC)
2690 gen_op_set_cc_op(s->cc_op);
367e86e8 2691 gen_op_cmps[6 + ot]();
4b74fe1f 2692 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
367e86e8 2693 } else if (prefixes & PREFIX_REPZ) {
4b74fe1f
FB
2694 if (s->cc_op != CC_OP_DYNAMIC)
2695 gen_op_set_cc_op(s->cc_op);
367e86e8 2696 gen_op_cmps[3 + ot]();
4b74fe1f 2697 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
367e86e8
FB
2698 } else {
2699 gen_op_cmps[ot]();
4b74fe1f 2700 s->cc_op = CC_OP_SUBB + ot;
367e86e8
FB
2701 }
2702 break;
2703
ba1c6e37
FB
2704 /************************/
2705 /* port I/O */
367e86e8
FB
2706 case 0x6c: /* insS */
2707 case 0x6d:
2708 if ((b & 1) == 0)
2709 ot = OT_BYTE;
2710 else
2711 ot = dflag ? OT_LONG : OT_WORD;
2712 if (prefixes & PREFIX_REPZ) {
2713 gen_op_ins[3 + ot]();
2714 } else {
2715 gen_op_ins[ot]();
2716 }
2717 break;
2718 case 0x6e: /* outsS */
2719 case 0x6f:
2720 if ((b & 1) == 0)
2721 ot = OT_BYTE;
2722 else
2723 ot = dflag ? OT_LONG : OT_WORD;
2724 if (prefixes & PREFIX_REPZ) {
2725 gen_op_outs[3 + ot]();
2726 } else {
2727 gen_op_outs[ot]();
2728 }
2729 break;
ba1c6e37
FB
2730 case 0xe4:
2731 case 0xe5:
2732 if ((b & 1) == 0)
2733 ot = OT_BYTE;
2734 else
2735 ot = dflag ? OT_LONG : OT_WORD;
2736 val = ldub(s->pc++);
2737 gen_op_movl_T0_im(val);
2738 gen_op_in[ot]();
2739 gen_op_mov_reg_T1[ot][R_EAX]();
2740 break;
2741 case 0xe6:
2742 case 0xe7:
2743 if ((b & 1) == 0)
2744 ot = OT_BYTE;
2745 else
2746 ot = dflag ? OT_LONG : OT_WORD;
2747 val = ldub(s->pc++);
2748 gen_op_movl_T0_im(val);
2749 gen_op_mov_TN_reg[ot][1][R_EAX]();
2750 gen_op_out[ot]();
2751 break;
2752 case 0xec:
2753 case 0xed:
2754 if ((b & 1) == 0)
2755 ot = OT_BYTE;
2756 else
2757 ot = dflag ? OT_LONG : OT_WORD;
2758 gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
2759 gen_op_in[ot]();
2760 gen_op_mov_reg_T1[ot][R_EAX]();
2761 break;
2762 case 0xee:
2763 case 0xef:
2764 if ((b & 1) == 0)
2765 ot = OT_BYTE;
2766 else
2767 ot = dflag ? OT_LONG : OT_WORD;
2768 gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
2769 gen_op_mov_TN_reg[ot][1][R_EAX]();
2770 gen_op_out[ot]();
2771 break;
367e86e8
FB
2772
2773 /************************/
2774 /* control */
2775 case 0xc2: /* ret im */
367e86e8
FB
2776 val = ldsw(s->pc);
2777 s->pc += 2;
dab2ed99
FB
2778 gen_pop_T0(s);
2779 if (s->ss32)
2780 gen_op_addl_ESP_im(val + (2 << s->dflag));
2781 else
2782 gen_op_addw_ESP_im(val + (2 << s->dflag));
2783 if (s->dflag == 0)
2784 gen_op_andl_T0_ffff();
367e86e8 2785 gen_op_jmp_T0();
6dbad63e 2786 s->is_jmp = 1;
367e86e8
FB
2787 break;
2788 case 0xc3: /* ret */
dab2ed99
FB
2789 gen_pop_T0(s);
2790 gen_pop_update(s);
2791 if (s->dflag == 0)
2792 gen_op_andl_T0_ffff();
367e86e8 2793 gen_op_jmp_T0();
6dbad63e 2794 s->is_jmp = 1;
367e86e8 2795 break;
dab2ed99
FB
2796 case 0xca: /* lret im */
2797 val = ldsw(s->pc);
2798 s->pc += 2;
2799 /* pop offset */
2800 gen_pop_T0(s);
2801 if (s->dflag == 0)
2802 gen_op_andl_T0_ffff();
2803 gen_op_jmp_T0();
2804 gen_pop_update(s);
2805 /* pop selector */
2806 gen_pop_T0(s);
2807 gen_movl_seg_T0(s, R_CS);
2808 gen_pop_update(s);
2809 /* add stack offset */
2810 if (s->ss32)
2811 gen_op_addl_ESP_im(val + (2 << s->dflag));
2812 else
2813 gen_op_addw_ESP_im(val + (2 << s->dflag));
2814 s->is_jmp = 1;
2815 break;
2816 case 0xcb: /* lret */
2817 /* pop offset */
2818 gen_pop_T0(s);
2819 if (s->dflag == 0)
2820 gen_op_andl_T0_ffff();
2821 gen_op_jmp_T0();
2822 gen_pop_update(s);
2823 /* pop selector */
2824 gen_pop_T0(s);
2825 gen_movl_seg_T0(s, R_CS);
2826 gen_pop_update(s);
6dbad63e 2827 s->is_jmp = 1;
367e86e8 2828 break;
dab2ed99
FB
2829 case 0xe8: /* call im */
2830 {
2831 unsigned int next_eip;
2832 ot = dflag ? OT_LONG : OT_WORD;
2833 val = insn_get(s, ot);
2834 next_eip = s->pc - s->cs_base;
2835 val += next_eip;
2836 if (s->dflag == 0)
2837 val &= 0xffff;
2838 gen_op_movl_T0_im(next_eip);
2839 gen_push_T0(s);
2840 gen_op_jmp_im(val);
2841 s->is_jmp = 1;
2842 }
2843 break;
2844 case 0x9a: /* lcall im */
2845 {
2846 unsigned int selector, offset;
2847
2848 ot = dflag ? OT_LONG : OT_WORD;
2849 offset = insn_get(s, ot);
2850 selector = insn_get(s, OT_WORD);
2851
2852 /* push return segment + offset */
2853 gen_op_movl_T0_seg(R_CS);
2854 gen_push_T0(s);
2855 next_eip = s->pc - s->cs_base;
2856 gen_op_movl_T0_im(next_eip);
2857 gen_push_T0(s);
2858
2859 /* change cs and pc */
2860 gen_op_movl_T0_im(selector);
2861 gen_movl_seg_T0(s, R_CS);
2862 gen_op_jmp_im((unsigned long)offset);
2863 s->is_jmp = 1;
2864 }
2865 break;
367e86e8 2866 case 0xe9: /* jmp */
dab2ed99
FB
2867 ot = dflag ? OT_LONG : OT_WORD;
2868 val = insn_get(s, ot);
2869 val += s->pc - s->cs_base;
2870 if (s->dflag == 0)
2871 val = val & 0xffff;
367e86e8 2872 gen_op_jmp_im(val);
6dbad63e 2873 s->is_jmp = 1;
367e86e8 2874 break;
dab2ed99
FB
2875 case 0xea: /* ljmp im */
2876 {
2877 unsigned int selector, offset;
2878
2879 ot = dflag ? OT_LONG : OT_WORD;
2880 offset = insn_get(s, ot);
2881 selector = insn_get(s, OT_WORD);
2882
2883 /* change cs and pc */
2884 gen_op_movl_T0_im(selector);
2885 gen_movl_seg_T0(s, R_CS);
2886 gen_op_jmp_im((unsigned long)offset);
2887 s->is_jmp = 1;
2888 }
2889 break;
367e86e8
FB
2890 case 0xeb: /* jmp Jb */
2891 val = (int8_t)insn_get(s, OT_BYTE);
dab2ed99
FB
2892 val += s->pc - s->cs_base;
2893 if (s->dflag == 0)
2894 val = val & 0xffff;
367e86e8 2895 gen_op_jmp_im(val);
6dbad63e 2896 s->is_jmp = 1;
367e86e8
FB
2897 break;
2898 case 0x70 ... 0x7f: /* jcc Jb */
2899 val = (int8_t)insn_get(s, OT_BYTE);
367e86e8
FB
2900 goto do_jcc;
2901 case 0x180 ... 0x18f: /* jcc Jv */
2902 if (dflag) {
2903 val = insn_get(s, OT_LONG);
2904 } else {
2905 val = (int16_t)insn_get(s, OT_WORD);
2906 }
367e86e8 2907 do_jcc:
dab2ed99
FB
2908 next_eip = s->pc - s->cs_base;
2909 val += next_eip;
2910 if (s->dflag == 0)
2911 val &= 0xffff;
2912 gen_jcc(s, b, val, next_eip);
6dbad63e 2913 s->is_jmp = 1;
367e86e8
FB
2914 break;
2915
5dd9488c 2916 case 0x190 ... 0x19f: /* setcc Gv */
367e86e8
FB
2917 modrm = ldub(s->pc++);
2918 gen_setcc(s, b);
2919 gen_ldst_modrm(s, modrm, OT_BYTE, OR_TMP0, 1);
2920 break;
5dd9488c
FB
2921 case 0x140 ... 0x14f: /* cmov Gv, Ev */
2922 ot = dflag ? OT_LONG : OT_WORD;
2923 modrm = ldub(s->pc++);
2924 reg = (modrm >> 3) & 7;
2925 mod = (modrm >> 6) & 3;
2926 gen_setcc(s, b);
2927 if (mod != 3) {
2928 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2929 gen_op_ld_T1_A0[ot]();
2930 } else {
2931 rm = modrm & 7;
2932 gen_op_mov_TN_reg[ot][1][rm]();
2933 }
2934 gen_op_cmov_reg_T1_T0[ot - OT_WORD][reg]();
2935 break;
2936
367e86e8
FB
2937 /************************/
2938 /* flags */
2939 case 0x9c: /* pushf */
1017ebe9
FB
2940 if (s->cc_op != CC_OP_DYNAMIC)
2941 gen_op_set_cc_op(s->cc_op);
367e86e8 2942 gen_op_movl_T0_eflags();
dab2ed99 2943 gen_push_T0(s);
367e86e8
FB
2944 break;
2945 case 0x9d: /* popf */
dab2ed99 2946 gen_pop_T0(s);
367e86e8 2947 gen_op_movl_eflags_T0();
dab2ed99 2948 gen_pop_update(s);
367e86e8
FB
2949 s->cc_op = CC_OP_EFLAGS;
2950 break;
2951 case 0x9e: /* sahf */
2952 gen_op_mov_TN_reg[OT_BYTE][0][R_AH]();
2953 if (s->cc_op != CC_OP_DYNAMIC)
1017ebe9 2954 gen_op_set_cc_op(s->cc_op);
367e86e8
FB
2955 gen_op_movb_eflags_T0();
2956 s->cc_op = CC_OP_EFLAGS;
2957 break;
2958 case 0x9f: /* lahf */
2959 if (s->cc_op != CC_OP_DYNAMIC)
1017ebe9 2960 gen_op_set_cc_op(s->cc_op);
367e86e8
FB
2961 gen_op_movl_T0_eflags();
2962 gen_op_mov_reg_T0[OT_BYTE][R_AH]();
2963 break;
2964 case 0xf5: /* cmc */
2965 if (s->cc_op != CC_OP_DYNAMIC)
1017ebe9 2966 gen_op_set_cc_op(s->cc_op);
367e86e8
FB
2967 gen_op_cmc();
2968 s->cc_op = CC_OP_EFLAGS;
2969 break;
2970 case 0xf8: /* clc */
2971 if (s->cc_op != CC_OP_DYNAMIC)
1017ebe9 2972 gen_op_set_cc_op(s->cc_op);
367e86e8
FB
2973 gen_op_clc();
2974 s->cc_op = CC_OP_EFLAGS;
2975 break;
2976 case 0xf9: /* stc */
2977 if (s->cc_op != CC_OP_DYNAMIC)
1017ebe9 2978 gen_op_set_cc_op(s->cc_op);
367e86e8
FB
2979 gen_op_stc();
2980 s->cc_op = CC_OP_EFLAGS;
2981 break;
2982 case 0xfc: /* cld */
2983 gen_op_cld();
2984 break;
2985 case 0xfd: /* std */
2986 gen_op_std();
2987 break;
2988
4b74fe1f
FB
2989 /************************/
2990 /* bit operations */
2991 case 0x1ba: /* bt/bts/btr/btc Gv, im */
2992 ot = dflag ? OT_LONG : OT_WORD;
2993 modrm = ldub(s->pc++);
2994 op = (modrm >> 3) & 7;
2995 mod = (modrm >> 6) & 3;
2996 rm = modrm & 7;
2997 if (mod != 3) {
2998 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2999 gen_op_ld_T0_A0[ot]();
3000 } else {
3001 gen_op_mov_TN_reg[ot][0][rm]();
3002 }
3003 /* load shift */
3004 val = ldub(s->pc++);
3005 gen_op_movl_T1_im(val);
3006 if (op < 4)
1a9353d2 3007 goto illegal_op;
4b74fe1f
FB
3008 op -= 4;
3009 gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
d57c4e01 3010 s->cc_op = CC_OP_SARB + ot;
4b74fe1f
FB
3011 if (op != 0) {
3012 if (mod != 3)
3013 gen_op_st_T0_A0[ot]();
3014 else
3015 gen_op_mov_reg_T0[ot][rm]();
3016 }
3017 break;
3018 case 0x1a3: /* bt Gv, Ev */
3019 op = 0;
3020 goto do_btx;
3021 case 0x1ab: /* bts */
3022 op = 1;
3023 goto do_btx;
3024 case 0x1b3: /* btr */
3025 op = 2;
3026 goto do_btx;
3027 case 0x1bb: /* btc */
3028 op = 3;
3029 do_btx:
3030 ot = dflag ? OT_LONG : OT_WORD;
3031 modrm = ldub(s->pc++);
3032 reg = (modrm >> 3) & 7;
3033 mod = (modrm >> 6) & 3;
3034 rm = modrm & 7;
3035 gen_op_mov_TN_reg[OT_LONG][1][reg]();
3036 if (mod != 3) {
3037 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3038 /* specific case: we need to add a displacement */
3039 if (ot == OT_WORD)
3040 gen_op_add_bitw_A0_T1();
3041 else
3042 gen_op_add_bitl_A0_T1();
3043 gen_op_ld_T0_A0[ot]();
3044 } else {
3045 gen_op_mov_TN_reg[ot][0][rm]();
3046 }
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;
77f8dd5a
FB
3056 case 0x1bc: /* bsf */
3057 case 0x1bd: /* bsr */
3058 ot = dflag ? OT_LONG : OT_WORD;
3059 modrm = ldub(s->pc++);
3060 reg = (modrm >> 3) & 7;
3061 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
3062 gen_op_bsx_T0_cc[ot - OT_WORD][b & 1]();
3063 /* NOTE: we always write back the result. Intel doc says it is
3064 undefined if T0 == 0 */
3065 gen_op_mov_reg_T0[ot][reg]();
3066 s->cc_op = CC_OP_LOGICB + ot;
3067 break;
367e86e8 3068 /************************/
27362c82
FB
3069 /* bcd */
3070 case 0x27: /* daa */
3071 if (s->cc_op != CC_OP_DYNAMIC)
3072 gen_op_set_cc_op(s->cc_op);
3073 gen_op_daa();
3074 s->cc_op = CC_OP_EFLAGS;
3075 break;
3076 case 0x2f: /* das */
3077 if (s->cc_op != CC_OP_DYNAMIC)
3078 gen_op_set_cc_op(s->cc_op);
3079 gen_op_das();
3080 s->cc_op = CC_OP_EFLAGS;
3081 break;
3082 case 0x37: /* aaa */
3083 if (s->cc_op != CC_OP_DYNAMIC)
3084 gen_op_set_cc_op(s->cc_op);
3085 gen_op_aaa();
3086 s->cc_op = CC_OP_EFLAGS;
3087 break;
3088 case 0x3f: /* aas */
3089 if (s->cc_op != CC_OP_DYNAMIC)
3090 gen_op_set_cc_op(s->cc_op);
3091 gen_op_aas();
3092 s->cc_op = CC_OP_EFLAGS;
3093 break;
3094 case 0xd4: /* aam */
3095 val = ldub(s->pc++);
3096 gen_op_aam(val);
3097 s->cc_op = CC_OP_LOGICB;
3098 break;
3099 case 0xd5: /* aad */
3100 val = ldub(s->pc++);
3101 gen_op_aad(val);
3102 s->cc_op = CC_OP_LOGICB;
3103 break;
3104 /************************/
367e86e8
FB
3105 /* misc */
3106 case 0x90: /* nop */
3107 break;
0ecfa993
FB
3108 case 0xcc: /* int3 */
3109 gen_op_int3((long)pc_start);
6dbad63e 3110 s->is_jmp = 1;
0ecfa993
FB
3111 break;
3112 case 0xcd: /* int N */
3113 val = ldub(s->pc++);
3114 /* XXX: currently we ignore the interrupt number */
3115 gen_op_int_im((long)pc_start);
6dbad63e 3116 s->is_jmp = 1;
0ecfa993
FB
3117 break;
3118 case 0xce: /* into */
3119 if (s->cc_op != CC_OP_DYNAMIC)
3120 gen_op_set_cc_op(s->cc_op);
3121 gen_op_into((long)pc_start, (long)s->pc);
6dbad63e 3122 s->is_jmp = 1;
0ecfa993 3123 break;
4b74fe1f 3124 case 0x1c8 ... 0x1cf: /* bswap reg */
27362c82
FB
3125 reg = b & 7;
3126 gen_op_mov_TN_reg[OT_LONG][0][reg]();
3127 gen_op_bswapl_T0();
3128 gen_op_mov_reg_T0[OT_LONG][reg]();
3129 break;
3130 case 0xd6: /* salc */
3131 if (s->cc_op != CC_OP_DYNAMIC)
3132 gen_op_set_cc_op(s->cc_op);
3133 gen_op_salc();
3134 break;
1a9353d2
FB
3135 case 0xe0: /* loopnz */
3136 case 0xe1: /* loopz */
3137 if (s->cc_op != CC_OP_DYNAMIC)
3138 gen_op_set_cc_op(s->cc_op);
3139 /* FALL THRU */
3140 case 0xe2: /* loop */
3141 case 0xe3: /* jecxz */
3142 val = (int8_t)insn_get(s, OT_BYTE);
dab2ed99
FB
3143 next_eip = s->pc - s->cs_base;
3144 val += next_eip;
3145 if (s->dflag == 0)
3146 val &= 0xffff;
3147 gen_op_loop[s->aflag][b & 3](val, next_eip);
1a9353d2
FB
3148 s->is_jmp = 1;
3149 break;
5dd9488c 3150 case 0x131: /* rdtsc */
27362c82
FB
3151 gen_op_rdtsc();
3152 break;
0ecfa993 3153#if 0
367e86e8
FB
3154 case 0x1a2: /* cpuid */
3155 gen_insn0(OP_ASM);
3156 break;
3157#endif
3158 default:
1a9353d2 3159 goto illegal_op;
367e86e8 3160 }
1b6b029e
FB
3161 /* lock generation */
3162 if (s->prefix & PREFIX_LOCK)
3163 gen_op_unlock();
367e86e8 3164 return (long)s->pc;
6dbad63e 3165 illegal_op:
1b6b029e 3166 /* XXX: ensure that no lock was generated */
6dbad63e 3167 return -1;
367e86e8
FB
3168}
3169
dc99065b
FB
3170#define CC_OSZAPC (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C)
3171#define CC_OSZAP (CC_O | CC_S | CC_Z | CC_A | CC_P)
3172
3173/* flags read by an operation */
3174static uint16_t opc_read_flags[NB_OPS] = {
3175 [INDEX_op_aas] = CC_A,
3176 [INDEX_op_aaa] = CC_A,
3177 [INDEX_op_das] = CC_A | CC_C,
3178 [INDEX_op_daa] = CC_A | CC_C,
3179
3180 [INDEX_op_adcb_T0_T1_cc] = CC_C,
3181 [INDEX_op_adcw_T0_T1_cc] = CC_C,
3182 [INDEX_op_adcl_T0_T1_cc] = CC_C,
3183 [INDEX_op_sbbb_T0_T1_cc] = CC_C,
3184 [INDEX_op_sbbw_T0_T1_cc] = CC_C,
3185 [INDEX_op_sbbl_T0_T1_cc] = CC_C,
3186
3187 [INDEX_op_into] = CC_O,
3188
3189 [INDEX_op_jo_cc] = CC_O,
3190 [INDEX_op_jb_cc] = CC_C,
3191 [INDEX_op_jz_cc] = CC_Z,
3192 [INDEX_op_jbe_cc] = CC_Z | CC_C,
3193 [INDEX_op_js_cc] = CC_S,
3194 [INDEX_op_jp_cc] = CC_P,
3195 [INDEX_op_jl_cc] = CC_O | CC_S,
3196 [INDEX_op_jle_cc] = CC_O | CC_S | CC_Z,
3197
3198 [INDEX_op_jb_subb] = CC_C,
3199 [INDEX_op_jb_subw] = CC_C,
3200 [INDEX_op_jb_subl] = CC_C,
3201
3202 [INDEX_op_jz_subb] = CC_Z,
3203 [INDEX_op_jz_subw] = CC_Z,
3204 [INDEX_op_jz_subl] = CC_Z,
3205
3206 [INDEX_op_jbe_subb] = CC_Z | CC_C,
3207 [INDEX_op_jbe_subw] = CC_Z | CC_C,
3208 [INDEX_op_jbe_subl] = CC_Z | CC_C,
3209
3210 [INDEX_op_js_subb] = CC_S,
3211 [INDEX_op_js_subw] = CC_S,
3212 [INDEX_op_js_subl] = CC_S,
3213
3214 [INDEX_op_jl_subb] = CC_O | CC_S,
3215 [INDEX_op_jl_subw] = CC_O | CC_S,
3216 [INDEX_op_jl_subl] = CC_O | CC_S,
3217
3218 [INDEX_op_jle_subb] = CC_O | CC_S | CC_Z,
3219 [INDEX_op_jle_subw] = CC_O | CC_S | CC_Z,
3220 [INDEX_op_jle_subl] = CC_O | CC_S | CC_Z,
3221
3222 [INDEX_op_loopnzw] = CC_Z,
3223 [INDEX_op_loopnzl] = CC_Z,
3224 [INDEX_op_loopzw] = CC_Z,
3225 [INDEX_op_loopzl] = CC_Z,
3226
3227 [INDEX_op_seto_T0_cc] = CC_O,
3228 [INDEX_op_setb_T0_cc] = CC_C,
3229 [INDEX_op_setz_T0_cc] = CC_Z,
3230 [INDEX_op_setbe_T0_cc] = CC_Z | CC_C,
3231 [INDEX_op_sets_T0_cc] = CC_S,
3232 [INDEX_op_setp_T0_cc] = CC_P,
3233 [INDEX_op_setl_T0_cc] = CC_O | CC_S,
3234 [INDEX_op_setle_T0_cc] = CC_O | CC_S | CC_Z,
3235
3236 [INDEX_op_setb_T0_subb] = CC_C,
3237 [INDEX_op_setb_T0_subw] = CC_C,
3238 [INDEX_op_setb_T0_subl] = CC_C,
3239
3240 [INDEX_op_setz_T0_subb] = CC_Z,
3241 [INDEX_op_setz_T0_subw] = CC_Z,
3242 [INDEX_op_setz_T0_subl] = CC_Z,
3243
3244 [INDEX_op_setbe_T0_subb] = CC_Z | CC_C,
3245 [INDEX_op_setbe_T0_subw] = CC_Z | CC_C,
3246 [INDEX_op_setbe_T0_subl] = CC_Z | CC_C,
3247
3248 [INDEX_op_sets_T0_subb] = CC_S,
3249 [INDEX_op_sets_T0_subw] = CC_S,
3250 [INDEX_op_sets_T0_subl] = CC_S,
3251
3252 [INDEX_op_setl_T0_subb] = CC_O | CC_S,
3253 [INDEX_op_setl_T0_subw] = CC_O | CC_S,
3254 [INDEX_op_setl_T0_subl] = CC_O | CC_S,
3255
3256 [INDEX_op_setle_T0_subb] = CC_O | CC_S | CC_Z,
3257 [INDEX_op_setle_T0_subw] = CC_O | CC_S | CC_Z,
3258 [INDEX_op_setle_T0_subl] = CC_O | CC_S | CC_Z,
3259
3260 [INDEX_op_movl_T0_eflags] = CC_OSZAPC,
3261 [INDEX_op_cmc] = CC_C,
3262 [INDEX_op_salc] = CC_C,
3263
3264 [INDEX_op_rclb_T0_T1_cc] = CC_C,
3265 [INDEX_op_rclw_T0_T1_cc] = CC_C,
3266 [INDEX_op_rcll_T0_T1_cc] = CC_C,
3267 [INDEX_op_rcrb_T0_T1_cc] = CC_C,
3268 [INDEX_op_rcrw_T0_T1_cc] = CC_C,
3269 [INDEX_op_rcrl_T0_T1_cc] = CC_C,
3270};
3271
3272/* flags written by an operation */
3273static uint16_t opc_write_flags[NB_OPS] = {
3274 [INDEX_op_addl_T0_T1_cc] = CC_OSZAPC,
3275 [INDEX_op_orl_T0_T1_cc] = CC_OSZAPC,
3276 [INDEX_op_adcb_T0_T1_cc] = CC_OSZAPC,
3277 [INDEX_op_adcw_T0_T1_cc] = CC_OSZAPC,
3278 [INDEX_op_adcl_T0_T1_cc] = CC_OSZAPC,
3279 [INDEX_op_sbbb_T0_T1_cc] = CC_OSZAPC,
3280 [INDEX_op_sbbw_T0_T1_cc] = CC_OSZAPC,
3281 [INDEX_op_sbbl_T0_T1_cc] = CC_OSZAPC,
3282 [INDEX_op_andl_T0_T1_cc] = CC_OSZAPC,
3283 [INDEX_op_subl_T0_T1_cc] = CC_OSZAPC,
3284 [INDEX_op_xorl_T0_T1_cc] = CC_OSZAPC,
3285 [INDEX_op_cmpl_T0_T1_cc] = CC_OSZAPC,
3286 [INDEX_op_negl_T0_cc] = CC_OSZAPC,
3287 [INDEX_op_incl_T0_cc] = CC_OSZAP,
3288 [INDEX_op_decl_T0_cc] = CC_OSZAP,
3289 [INDEX_op_testl_T0_T1_cc] = CC_OSZAPC,
3290
3291 [INDEX_op_mulb_AL_T0] = CC_OSZAPC,
3292 [INDEX_op_imulb_AL_T0] = CC_OSZAPC,
3293 [INDEX_op_mulw_AX_T0] = CC_OSZAPC,
3294 [INDEX_op_imulw_AX_T0] = CC_OSZAPC,
3295 [INDEX_op_mull_EAX_T0] = CC_OSZAPC,
3296 [INDEX_op_imull_EAX_T0] = CC_OSZAPC,
3297 [INDEX_op_imulw_T0_T1] = CC_OSZAPC,
3298 [INDEX_op_imull_T0_T1] = CC_OSZAPC,
3299
3300 /* bcd */
3301 [INDEX_op_aam] = CC_OSZAPC,
3302 [INDEX_op_aad] = CC_OSZAPC,
3303 [INDEX_op_aas] = CC_OSZAPC,
3304 [INDEX_op_aaa] = CC_OSZAPC,
3305 [INDEX_op_das] = CC_OSZAPC,
3306 [INDEX_op_daa] = CC_OSZAPC,
3307
3308 [INDEX_op_movb_eflags_T0] = CC_S | CC_Z | CC_A | CC_P | CC_C,
3309 [INDEX_op_movl_eflags_T0] = CC_OSZAPC,
3310 [INDEX_op_clc] = CC_C,
3311 [INDEX_op_stc] = CC_C,
3312 [INDEX_op_cmc] = CC_C,
3313
3314 [INDEX_op_rolb_T0_T1_cc] = CC_O | CC_C,
3315 [INDEX_op_rolw_T0_T1_cc] = CC_O | CC_C,
3316 [INDEX_op_roll_T0_T1_cc] = CC_O | CC_C,
3317 [INDEX_op_rorb_T0_T1_cc] = CC_O | CC_C,
3318 [INDEX_op_rorw_T0_T1_cc] = CC_O | CC_C,
3319 [INDEX_op_rorl_T0_T1_cc] = CC_O | CC_C,
3320
3321 [INDEX_op_rclb_T0_T1_cc] = CC_O | CC_C,
3322 [INDEX_op_rclw_T0_T1_cc] = CC_O | CC_C,
3323 [INDEX_op_rcll_T0_T1_cc] = CC_O | CC_C,
3324 [INDEX_op_rcrb_T0_T1_cc] = CC_O | CC_C,
3325 [INDEX_op_rcrw_T0_T1_cc] = CC_O | CC_C,
3326 [INDEX_op_rcrl_T0_T1_cc] = CC_O | CC_C,
3327
3328 [INDEX_op_shlb_T0_T1_cc] = CC_OSZAPC,
3329 [INDEX_op_shlw_T0_T1_cc] = CC_OSZAPC,
3330 [INDEX_op_shll_T0_T1_cc] = CC_OSZAPC,
3331
3332 [INDEX_op_shrb_T0_T1_cc] = CC_OSZAPC,
3333 [INDEX_op_shrw_T0_T1_cc] = CC_OSZAPC,
3334 [INDEX_op_shrl_T0_T1_cc] = CC_OSZAPC,
3335
3336 [INDEX_op_sarb_T0_T1_cc] = CC_OSZAPC,
3337 [INDEX_op_sarw_T0_T1_cc] = CC_OSZAPC,
3338 [INDEX_op_sarl_T0_T1_cc] = CC_OSZAPC,
3339
3340 [INDEX_op_shldw_T0_T1_ECX_cc] = CC_OSZAPC,
3341 [INDEX_op_shldl_T0_T1_ECX_cc] = CC_OSZAPC,
3342 [INDEX_op_shldw_T0_T1_im_cc] = CC_OSZAPC,
3343 [INDEX_op_shldl_T0_T1_im_cc] = CC_OSZAPC,
3344
3345 [INDEX_op_shrdw_T0_T1_ECX_cc] = CC_OSZAPC,
3346 [INDEX_op_shrdl_T0_T1_ECX_cc] = CC_OSZAPC,
3347 [INDEX_op_shrdw_T0_T1_im_cc] = CC_OSZAPC,
3348 [INDEX_op_shrdl_T0_T1_im_cc] = CC_OSZAPC,
3349
3350 [INDEX_op_btw_T0_T1_cc] = CC_OSZAPC,
3351 [INDEX_op_btl_T0_T1_cc] = CC_OSZAPC,
3352 [INDEX_op_btsw_T0_T1_cc] = CC_OSZAPC,
3353 [INDEX_op_btsl_T0_T1_cc] = CC_OSZAPC,
3354 [INDEX_op_btrw_T0_T1_cc] = CC_OSZAPC,
3355 [INDEX_op_btrl_T0_T1_cc] = CC_OSZAPC,
3356 [INDEX_op_btcw_T0_T1_cc] = CC_OSZAPC,
3357 [INDEX_op_btcl_T0_T1_cc] = CC_OSZAPC,
3358
3359 [INDEX_op_bsfw_T0_cc] = CC_OSZAPC,
3360 [INDEX_op_bsfl_T0_cc] = CC_OSZAPC,
3361 [INDEX_op_bsrw_T0_cc] = CC_OSZAPC,
3362 [INDEX_op_bsrl_T0_cc] = CC_OSZAPC,
3363
3364 [INDEX_op_scasb] = CC_OSZAPC,
3365 [INDEX_op_scasw] = CC_OSZAPC,
3366 [INDEX_op_scasl] = CC_OSZAPC,
3367 [INDEX_op_repz_scasb] = CC_OSZAPC,
3368 [INDEX_op_repz_scasw] = CC_OSZAPC,
3369 [INDEX_op_repz_scasl] = CC_OSZAPC,
3370 [INDEX_op_repnz_scasb] = CC_OSZAPC,
3371 [INDEX_op_repnz_scasw] = CC_OSZAPC,
3372 [INDEX_op_repnz_scasl] = CC_OSZAPC,
3373
3374 [INDEX_op_cmpsb] = CC_OSZAPC,
3375 [INDEX_op_cmpsw] = CC_OSZAPC,
3376 [INDEX_op_cmpsl] = CC_OSZAPC,
3377 [INDEX_op_repz_cmpsb] = CC_OSZAPC,
3378 [INDEX_op_repz_cmpsw] = CC_OSZAPC,
3379 [INDEX_op_repz_cmpsl] = CC_OSZAPC,
3380 [INDEX_op_repnz_cmpsb] = CC_OSZAPC,
3381 [INDEX_op_repnz_cmpsw] = CC_OSZAPC,
3382 [INDEX_op_repnz_cmpsl] = CC_OSZAPC,
3383
3384 [INDEX_op_cmpxchgw_T0_T1_EAX_cc] = CC_OSZAPC,
3385 [INDEX_op_cmpxchgl_T0_T1_EAX_cc] = CC_OSZAPC,
3386};
3387
3388/* simpler form of an operation if no flags need to be generated */
3389static uint16_t opc_simpler[NB_OPS] = {
3390 [INDEX_op_addl_T0_T1_cc] = INDEX_op_addl_T0_T1,
3391 [INDEX_op_orl_T0_T1_cc] = INDEX_op_orl_T0_T1,
3392 [INDEX_op_andl_T0_T1_cc] = INDEX_op_andl_T0_T1,
3393 [INDEX_op_subl_T0_T1_cc] = INDEX_op_subl_T0_T1,
3394 [INDEX_op_xorl_T0_T1_cc] = INDEX_op_xorl_T0_T1,
3395 [INDEX_op_negl_T0_cc] = INDEX_op_negl_T0,
3396 [INDEX_op_incl_T0_cc] = INDEX_op_incl_T0,
3397 [INDEX_op_decl_T0_cc] = INDEX_op_decl_T0,
3398
3399 [INDEX_op_rolb_T0_T1_cc] = INDEX_op_rolb_T0_T1,
3400 [INDEX_op_rolw_T0_T1_cc] = INDEX_op_rolw_T0_T1,
3401 [INDEX_op_roll_T0_T1_cc] = INDEX_op_roll_T0_T1,
3402
3403 [INDEX_op_rorb_T0_T1_cc] = INDEX_op_rorb_T0_T1,
3404 [INDEX_op_rorw_T0_T1_cc] = INDEX_op_rorw_T0_T1,
3405 [INDEX_op_rorl_T0_T1_cc] = INDEX_op_rorl_T0_T1,
3406
3407 [INDEX_op_shlb_T0_T1_cc] = INDEX_op_shlb_T0_T1,
3408 [INDEX_op_shlw_T0_T1_cc] = INDEX_op_shlw_T0_T1,
3409 [INDEX_op_shll_T0_T1_cc] = INDEX_op_shll_T0_T1,
3410
3411 [INDEX_op_shrb_T0_T1_cc] = INDEX_op_shrb_T0_T1,
3412 [INDEX_op_shrw_T0_T1_cc] = INDEX_op_shrw_T0_T1,
3413 [INDEX_op_shrl_T0_T1_cc] = INDEX_op_shrl_T0_T1,
3414
3415 [INDEX_op_sarb_T0_T1_cc] = INDEX_op_sarb_T0_T1,
3416 [INDEX_op_sarw_T0_T1_cc] = INDEX_op_sarw_T0_T1,
3417 [INDEX_op_sarl_T0_T1_cc] = INDEX_op_sarl_T0_T1,
3418};
3419
3420static void optimize_flags_init(void)
3421{
3422 int i;
3423 /* put default values in arrays */
3424 for(i = 0; i < NB_OPS; i++) {
3425 if (opc_simpler[i] == 0)
3426 opc_simpler[i] = i;
3427 }
3428}
3429
3430/* CPU flags computation optimization: we move backward thru the
3431 generated code to see which flags are needed. The operation is
3432 modified if suitable */
3433static void optimize_flags(uint16_t *opc_buf, int opc_buf_len)
3434{
3435 uint16_t *opc_ptr;
3436 int live_flags, write_flags, op;
3437
3438 opc_ptr = opc_buf + opc_buf_len;
3439 /* live_flags contains the flags needed by the next instructions
3440 in the code. At the end of the bloc, we consider that all the
3441 flags are live. */
3442 live_flags = CC_OSZAPC;
3443 while (opc_ptr > opc_buf) {
3444 op = *--opc_ptr;
3445 /* if none of the flags written by the instruction is used,
3446 then we can try to find a simpler instruction */
3447 write_flags = opc_write_flags[op];
3448 if ((live_flags & write_flags) == 0) {
3449 *opc_ptr = opc_simpler[op];
3450 }
3451 /* compute the live flags before the instruction */
3452 live_flags &= ~write_flags;
3453 live_flags |= opc_read_flags[op];
3454 }
3455}
3456
3457
3458#ifdef DEBUG_DISAS
3459static const char *op_str[] = {
3460#define DEF(s) #s,
3461#include "opc-i386.h"
3462#undef DEF
3463};
3464
3465static void dump_ops(const uint16_t *opc_buf)
3466{
3467 const uint16_t *opc_ptr;
3468 int c;
3469 opc_ptr = opc_buf;
3470 for(;;) {
3471 c = *opc_ptr++;
3472 fprintf(logfile, "0x%04x: %s\n", opc_ptr - opc_buf - 1, op_str[c]);
3473 if (c == INDEX_op_end)
3474 break;
3475 }
3476}
3477
3478#endif
3479
3480/* XXX: make this buffer thread safe */
3481/* XXX: make safe guess about sizes */
3482#define MAX_OP_PER_INSTR 32
3483#define OPC_BUF_SIZE 512
3484#define OPC_MAX_SIZE (OPC_BUF_SIZE - MAX_OP_PER_INSTR)
3485
3486#define OPPARAM_BUF_SIZE (OPC_BUF_SIZE * 3)
3487
3488static uint16_t gen_opc_buf[OPC_BUF_SIZE];
3489static uint32_t gen_opparam_buf[OPPARAM_BUF_SIZE];
3490
9de5e440
FB
3491/* return non zero if the very first instruction is invalid so that
3492 the virtual CPU can trigger an exception. */
1017ebe9 3493int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size,
dab2ed99
FB
3494 int *gen_code_size_ptr,
3495 uint8_t *pc_start, uint8_t *cs_base, int flags)
ba1c6e37
FB
3496{
3497 DisasContext dc1, *dc = &dc1;
dc99065b
FB
3498 uint8_t *pc_ptr;
3499 uint16_t *gen_opc_end;
04369ff2 3500 int gen_code_size;
ba1c6e37 3501 long ret;
0ecfa993
FB
3502#ifdef DEBUG_DISAS
3503 struct disassemble_info disasm_info;
3504#endif
dc99065b
FB
3505
3506 /* generate intermediate code */
3507
6dbad63e 3508 dc->code32 = (flags >> GEN_FLAG_CODE32_SHIFT) & 1;
dab2ed99 3509 dc->ss32 = (flags >> GEN_FLAG_SS32_SHIFT) & 1;
6dbad63e
FB
3510 dc->addseg = (flags >> GEN_FLAG_ADDSEG_SHIFT) & 1;
3511 dc->f_st = (flags >> GEN_FLAG_ST_SHIFT) & 7;
ba1c6e37 3512 dc->cc_op = CC_OP_DYNAMIC;
dab2ed99 3513 dc->cs_base = cs_base;
dc99065b
FB
3514
3515 gen_opc_ptr = gen_opc_buf;
3516 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
3517 gen_opparam_ptr = gen_opparam_buf;
0ecfa993 3518
6dbad63e 3519 dc->is_jmp = 0;
1017ebe9
FB
3520 pc_ptr = pc_start;
3521 do {
6dbad63e 3522 ret = disas_insn(dc, pc_ptr);
1a9353d2 3523 if (ret == -1) {
9de5e440
FB
3524 /* we trigger an illegal instruction operation only if it
3525 is the first instruction. Otherwise, we simply stop
3526 generating the code just before it */
3527 if (pc_ptr == pc_start)
3528 return -1;
3529 else
3530 break;
1a9353d2 3531 }
1017ebe9 3532 pc_ptr = (void *)ret;
dc99065b 3533 } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end);
0ecfa993
FB
3534 /* we must store the eflags state if it is not already done */
3535 if (dc->cc_op != CC_OP_DYNAMIC)
3536 gen_op_set_cc_op(dc->cc_op);
6dbad63e 3537 if (dc->is_jmp != 1) {
0ecfa993 3538 /* we add an additionnal jmp to update the simulated PC */
dab2ed99 3539 gen_op_jmp_im(ret - (unsigned long)dc->cs_base);
0ecfa993 3540 }
dc99065b 3541 *gen_opc_ptr = INDEX_op_end;
0ecfa993 3542
dc99065b 3543 /* optimize flag computations */
0ecfa993 3544#ifdef DEBUG_DISAS
586314f2 3545 if (loglevel) {
0ecfa993
FB
3546 uint8_t *pc;
3547 int count;
3548
1017ebe9
FB
3549 INIT_DISASSEMBLE_INFO(disasm_info, logfile, fprintf);
3550#if 0
3551 disasm_info.flavour = bfd_get_flavour (abfd);
3552 disasm_info.arch = bfd_get_arch (abfd);
3553 disasm_info.mach = bfd_get_mach (abfd);
3554#endif
1017ebe9 3555 disasm_info.endian = BFD_ENDIAN_LITTLE;
dab2ed99
FB
3556 if (dc->code32)
3557 disasm_info.mach = bfd_mach_i386_i386;
3558 else
3559 disasm_info.mach = bfd_mach_i386_i8086;
dc99065b 3560 fprintf(logfile, "----------------\n");
1017ebe9
FB
3561 fprintf(logfile, "IN:\n");
3562 disasm_info.buffer = pc_start;
3563 disasm_info.buffer_vma = (unsigned long)pc_start;
3564 disasm_info.buffer_length = pc_ptr - pc_start;
3565 pc = pc_start;
3566 while (pc < pc_ptr) {
3567 fprintf(logfile, "0x%08lx: ", (long)pc);
3568 count = print_insn_i386((unsigned long)pc, &disasm_info);
3569 fprintf(logfile, "\n");
3570 pc += count;
3571 }
3572 fprintf(logfile, "\n");
3573
dc99065b
FB
3574 fprintf(logfile, "OP:\n");
3575 dump_ops(gen_opc_buf);
3576 fprintf(logfile, "\n");
3577 }
3578#endif
3579
3580 /* optimize flag computations */
3581 optimize_flags(gen_opc_buf, gen_opc_ptr - gen_opc_buf);
3582
3583#ifdef DEBUG_DISAS
3584 if (loglevel) {
3585 fprintf(logfile, "AFTER FLAGS OPT:\n");
3586 dump_ops(gen_opc_buf);
3587 fprintf(logfile, "\n");
3588 }
3589#endif
3590
3591 /* generate machine code */
04369ff2
FB
3592 gen_code_size = dyngen_code(gen_code_buf, gen_opc_buf, gen_opparam_buf);
3593 flush_icache_range((unsigned long)gen_code_buf, (unsigned long)(gen_code_buf + gen_code_size));
3594 *gen_code_size_ptr = gen_code_size;
dc99065b
FB
3595
3596#ifdef DEBUG_DISAS
3597 if (loglevel) {
3598 uint8_t *pc;
3599 int count;
3600
dab2ed99
FB
3601 INIT_DISASSEMBLE_INFO(disasm_info, logfile, fprintf);
3602#if 0
3603 disasm_info.flavour = bfd_get_flavour (abfd);
3604 disasm_info.arch = bfd_get_arch (abfd);
3605 disasm_info.mach = bfd_get_mach (abfd);
3606#endif
3607#ifdef WORDS_BIGENDIAN
3608 disasm_info.endian = BFD_ENDIAN_BIG;
3609#else
3610 disasm_info.endian = BFD_ENDIAN_LITTLE;
3611#endif
3612 disasm_info.mach = bfd_mach_i386_i386;
3613
0ecfa993
FB
3614 pc = gen_code_buf;
3615 disasm_info.buffer = pc;
3616 disasm_info.buffer_vma = (unsigned long)pc;
3617 disasm_info.buffer_length = *gen_code_size_ptr;
3618 fprintf(logfile, "OUT: [size=%d]\n", *gen_code_size_ptr);
dc99065b 3619 while (pc < gen_code_buf + *gen_code_size_ptr) {
0ecfa993
FB
3620 fprintf(logfile, "0x%08lx: ", (long)pc);
3621 count = print_insn_i386((unsigned long)pc, &disasm_info);
3622 fprintf(logfile, "\n");
3623 pc += count;
3624 }
3625 fprintf(logfile, "\n");
1b6b029e 3626 fflush(logfile);
0ecfa993
FB
3627 }
3628#endif
ba1c6e37
FB
3629 return 0;
3630}
3631
3632CPUX86State *cpu_x86_init(void)
3633{
3634 CPUX86State *env;
3635 int i;
dc99065b 3636 static int inited;
ba1c6e37 3637
7d13299d
FB
3638 cpu_x86_tblocks_init();
3639
ba1c6e37
FB
3640 env = malloc(sizeof(CPUX86State));
3641 if (!env)
3642 return NULL;
3643 memset(env, 0, sizeof(CPUX86State));
3644 /* basic FPU init */
3645 for(i = 0;i < 8; i++)
3646 env->fptags[i] = 1;
3647 env->fpuc = 0x37f;
3648 /* flags setup */
9de5e440 3649 env->eflags = 0;
dc99065b
FB
3650
3651 /* init various static tables */
3652 if (!inited) {
3653 inited = 1;
3654 optimize_flags_init();
3655 }
ba1c6e37
FB
3656 return env;
3657}
3658
3659void cpu_x86_close(CPUX86State *env)
3660{
3661 free(env);
3662}