]> git.proxmox.com Git - qemu.git/blob - translate-i386.c
ring 0 ops
[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,segs[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,segs[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,segs[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,segs[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 if (!s->addseg && seg_reg < R_FS)
1151 s->is_jmp = 2; /* abort translation because the register may
1152 have a non zero base */
1153 }
1154
1155 /* generate a push. It depends on ss32, addseg and dflag */
1156 static void gen_push_T0(DisasContext *s)
1157 {
1158 if (s->ss32) {
1159 if (!s->addseg) {
1160 if (s->dflag)
1161 gen_op_pushl_T0();
1162 else
1163 gen_op_pushw_T0();
1164 } else {
1165 if (s->dflag)
1166 gen_op_pushl_ss32_T0();
1167 else
1168 gen_op_pushw_ss32_T0();
1169 }
1170 } else {
1171 if (s->dflag)
1172 gen_op_pushl_ss16_T0();
1173 else
1174 gen_op_pushw_ss16_T0();
1175 }
1176 }
1177
1178 /* two step pop is necessary for precise exceptions */
1179 static void gen_pop_T0(DisasContext *s)
1180 {
1181 if (s->ss32) {
1182 if (!s->addseg) {
1183 if (s->dflag)
1184 gen_op_popl_T0();
1185 else
1186 gen_op_popw_T0();
1187 } else {
1188 if (s->dflag)
1189 gen_op_popl_ss32_T0();
1190 else
1191 gen_op_popw_ss32_T0();
1192 }
1193 } else {
1194 if (s->dflag)
1195 gen_op_popl_ss16_T0();
1196 else
1197 gen_op_popw_ss16_T0();
1198 }
1199 }
1200
1201 static inline void gen_stack_update(DisasContext *s, int addend)
1202 {
1203 if (s->ss32) {
1204 if (addend == 2)
1205 gen_op_addl_ESP_2();
1206 else if (addend == 4)
1207 gen_op_addl_ESP_4();
1208 else
1209 gen_op_addl_ESP_im(addend);
1210 } else {
1211 if (addend == 2)
1212 gen_op_addw_ESP_2();
1213 else if (addend == 4)
1214 gen_op_addw_ESP_4();
1215 else
1216 gen_op_addw_ESP_im(addend);
1217 }
1218 }
1219
1220 static void gen_pop_update(DisasContext *s)
1221 {
1222 gen_stack_update(s, 2 << s->dflag);
1223 }
1224
1225 static void gen_stack_A0(DisasContext *s)
1226 {
1227 gen_op_movl_A0_ESP();
1228 if (!s->ss32)
1229 gen_op_andl_A0_ffff();
1230 gen_op_movl_T1_A0();
1231 if (s->addseg)
1232 gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
1233 }
1234
1235 /* NOTE: wrap around in 16 bit not fully handled */
1236 static void gen_pusha(DisasContext *s)
1237 {
1238 int i;
1239 gen_op_movl_A0_ESP();
1240 gen_op_addl_A0_im(-16 << s->dflag);
1241 if (!s->ss32)
1242 gen_op_andl_A0_ffff();
1243 gen_op_movl_T1_A0();
1244 if (s->addseg)
1245 gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
1246 for(i = 0;i < 8; i++) {
1247 gen_op_mov_TN_reg[OT_LONG][0][7 - i]();
1248 gen_op_st_T0_A0[OT_WORD + s->dflag]();
1249 gen_op_addl_A0_im(2 << s->dflag);
1250 }
1251 gen_op_mov_reg_T1[OT_WORD + s->dflag][R_ESP]();
1252 }
1253
1254 /* NOTE: wrap around in 16 bit not fully handled */
1255 static void gen_popa(DisasContext *s)
1256 {
1257 int i;
1258 gen_op_movl_A0_ESP();
1259 if (!s->ss32)
1260 gen_op_andl_A0_ffff();
1261 gen_op_movl_T1_A0();
1262 gen_op_addl_T1_im(16 << s->dflag);
1263 if (s->addseg)
1264 gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
1265 for(i = 0;i < 8; i++) {
1266 /* ESP is not reloaded */
1267 if (i != 3) {
1268 gen_op_ld_T0_A0[OT_WORD + s->dflag]();
1269 gen_op_mov_reg_T0[OT_WORD + s->dflag][7 - i]();
1270 }
1271 gen_op_addl_A0_im(2 << s->dflag);
1272 }
1273 gen_op_mov_reg_T1[OT_WORD + s->dflag][R_ESP]();
1274 }
1275
1276 /* NOTE: wrap around in 16 bit not fully handled */
1277 /* XXX: check this */
1278 static void gen_enter(DisasContext *s, int esp_addend, int level)
1279 {
1280 int ot, level1, addend, opsize;
1281
1282 ot = s->dflag + OT_WORD;
1283 level &= 0x1f;
1284 level1 = level;
1285 opsize = 2 << s->dflag;
1286
1287 gen_op_movl_A0_ESP();
1288 gen_op_addl_A0_im(-opsize);
1289 if (!s->ss32)
1290 gen_op_andl_A0_ffff();
1291 gen_op_movl_T1_A0();
1292 if (s->addseg)
1293 gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
1294 /* push bp */
1295 gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
1296 gen_op_st_T0_A0[ot]();
1297 if (level) {
1298 while (level--) {
1299 gen_op_addl_A0_im(-opsize);
1300 gen_op_addl_T0_im(-opsize);
1301 gen_op_st_T0_A0[ot]();
1302 }
1303 gen_op_addl_A0_im(-opsize);
1304 /* XXX: add st_T1_A0 ? */
1305 gen_op_movl_T0_T1();
1306 gen_op_st_T0_A0[ot]();
1307 }
1308 gen_op_mov_reg_T1[ot][R_EBP]();
1309 addend = -esp_addend;
1310 if (level1)
1311 addend -= opsize * (level1 + 1);
1312 gen_op_addl_T1_im(addend);
1313 gen_op_mov_reg_T1[ot][R_ESP]();
1314 }
1315
1316 static void gen_exception(DisasContext *s, int trapno, unsigned int cur_eip)
1317 {
1318 if (s->cc_op != CC_OP_DYNAMIC)
1319 gen_op_set_cc_op(s->cc_op);
1320 gen_op_jmp_im(cur_eip);
1321 gen_op_raise_exception(trapno);
1322 s->is_jmp = 1;
1323 }
1324
1325 /* an interrupt is different from an exception because of the
1326 priviledge checks */
1327 static void gen_interrupt(DisasContext *s, int intno,
1328 unsigned int cur_eip, unsigned int next_eip)
1329 {
1330 if (s->cc_op != CC_OP_DYNAMIC)
1331 gen_op_set_cc_op(s->cc_op);
1332 gen_op_jmp_im(cur_eip);
1333 gen_op_raise_interrupt(intno, next_eip);
1334 s->is_jmp = 1;
1335 }
1336
1337 /* generate a jump to eip. No segment change must happen before as a
1338 direct call to the next block may occur */
1339 static void gen_jmp(DisasContext *s, unsigned int eip)
1340 {
1341 TranslationBlock *tb = s->tb;
1342
1343 if (s->cc_op != CC_OP_DYNAMIC)
1344 gen_op_set_cc_op(s->cc_op);
1345 gen_op_jmp_tb_next((long)tb, eip);
1346 s->is_jmp = 3;
1347 }
1348
1349 /* return the next pc address. Return -1 if no insn found. *is_jmp_ptr
1350 is set to true if the instruction sets the PC (last instruction of
1351 a basic block) */
1352 long disas_insn(DisasContext *s, uint8_t *pc_start)
1353 {
1354 int b, prefixes, aflag, dflag;
1355 int shift, ot;
1356 int modrm, reg, rm, mod, reg_addr, op, opreg, offset_addr, val;
1357 unsigned int next_eip;
1358
1359 s->pc = pc_start;
1360 prefixes = 0;
1361 aflag = s->code32;
1362 dflag = s->code32;
1363 s->override = -1;
1364 next_byte:
1365 b = ldub(s->pc);
1366 s->pc++;
1367 /* check prefixes */
1368 switch (b) {
1369 case 0xf3:
1370 prefixes |= PREFIX_REPZ;
1371 goto next_byte;
1372 case 0xf2:
1373 prefixes |= PREFIX_REPNZ;
1374 goto next_byte;
1375 case 0xf0:
1376 prefixes |= PREFIX_LOCK;
1377 goto next_byte;
1378 case 0x2e:
1379 s->override = R_CS;
1380 goto next_byte;
1381 case 0x36:
1382 s->override = R_SS;
1383 goto next_byte;
1384 case 0x3e:
1385 s->override = R_DS;
1386 goto next_byte;
1387 case 0x26:
1388 s->override = R_ES;
1389 goto next_byte;
1390 case 0x64:
1391 s->override = R_FS;
1392 goto next_byte;
1393 case 0x65:
1394 s->override = R_GS;
1395 goto next_byte;
1396 case 0x66:
1397 prefixes |= PREFIX_DATA;
1398 goto next_byte;
1399 case 0x67:
1400 prefixes |= PREFIX_ADR;
1401 goto next_byte;
1402 }
1403
1404 if (prefixes & PREFIX_DATA)
1405 dflag ^= 1;
1406 if (prefixes & PREFIX_ADR)
1407 aflag ^= 1;
1408
1409 s->prefix = prefixes;
1410 s->aflag = aflag;
1411 s->dflag = dflag;
1412
1413 /* lock generation */
1414 if (prefixes & PREFIX_LOCK)
1415 gen_op_lock();
1416
1417 /* now check op code */
1418 reswitch:
1419 switch(b) {
1420 case 0x0f:
1421 /**************************/
1422 /* extended op code */
1423 b = ldub(s->pc++) | 0x100;
1424 goto reswitch;
1425
1426 /**************************/
1427 /* arith & logic */
1428 case 0x00 ... 0x05:
1429 case 0x08 ... 0x0d:
1430 case 0x10 ... 0x15:
1431 case 0x18 ... 0x1d:
1432 case 0x20 ... 0x25:
1433 case 0x28 ... 0x2d:
1434 case 0x30 ... 0x35:
1435 case 0x38 ... 0x3d:
1436 {
1437 int op, f, val;
1438 op = (b >> 3) & 7;
1439 f = (b >> 1) & 3;
1440
1441 if ((b & 1) == 0)
1442 ot = OT_BYTE;
1443 else
1444 ot = dflag ? OT_LONG : OT_WORD;
1445
1446 switch(f) {
1447 case 0: /* OP Ev, Gv */
1448 modrm = ldub(s->pc++);
1449 reg = ((modrm >> 3) & 7) + OR_EAX;
1450 mod = (modrm >> 6) & 3;
1451 rm = modrm & 7;
1452 if (mod != 3) {
1453 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1454 gen_op_ld_T0_A0[ot]();
1455 opreg = OR_TMP0;
1456 } else {
1457 opreg = OR_EAX + rm;
1458 }
1459 gen_op(s, op, ot, opreg, reg);
1460 if (mod != 3 && op != 7) {
1461 gen_op_st_T0_A0[ot]();
1462 }
1463 break;
1464 case 1: /* OP Gv, Ev */
1465 modrm = ldub(s->pc++);
1466 mod = (modrm >> 6) & 3;
1467 reg = ((modrm >> 3) & 7) + OR_EAX;
1468 rm = modrm & 7;
1469 if (mod != 3) {
1470 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1471 gen_op_ld_T1_A0[ot]();
1472 opreg = OR_TMP1;
1473 } else {
1474 opreg = OR_EAX + rm;
1475 }
1476 gen_op(s, op, ot, reg, opreg);
1477 break;
1478 case 2: /* OP A, Iv */
1479 val = insn_get(s, ot);
1480 gen_opi(s, op, ot, OR_EAX, val);
1481 break;
1482 }
1483 }
1484 break;
1485
1486 case 0x80: /* GRP1 */
1487 case 0x81:
1488 case 0x83:
1489 {
1490 int val;
1491
1492 if ((b & 1) == 0)
1493 ot = OT_BYTE;
1494 else
1495 ot = dflag ? OT_LONG : OT_WORD;
1496
1497 modrm = ldub(s->pc++);
1498 mod = (modrm >> 6) & 3;
1499 rm = modrm & 7;
1500 op = (modrm >> 3) & 7;
1501
1502 if (mod != 3) {
1503 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1504 gen_op_ld_T0_A0[ot]();
1505 opreg = OR_TMP0;
1506 } else {
1507 opreg = rm + OR_EAX;
1508 }
1509
1510 switch(b) {
1511 default:
1512 case 0x80:
1513 case 0x81:
1514 val = insn_get(s, ot);
1515 break;
1516 case 0x83:
1517 val = (int8_t)insn_get(s, OT_BYTE);
1518 break;
1519 }
1520
1521 gen_opi(s, op, ot, opreg, val);
1522 if (op != 7 && mod != 3) {
1523 gen_op_st_T0_A0[ot]();
1524 }
1525 }
1526 break;
1527
1528 /**************************/
1529 /* inc, dec, and other misc arith */
1530 case 0x40 ... 0x47: /* inc Gv */
1531 ot = dflag ? OT_LONG : OT_WORD;
1532 gen_inc(s, ot, OR_EAX + (b & 7), 1);
1533 break;
1534 case 0x48 ... 0x4f: /* dec Gv */
1535 ot = dflag ? OT_LONG : OT_WORD;
1536 gen_inc(s, ot, OR_EAX + (b & 7), -1);
1537 break;
1538 case 0xf6: /* GRP3 */
1539 case 0xf7:
1540 if ((b & 1) == 0)
1541 ot = OT_BYTE;
1542 else
1543 ot = dflag ? OT_LONG : OT_WORD;
1544
1545 modrm = ldub(s->pc++);
1546 mod = (modrm >> 6) & 3;
1547 rm = modrm & 7;
1548 op = (modrm >> 3) & 7;
1549 if (mod != 3) {
1550 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1551 gen_op_ld_T0_A0[ot]();
1552 } else {
1553 gen_op_mov_TN_reg[ot][0][rm]();
1554 }
1555
1556 switch(op) {
1557 case 0: /* test */
1558 val = insn_get(s, ot);
1559 gen_op_movl_T1_im(val);
1560 gen_op_testl_T0_T1_cc();
1561 s->cc_op = CC_OP_LOGICB + ot;
1562 break;
1563 case 2: /* not */
1564 gen_op_notl_T0();
1565 if (mod != 3) {
1566 gen_op_st_T0_A0[ot]();
1567 } else {
1568 gen_op_mov_reg_T0[ot][rm]();
1569 }
1570 break;
1571 case 3: /* neg */
1572 gen_op_negl_T0_cc();
1573 if (mod != 3) {
1574 gen_op_st_T0_A0[ot]();
1575 } else {
1576 gen_op_mov_reg_T0[ot][rm]();
1577 }
1578 s->cc_op = CC_OP_SUBB + ot;
1579 break;
1580 case 4: /* mul */
1581 switch(ot) {
1582 case OT_BYTE:
1583 gen_op_mulb_AL_T0();
1584 break;
1585 case OT_WORD:
1586 gen_op_mulw_AX_T0();
1587 break;
1588 default:
1589 case OT_LONG:
1590 gen_op_mull_EAX_T0();
1591 break;
1592 }
1593 s->cc_op = CC_OP_MUL;
1594 break;
1595 case 5: /* imul */
1596 switch(ot) {
1597 case OT_BYTE:
1598 gen_op_imulb_AL_T0();
1599 break;
1600 case OT_WORD:
1601 gen_op_imulw_AX_T0();
1602 break;
1603 default:
1604 case OT_LONG:
1605 gen_op_imull_EAX_T0();
1606 break;
1607 }
1608 s->cc_op = CC_OP_MUL;
1609 break;
1610 case 6: /* div */
1611 switch(ot) {
1612 case OT_BYTE:
1613 gen_op_divb_AL_T0(pc_start - s->cs_base);
1614 break;
1615 case OT_WORD:
1616 gen_op_divw_AX_T0(pc_start - s->cs_base);
1617 break;
1618 default:
1619 case OT_LONG:
1620 gen_op_divl_EAX_T0(pc_start - s->cs_base);
1621 break;
1622 }
1623 break;
1624 case 7: /* idiv */
1625 switch(ot) {
1626 case OT_BYTE:
1627 gen_op_idivb_AL_T0(pc_start - s->cs_base);
1628 break;
1629 case OT_WORD:
1630 gen_op_idivw_AX_T0(pc_start - s->cs_base);
1631 break;
1632 default:
1633 case OT_LONG:
1634 gen_op_idivl_EAX_T0(pc_start - s->cs_base);
1635 break;
1636 }
1637 break;
1638 default:
1639 goto illegal_op;
1640 }
1641 break;
1642
1643 case 0xfe: /* GRP4 */
1644 case 0xff: /* GRP5 */
1645 if ((b & 1) == 0)
1646 ot = OT_BYTE;
1647 else
1648 ot = dflag ? OT_LONG : OT_WORD;
1649
1650 modrm = ldub(s->pc++);
1651 mod = (modrm >> 6) & 3;
1652 rm = modrm & 7;
1653 op = (modrm >> 3) & 7;
1654 if (op >= 2 && b == 0xfe) {
1655 goto illegal_op;
1656 }
1657 if (mod != 3) {
1658 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1659 if (op != 3 && op != 5)
1660 gen_op_ld_T0_A0[ot]();
1661 } else {
1662 gen_op_mov_TN_reg[ot][0][rm]();
1663 }
1664
1665 switch(op) {
1666 case 0: /* inc Ev */
1667 gen_inc(s, ot, OR_TMP0, 1);
1668 if (mod != 3)
1669 gen_op_st_T0_A0[ot]();
1670 else
1671 gen_op_mov_reg_T0[ot][rm]();
1672 break;
1673 case 1: /* dec Ev */
1674 gen_inc(s, ot, OR_TMP0, -1);
1675 if (mod != 3)
1676 gen_op_st_T0_A0[ot]();
1677 else
1678 gen_op_mov_reg_T0[ot][rm]();
1679 break;
1680 case 2: /* call Ev */
1681 /* XXX: optimize if memory (no and is necessary) */
1682 if (s->dflag == 0)
1683 gen_op_andl_T0_ffff();
1684 gen_op_jmp_T0();
1685 next_eip = s->pc - s->cs_base;
1686 gen_op_movl_T0_im(next_eip);
1687 gen_push_T0(s);
1688 s->is_jmp = 1;
1689 break;
1690 case 3: /* lcall Ev */
1691 /* push return segment + offset */
1692 gen_op_movl_T0_seg(R_CS);
1693 gen_push_T0(s);
1694 next_eip = s->pc - s->cs_base;
1695 gen_op_movl_T0_im(next_eip);
1696 gen_push_T0(s);
1697
1698 gen_op_ld_T1_A0[ot]();
1699 gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
1700 gen_op_lduw_T0_A0();
1701 gen_movl_seg_T0(s, R_CS, pc_start - s->cs_base);
1702 gen_op_movl_T0_T1();
1703 gen_op_jmp_T0();
1704 s->is_jmp = 1;
1705 break;
1706 case 4: /* jmp Ev */
1707 if (s->dflag == 0)
1708 gen_op_andl_T0_ffff();
1709 gen_op_jmp_T0();
1710 s->is_jmp = 1;
1711 break;
1712 case 5: /* ljmp Ev */
1713 gen_op_ld_T1_A0[ot]();
1714 gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
1715 gen_op_lduw_T0_A0();
1716 if (!s->vm86) {
1717 /* we compute EIP to handle the exception case */
1718 gen_op_jmp_im(pc_start - s->cs_base);
1719 gen_op_ljmp_T0_T1();
1720 } else {
1721 gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[R_CS]));
1722 gen_op_movl_T0_T1();
1723 gen_op_jmp_T0();
1724 }
1725 s->is_jmp = 1;
1726 break;
1727 case 6: /* push Ev */
1728 gen_push_T0(s);
1729 break;
1730 default:
1731 goto illegal_op;
1732 }
1733 break;
1734
1735 case 0x84: /* test Ev, Gv */
1736 case 0x85:
1737 if ((b & 1) == 0)
1738 ot = OT_BYTE;
1739 else
1740 ot = dflag ? OT_LONG : OT_WORD;
1741
1742 modrm = ldub(s->pc++);
1743 mod = (modrm >> 6) & 3;
1744 rm = modrm & 7;
1745 reg = (modrm >> 3) & 7;
1746
1747 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1748 gen_op_mov_TN_reg[ot][1][reg + OR_EAX]();
1749 gen_op_testl_T0_T1_cc();
1750 s->cc_op = CC_OP_LOGICB + ot;
1751 break;
1752
1753 case 0xa8: /* test eAX, Iv */
1754 case 0xa9:
1755 if ((b & 1) == 0)
1756 ot = OT_BYTE;
1757 else
1758 ot = dflag ? OT_LONG : OT_WORD;
1759 val = insn_get(s, ot);
1760
1761 gen_op_mov_TN_reg[ot][0][OR_EAX]();
1762 gen_op_movl_T1_im(val);
1763 gen_op_testl_T0_T1_cc();
1764 s->cc_op = CC_OP_LOGICB + ot;
1765 break;
1766
1767 case 0x98: /* CWDE/CBW */
1768 if (dflag)
1769 gen_op_movswl_EAX_AX();
1770 else
1771 gen_op_movsbw_AX_AL();
1772 break;
1773 case 0x99: /* CDQ/CWD */
1774 if (dflag)
1775 gen_op_movslq_EDX_EAX();
1776 else
1777 gen_op_movswl_DX_AX();
1778 break;
1779 case 0x1af: /* imul Gv, Ev */
1780 case 0x69: /* imul Gv, Ev, I */
1781 case 0x6b:
1782 ot = dflag ? OT_LONG : OT_WORD;
1783 modrm = ldub(s->pc++);
1784 reg = ((modrm >> 3) & 7) + OR_EAX;
1785 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1786 if (b == 0x69) {
1787 val = insn_get(s, ot);
1788 gen_op_movl_T1_im(val);
1789 } else if (b == 0x6b) {
1790 val = insn_get(s, OT_BYTE);
1791 gen_op_movl_T1_im(val);
1792 } else {
1793 gen_op_mov_TN_reg[ot][1][reg]();
1794 }
1795
1796 if (ot == OT_LONG) {
1797 gen_op_imull_T0_T1();
1798 } else {
1799 gen_op_imulw_T0_T1();
1800 }
1801 gen_op_mov_reg_T0[ot][reg]();
1802 s->cc_op = CC_OP_MUL;
1803 break;
1804 case 0x1c0:
1805 case 0x1c1: /* xadd Ev, Gv */
1806 if ((b & 1) == 0)
1807 ot = OT_BYTE;
1808 else
1809 ot = dflag ? OT_LONG : OT_WORD;
1810 modrm = ldub(s->pc++);
1811 reg = (modrm >> 3) & 7;
1812 mod = (modrm >> 6) & 3;
1813 if (mod == 3) {
1814 rm = modrm & 7;
1815 gen_op_mov_TN_reg[ot][0][reg]();
1816 gen_op_mov_TN_reg[ot][1][rm]();
1817 gen_op_addl_T0_T1_cc();
1818 gen_op_mov_reg_T0[ot][rm]();
1819 gen_op_mov_reg_T1[ot][reg]();
1820 } else {
1821 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1822 gen_op_mov_TN_reg[ot][0][reg]();
1823 gen_op_ld_T1_A0[ot]();
1824 gen_op_addl_T0_T1_cc();
1825 gen_op_st_T0_A0[ot]();
1826 gen_op_mov_reg_T1[ot][reg]();
1827 }
1828 s->cc_op = CC_OP_ADDB + ot;
1829 break;
1830 case 0x1b0:
1831 case 0x1b1: /* cmpxchg Ev, Gv */
1832 if ((b & 1) == 0)
1833 ot = OT_BYTE;
1834 else
1835 ot = dflag ? OT_LONG : OT_WORD;
1836 modrm = ldub(s->pc++);
1837 reg = (modrm >> 3) & 7;
1838 mod = (modrm >> 6) & 3;
1839 gen_op_mov_TN_reg[ot][1][reg]();
1840 if (mod == 3) {
1841 rm = modrm & 7;
1842 gen_op_mov_TN_reg[ot][0][rm]();
1843 gen_op_cmpxchg_T0_T1_EAX_cc[ot]();
1844 gen_op_mov_reg_T0[ot][rm]();
1845 } else {
1846 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1847 gen_op_ld_T0_A0[ot]();
1848 gen_op_cmpxchg_T0_T1_EAX_cc[ot]();
1849 gen_op_st_T0_A0[ot]();
1850 }
1851 s->cc_op = CC_OP_SUBB + ot;
1852 break;
1853 case 0x1c7: /* cmpxchg8b */
1854 modrm = ldub(s->pc++);
1855 mod = (modrm >> 6) & 3;
1856 if (mod == 3)
1857 goto illegal_op;
1858 if (s->cc_op != CC_OP_DYNAMIC)
1859 gen_op_set_cc_op(s->cc_op);
1860 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1861 gen_op_cmpxchg8b();
1862 s->cc_op = CC_OP_EFLAGS;
1863 break;
1864
1865 /**************************/
1866 /* push/pop */
1867 case 0x50 ... 0x57: /* push */
1868 gen_op_mov_TN_reg[OT_LONG][0][b & 7]();
1869 gen_push_T0(s);
1870 break;
1871 case 0x58 ... 0x5f: /* pop */
1872 ot = dflag ? OT_LONG : OT_WORD;
1873 gen_pop_T0(s);
1874 gen_op_mov_reg_T0[ot][b & 7]();
1875 gen_pop_update(s);
1876 break;
1877 case 0x60: /* pusha */
1878 gen_pusha(s);
1879 break;
1880 case 0x61: /* popa */
1881 gen_popa(s);
1882 break;
1883 case 0x68: /* push Iv */
1884 case 0x6a:
1885 ot = dflag ? OT_LONG : OT_WORD;
1886 if (b == 0x68)
1887 val = insn_get(s, ot);
1888 else
1889 val = (int8_t)insn_get(s, OT_BYTE);
1890 gen_op_movl_T0_im(val);
1891 gen_push_T0(s);
1892 break;
1893 case 0x8f: /* pop Ev */
1894 ot = dflag ? OT_LONG : OT_WORD;
1895 modrm = ldub(s->pc++);
1896 gen_pop_T0(s);
1897 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
1898 gen_pop_update(s);
1899 break;
1900 case 0xc8: /* enter */
1901 {
1902 int level;
1903 val = lduw(s->pc);
1904 s->pc += 2;
1905 level = ldub(s->pc++);
1906 gen_enter(s, val, level);
1907 }
1908 break;
1909 case 0xc9: /* leave */
1910 /* XXX: exception not precise (ESP is updated before potential exception) */
1911 if (s->ss32) {
1912 gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
1913 gen_op_mov_reg_T0[OT_LONG][R_ESP]();
1914 } else {
1915 gen_op_mov_TN_reg[OT_WORD][0][R_EBP]();
1916 gen_op_mov_reg_T0[OT_WORD][R_ESP]();
1917 }
1918 gen_pop_T0(s);
1919 ot = dflag ? OT_LONG : OT_WORD;
1920 gen_op_mov_reg_T0[ot][R_EBP]();
1921 gen_pop_update(s);
1922 break;
1923 case 0x06: /* push es */
1924 case 0x0e: /* push cs */
1925 case 0x16: /* push ss */
1926 case 0x1e: /* push ds */
1927 gen_op_movl_T0_seg(b >> 3);
1928 gen_push_T0(s);
1929 break;
1930 case 0x1a0: /* push fs */
1931 case 0x1a8: /* push gs */
1932 gen_op_movl_T0_seg((b >> 3) & 7);
1933 gen_push_T0(s);
1934 break;
1935 case 0x07: /* pop es */
1936 case 0x17: /* pop ss */
1937 case 0x1f: /* pop ds */
1938 gen_pop_T0(s);
1939 gen_movl_seg_T0(s, b >> 3, pc_start - s->cs_base);
1940 gen_pop_update(s);
1941 break;
1942 case 0x1a1: /* pop fs */
1943 case 0x1a9: /* pop gs */
1944 gen_pop_T0(s);
1945 gen_movl_seg_T0(s, (b >> 3) & 7, pc_start - s->cs_base);
1946 gen_pop_update(s);
1947 break;
1948
1949 /**************************/
1950 /* mov */
1951 case 0x88:
1952 case 0x89: /* mov Gv, Ev */
1953 if ((b & 1) == 0)
1954 ot = OT_BYTE;
1955 else
1956 ot = dflag ? OT_LONG : OT_WORD;
1957 modrm = ldub(s->pc++);
1958 reg = (modrm >> 3) & 7;
1959
1960 /* generate a generic store */
1961 gen_ldst_modrm(s, modrm, ot, OR_EAX + reg, 1);
1962 break;
1963 case 0xc6:
1964 case 0xc7: /* mov Ev, Iv */
1965 if ((b & 1) == 0)
1966 ot = OT_BYTE;
1967 else
1968 ot = dflag ? OT_LONG : OT_WORD;
1969 modrm = ldub(s->pc++);
1970 mod = (modrm >> 6) & 3;
1971 if (mod != 3)
1972 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1973 val = insn_get(s, ot);
1974 gen_op_movl_T0_im(val);
1975 if (mod != 3)
1976 gen_op_st_T0_A0[ot]();
1977 else
1978 gen_op_mov_reg_T0[ot][modrm & 7]();
1979 break;
1980 case 0x8a:
1981 case 0x8b: /* mov Ev, Gv */
1982 if ((b & 1) == 0)
1983 ot = OT_BYTE;
1984 else
1985 ot = dflag ? OT_LONG : OT_WORD;
1986 modrm = ldub(s->pc++);
1987 reg = (modrm >> 3) & 7;
1988
1989 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1990 gen_op_mov_reg_T0[ot][reg]();
1991 break;
1992 case 0x8e: /* mov seg, Gv */
1993 ot = dflag ? OT_LONG : OT_WORD;
1994 modrm = ldub(s->pc++);
1995 reg = (modrm >> 3) & 7;
1996 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1997 if (reg >= 6 || reg == R_CS)
1998 goto illegal_op;
1999 gen_movl_seg_T0(s, reg, pc_start - s->cs_base);
2000 break;
2001 case 0x8c: /* mov Gv, seg */
2002 ot = dflag ? OT_LONG : OT_WORD;
2003 modrm = ldub(s->pc++);
2004 reg = (modrm >> 3) & 7;
2005 if (reg >= 6)
2006 goto illegal_op;
2007 gen_op_movl_T0_seg(reg);
2008 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
2009 break;
2010
2011 case 0x1b6: /* movzbS Gv, Eb */
2012 case 0x1b7: /* movzwS Gv, Eb */
2013 case 0x1be: /* movsbS Gv, Eb */
2014 case 0x1bf: /* movswS Gv, Eb */
2015 {
2016 int d_ot;
2017 /* d_ot is the size of destination */
2018 d_ot = dflag + OT_WORD;
2019 /* ot is the size of source */
2020 ot = (b & 1) + OT_BYTE;
2021 modrm = ldub(s->pc++);
2022 reg = ((modrm >> 3) & 7) + OR_EAX;
2023 mod = (modrm >> 6) & 3;
2024 rm = modrm & 7;
2025
2026 if (mod == 3) {
2027 gen_op_mov_TN_reg[ot][0][rm]();
2028 switch(ot | (b & 8)) {
2029 case OT_BYTE:
2030 gen_op_movzbl_T0_T0();
2031 break;
2032 case OT_BYTE | 8:
2033 gen_op_movsbl_T0_T0();
2034 break;
2035 case OT_WORD:
2036 gen_op_movzwl_T0_T0();
2037 break;
2038 default:
2039 case OT_WORD | 8:
2040 gen_op_movswl_T0_T0();
2041 break;
2042 }
2043 gen_op_mov_reg_T0[d_ot][reg]();
2044 } else {
2045 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2046 if (b & 8) {
2047 gen_op_lds_T0_A0[ot]();
2048 } else {
2049 gen_op_ldu_T0_A0[ot]();
2050 }
2051 gen_op_mov_reg_T0[d_ot][reg]();
2052 }
2053 }
2054 break;
2055
2056 case 0x8d: /* lea */
2057 ot = dflag ? OT_LONG : OT_WORD;
2058 modrm = ldub(s->pc++);
2059 reg = (modrm >> 3) & 7;
2060 /* we must ensure that no segment is added */
2061 s->override = -1;
2062 val = s->addseg;
2063 s->addseg = 0;
2064 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2065 s->addseg = val;
2066 gen_op_mov_reg_A0[ot - OT_WORD][reg]();
2067 break;
2068
2069 case 0xa0: /* mov EAX, Ov */
2070 case 0xa1:
2071 case 0xa2: /* mov Ov, EAX */
2072 case 0xa3:
2073 if ((b & 1) == 0)
2074 ot = OT_BYTE;
2075 else
2076 ot = dflag ? OT_LONG : OT_WORD;
2077 if (s->aflag)
2078 offset_addr = insn_get(s, OT_LONG);
2079 else
2080 offset_addr = insn_get(s, OT_WORD);
2081 gen_op_movl_A0_im(offset_addr);
2082 /* handle override */
2083 {
2084 int override, must_add_seg;
2085 must_add_seg = s->addseg;
2086 if (s->override >= 0) {
2087 override = s->override;
2088 must_add_seg = 1;
2089 } else {
2090 override = R_DS;
2091 }
2092 if (must_add_seg) {
2093 gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base));
2094 }
2095 }
2096 if ((b & 2) == 0) {
2097 gen_op_ld_T0_A0[ot]();
2098 gen_op_mov_reg_T0[ot][R_EAX]();
2099 } else {
2100 gen_op_mov_TN_reg[ot][0][R_EAX]();
2101 gen_op_st_T0_A0[ot]();
2102 }
2103 break;
2104 case 0xd7: /* xlat */
2105 gen_op_movl_A0_reg[R_EBX]();
2106 gen_op_addl_A0_AL();
2107 if (s->aflag == 0)
2108 gen_op_andl_A0_ffff();
2109 /* handle override */
2110 {
2111 int override, must_add_seg;
2112 must_add_seg = s->addseg;
2113 override = R_DS;
2114 if (s->override >= 0) {
2115 override = s->override;
2116 must_add_seg = 1;
2117 } else {
2118 override = R_DS;
2119 }
2120 if (must_add_seg) {
2121 gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base));
2122 }
2123 }
2124 gen_op_ldub_T0_A0();
2125 gen_op_mov_reg_T0[OT_BYTE][R_EAX]();
2126 break;
2127 case 0xb0 ... 0xb7: /* mov R, Ib */
2128 val = insn_get(s, OT_BYTE);
2129 gen_op_movl_T0_im(val);
2130 gen_op_mov_reg_T0[OT_BYTE][b & 7]();
2131 break;
2132 case 0xb8 ... 0xbf: /* mov R, Iv */
2133 ot = dflag ? OT_LONG : OT_WORD;
2134 val = insn_get(s, ot);
2135 reg = OR_EAX + (b & 7);
2136 gen_op_movl_T0_im(val);
2137 gen_op_mov_reg_T0[ot][reg]();
2138 break;
2139
2140 case 0x91 ... 0x97: /* xchg R, EAX */
2141 ot = dflag ? OT_LONG : OT_WORD;
2142 reg = b & 7;
2143 rm = R_EAX;
2144 goto do_xchg_reg;
2145 case 0x86:
2146 case 0x87: /* xchg Ev, Gv */
2147 if ((b & 1) == 0)
2148 ot = OT_BYTE;
2149 else
2150 ot = dflag ? OT_LONG : OT_WORD;
2151 modrm = ldub(s->pc++);
2152 reg = (modrm >> 3) & 7;
2153 mod = (modrm >> 6) & 3;
2154 if (mod == 3) {
2155 rm = modrm & 7;
2156 do_xchg_reg:
2157 gen_op_mov_TN_reg[ot][0][reg]();
2158 gen_op_mov_TN_reg[ot][1][rm]();
2159 gen_op_mov_reg_T0[ot][rm]();
2160 gen_op_mov_reg_T1[ot][reg]();
2161 } else {
2162 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2163 gen_op_mov_TN_reg[ot][0][reg]();
2164 /* for xchg, lock is implicit */
2165 if (!(prefixes & PREFIX_LOCK))
2166 gen_op_lock();
2167 gen_op_ld_T1_A0[ot]();
2168 gen_op_st_T0_A0[ot]();
2169 if (!(prefixes & PREFIX_LOCK))
2170 gen_op_unlock();
2171 gen_op_mov_reg_T1[ot][reg]();
2172 }
2173 break;
2174 case 0xc4: /* les Gv */
2175 op = R_ES;
2176 goto do_lxx;
2177 case 0xc5: /* lds Gv */
2178 op = R_DS;
2179 goto do_lxx;
2180 case 0x1b2: /* lss Gv */
2181 op = R_SS;
2182 goto do_lxx;
2183 case 0x1b4: /* lfs Gv */
2184 op = R_FS;
2185 goto do_lxx;
2186 case 0x1b5: /* lgs Gv */
2187 op = R_GS;
2188 do_lxx:
2189 ot = dflag ? OT_LONG : OT_WORD;
2190 modrm = ldub(s->pc++);
2191 reg = (modrm >> 3) & 7;
2192 mod = (modrm >> 6) & 3;
2193 if (mod == 3)
2194 goto illegal_op;
2195 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2196 gen_op_ld_T1_A0[ot]();
2197 gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
2198 /* load the segment first to handle exceptions properly */
2199 gen_op_lduw_T0_A0();
2200 gen_movl_seg_T0(s, op, pc_start - s->cs_base);
2201 /* then put the data */
2202 gen_op_mov_reg_T1[ot][reg]();
2203 break;
2204
2205 /************************/
2206 /* shifts */
2207 case 0xc0:
2208 case 0xc1:
2209 /* shift Ev,Ib */
2210 shift = 2;
2211 grp2:
2212 {
2213 if ((b & 1) == 0)
2214 ot = OT_BYTE;
2215 else
2216 ot = dflag ? OT_LONG : OT_WORD;
2217
2218 modrm = ldub(s->pc++);
2219 mod = (modrm >> 6) & 3;
2220 rm = modrm & 7;
2221 op = (modrm >> 3) & 7;
2222
2223 if (mod != 3) {
2224 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2225 gen_op_ld_T0_A0[ot]();
2226 opreg = OR_TMP0;
2227 } else {
2228 opreg = rm + OR_EAX;
2229 }
2230
2231 /* simpler op */
2232 if (shift == 0) {
2233 gen_shift(s, op, ot, opreg, OR_ECX);
2234 } else {
2235 if (shift == 2) {
2236 shift = ldub(s->pc++);
2237 }
2238 gen_shifti(s, op, ot, opreg, shift);
2239 }
2240
2241 if (mod != 3) {
2242 gen_op_st_T0_A0[ot]();
2243 }
2244 }
2245 break;
2246 case 0xd0:
2247 case 0xd1:
2248 /* shift Ev,1 */
2249 shift = 1;
2250 goto grp2;
2251 case 0xd2:
2252 case 0xd3:
2253 /* shift Ev,cl */
2254 shift = 0;
2255 goto grp2;
2256
2257 case 0x1a4: /* shld imm */
2258 op = 0;
2259 shift = 1;
2260 goto do_shiftd;
2261 case 0x1a5: /* shld cl */
2262 op = 0;
2263 shift = 0;
2264 goto do_shiftd;
2265 case 0x1ac: /* shrd imm */
2266 op = 1;
2267 shift = 1;
2268 goto do_shiftd;
2269 case 0x1ad: /* shrd cl */
2270 op = 1;
2271 shift = 0;
2272 do_shiftd:
2273 ot = dflag ? OT_LONG : OT_WORD;
2274 modrm = ldub(s->pc++);
2275 mod = (modrm >> 6) & 3;
2276 rm = modrm & 7;
2277 reg = (modrm >> 3) & 7;
2278
2279 if (mod != 3) {
2280 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2281 gen_op_ld_T0_A0[ot]();
2282 } else {
2283 gen_op_mov_TN_reg[ot][0][rm]();
2284 }
2285 gen_op_mov_TN_reg[ot][1][reg]();
2286
2287 if (shift) {
2288 val = ldub(s->pc++);
2289 val &= 0x1f;
2290 if (val) {
2291 gen_op_shiftd_T0_T1_im_cc[ot - OT_WORD][op](val);
2292 if (op == 0 && ot != OT_WORD)
2293 s->cc_op = CC_OP_SHLB + ot;
2294 else
2295 s->cc_op = CC_OP_SARB + ot;
2296 }
2297 } else {
2298 if (s->cc_op != CC_OP_DYNAMIC)
2299 gen_op_set_cc_op(s->cc_op);
2300 gen_op_shiftd_T0_T1_ECX_cc[ot - OT_WORD][op]();
2301 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2302 }
2303 if (mod != 3) {
2304 gen_op_st_T0_A0[ot]();
2305 } else {
2306 gen_op_mov_reg_T0[ot][rm]();
2307 }
2308 break;
2309
2310 /************************/
2311 /* floats */
2312 case 0xd8 ... 0xdf:
2313 modrm = ldub(s->pc++);
2314 mod = (modrm >> 6) & 3;
2315 rm = modrm & 7;
2316 op = ((b & 7) << 3) | ((modrm >> 3) & 7);
2317
2318 if (mod != 3) {
2319 /* memory op */
2320 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2321 switch(op) {
2322 case 0x00 ... 0x07: /* fxxxs */
2323 case 0x10 ... 0x17: /* fixxxl */
2324 case 0x20 ... 0x27: /* fxxxl */
2325 case 0x30 ... 0x37: /* fixxx */
2326 {
2327 int op1;
2328 op1 = op & 7;
2329
2330 switch(op >> 4) {
2331 case 0:
2332 gen_op_flds_FT0_A0();
2333 break;
2334 case 1:
2335 gen_op_fildl_FT0_A0();
2336 break;
2337 case 2:
2338 gen_op_fldl_FT0_A0();
2339 break;
2340 case 3:
2341 default:
2342 gen_op_fild_FT0_A0();
2343 break;
2344 }
2345
2346 gen_op_fp_arith_ST0_FT0[op1]();
2347 if (op1 == 3) {
2348 /* fcomp needs pop */
2349 gen_op_fpop();
2350 }
2351 }
2352 break;
2353 case 0x08: /* flds */
2354 case 0x0a: /* fsts */
2355 case 0x0b: /* fstps */
2356 case 0x18: /* fildl */
2357 case 0x1a: /* fistl */
2358 case 0x1b: /* fistpl */
2359 case 0x28: /* fldl */
2360 case 0x2a: /* fstl */
2361 case 0x2b: /* fstpl */
2362 case 0x38: /* filds */
2363 case 0x3a: /* fists */
2364 case 0x3b: /* fistps */
2365
2366 switch(op & 7) {
2367 case 0:
2368 gen_op_fpush();
2369 switch(op >> 4) {
2370 case 0:
2371 gen_op_flds_ST0_A0();
2372 break;
2373 case 1:
2374 gen_op_fildl_ST0_A0();
2375 break;
2376 case 2:
2377 gen_op_fldl_ST0_A0();
2378 break;
2379 case 3:
2380 default:
2381 gen_op_fild_ST0_A0();
2382 break;
2383 }
2384 break;
2385 default:
2386 switch(op >> 4) {
2387 case 0:
2388 gen_op_fsts_ST0_A0();
2389 break;
2390 case 1:
2391 gen_op_fistl_ST0_A0();
2392 break;
2393 case 2:
2394 gen_op_fstl_ST0_A0();
2395 break;
2396 case 3:
2397 default:
2398 gen_op_fist_ST0_A0();
2399 break;
2400 }
2401 if ((op & 7) == 3)
2402 gen_op_fpop();
2403 break;
2404 }
2405 break;
2406 case 0x0c: /* fldenv mem */
2407 gen_op_fldenv_A0(s->dflag);
2408 break;
2409 case 0x0d: /* fldcw mem */
2410 gen_op_fldcw_A0();
2411 break;
2412 case 0x0e: /* fnstenv mem */
2413 gen_op_fnstenv_A0(s->dflag);
2414 break;
2415 case 0x0f: /* fnstcw mem */
2416 gen_op_fnstcw_A0();
2417 break;
2418 case 0x1d: /* fldt mem */
2419 gen_op_fpush();
2420 gen_op_fldt_ST0_A0();
2421 break;
2422 case 0x1f: /* fstpt mem */
2423 gen_op_fstt_ST0_A0();
2424 gen_op_fpop();
2425 break;
2426 case 0x2c: /* frstor mem */
2427 gen_op_frstor_A0(s->dflag);
2428 break;
2429 case 0x2e: /* fnsave mem */
2430 gen_op_fnsave_A0(s->dflag);
2431 break;
2432 case 0x2f: /* fnstsw mem */
2433 gen_op_fnstsw_A0();
2434 break;
2435 case 0x3c: /* fbld */
2436 gen_op_fpush();
2437 gen_op_fbld_ST0_A0();
2438 break;
2439 case 0x3e: /* fbstp */
2440 gen_op_fbst_ST0_A0();
2441 gen_op_fpop();
2442 break;
2443 case 0x3d: /* fildll */
2444 gen_op_fpush();
2445 gen_op_fildll_ST0_A0();
2446 break;
2447 case 0x3f: /* fistpll */
2448 gen_op_fistll_ST0_A0();
2449 gen_op_fpop();
2450 break;
2451 default:
2452 goto illegal_op;
2453 }
2454 } else {
2455 /* register float ops */
2456 opreg = rm;
2457
2458 switch(op) {
2459 case 0x08: /* fld sti */
2460 gen_op_fpush();
2461 gen_op_fmov_ST0_STN((opreg + 1) & 7);
2462 break;
2463 case 0x09: /* fxchg sti */
2464 gen_op_fxchg_ST0_STN(opreg);
2465 break;
2466 case 0x0a: /* grp d9/2 */
2467 switch(rm) {
2468 case 0: /* fnop */
2469 break;
2470 default:
2471 goto illegal_op;
2472 }
2473 break;
2474 case 0x0c: /* grp d9/4 */
2475 switch(rm) {
2476 case 0: /* fchs */
2477 gen_op_fchs_ST0();
2478 break;
2479 case 1: /* fabs */
2480 gen_op_fabs_ST0();
2481 break;
2482 case 4: /* ftst */
2483 gen_op_fldz_FT0();
2484 gen_op_fcom_ST0_FT0();
2485 break;
2486 case 5: /* fxam */
2487 gen_op_fxam_ST0();
2488 break;
2489 default:
2490 goto illegal_op;
2491 }
2492 break;
2493 case 0x0d: /* grp d9/5 */
2494 {
2495 switch(rm) {
2496 case 0:
2497 gen_op_fpush();
2498 gen_op_fld1_ST0();
2499 break;
2500 case 1:
2501 gen_op_fpush();
2502 gen_op_fldl2t_ST0();
2503 break;
2504 case 2:
2505 gen_op_fpush();
2506 gen_op_fldl2e_ST0();
2507 break;
2508 case 3:
2509 gen_op_fpush();
2510 gen_op_fldpi_ST0();
2511 break;
2512 case 4:
2513 gen_op_fpush();
2514 gen_op_fldlg2_ST0();
2515 break;
2516 case 5:
2517 gen_op_fpush();
2518 gen_op_fldln2_ST0();
2519 break;
2520 case 6:
2521 gen_op_fpush();
2522 gen_op_fldz_ST0();
2523 break;
2524 default:
2525 goto illegal_op;
2526 }
2527 }
2528 break;
2529 case 0x0e: /* grp d9/6 */
2530 switch(rm) {
2531 case 0: /* f2xm1 */
2532 gen_op_f2xm1();
2533 break;
2534 case 1: /* fyl2x */
2535 gen_op_fyl2x();
2536 break;
2537 case 2: /* fptan */
2538 gen_op_fptan();
2539 break;
2540 case 3: /* fpatan */
2541 gen_op_fpatan();
2542 break;
2543 case 4: /* fxtract */
2544 gen_op_fxtract();
2545 break;
2546 case 5: /* fprem1 */
2547 gen_op_fprem1();
2548 break;
2549 case 6: /* fdecstp */
2550 gen_op_fdecstp();
2551 break;
2552 default:
2553 case 7: /* fincstp */
2554 gen_op_fincstp();
2555 break;
2556 }
2557 break;
2558 case 0x0f: /* grp d9/7 */
2559 switch(rm) {
2560 case 0: /* fprem */
2561 gen_op_fprem();
2562 break;
2563 case 1: /* fyl2xp1 */
2564 gen_op_fyl2xp1();
2565 break;
2566 case 2: /* fsqrt */
2567 gen_op_fsqrt();
2568 break;
2569 case 3: /* fsincos */
2570 gen_op_fsincos();
2571 break;
2572 case 5: /* fscale */
2573 gen_op_fscale();
2574 break;
2575 case 4: /* frndint */
2576 gen_op_frndint();
2577 break;
2578 case 6: /* fsin */
2579 gen_op_fsin();
2580 break;
2581 default:
2582 case 7: /* fcos */
2583 gen_op_fcos();
2584 break;
2585 }
2586 break;
2587 case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
2588 case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
2589 case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
2590 {
2591 int op1;
2592
2593 op1 = op & 7;
2594 if (op >= 0x20) {
2595 gen_op_fp_arith_STN_ST0[op1](opreg);
2596 if (op >= 0x30)
2597 gen_op_fpop();
2598 } else {
2599 gen_op_fmov_FT0_STN(opreg);
2600 gen_op_fp_arith_ST0_FT0[op1]();
2601 }
2602 }
2603 break;
2604 case 0x02: /* fcom */
2605 gen_op_fmov_FT0_STN(opreg);
2606 gen_op_fcom_ST0_FT0();
2607 break;
2608 case 0x03: /* fcomp */
2609 gen_op_fmov_FT0_STN(opreg);
2610 gen_op_fcom_ST0_FT0();
2611 gen_op_fpop();
2612 break;
2613 case 0x15: /* da/5 */
2614 switch(rm) {
2615 case 1: /* fucompp */
2616 gen_op_fmov_FT0_STN(1);
2617 gen_op_fucom_ST0_FT0();
2618 gen_op_fpop();
2619 gen_op_fpop();
2620 break;
2621 default:
2622 goto illegal_op;
2623 }
2624 break;
2625 case 0x1c:
2626 switch(rm) {
2627 case 0: /* feni (287 only, just do nop here) */
2628 break;
2629 case 1: /* fdisi (287 only, just do nop here) */
2630 break;
2631 case 2: /* fclex */
2632 gen_op_fclex();
2633 break;
2634 case 3: /* fninit */
2635 gen_op_fninit();
2636 break;
2637 case 4: /* fsetpm (287 only, just do nop here) */
2638 break;
2639 default:
2640 goto illegal_op;
2641 }
2642 break;
2643 case 0x1d: /* fucomi */
2644 if (s->cc_op != CC_OP_DYNAMIC)
2645 gen_op_set_cc_op(s->cc_op);
2646 gen_op_fmov_FT0_STN(opreg);
2647 gen_op_fucomi_ST0_FT0();
2648 s->cc_op = CC_OP_EFLAGS;
2649 break;
2650 case 0x1e: /* fcomi */
2651 if (s->cc_op != CC_OP_DYNAMIC)
2652 gen_op_set_cc_op(s->cc_op);
2653 gen_op_fmov_FT0_STN(opreg);
2654 gen_op_fcomi_ST0_FT0();
2655 s->cc_op = CC_OP_EFLAGS;
2656 break;
2657 case 0x2a: /* fst sti */
2658 gen_op_fmov_STN_ST0(opreg);
2659 break;
2660 case 0x2b: /* fstp sti */
2661 gen_op_fmov_STN_ST0(opreg);
2662 gen_op_fpop();
2663 break;
2664 case 0x2c: /* fucom st(i) */
2665 gen_op_fmov_FT0_STN(opreg);
2666 gen_op_fucom_ST0_FT0();
2667 break;
2668 case 0x2d: /* fucomp st(i) */
2669 gen_op_fmov_FT0_STN(opreg);
2670 gen_op_fucom_ST0_FT0();
2671 gen_op_fpop();
2672 break;
2673 case 0x33: /* de/3 */
2674 switch(rm) {
2675 case 1: /* fcompp */
2676 gen_op_fmov_FT0_STN(1);
2677 gen_op_fcom_ST0_FT0();
2678 gen_op_fpop();
2679 gen_op_fpop();
2680 break;
2681 default:
2682 goto illegal_op;
2683 }
2684 break;
2685 case 0x3c: /* df/4 */
2686 switch(rm) {
2687 case 0:
2688 gen_op_fnstsw_EAX();
2689 break;
2690 default:
2691 goto illegal_op;
2692 }
2693 break;
2694 case 0x3d: /* fucomip */
2695 if (s->cc_op != CC_OP_DYNAMIC)
2696 gen_op_set_cc_op(s->cc_op);
2697 gen_op_fmov_FT0_STN(opreg);
2698 gen_op_fucomi_ST0_FT0();
2699 gen_op_fpop();
2700 s->cc_op = CC_OP_EFLAGS;
2701 break;
2702 case 0x3e: /* fcomip */
2703 if (s->cc_op != CC_OP_DYNAMIC)
2704 gen_op_set_cc_op(s->cc_op);
2705 gen_op_fmov_FT0_STN(opreg);
2706 gen_op_fcomi_ST0_FT0();
2707 gen_op_fpop();
2708 s->cc_op = CC_OP_EFLAGS;
2709 break;
2710 default:
2711 goto illegal_op;
2712 }
2713 }
2714 break;
2715 /************************/
2716 /* string ops */
2717
2718 case 0xa4: /* movsS */
2719 case 0xa5:
2720 if ((b & 1) == 0)
2721 ot = OT_BYTE;
2722 else
2723 ot = dflag ? OT_LONG : OT_WORD;
2724
2725 if (prefixes & PREFIX_REPZ) {
2726 gen_string_ds(s, ot, gen_op_movs + 9);
2727 } else {
2728 gen_string_ds(s, ot, gen_op_movs);
2729 }
2730 break;
2731
2732 case 0xaa: /* stosS */
2733 case 0xab:
2734 if ((b & 1) == 0)
2735 ot = OT_BYTE;
2736 else
2737 ot = dflag ? OT_LONG : OT_WORD;
2738
2739 if (prefixes & PREFIX_REPZ) {
2740 gen_string_es(s, ot, gen_op_stos + 9);
2741 } else {
2742 gen_string_es(s, ot, gen_op_stos);
2743 }
2744 break;
2745 case 0xac: /* lodsS */
2746 case 0xad:
2747 if ((b & 1) == 0)
2748 ot = OT_BYTE;
2749 else
2750 ot = dflag ? OT_LONG : OT_WORD;
2751 if (prefixes & PREFIX_REPZ) {
2752 gen_string_ds(s, ot, gen_op_lods + 9);
2753 } else {
2754 gen_string_ds(s, ot, gen_op_lods);
2755 }
2756 break;
2757 case 0xae: /* scasS */
2758 case 0xaf:
2759 if ((b & 1) == 0)
2760 ot = OT_BYTE;
2761 else
2762 ot = dflag ? OT_LONG : OT_WORD;
2763 if (prefixes & PREFIX_REPNZ) {
2764 if (s->cc_op != CC_OP_DYNAMIC)
2765 gen_op_set_cc_op(s->cc_op);
2766 gen_string_es(s, ot, gen_op_scas + 9 * 2);
2767 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2768 } else if (prefixes & PREFIX_REPZ) {
2769 if (s->cc_op != CC_OP_DYNAMIC)
2770 gen_op_set_cc_op(s->cc_op);
2771 gen_string_es(s, ot, gen_op_scas + 9);
2772 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2773 } else {
2774 gen_string_es(s, ot, gen_op_scas);
2775 s->cc_op = CC_OP_SUBB + ot;
2776 }
2777 break;
2778
2779 case 0xa6: /* cmpsS */
2780 case 0xa7:
2781 if ((b & 1) == 0)
2782 ot = OT_BYTE;
2783 else
2784 ot = dflag ? OT_LONG : OT_WORD;
2785 if (prefixes & PREFIX_REPNZ) {
2786 if (s->cc_op != CC_OP_DYNAMIC)
2787 gen_op_set_cc_op(s->cc_op);
2788 gen_string_ds(s, ot, gen_op_cmps + 9 * 2);
2789 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2790 } else if (prefixes & PREFIX_REPZ) {
2791 if (s->cc_op != CC_OP_DYNAMIC)
2792 gen_op_set_cc_op(s->cc_op);
2793 gen_string_ds(s, ot, gen_op_cmps + 9);
2794 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2795 } else {
2796 gen_string_ds(s, ot, gen_op_cmps);
2797 s->cc_op = CC_OP_SUBB + ot;
2798 }
2799 break;
2800 case 0x6c: /* insS */
2801 case 0x6d:
2802 if (s->cpl > s->iopl || s->vm86) {
2803 /* NOTE: even for (E)CX = 0 the exception is raised */
2804 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
2805 } else {
2806 if ((b & 1) == 0)
2807 ot = OT_BYTE;
2808 else
2809 ot = dflag ? OT_LONG : OT_WORD;
2810 if (prefixes & PREFIX_REPZ) {
2811 gen_string_es(s, ot, gen_op_ins + 9);
2812 } else {
2813 gen_string_es(s, ot, gen_op_ins);
2814 }
2815 }
2816 break;
2817 case 0x6e: /* outsS */
2818 case 0x6f:
2819 if (s->cpl > s->iopl || s->vm86) {
2820 /* NOTE: even for (E)CX = 0 the exception is raised */
2821 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
2822 } else {
2823 if ((b & 1) == 0)
2824 ot = OT_BYTE;
2825 else
2826 ot = dflag ? OT_LONG : OT_WORD;
2827 if (prefixes & PREFIX_REPZ) {
2828 gen_string_ds(s, ot, gen_op_outs + 9);
2829 } else {
2830 gen_string_ds(s, ot, gen_op_outs);
2831 }
2832 }
2833 break;
2834
2835 /************************/
2836 /* port I/O */
2837 case 0xe4:
2838 case 0xe5:
2839 if (s->cpl > s->iopl || s->vm86) {
2840 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
2841 } else {
2842 if ((b & 1) == 0)
2843 ot = OT_BYTE;
2844 else
2845 ot = dflag ? OT_LONG : OT_WORD;
2846 val = ldub(s->pc++);
2847 gen_op_movl_T0_im(val);
2848 gen_op_in[ot]();
2849 gen_op_mov_reg_T1[ot][R_EAX]();
2850 }
2851 break;
2852 case 0xe6:
2853 case 0xe7:
2854 if (s->cpl > s->iopl || s->vm86) {
2855 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
2856 } else {
2857 if ((b & 1) == 0)
2858 ot = OT_BYTE;
2859 else
2860 ot = dflag ? OT_LONG : OT_WORD;
2861 val = ldub(s->pc++);
2862 gen_op_movl_T0_im(val);
2863 gen_op_mov_TN_reg[ot][1][R_EAX]();
2864 gen_op_out[ot]();
2865 }
2866 break;
2867 case 0xec:
2868 case 0xed:
2869 if (s->cpl > s->iopl || s->vm86) {
2870 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
2871 } else {
2872 if ((b & 1) == 0)
2873 ot = OT_BYTE;
2874 else
2875 ot = dflag ? OT_LONG : OT_WORD;
2876 gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
2877 gen_op_in[ot]();
2878 gen_op_mov_reg_T1[ot][R_EAX]();
2879 }
2880 break;
2881 case 0xee:
2882 case 0xef:
2883 if (s->cpl > s->iopl || s->vm86) {
2884 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
2885 } else {
2886 if ((b & 1) == 0)
2887 ot = OT_BYTE;
2888 else
2889 ot = dflag ? OT_LONG : OT_WORD;
2890 gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
2891 gen_op_mov_TN_reg[ot][1][R_EAX]();
2892 gen_op_out[ot]();
2893 }
2894 break;
2895
2896 /************************/
2897 /* control */
2898 case 0xc2: /* ret im */
2899 val = ldsw(s->pc);
2900 s->pc += 2;
2901 gen_pop_T0(s);
2902 gen_stack_update(s, val + (2 << s->dflag));
2903 if (s->dflag == 0)
2904 gen_op_andl_T0_ffff();
2905 gen_op_jmp_T0();
2906 s->is_jmp = 1;
2907 break;
2908 case 0xc3: /* ret */
2909 gen_pop_T0(s);
2910 gen_pop_update(s);
2911 if (s->dflag == 0)
2912 gen_op_andl_T0_ffff();
2913 gen_op_jmp_T0();
2914 s->is_jmp = 1;
2915 break;
2916 case 0xca: /* lret im */
2917 val = ldsw(s->pc);
2918 s->pc += 2;
2919 do_lret:
2920 gen_stack_A0(s);
2921 /* pop offset */
2922 gen_op_ld_T0_A0[1 + s->dflag]();
2923 if (s->dflag == 0)
2924 gen_op_andl_T0_ffff();
2925 /* NOTE: keeping EIP updated is not a problem in case of
2926 exception */
2927 gen_op_jmp_T0();
2928 /* pop selector */
2929 gen_op_addl_A0_im(2 << s->dflag);
2930 gen_op_ld_T0_A0[1 + s->dflag]();
2931 gen_movl_seg_T0(s, R_CS, pc_start - s->cs_base);
2932 /* add stack offset */
2933 gen_stack_update(s, val + (4 << s->dflag));
2934 s->is_jmp = 1;
2935 break;
2936 case 0xcb: /* lret */
2937 val = 0;
2938 goto do_lret;
2939 case 0xcf: /* iret */
2940 if (s->vm86 && s->iopl != 3) {
2941 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
2942 } else {
2943 /* XXX: not restartable */
2944 gen_stack_A0(s);
2945 /* pop offset */
2946 gen_op_ld_T0_A0[1 + s->dflag]();
2947 if (s->dflag == 0)
2948 gen_op_andl_T0_ffff();
2949 /* NOTE: keeping EIP updated is not a problem in case of
2950 exception */
2951 gen_op_jmp_T0();
2952 /* pop selector */
2953 gen_op_addl_A0_im(2 << s->dflag);
2954 gen_op_ld_T0_A0[1 + s->dflag]();
2955 /* pop eflags */
2956 gen_op_addl_A0_im(2 << s->dflag);
2957 gen_op_ld_T1_A0[1 + s->dflag]();
2958 gen_movl_seg_T0(s, R_CS, pc_start - s->cs_base);
2959 gen_op_movl_T0_T1();
2960 if (s->dflag) {
2961 gen_op_movl_eflags_T0();
2962 } else {
2963 gen_op_movw_eflags_T0();
2964 }
2965 gen_stack_update(s, (6 << s->dflag));
2966 s->cc_op = CC_OP_EFLAGS;
2967 }
2968 s->is_jmp = 1;
2969 break;
2970 case 0xe8: /* call im */
2971 {
2972 unsigned int next_eip;
2973 ot = dflag ? OT_LONG : OT_WORD;
2974 val = insn_get(s, ot);
2975 next_eip = s->pc - s->cs_base;
2976 val += next_eip;
2977 if (s->dflag == 0)
2978 val &= 0xffff;
2979 gen_op_movl_T0_im(next_eip);
2980 gen_push_T0(s);
2981 gen_jmp(s, val);
2982 }
2983 break;
2984 case 0x9a: /* lcall im */
2985 {
2986 unsigned int selector, offset;
2987 /* XXX: not restartable */
2988
2989 ot = dflag ? OT_LONG : OT_WORD;
2990 offset = insn_get(s, ot);
2991 selector = insn_get(s, OT_WORD);
2992
2993 /* push return segment + offset */
2994 gen_op_movl_T0_seg(R_CS);
2995 gen_push_T0(s);
2996 next_eip = s->pc - s->cs_base;
2997 gen_op_movl_T0_im(next_eip);
2998 gen_push_T0(s);
2999
3000 /* change cs and pc */
3001 gen_op_movl_T0_im(selector);
3002 gen_movl_seg_T0(s, R_CS, pc_start - s->cs_base);
3003 gen_op_jmp_im((unsigned long)offset);
3004 s->is_jmp = 1;
3005 }
3006 break;
3007 case 0xe9: /* jmp */
3008 ot = dflag ? OT_LONG : OT_WORD;
3009 val = insn_get(s, ot);
3010 val += s->pc - s->cs_base;
3011 if (s->dflag == 0)
3012 val = val & 0xffff;
3013 gen_jmp(s, val);
3014 break;
3015 case 0xea: /* ljmp im */
3016 {
3017 unsigned int selector, offset;
3018
3019 ot = dflag ? OT_LONG : OT_WORD;
3020 offset = insn_get(s, ot);
3021 selector = insn_get(s, OT_WORD);
3022
3023 /* change cs and pc */
3024 gen_op_movl_T0_im(selector);
3025 if (!s->vm86) {
3026 /* we compute EIP to handle the exception case */
3027 gen_op_jmp_im(pc_start - s->cs_base);
3028 gen_op_movl_T1_im(offset);
3029 gen_op_ljmp_T0_T1();
3030 } else {
3031 gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[R_CS]));
3032 gen_op_jmp_im((unsigned long)offset);
3033 }
3034 s->is_jmp = 1;
3035 }
3036 break;
3037 case 0xeb: /* jmp Jb */
3038 val = (int8_t)insn_get(s, OT_BYTE);
3039 val += s->pc - s->cs_base;
3040 if (s->dflag == 0)
3041 val = val & 0xffff;
3042 gen_jmp(s, val);
3043 break;
3044 case 0x70 ... 0x7f: /* jcc Jb */
3045 val = (int8_t)insn_get(s, OT_BYTE);
3046 goto do_jcc;
3047 case 0x180 ... 0x18f: /* jcc Jv */
3048 if (dflag) {
3049 val = insn_get(s, OT_LONG);
3050 } else {
3051 val = (int16_t)insn_get(s, OT_WORD);
3052 }
3053 do_jcc:
3054 next_eip = s->pc - s->cs_base;
3055 val += next_eip;
3056 if (s->dflag == 0)
3057 val &= 0xffff;
3058 gen_jcc(s, b, val, next_eip);
3059 break;
3060
3061 case 0x190 ... 0x19f: /* setcc Gv */
3062 modrm = ldub(s->pc++);
3063 gen_setcc(s, b);
3064 gen_ldst_modrm(s, modrm, OT_BYTE, OR_TMP0, 1);
3065 break;
3066 case 0x140 ... 0x14f: /* cmov Gv, Ev */
3067 ot = dflag ? OT_LONG : OT_WORD;
3068 modrm = ldub(s->pc++);
3069 reg = (modrm >> 3) & 7;
3070 mod = (modrm >> 6) & 3;
3071 gen_setcc(s, b);
3072 if (mod != 3) {
3073 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3074 gen_op_ld_T1_A0[ot]();
3075 } else {
3076 rm = modrm & 7;
3077 gen_op_mov_TN_reg[ot][1][rm]();
3078 }
3079 gen_op_cmov_reg_T1_T0[ot - OT_WORD][reg]();
3080 break;
3081
3082 /************************/
3083 /* flags */
3084 case 0x9c: /* pushf */
3085 if (s->vm86 && s->iopl != 3) {
3086 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3087 } else {
3088 if (s->cc_op != CC_OP_DYNAMIC)
3089 gen_op_set_cc_op(s->cc_op);
3090 gen_op_movl_T0_eflags();
3091 gen_push_T0(s);
3092 }
3093 break;
3094 case 0x9d: /* popf */
3095 if (s->vm86 && s->iopl != 3) {
3096 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3097 } else {
3098 gen_pop_T0(s);
3099 if (s->dflag) {
3100 gen_op_movl_eflags_T0();
3101 } else {
3102 gen_op_movw_eflags_T0();
3103 }
3104 gen_pop_update(s);
3105 s->cc_op = CC_OP_EFLAGS;
3106 s->is_jmp = 2; /* abort translation because TF flag may change */
3107 }
3108 break;
3109 case 0x9e: /* sahf */
3110 gen_op_mov_TN_reg[OT_BYTE][0][R_AH]();
3111 if (s->cc_op != CC_OP_DYNAMIC)
3112 gen_op_set_cc_op(s->cc_op);
3113 gen_op_movb_eflags_T0();
3114 s->cc_op = CC_OP_EFLAGS;
3115 break;
3116 case 0x9f: /* lahf */
3117 if (s->cc_op != CC_OP_DYNAMIC)
3118 gen_op_set_cc_op(s->cc_op);
3119 gen_op_movl_T0_eflags();
3120 gen_op_mov_reg_T0[OT_BYTE][R_AH]();
3121 break;
3122 case 0xf5: /* cmc */
3123 if (s->cc_op != CC_OP_DYNAMIC)
3124 gen_op_set_cc_op(s->cc_op);
3125 gen_op_cmc();
3126 s->cc_op = CC_OP_EFLAGS;
3127 break;
3128 case 0xf8: /* clc */
3129 if (s->cc_op != CC_OP_DYNAMIC)
3130 gen_op_set_cc_op(s->cc_op);
3131 gen_op_clc();
3132 s->cc_op = CC_OP_EFLAGS;
3133 break;
3134 case 0xf9: /* stc */
3135 if (s->cc_op != CC_OP_DYNAMIC)
3136 gen_op_set_cc_op(s->cc_op);
3137 gen_op_stc();
3138 s->cc_op = CC_OP_EFLAGS;
3139 break;
3140 case 0xfc: /* cld */
3141 gen_op_cld();
3142 break;
3143 case 0xfd: /* std */
3144 gen_op_std();
3145 break;
3146
3147 /************************/
3148 /* bit operations */
3149 case 0x1ba: /* bt/bts/btr/btc Gv, im */
3150 ot = dflag ? OT_LONG : OT_WORD;
3151 modrm = ldub(s->pc++);
3152 op = (modrm >> 3) & 7;
3153 mod = (modrm >> 6) & 3;
3154 rm = modrm & 7;
3155 if (mod != 3) {
3156 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3157 gen_op_ld_T0_A0[ot]();
3158 } else {
3159 gen_op_mov_TN_reg[ot][0][rm]();
3160 }
3161 /* load shift */
3162 val = ldub(s->pc++);
3163 gen_op_movl_T1_im(val);
3164 if (op < 4)
3165 goto illegal_op;
3166 op -= 4;
3167 gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
3168 s->cc_op = CC_OP_SARB + ot;
3169 if (op != 0) {
3170 if (mod != 3)
3171 gen_op_st_T0_A0[ot]();
3172 else
3173 gen_op_mov_reg_T0[ot][rm]();
3174 }
3175 break;
3176 case 0x1a3: /* bt Gv, Ev */
3177 op = 0;
3178 goto do_btx;
3179 case 0x1ab: /* bts */
3180 op = 1;
3181 goto do_btx;
3182 case 0x1b3: /* btr */
3183 op = 2;
3184 goto do_btx;
3185 case 0x1bb: /* btc */
3186 op = 3;
3187 do_btx:
3188 ot = dflag ? OT_LONG : OT_WORD;
3189 modrm = ldub(s->pc++);
3190 reg = (modrm >> 3) & 7;
3191 mod = (modrm >> 6) & 3;
3192 rm = modrm & 7;
3193 gen_op_mov_TN_reg[OT_LONG][1][reg]();
3194 if (mod != 3) {
3195 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3196 /* specific case: we need to add a displacement */
3197 if (ot == OT_WORD)
3198 gen_op_add_bitw_A0_T1();
3199 else
3200 gen_op_add_bitl_A0_T1();
3201 gen_op_ld_T0_A0[ot]();
3202 } else {
3203 gen_op_mov_TN_reg[ot][0][rm]();
3204 }
3205 gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
3206 s->cc_op = CC_OP_SARB + ot;
3207 if (op != 0) {
3208 if (mod != 3)
3209 gen_op_st_T0_A0[ot]();
3210 else
3211 gen_op_mov_reg_T0[ot][rm]();
3212 }
3213 break;
3214 case 0x1bc: /* bsf */
3215 case 0x1bd: /* bsr */
3216 ot = dflag ? OT_LONG : OT_WORD;
3217 modrm = ldub(s->pc++);
3218 reg = (modrm >> 3) & 7;
3219 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
3220 gen_op_bsx_T0_cc[ot - OT_WORD][b & 1]();
3221 /* NOTE: we always write back the result. Intel doc says it is
3222 undefined if T0 == 0 */
3223 gen_op_mov_reg_T0[ot][reg]();
3224 s->cc_op = CC_OP_LOGICB + ot;
3225 break;
3226 /************************/
3227 /* bcd */
3228 case 0x27: /* daa */
3229 if (s->cc_op != CC_OP_DYNAMIC)
3230 gen_op_set_cc_op(s->cc_op);
3231 gen_op_daa();
3232 s->cc_op = CC_OP_EFLAGS;
3233 break;
3234 case 0x2f: /* das */
3235 if (s->cc_op != CC_OP_DYNAMIC)
3236 gen_op_set_cc_op(s->cc_op);
3237 gen_op_das();
3238 s->cc_op = CC_OP_EFLAGS;
3239 break;
3240 case 0x37: /* aaa */
3241 if (s->cc_op != CC_OP_DYNAMIC)
3242 gen_op_set_cc_op(s->cc_op);
3243 gen_op_aaa();
3244 s->cc_op = CC_OP_EFLAGS;
3245 break;
3246 case 0x3f: /* aas */
3247 if (s->cc_op != CC_OP_DYNAMIC)
3248 gen_op_set_cc_op(s->cc_op);
3249 gen_op_aas();
3250 s->cc_op = CC_OP_EFLAGS;
3251 break;
3252 case 0xd4: /* aam */
3253 val = ldub(s->pc++);
3254 gen_op_aam(val);
3255 s->cc_op = CC_OP_LOGICB;
3256 break;
3257 case 0xd5: /* aad */
3258 val = ldub(s->pc++);
3259 gen_op_aad(val);
3260 s->cc_op = CC_OP_LOGICB;
3261 break;
3262 /************************/
3263 /* misc */
3264 case 0x90: /* nop */
3265 break;
3266 case 0x9b: /* fwait */
3267 break;
3268 case 0xcc: /* int3 */
3269 gen_interrupt(s, EXCP03_INT3, pc_start - s->cs_base, s->pc - s->cs_base);
3270 break;
3271 case 0xcd: /* int N */
3272 val = ldub(s->pc++);
3273 /* XXX: add error code for vm86 GPF */
3274 if (!s->vm86)
3275 gen_interrupt(s, val, pc_start - s->cs_base, s->pc - s->cs_base);
3276 else
3277 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3278 break;
3279 case 0xce: /* into */
3280 if (s->cc_op != CC_OP_DYNAMIC)
3281 gen_op_set_cc_op(s->cc_op);
3282 gen_op_into(s->pc - s->cs_base);
3283 break;
3284 case 0xfa: /* cli */
3285 if (!s->vm86) {
3286 if (s->cpl <= s->iopl) {
3287 gen_op_cli();
3288 } else {
3289 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3290 }
3291 } else {
3292 if (s->iopl == 3) {
3293 gen_op_cli();
3294 } else {
3295 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3296 }
3297 }
3298 break;
3299 case 0xfb: /* sti */
3300 if (!s->vm86) {
3301 if (s->cpl <= s->iopl) {
3302 gen_op_sti();
3303 } else {
3304 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3305 }
3306 } else {
3307 if (s->iopl == 3) {
3308 gen_op_sti();
3309 } else {
3310 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3311 }
3312 }
3313 break;
3314 case 0x62: /* bound */
3315 ot = dflag ? OT_LONG : OT_WORD;
3316 modrm = ldub(s->pc++);
3317 reg = (modrm >> 3) & 7;
3318 mod = (modrm >> 6) & 3;
3319 if (mod == 3)
3320 goto illegal_op;
3321 gen_op_mov_reg_T0[ot][reg]();
3322 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3323 if (ot == OT_WORD)
3324 gen_op_boundw(pc_start - s->cs_base);
3325 else
3326 gen_op_boundl(pc_start - s->cs_base);
3327 break;
3328 case 0x1c8 ... 0x1cf: /* bswap reg */
3329 reg = b & 7;
3330 gen_op_mov_TN_reg[OT_LONG][0][reg]();
3331 gen_op_bswapl_T0();
3332 gen_op_mov_reg_T0[OT_LONG][reg]();
3333 break;
3334 case 0xd6: /* salc */
3335 if (s->cc_op != CC_OP_DYNAMIC)
3336 gen_op_set_cc_op(s->cc_op);
3337 gen_op_salc();
3338 break;
3339 case 0xe0: /* loopnz */
3340 case 0xe1: /* loopz */
3341 if (s->cc_op != CC_OP_DYNAMIC)
3342 gen_op_set_cc_op(s->cc_op);
3343 /* FALL THRU */
3344 case 0xe2: /* loop */
3345 case 0xe3: /* jecxz */
3346 val = (int8_t)insn_get(s, OT_BYTE);
3347 next_eip = s->pc - s->cs_base;
3348 val += next_eip;
3349 if (s->dflag == 0)
3350 val &= 0xffff;
3351 gen_op_loop[s->aflag][b & 3](val, next_eip);
3352 s->is_jmp = 1;
3353 break;
3354 case 0x131: /* rdtsc */
3355 gen_op_rdtsc();
3356 break;
3357 case 0x1a2: /* cpuid */
3358 gen_op_cpuid();
3359 break;
3360 case 0xf4: /* hlt */
3361 /* XXX: if cpl == 0, then should do something else */
3362 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3363 break;
3364 case 0x100:
3365 modrm = ldub(s->pc++);
3366 mod = (modrm >> 6) & 3;
3367 op = (modrm >> 3) & 7;
3368 switch(op) {
3369 case 0: /* sldt */
3370 gen_op_movl_T0_env(offsetof(CPUX86State,ldt.selector));
3371 ot = OT_WORD;
3372 if (mod == 3)
3373 ot += s->dflag;
3374 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
3375 break;
3376 case 2: /* lldt */
3377 if (s->cpl != 0) {
3378 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3379 } else {
3380 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
3381 gen_op_jmp_im(pc_start - s->cs_base);
3382 gen_op_lldt_T0();
3383 }
3384 break;
3385 case 1: /* str */
3386 gen_op_movl_T0_env(offsetof(CPUX86State,tr.selector));
3387 ot = OT_WORD;
3388 if (mod == 3)
3389 ot += s->dflag;
3390 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
3391 break;
3392 case 3: /* ltr */
3393 if (s->cpl != 0) {
3394 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3395 } else {
3396 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
3397 gen_op_jmp_im(pc_start - s->cs_base);
3398 gen_op_ltr_T0();
3399 }
3400 break;
3401 case 4: /* verr */
3402 case 5: /* verw */
3403 default:
3404 goto illegal_op;
3405 }
3406 break;
3407 case 0x101:
3408 modrm = ldub(s->pc++);
3409 mod = (modrm >> 6) & 3;
3410 op = (modrm >> 3) & 7;
3411 switch(op) {
3412 case 0: /* sgdt */
3413 case 1: /* sidt */
3414 if (mod == 3)
3415 goto illegal_op;
3416 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3417 if (op == 0)
3418 gen_op_movl_T0_env(offsetof(CPUX86State,gdt.limit));
3419 else
3420 gen_op_movl_T0_env(offsetof(CPUX86State,idt.limit));
3421 gen_op_stw_T0_A0();
3422 gen_op_addl_A0_im(2);
3423 if (op == 0)
3424 gen_op_movl_T0_env(offsetof(CPUX86State,gdt.base));
3425 else
3426 gen_op_movl_T0_env(offsetof(CPUX86State,idt.base));
3427 if (!s->dflag)
3428 gen_op_andl_T0_im(0xffffff);
3429 gen_op_stl_T0_A0();
3430 break;
3431 case 2: /* lgdt */
3432 case 3: /* lidt */
3433 if (mod == 3)
3434 goto illegal_op;
3435 if (s->cpl != 0) {
3436 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3437 } else {
3438 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3439 gen_op_lduw_T1_A0();
3440 gen_op_addl_A0_im(2);
3441 gen_op_ldl_T0_A0();
3442 if (!s->dflag)
3443 gen_op_andl_T0_im(0xffffff);
3444 if (op == 2) {
3445 gen_op_movl_env_T0(offsetof(CPUX86State,gdt.base));
3446 gen_op_movl_env_T1(offsetof(CPUX86State,gdt.limit));
3447 } else {
3448 gen_op_movl_env_T0(offsetof(CPUX86State,idt.base));
3449 gen_op_movl_env_T1(offsetof(CPUX86State,idt.limit));
3450 }
3451 }
3452 break;
3453 case 4: /* smsw */
3454 gen_op_movl_T0_env(offsetof(CPUX86State,cr[0]));
3455 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 1);
3456 break;
3457 case 6: /* lmsw */
3458 if (s->cpl != 0) {
3459 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3460 } else {
3461 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
3462 gen_op_lmsw_T0();
3463 }
3464 break;
3465 default:
3466 goto illegal_op;
3467 }
3468 break;
3469 case 0x102: /* lar */
3470 case 0x103: /* lsl */
3471 if (s->vm86)
3472 goto illegal_op;
3473 ot = dflag ? OT_LONG : OT_WORD;
3474 modrm = ldub(s->pc++);
3475 reg = (modrm >> 3) & 7;
3476 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
3477 gen_op_mov_TN_reg[ot][1][reg]();
3478 if (s->cc_op != CC_OP_DYNAMIC)
3479 gen_op_set_cc_op(s->cc_op);
3480 if (b == 0x102)
3481 gen_op_lar();
3482 else
3483 gen_op_lsl();
3484 s->cc_op = CC_OP_EFLAGS;
3485 gen_op_mov_reg_T1[ot][reg]();
3486 break;
3487 case 0x118:
3488 modrm = ldub(s->pc++);
3489 mod = (modrm >> 6) & 3;
3490 op = (modrm >> 3) & 7;
3491 switch(op) {
3492 case 0: /* prefetchnta */
3493 case 1: /* prefetchnt0 */
3494 case 2: /* prefetchnt0 */
3495 case 3: /* prefetchnt0 */
3496 if (mod == 3)
3497 goto illegal_op;
3498 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3499 /* nothing more to do */
3500 break;
3501 default:
3502 goto illegal_op;
3503 }
3504 break;
3505 case 0x120: /* mov reg, crN */
3506 case 0x122: /* mov crN, reg */
3507 if (s->cpl != 0) {
3508 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3509 } else {
3510 modrm = ldub(s->pc++);
3511 if ((modrm & 0xc0) != 0xc0)
3512 goto illegal_op;
3513 rm = modrm & 7;
3514 reg = (modrm >> 3) & 7;
3515 switch(reg) {
3516 case 0:
3517 case 2:
3518 case 3:
3519 case 4:
3520 if (b & 2) {
3521 gen_op_mov_TN_reg[OT_LONG][0][rm]();
3522 gen_op_movl_crN_T0(reg);
3523 s->is_jmp = 2;
3524 } else {
3525 gen_op_movl_T0_env(offsetof(CPUX86State,cr[reg]));
3526 gen_op_mov_reg_T0[OT_LONG][rm]();
3527 }
3528 break;
3529 default:
3530 goto illegal_op;
3531 }
3532 }
3533 break;
3534 case 0x121: /* mov reg, drN */
3535 case 0x123: /* mov drN, reg */
3536 if (s->cpl != 0) {
3537 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3538 } else {
3539 modrm = ldub(s->pc++);
3540 if ((modrm & 0xc0) != 0xc0)
3541 goto illegal_op;
3542 rm = modrm & 7;
3543 reg = (modrm >> 3) & 7;
3544 /* XXX: do it dynamically with CR4.DE bit */
3545 if (reg == 4 || reg == 5)
3546 goto illegal_op;
3547 if (b & 2) {
3548 gen_op_mov_TN_reg[OT_LONG][0][rm]();
3549 gen_op_movl_drN_T0(reg);
3550 s->is_jmp = 2;
3551 } else {
3552 gen_op_movl_T0_env(offsetof(CPUX86State,dr[reg]));
3553 gen_op_mov_reg_T0[OT_LONG][rm]();
3554 }
3555 }
3556 break;
3557 case 0x106: /* clts */
3558 if (s->cpl != 0) {
3559 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3560 } else {
3561 gen_op_clts();
3562 }
3563 break;
3564 default:
3565 goto illegal_op;
3566 }
3567 /* lock generation */
3568 if (s->prefix & PREFIX_LOCK)
3569 gen_op_unlock();
3570 return (long)s->pc;
3571 illegal_op:
3572 /* XXX: ensure that no lock was generated */
3573 return -1;
3574 }
3575
3576 #define CC_OSZAPC (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C)
3577 #define CC_OSZAP (CC_O | CC_S | CC_Z | CC_A | CC_P)
3578
3579 /* flags read by an operation */
3580 static uint16_t opc_read_flags[NB_OPS] = {
3581 [INDEX_op_aas] = CC_A,
3582 [INDEX_op_aaa] = CC_A,
3583 [INDEX_op_das] = CC_A | CC_C,
3584 [INDEX_op_daa] = CC_A | CC_C,
3585
3586 [INDEX_op_adcb_T0_T1_cc] = CC_C,
3587 [INDEX_op_adcw_T0_T1_cc] = CC_C,
3588 [INDEX_op_adcl_T0_T1_cc] = CC_C,
3589 [INDEX_op_sbbb_T0_T1_cc] = CC_C,
3590 [INDEX_op_sbbw_T0_T1_cc] = CC_C,
3591 [INDEX_op_sbbl_T0_T1_cc] = CC_C,
3592
3593 /* subtle: due to the incl/decl implementation, C is used */
3594 [INDEX_op_incl_T0_cc] = CC_C,
3595 [INDEX_op_decl_T0_cc] = CC_C,
3596
3597 [INDEX_op_into] = CC_O,
3598
3599 [INDEX_op_jb_subb] = CC_C,
3600 [INDEX_op_jb_subw] = CC_C,
3601 [INDEX_op_jb_subl] = CC_C,
3602
3603 [INDEX_op_jz_subb] = CC_Z,
3604 [INDEX_op_jz_subw] = CC_Z,
3605 [INDEX_op_jz_subl] = CC_Z,
3606
3607 [INDEX_op_jbe_subb] = CC_Z | CC_C,
3608 [INDEX_op_jbe_subw] = CC_Z | CC_C,
3609 [INDEX_op_jbe_subl] = CC_Z | CC_C,
3610
3611 [INDEX_op_js_subb] = CC_S,
3612 [INDEX_op_js_subw] = CC_S,
3613 [INDEX_op_js_subl] = CC_S,
3614
3615 [INDEX_op_jl_subb] = CC_O | CC_S,
3616 [INDEX_op_jl_subw] = CC_O | CC_S,
3617 [INDEX_op_jl_subl] = CC_O | CC_S,
3618
3619 [INDEX_op_jle_subb] = CC_O | CC_S | CC_Z,
3620 [INDEX_op_jle_subw] = CC_O | CC_S | CC_Z,
3621 [INDEX_op_jle_subl] = CC_O | CC_S | CC_Z,
3622
3623 [INDEX_op_loopnzw] = CC_Z,
3624 [INDEX_op_loopnzl] = CC_Z,
3625 [INDEX_op_loopzw] = CC_Z,
3626 [INDEX_op_loopzl] = CC_Z,
3627
3628 [INDEX_op_seto_T0_cc] = CC_O,
3629 [INDEX_op_setb_T0_cc] = CC_C,
3630 [INDEX_op_setz_T0_cc] = CC_Z,
3631 [INDEX_op_setbe_T0_cc] = CC_Z | CC_C,
3632 [INDEX_op_sets_T0_cc] = CC_S,
3633 [INDEX_op_setp_T0_cc] = CC_P,
3634 [INDEX_op_setl_T0_cc] = CC_O | CC_S,
3635 [INDEX_op_setle_T0_cc] = CC_O | CC_S | CC_Z,
3636
3637 [INDEX_op_setb_T0_subb] = CC_C,
3638 [INDEX_op_setb_T0_subw] = CC_C,
3639 [INDEX_op_setb_T0_subl] = CC_C,
3640
3641 [INDEX_op_setz_T0_subb] = CC_Z,
3642 [INDEX_op_setz_T0_subw] = CC_Z,
3643 [INDEX_op_setz_T0_subl] = CC_Z,
3644
3645 [INDEX_op_setbe_T0_subb] = CC_Z | CC_C,
3646 [INDEX_op_setbe_T0_subw] = CC_Z | CC_C,
3647 [INDEX_op_setbe_T0_subl] = CC_Z | CC_C,
3648
3649 [INDEX_op_sets_T0_subb] = CC_S,
3650 [INDEX_op_sets_T0_subw] = CC_S,
3651 [INDEX_op_sets_T0_subl] = CC_S,
3652
3653 [INDEX_op_setl_T0_subb] = CC_O | CC_S,
3654 [INDEX_op_setl_T0_subw] = CC_O | CC_S,
3655 [INDEX_op_setl_T0_subl] = CC_O | CC_S,
3656
3657 [INDEX_op_setle_T0_subb] = CC_O | CC_S | CC_Z,
3658 [INDEX_op_setle_T0_subw] = CC_O | CC_S | CC_Z,
3659 [INDEX_op_setle_T0_subl] = CC_O | CC_S | CC_Z,
3660
3661 [INDEX_op_movl_T0_eflags] = CC_OSZAPC,
3662 [INDEX_op_cmc] = CC_C,
3663 [INDEX_op_salc] = CC_C,
3664
3665 [INDEX_op_rclb_T0_T1_cc] = CC_C,
3666 [INDEX_op_rclw_T0_T1_cc] = CC_C,
3667 [INDEX_op_rcll_T0_T1_cc] = CC_C,
3668 [INDEX_op_rcrb_T0_T1_cc] = CC_C,
3669 [INDEX_op_rcrw_T0_T1_cc] = CC_C,
3670 [INDEX_op_rcrl_T0_T1_cc] = CC_C,
3671 };
3672
3673 /* flags written by an operation */
3674 static uint16_t opc_write_flags[NB_OPS] = {
3675 [INDEX_op_addl_T0_T1_cc] = CC_OSZAPC,
3676 [INDEX_op_orl_T0_T1_cc] = CC_OSZAPC,
3677 [INDEX_op_adcb_T0_T1_cc] = CC_OSZAPC,
3678 [INDEX_op_adcw_T0_T1_cc] = CC_OSZAPC,
3679 [INDEX_op_adcl_T0_T1_cc] = CC_OSZAPC,
3680 [INDEX_op_sbbb_T0_T1_cc] = CC_OSZAPC,
3681 [INDEX_op_sbbw_T0_T1_cc] = CC_OSZAPC,
3682 [INDEX_op_sbbl_T0_T1_cc] = CC_OSZAPC,
3683 [INDEX_op_andl_T0_T1_cc] = CC_OSZAPC,
3684 [INDEX_op_subl_T0_T1_cc] = CC_OSZAPC,
3685 [INDEX_op_xorl_T0_T1_cc] = CC_OSZAPC,
3686 [INDEX_op_cmpl_T0_T1_cc] = CC_OSZAPC,
3687 [INDEX_op_negl_T0_cc] = CC_OSZAPC,
3688 /* subtle: due to the incl/decl implementation, C is used */
3689 [INDEX_op_incl_T0_cc] = CC_OSZAPC,
3690 [INDEX_op_decl_T0_cc] = CC_OSZAPC,
3691 [INDEX_op_testl_T0_T1_cc] = CC_OSZAPC,
3692
3693 [INDEX_op_mulb_AL_T0] = CC_OSZAPC,
3694 [INDEX_op_imulb_AL_T0] = CC_OSZAPC,
3695 [INDEX_op_mulw_AX_T0] = CC_OSZAPC,
3696 [INDEX_op_imulw_AX_T0] = CC_OSZAPC,
3697 [INDEX_op_mull_EAX_T0] = CC_OSZAPC,
3698 [INDEX_op_imull_EAX_T0] = CC_OSZAPC,
3699 [INDEX_op_imulw_T0_T1] = CC_OSZAPC,
3700 [INDEX_op_imull_T0_T1] = CC_OSZAPC,
3701
3702 /* bcd */
3703 [INDEX_op_aam] = CC_OSZAPC,
3704 [INDEX_op_aad] = CC_OSZAPC,
3705 [INDEX_op_aas] = CC_OSZAPC,
3706 [INDEX_op_aaa] = CC_OSZAPC,
3707 [INDEX_op_das] = CC_OSZAPC,
3708 [INDEX_op_daa] = CC_OSZAPC,
3709
3710 [INDEX_op_movb_eflags_T0] = CC_S | CC_Z | CC_A | CC_P | CC_C,
3711 [INDEX_op_movw_eflags_T0] = CC_OSZAPC,
3712 [INDEX_op_movl_eflags_T0] = CC_OSZAPC,
3713 [INDEX_op_clc] = CC_C,
3714 [INDEX_op_stc] = CC_C,
3715 [INDEX_op_cmc] = CC_C,
3716
3717 [INDEX_op_rolb_T0_T1_cc] = CC_O | CC_C,
3718 [INDEX_op_rolw_T0_T1_cc] = CC_O | CC_C,
3719 [INDEX_op_roll_T0_T1_cc] = CC_O | CC_C,
3720 [INDEX_op_rorb_T0_T1_cc] = CC_O | CC_C,
3721 [INDEX_op_rorw_T0_T1_cc] = CC_O | CC_C,
3722 [INDEX_op_rorl_T0_T1_cc] = CC_O | CC_C,
3723
3724 [INDEX_op_rclb_T0_T1_cc] = CC_O | CC_C,
3725 [INDEX_op_rclw_T0_T1_cc] = CC_O | CC_C,
3726 [INDEX_op_rcll_T0_T1_cc] = CC_O | CC_C,
3727 [INDEX_op_rcrb_T0_T1_cc] = CC_O | CC_C,
3728 [INDEX_op_rcrw_T0_T1_cc] = CC_O | CC_C,
3729 [INDEX_op_rcrl_T0_T1_cc] = CC_O | CC_C,
3730
3731 [INDEX_op_shlb_T0_T1_cc] = CC_OSZAPC,
3732 [INDEX_op_shlw_T0_T1_cc] = CC_OSZAPC,
3733 [INDEX_op_shll_T0_T1_cc] = CC_OSZAPC,
3734
3735 [INDEX_op_shrb_T0_T1_cc] = CC_OSZAPC,
3736 [INDEX_op_shrw_T0_T1_cc] = CC_OSZAPC,
3737 [INDEX_op_shrl_T0_T1_cc] = CC_OSZAPC,
3738
3739 [INDEX_op_sarb_T0_T1_cc] = CC_OSZAPC,
3740 [INDEX_op_sarw_T0_T1_cc] = CC_OSZAPC,
3741 [INDEX_op_sarl_T0_T1_cc] = CC_OSZAPC,
3742
3743 [INDEX_op_shldw_T0_T1_ECX_cc] = CC_OSZAPC,
3744 [INDEX_op_shldl_T0_T1_ECX_cc] = CC_OSZAPC,
3745 [INDEX_op_shldw_T0_T1_im_cc] = CC_OSZAPC,
3746 [INDEX_op_shldl_T0_T1_im_cc] = CC_OSZAPC,
3747
3748 [INDEX_op_shrdw_T0_T1_ECX_cc] = CC_OSZAPC,
3749 [INDEX_op_shrdl_T0_T1_ECX_cc] = CC_OSZAPC,
3750 [INDEX_op_shrdw_T0_T1_im_cc] = CC_OSZAPC,
3751 [INDEX_op_shrdl_T0_T1_im_cc] = CC_OSZAPC,
3752
3753 [INDEX_op_btw_T0_T1_cc] = CC_OSZAPC,
3754 [INDEX_op_btl_T0_T1_cc] = CC_OSZAPC,
3755 [INDEX_op_btsw_T0_T1_cc] = CC_OSZAPC,
3756 [INDEX_op_btsl_T0_T1_cc] = CC_OSZAPC,
3757 [INDEX_op_btrw_T0_T1_cc] = CC_OSZAPC,
3758 [INDEX_op_btrl_T0_T1_cc] = CC_OSZAPC,
3759 [INDEX_op_btcw_T0_T1_cc] = CC_OSZAPC,
3760 [INDEX_op_btcl_T0_T1_cc] = CC_OSZAPC,
3761
3762 [INDEX_op_bsfw_T0_cc] = CC_OSZAPC,
3763 [INDEX_op_bsfl_T0_cc] = CC_OSZAPC,
3764 [INDEX_op_bsrw_T0_cc] = CC_OSZAPC,
3765 [INDEX_op_bsrl_T0_cc] = CC_OSZAPC,
3766
3767 #undef STRINGOP
3768 #define STRINGOP(x) \
3769 [INDEX_op_ ## x ## b_fast] = CC_OSZAPC, \
3770 [INDEX_op_ ## x ## w_fast] = CC_OSZAPC, \
3771 [INDEX_op_ ## x ## l_fast] = CC_OSZAPC, \
3772 [INDEX_op_ ## x ## b_a32] = CC_OSZAPC, \
3773 [INDEX_op_ ## x ## w_a32] = CC_OSZAPC, \
3774 [INDEX_op_ ## x ## l_a32] = CC_OSZAPC, \
3775 [INDEX_op_ ## x ## b_a16] = CC_OSZAPC, \
3776 [INDEX_op_ ## x ## w_a16] = CC_OSZAPC, \
3777 [INDEX_op_ ## x ## l_a16] = CC_OSZAPC,
3778
3779 STRINGOP(scas)
3780 STRINGOP(repz_scas)
3781 STRINGOP(repnz_scas)
3782 STRINGOP(cmps)
3783 STRINGOP(repz_cmps)
3784 STRINGOP(repnz_cmps)
3785
3786 [INDEX_op_cmpxchgb_T0_T1_EAX_cc] = CC_OSZAPC,
3787 [INDEX_op_cmpxchgw_T0_T1_EAX_cc] = CC_OSZAPC,
3788 [INDEX_op_cmpxchgl_T0_T1_EAX_cc] = CC_OSZAPC,
3789
3790 [INDEX_op_cmpxchg8b] = CC_Z,
3791 [INDEX_op_lar] = CC_Z,
3792 [INDEX_op_lsl] = CC_Z,
3793 [INDEX_op_fcomi_ST0_FT0] = CC_Z | CC_P | CC_C,
3794 [INDEX_op_fucomi_ST0_FT0] = CC_Z | CC_P | CC_C,
3795 };
3796
3797 /* simpler form of an operation if no flags need to be generated */
3798 static uint16_t opc_simpler[NB_OPS] = {
3799 [INDEX_op_addl_T0_T1_cc] = INDEX_op_addl_T0_T1,
3800 [INDEX_op_orl_T0_T1_cc] = INDEX_op_orl_T0_T1,
3801 [INDEX_op_andl_T0_T1_cc] = INDEX_op_andl_T0_T1,
3802 [INDEX_op_subl_T0_T1_cc] = INDEX_op_subl_T0_T1,
3803 [INDEX_op_xorl_T0_T1_cc] = INDEX_op_xorl_T0_T1,
3804 [INDEX_op_negl_T0_cc] = INDEX_op_negl_T0,
3805 [INDEX_op_incl_T0_cc] = INDEX_op_incl_T0,
3806 [INDEX_op_decl_T0_cc] = INDEX_op_decl_T0,
3807
3808 [INDEX_op_rolb_T0_T1_cc] = INDEX_op_rolb_T0_T1,
3809 [INDEX_op_rolw_T0_T1_cc] = INDEX_op_rolw_T0_T1,
3810 [INDEX_op_roll_T0_T1_cc] = INDEX_op_roll_T0_T1,
3811
3812 [INDEX_op_rorb_T0_T1_cc] = INDEX_op_rorb_T0_T1,
3813 [INDEX_op_rorw_T0_T1_cc] = INDEX_op_rorw_T0_T1,
3814 [INDEX_op_rorl_T0_T1_cc] = INDEX_op_rorl_T0_T1,
3815
3816 [INDEX_op_shlb_T0_T1_cc] = INDEX_op_shlb_T0_T1,
3817 [INDEX_op_shlw_T0_T1_cc] = INDEX_op_shlw_T0_T1,
3818 [INDEX_op_shll_T0_T1_cc] = INDEX_op_shll_T0_T1,
3819
3820 [INDEX_op_shrb_T0_T1_cc] = INDEX_op_shrb_T0_T1,
3821 [INDEX_op_shrw_T0_T1_cc] = INDEX_op_shrw_T0_T1,
3822 [INDEX_op_shrl_T0_T1_cc] = INDEX_op_shrl_T0_T1,
3823
3824 [INDEX_op_sarb_T0_T1_cc] = INDEX_op_sarb_T0_T1,
3825 [INDEX_op_sarw_T0_T1_cc] = INDEX_op_sarw_T0_T1,
3826 [INDEX_op_sarl_T0_T1_cc] = INDEX_op_sarl_T0_T1,
3827 };
3828
3829 static void optimize_flags_init(void)
3830 {
3831 int i;
3832 /* put default values in arrays */
3833 for(i = 0; i < NB_OPS; i++) {
3834 if (opc_simpler[i] == 0)
3835 opc_simpler[i] = i;
3836 }
3837 }
3838
3839 /* CPU flags computation optimization: we move backward thru the
3840 generated code to see which flags are needed. The operation is
3841 modified if suitable */
3842 static void optimize_flags(uint16_t *opc_buf, int opc_buf_len)
3843 {
3844 uint16_t *opc_ptr;
3845 int live_flags, write_flags, op;
3846
3847 opc_ptr = opc_buf + opc_buf_len;
3848 /* live_flags contains the flags needed by the next instructions
3849 in the code. At the end of the bloc, we consider that all the
3850 flags are live. */
3851 live_flags = CC_OSZAPC;
3852 while (opc_ptr > opc_buf) {
3853 op = *--opc_ptr;
3854 /* if none of the flags written by the instruction is used,
3855 then we can try to find a simpler instruction */
3856 write_flags = opc_write_flags[op];
3857 if ((live_flags & write_flags) == 0) {
3858 *opc_ptr = opc_simpler[op];
3859 }
3860 /* compute the live flags before the instruction */
3861 live_flags &= ~write_flags;
3862 live_flags |= opc_read_flags[op];
3863 }
3864 }
3865
3866 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
3867 basic block 'tb'. If search_pc is TRUE, also generate PC
3868 information for each intermediate instruction. */
3869 int gen_intermediate_code(TranslationBlock *tb, int search_pc)
3870 {
3871 DisasContext dc1, *dc = &dc1;
3872 uint8_t *pc_ptr;
3873 uint16_t *gen_opc_end;
3874 int flags, j, lj;
3875 long ret;
3876 uint8_t *pc_start;
3877 uint8_t *cs_base;
3878
3879 /* generate intermediate code */
3880 pc_start = (uint8_t *)tb->pc;
3881 cs_base = (uint8_t *)tb->cs_base;
3882 flags = tb->flags;
3883
3884 dc->code32 = (flags >> GEN_FLAG_CODE32_SHIFT) & 1;
3885 dc->ss32 = (flags >> GEN_FLAG_SS32_SHIFT) & 1;
3886 dc->addseg = (flags >> GEN_FLAG_ADDSEG_SHIFT) & 1;
3887 dc->f_st = (flags >> GEN_FLAG_ST_SHIFT) & 7;
3888 dc->vm86 = (flags >> GEN_FLAG_VM_SHIFT) & 1;
3889 dc->cpl = (flags >> GEN_FLAG_CPL_SHIFT) & 3;
3890 dc->iopl = (flags >> GEN_FLAG_IOPL_SHIFT) & 3;
3891 dc->tf = (flags >> GEN_FLAG_TF_SHIFT) & 1;
3892 dc->cc_op = CC_OP_DYNAMIC;
3893 dc->cs_base = cs_base;
3894 dc->tb = tb;
3895
3896 gen_opc_ptr = gen_opc_buf;
3897 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
3898 gen_opparam_ptr = gen_opparam_buf;
3899
3900 dc->is_jmp = DISAS_NEXT;
3901 pc_ptr = pc_start;
3902 lj = -1;
3903 do {
3904 if (search_pc) {
3905 j = gen_opc_ptr - gen_opc_buf;
3906 if (lj < j) {
3907 lj++;
3908 while (lj < j)
3909 gen_opc_instr_start[lj++] = 0;
3910 gen_opc_pc[lj] = (uint32_t)pc_ptr;
3911 gen_opc_instr_start[lj] = 1;
3912 }
3913 }
3914 ret = disas_insn(dc, pc_ptr);
3915 if (ret == -1) {
3916 /* we trigger an illegal instruction operation only if it
3917 is the first instruction. Otherwise, we simply stop
3918 generating the code just before it */
3919 if (pc_ptr == pc_start)
3920 return -1;
3921 else
3922 break;
3923 }
3924 pc_ptr = (void *)ret;
3925 /* if single step mode, we generate only one instruction and
3926 generate an exception */
3927 if (dc->tf)
3928 break;
3929 } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
3930 (pc_ptr - pc_start) < (TARGET_PAGE_SIZE - 32));
3931 /* we must store the eflags state if it is not already done */
3932 if (dc->is_jmp != DISAS_TB_JUMP) {
3933 if (dc->cc_op != CC_OP_DYNAMIC)
3934 gen_op_set_cc_op(dc->cc_op);
3935 if (dc->is_jmp != DISAS_JUMP) {
3936 /* we add an additionnal jmp to update the simulated PC */
3937 gen_op_jmp_im(ret - (unsigned long)dc->cs_base);
3938 }
3939 }
3940 if (dc->tf) {
3941 gen_op_raise_exception(EXCP01_SSTP);
3942 }
3943 if (dc->is_jmp != 3) {
3944 /* indicate that the hash table must be used to find the next TB */
3945 gen_op_movl_T0_0();
3946 }
3947 *gen_opc_ptr = INDEX_op_end;
3948
3949 #ifdef DEBUG_DISAS
3950 if (loglevel) {
3951 fprintf(logfile, "----------------\n");
3952 fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
3953 disas(logfile, pc_start, pc_ptr - pc_start, 0, !dc->code32);
3954 fprintf(logfile, "\n");
3955
3956 fprintf(logfile, "OP:\n");
3957 dump_ops(gen_opc_buf, gen_opparam_buf);
3958 fprintf(logfile, "\n");
3959 }
3960 #endif
3961
3962 /* optimize flag computations */
3963 optimize_flags(gen_opc_buf, gen_opc_ptr - gen_opc_buf);
3964
3965 #ifdef DEBUG_DISAS
3966 if (loglevel) {
3967 fprintf(logfile, "AFTER FLAGS OPT:\n");
3968 dump_ops(gen_opc_buf, gen_opparam_buf);
3969 fprintf(logfile, "\n");
3970 }
3971 #endif
3972 if (!search_pc)
3973 tb->size = pc_ptr - pc_start;
3974 return 0;
3975 }
3976
3977 CPUX86State *cpu_x86_init(void)
3978 {
3979 CPUX86State *env;
3980 int i;
3981 static int inited;
3982
3983 cpu_exec_init();
3984
3985 env = malloc(sizeof(CPUX86State));
3986 if (!env)
3987 return NULL;
3988 memset(env, 0, sizeof(CPUX86State));
3989 /* basic FPU init */
3990 for(i = 0;i < 8; i++)
3991 env->fptags[i] = 1;
3992 env->fpuc = 0x37f;
3993 /* flags setup : we activate the IRQs by default as in user mode */
3994 env->eflags = 0x2 | IF_MASK;
3995
3996 /* init various static tables */
3997 if (!inited) {
3998 inited = 1;
3999 optimize_flags_init();
4000 }
4001 return env;
4002 }
4003
4004 void cpu_x86_close(CPUX86State *env)
4005 {
4006 free(env);
4007 }
4008
4009 static const char *cc_op_str[] = {
4010 "DYNAMIC",
4011 "EFLAGS",
4012 "MUL",
4013 "ADDB",
4014 "ADDW",
4015 "ADDL",
4016 "ADCB",
4017 "ADCW",
4018 "ADCL",
4019 "SUBB",
4020 "SUBW",
4021 "SUBL",
4022 "SBBB",
4023 "SBBW",
4024 "SBBL",
4025 "LOGICB",
4026 "LOGICW",
4027 "LOGICL",
4028 "INCB",
4029 "INCW",
4030 "INCL",
4031 "DECB",
4032 "DECW",
4033 "DECL",
4034 "SHLB",
4035 "SHLW",
4036 "SHLL",
4037 "SARB",
4038 "SARW",
4039 "SARL",
4040 };
4041
4042 void cpu_x86_dump_state(CPUX86State *env, FILE *f, int flags)
4043 {
4044 int eflags;
4045 char cc_op_name[32];
4046
4047 eflags = env->eflags;
4048 fprintf(f, "EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n"
4049 "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n"
4050 "EIP=%08x EFL=%08x [%c%c%c%c%c%c%c]\n",
4051 env->regs[R_EAX], env->regs[R_EBX], env->regs[R_ECX], env->regs[R_EDX],
4052 env->regs[R_ESI], env->regs[R_EDI], env->regs[R_EBP], env->regs[R_ESP],
4053 env->eip, eflags,
4054 eflags & DF_MASK ? 'D' : '-',
4055 eflags & CC_O ? 'O' : '-',
4056 eflags & CC_S ? 'S' : '-',
4057 eflags & CC_Z ? 'Z' : '-',
4058 eflags & CC_A ? 'A' : '-',
4059 eflags & CC_P ? 'P' : '-',
4060 eflags & CC_C ? 'C' : '-');
4061 fprintf(f, "CS=%04x SS=%04x DS=%04x ES=%04x FS=%04x GS=%04x\n",
4062 env->segs[R_CS].selector,
4063 env->segs[R_SS].selector,
4064 env->segs[R_DS].selector,
4065 env->segs[R_ES].selector,
4066 env->segs[R_FS].selector,
4067 env->segs[R_GS].selector);
4068 if (flags & X86_DUMP_CCOP) {
4069 if ((unsigned)env->cc_op < CC_OP_NB)
4070 strcpy(cc_op_name, cc_op_str[env->cc_op]);
4071 else
4072 snprintf(cc_op_name, sizeof(cc_op_name), "[%d]", env->cc_op);
4073 fprintf(f, "CCS=%08x CCD=%08x CCO=%-8s\n",
4074 env->cc_src, env->cc_dst, cc_op_name);
4075 }
4076 if (flags & X86_DUMP_FPU) {
4077 fprintf(f, "ST0=%f ST1=%f ST2=%f ST3=%f\n",
4078 (double)env->fpregs[0],
4079 (double)env->fpregs[1],
4080 (double)env->fpregs[2],
4081 (double)env->fpregs[3]);
4082 fprintf(f, "ST4=%f ST5=%f ST6=%f ST7=%f\n",
4083 (double)env->fpregs[4],
4084 (double)env->fpregs[5],
4085 (double)env->fpregs[7],
4086 (double)env->fpregs[8]);
4087 }
4088 }