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