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