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