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