]> git.proxmox.com Git - mirror_qemu.git/blame - target-i386/translate.c
No write-protect detect diode on Mainstone II.
[mirror_qemu.git] / target-i386 / translate.c
CommitLineData
2c0262af
FB
1/*
2 * i386 translation
5fafdf24 3 *
2c0262af
FB
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>
2c0262af
FB
27
28#include "cpu.h"
29#include "exec-all.h"
30#include "disas.h"
31
32/* XXX: move that elsewhere */
33static uint16_t *gen_opc_ptr;
34static uint32_t *gen_opparam_ptr;
35
36#define PREFIX_REPZ 0x01
37#define PREFIX_REPNZ 0x02
38#define PREFIX_LOCK 0x04
39#define PREFIX_DATA 0x08
40#define PREFIX_ADR 0x10
41
14ce26e7
FB
42#ifdef TARGET_X86_64
43#define X86_64_ONLY(x) x
44#define X86_64_DEF(x...) x
45#define CODE64(s) ((s)->code64)
46#define REX_X(s) ((s)->rex_x)
47#define REX_B(s) ((s)->rex_b)
48/* XXX: gcc generates push/pop in some opcodes, so we cannot use them */
49#if 1
50#define BUGGY_64(x) NULL
51#endif
52#else
53#define X86_64_ONLY(x) NULL
54#define X86_64_DEF(x...)
55#define CODE64(s) 0
56#define REX_X(s) 0
57#define REX_B(s) 0
58#endif
59
60#ifdef TARGET_X86_64
61static int x86_64_hregs;
62#endif
63
ae063a68
FB
64#ifdef USE_DIRECT_JUMP
65#define TBPARAM(x)
66#else
67#define TBPARAM(x) (long)(x)
68#endif
69
2c0262af
FB
70typedef struct DisasContext {
71 /* current insn context */
72 int override; /* -1 if no override */
73 int prefix;
74 int aflag, dflag;
14ce26e7 75 target_ulong pc; /* pc = eip + cs_base */
2c0262af
FB
76 int is_jmp; /* 1 = means jump (stop translation), 2 means CPU
77 static state change (stop translation) */
78 /* current block context */
14ce26e7 79 target_ulong cs_base; /* base of CS segment */
2c0262af
FB
80 int pe; /* protected mode */
81 int code32; /* 32 bit code segment */
14ce26e7
FB
82#ifdef TARGET_X86_64
83 int lma; /* long mode active */
84 int code64; /* 64 bit code segment */
85 int rex_x, rex_b;
86#endif
2c0262af
FB
87 int ss32; /* 32 bit stack segment */
88 int cc_op; /* current CC operation */
89 int addseg; /* non zero if either DS/ES/SS have a non zero base */
90 int f_st; /* currently unused */
91 int vm86; /* vm86 mode */
92 int cpl;
93 int iopl;
94 int tf; /* TF cpu flag */
34865134 95 int singlestep_enabled; /* "hardware" single step enabled */
2c0262af
FB
96 int jmp_opt; /* use direct block chaining for direct jumps */
97 int mem_index; /* select memory access functions */
c068688b 98 uint64_t flags; /* all execution flags */
2c0262af
FB
99 struct TranslationBlock *tb;
100 int popl_esp_hack; /* for correct popl with esp base handling */
14ce26e7
FB
101 int rip_offset; /* only used in x86_64, but left for simplicity */
102 int cpuid_features;
3d7374c5 103 int cpuid_ext_features;
2c0262af
FB
104} DisasContext;
105
106static void gen_eob(DisasContext *s);
14ce26e7
FB
107static void gen_jmp(DisasContext *s, target_ulong eip);
108static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num);
2c0262af
FB
109
110/* i386 arith/logic operations */
111enum {
5fafdf24
TS
112 OP_ADDL,
113 OP_ORL,
114 OP_ADCL,
2c0262af 115 OP_SBBL,
5fafdf24
TS
116 OP_ANDL,
117 OP_SUBL,
118 OP_XORL,
2c0262af
FB
119 OP_CMPL,
120};
121
122/* i386 shift ops */
123enum {
5fafdf24
TS
124 OP_ROL,
125 OP_ROR,
126 OP_RCL,
127 OP_RCR,
128 OP_SHL,
129 OP_SHR,
2c0262af
FB
130 OP_SHL1, /* undocumented */
131 OP_SAR = 7,
132};
133
134enum {
135#define DEF(s, n, copy_size) INDEX_op_ ## s,
136#include "opc.h"
137#undef DEF
138 NB_OPS,
139};
140
141#include "gen-op.h"
142
143/* operand size */
144enum {
145 OT_BYTE = 0,
146 OT_WORD,
5fafdf24 147 OT_LONG,
2c0262af
FB
148 OT_QUAD,
149};
150
151enum {
152 /* I386 int registers */
153 OR_EAX, /* MUST be even numbered */
154 OR_ECX,
155 OR_EDX,
156 OR_EBX,
157 OR_ESP,
158 OR_EBP,
159 OR_ESI,
160 OR_EDI,
14ce26e7
FB
161
162 OR_TMP0 = 16, /* temporary operand register */
2c0262af
FB
163 OR_TMP1,
164 OR_A0, /* temporary register used when doing address evaluation */
2c0262af
FB
165};
166
14ce26e7
FB
167#ifdef TARGET_X86_64
168
169#define NB_OP_SIZES 4
170
171#define DEF_REGS(prefix, suffix) \
172 prefix ## EAX ## suffix,\
173 prefix ## ECX ## suffix,\
174 prefix ## EDX ## suffix,\
175 prefix ## EBX ## suffix,\
176 prefix ## ESP ## suffix,\
177 prefix ## EBP ## suffix,\
178 prefix ## ESI ## suffix,\
179 prefix ## EDI ## suffix,\
180 prefix ## R8 ## suffix,\
181 prefix ## R9 ## suffix,\
182 prefix ## R10 ## suffix,\
183 prefix ## R11 ## suffix,\
184 prefix ## R12 ## suffix,\
185 prefix ## R13 ## suffix,\
186 prefix ## R14 ## suffix,\
187 prefix ## R15 ## suffix,
188
189#define DEF_BREGS(prefixb, prefixh, suffix) \
190 \
191static void prefixb ## ESP ## suffix ## _wrapper(void) \
192{ \
193 if (x86_64_hregs) \
194 prefixb ## ESP ## suffix (); \
195 else \
196 prefixh ## EAX ## suffix (); \
197} \
198 \
199static void prefixb ## EBP ## suffix ## _wrapper(void) \
200{ \
201 if (x86_64_hregs) \
202 prefixb ## EBP ## suffix (); \
203 else \
204 prefixh ## ECX ## suffix (); \
205} \
206 \
207static void prefixb ## ESI ## suffix ## _wrapper(void) \
208{ \
209 if (x86_64_hregs) \
210 prefixb ## ESI ## suffix (); \
211 else \
212 prefixh ## EDX ## suffix (); \
213} \
214 \
215static void prefixb ## EDI ## suffix ## _wrapper(void) \
216{ \
217 if (x86_64_hregs) \
218 prefixb ## EDI ## suffix (); \
219 else \
220 prefixh ## EBX ## suffix (); \
221}
222
223DEF_BREGS(gen_op_movb_, gen_op_movh_, _T0)
224DEF_BREGS(gen_op_movb_, gen_op_movh_, _T1)
225DEF_BREGS(gen_op_movl_T0_, gen_op_movh_T0_, )
226DEF_BREGS(gen_op_movl_T1_, gen_op_movh_T1_, )
227
228#else /* !TARGET_X86_64 */
229
230#define NB_OP_SIZES 3
231
232#define DEF_REGS(prefix, suffix) \
233 prefix ## EAX ## suffix,\
234 prefix ## ECX ## suffix,\
235 prefix ## EDX ## suffix,\
236 prefix ## EBX ## suffix,\
237 prefix ## ESP ## suffix,\
238 prefix ## EBP ## suffix,\
239 prefix ## ESI ## suffix,\
240 prefix ## EDI ## suffix,
241
242#endif /* !TARGET_X86_64 */
243
244static GenOpFunc *gen_op_mov_reg_T0[NB_OP_SIZES][CPU_NB_REGS] = {
2c0262af
FB
245 [OT_BYTE] = {
246 gen_op_movb_EAX_T0,
247 gen_op_movb_ECX_T0,
248 gen_op_movb_EDX_T0,
249 gen_op_movb_EBX_T0,
14ce26e7
FB
250#ifdef TARGET_X86_64
251 gen_op_movb_ESP_T0_wrapper,
252 gen_op_movb_EBP_T0_wrapper,
253 gen_op_movb_ESI_T0_wrapper,
254 gen_op_movb_EDI_T0_wrapper,
255 gen_op_movb_R8_T0,
256 gen_op_movb_R9_T0,
257 gen_op_movb_R10_T0,
258 gen_op_movb_R11_T0,
259 gen_op_movb_R12_T0,
260 gen_op_movb_R13_T0,
261 gen_op_movb_R14_T0,
262 gen_op_movb_R15_T0,
263#else
2c0262af
FB
264 gen_op_movh_EAX_T0,
265 gen_op_movh_ECX_T0,
266 gen_op_movh_EDX_T0,
267 gen_op_movh_EBX_T0,
14ce26e7 268#endif
2c0262af
FB
269 },
270 [OT_WORD] = {
14ce26e7 271 DEF_REGS(gen_op_movw_, _T0)
2c0262af
FB
272 },
273 [OT_LONG] = {
14ce26e7 274 DEF_REGS(gen_op_movl_, _T0)
2c0262af 275 },
14ce26e7
FB
276#ifdef TARGET_X86_64
277 [OT_QUAD] = {
278 DEF_REGS(gen_op_movq_, _T0)
279 },
280#endif
2c0262af
FB
281};
282
14ce26e7 283static GenOpFunc *gen_op_mov_reg_T1[NB_OP_SIZES][CPU_NB_REGS] = {
2c0262af
FB
284 [OT_BYTE] = {
285 gen_op_movb_EAX_T1,
286 gen_op_movb_ECX_T1,
287 gen_op_movb_EDX_T1,
288 gen_op_movb_EBX_T1,
14ce26e7
FB
289#ifdef TARGET_X86_64
290 gen_op_movb_ESP_T1_wrapper,
291 gen_op_movb_EBP_T1_wrapper,
292 gen_op_movb_ESI_T1_wrapper,
293 gen_op_movb_EDI_T1_wrapper,
294 gen_op_movb_R8_T1,
295 gen_op_movb_R9_T1,
296 gen_op_movb_R10_T1,
297 gen_op_movb_R11_T1,
298 gen_op_movb_R12_T1,
299 gen_op_movb_R13_T1,
300 gen_op_movb_R14_T1,
301 gen_op_movb_R15_T1,
302#else
2c0262af
FB
303 gen_op_movh_EAX_T1,
304 gen_op_movh_ECX_T1,
305 gen_op_movh_EDX_T1,
306 gen_op_movh_EBX_T1,
14ce26e7 307#endif
2c0262af
FB
308 },
309 [OT_WORD] = {
14ce26e7 310 DEF_REGS(gen_op_movw_, _T1)
2c0262af
FB
311 },
312 [OT_LONG] = {
14ce26e7
FB
313 DEF_REGS(gen_op_movl_, _T1)
314 },
315#ifdef TARGET_X86_64
316 [OT_QUAD] = {
317 DEF_REGS(gen_op_movq_, _T1)
2c0262af 318 },
14ce26e7 319#endif
2c0262af
FB
320};
321
14ce26e7 322static GenOpFunc *gen_op_mov_reg_A0[NB_OP_SIZES - 1][CPU_NB_REGS] = {
2c0262af 323 [0] = {
14ce26e7 324 DEF_REGS(gen_op_movw_, _A0)
2c0262af
FB
325 },
326 [1] = {
14ce26e7
FB
327 DEF_REGS(gen_op_movl_, _A0)
328 },
329#ifdef TARGET_X86_64
330 [2] = {
331 DEF_REGS(gen_op_movq_, _A0)
2c0262af 332 },
14ce26e7 333#endif
2c0262af
FB
334};
335
5fafdf24 336static GenOpFunc *gen_op_mov_TN_reg[NB_OP_SIZES][2][CPU_NB_REGS] =
2c0262af
FB
337{
338 [OT_BYTE] = {
339 {
340 gen_op_movl_T0_EAX,
341 gen_op_movl_T0_ECX,
342 gen_op_movl_T0_EDX,
343 gen_op_movl_T0_EBX,
14ce26e7
FB
344#ifdef TARGET_X86_64
345 gen_op_movl_T0_ESP_wrapper,
346 gen_op_movl_T0_EBP_wrapper,
347 gen_op_movl_T0_ESI_wrapper,
348 gen_op_movl_T0_EDI_wrapper,
349 gen_op_movl_T0_R8,
350 gen_op_movl_T0_R9,
351 gen_op_movl_T0_R10,
352 gen_op_movl_T0_R11,
353 gen_op_movl_T0_R12,
354 gen_op_movl_T0_R13,
355 gen_op_movl_T0_R14,
356 gen_op_movl_T0_R15,
357#else
2c0262af
FB
358 gen_op_movh_T0_EAX,
359 gen_op_movh_T0_ECX,
360 gen_op_movh_T0_EDX,
361 gen_op_movh_T0_EBX,
14ce26e7 362#endif
2c0262af
FB
363 },
364 {
365 gen_op_movl_T1_EAX,
366 gen_op_movl_T1_ECX,
367 gen_op_movl_T1_EDX,
368 gen_op_movl_T1_EBX,
14ce26e7
FB
369#ifdef TARGET_X86_64
370 gen_op_movl_T1_ESP_wrapper,
371 gen_op_movl_T1_EBP_wrapper,
372 gen_op_movl_T1_ESI_wrapper,
373 gen_op_movl_T1_EDI_wrapper,
374 gen_op_movl_T1_R8,
375 gen_op_movl_T1_R9,
376 gen_op_movl_T1_R10,
377 gen_op_movl_T1_R11,
378 gen_op_movl_T1_R12,
379 gen_op_movl_T1_R13,
380 gen_op_movl_T1_R14,
381 gen_op_movl_T1_R15,
382#else
2c0262af
FB
383 gen_op_movh_T1_EAX,
384 gen_op_movh_T1_ECX,
385 gen_op_movh_T1_EDX,
386 gen_op_movh_T1_EBX,
14ce26e7 387#endif
2c0262af
FB
388 },
389 },
390 [OT_WORD] = {
391 {
14ce26e7 392 DEF_REGS(gen_op_movl_T0_, )
2c0262af
FB
393 },
394 {
14ce26e7 395 DEF_REGS(gen_op_movl_T1_, )
2c0262af
FB
396 },
397 },
398 [OT_LONG] = {
399 {
14ce26e7 400 DEF_REGS(gen_op_movl_T0_, )
2c0262af
FB
401 },
402 {
14ce26e7 403 DEF_REGS(gen_op_movl_T1_, )
2c0262af
FB
404 },
405 },
14ce26e7
FB
406#ifdef TARGET_X86_64
407 [OT_QUAD] = {
408 {
409 DEF_REGS(gen_op_movl_T0_, )
410 },
411 {
412 DEF_REGS(gen_op_movl_T1_, )
413 },
414 },
415#endif
2c0262af
FB
416};
417
14ce26e7
FB
418static GenOpFunc *gen_op_movl_A0_reg[CPU_NB_REGS] = {
419 DEF_REGS(gen_op_movl_A0_, )
2c0262af
FB
420};
421
14ce26e7 422static GenOpFunc *gen_op_addl_A0_reg_sN[4][CPU_NB_REGS] = {
2c0262af 423 [0] = {
14ce26e7 424 DEF_REGS(gen_op_addl_A0_, )
2c0262af
FB
425 },
426 [1] = {
14ce26e7 427 DEF_REGS(gen_op_addl_A0_, _s1)
2c0262af
FB
428 },
429 [2] = {
14ce26e7 430 DEF_REGS(gen_op_addl_A0_, _s2)
2c0262af
FB
431 },
432 [3] = {
14ce26e7 433 DEF_REGS(gen_op_addl_A0_, _s3)
2c0262af
FB
434 },
435};
436
14ce26e7
FB
437#ifdef TARGET_X86_64
438static GenOpFunc *gen_op_movq_A0_reg[CPU_NB_REGS] = {
439 DEF_REGS(gen_op_movq_A0_, )
440};
441
442static GenOpFunc *gen_op_addq_A0_reg_sN[4][CPU_NB_REGS] = {
2c0262af 443 [0] = {
14ce26e7 444 DEF_REGS(gen_op_addq_A0_, )
2c0262af
FB
445 },
446 [1] = {
14ce26e7
FB
447 DEF_REGS(gen_op_addq_A0_, _s1)
448 },
449 [2] = {
450 DEF_REGS(gen_op_addq_A0_, _s2)
451 },
452 [3] = {
453 DEF_REGS(gen_op_addq_A0_, _s3)
2c0262af
FB
454 },
455};
14ce26e7
FB
456#endif
457
458static GenOpFunc *gen_op_cmov_reg_T1_T0[NB_OP_SIZES - 1][CPU_NB_REGS] = {
459 [0] = {
460 DEF_REGS(gen_op_cmovw_, _T1_T0)
461 },
462 [1] = {
463 DEF_REGS(gen_op_cmovl_, _T1_T0)
464 },
465#ifdef TARGET_X86_64
466 [2] = {
467 DEF_REGS(gen_op_cmovq_, _T1_T0)
468 },
469#endif
470};
2c0262af
FB
471
472static GenOpFunc *gen_op_arith_T0_T1_cc[8] = {
473 NULL,
474 gen_op_orl_T0_T1,
475 NULL,
476 NULL,
477 gen_op_andl_T0_T1,
478 NULL,
479 gen_op_xorl_T0_T1,
480 NULL,
481};
482
4f31916f
FB
483#define DEF_ARITHC(SUFFIX)\
484 {\
485 gen_op_adcb ## SUFFIX ## _T0_T1_cc,\
486 gen_op_sbbb ## SUFFIX ## _T0_T1_cc,\
487 },\
488 {\
489 gen_op_adcw ## SUFFIX ## _T0_T1_cc,\
490 gen_op_sbbw ## SUFFIX ## _T0_T1_cc,\
491 },\
492 {\
493 gen_op_adcl ## SUFFIX ## _T0_T1_cc,\
494 gen_op_sbbl ## SUFFIX ## _T0_T1_cc,\
14ce26e7
FB
495 },\
496 {\
497 X86_64_ONLY(gen_op_adcq ## SUFFIX ## _T0_T1_cc),\
498 X86_64_ONLY(gen_op_sbbq ## SUFFIX ## _T0_T1_cc),\
2c0262af 499 },
4f31916f 500
14ce26e7 501static GenOpFunc *gen_op_arithc_T0_T1_cc[4][2] = {
4bb2fcc7 502 DEF_ARITHC( )
2c0262af
FB
503};
504
14ce26e7 505static GenOpFunc *gen_op_arithc_mem_T0_T1_cc[3 * 4][2] = {
4f31916f
FB
506 DEF_ARITHC(_raw)
507#ifndef CONFIG_USER_ONLY
508 DEF_ARITHC(_kernel)
509 DEF_ARITHC(_user)
510#endif
2c0262af
FB
511};
512
513static const int cc_op_arithb[8] = {
514 CC_OP_ADDB,
515 CC_OP_LOGICB,
516 CC_OP_ADDB,
517 CC_OP_SUBB,
518 CC_OP_LOGICB,
519 CC_OP_SUBB,
520 CC_OP_LOGICB,
521 CC_OP_SUBB,
522};
523
4f31916f
FB
524#define DEF_CMPXCHG(SUFFIX)\
525 gen_op_cmpxchgb ## SUFFIX ## _T0_T1_EAX_cc,\
526 gen_op_cmpxchgw ## SUFFIX ## _T0_T1_EAX_cc,\
14ce26e7
FB
527 gen_op_cmpxchgl ## SUFFIX ## _T0_T1_EAX_cc,\
528 X86_64_ONLY(gen_op_cmpxchgq ## SUFFIX ## _T0_T1_EAX_cc),
4f31916f 529
14ce26e7 530static GenOpFunc *gen_op_cmpxchg_T0_T1_EAX_cc[4] = {
4bb2fcc7 531 DEF_CMPXCHG( )
2c0262af
FB
532};
533
14ce26e7 534static GenOpFunc *gen_op_cmpxchg_mem_T0_T1_EAX_cc[3 * 4] = {
4f31916f
FB
535 DEF_CMPXCHG(_raw)
536#ifndef CONFIG_USER_ONLY
537 DEF_CMPXCHG(_kernel)
538 DEF_CMPXCHG(_user)
539#endif
2c0262af
FB
540};
541
4f31916f
FB
542#define DEF_SHIFT(SUFFIX)\
543 {\
544 gen_op_rolb ## SUFFIX ## _T0_T1_cc,\
545 gen_op_rorb ## SUFFIX ## _T0_T1_cc,\
546 gen_op_rclb ## SUFFIX ## _T0_T1_cc,\
547 gen_op_rcrb ## SUFFIX ## _T0_T1_cc,\
548 gen_op_shlb ## SUFFIX ## _T0_T1_cc,\
549 gen_op_shrb ## SUFFIX ## _T0_T1_cc,\
550 gen_op_shlb ## SUFFIX ## _T0_T1_cc,\
551 gen_op_sarb ## SUFFIX ## _T0_T1_cc,\
552 },\
553 {\
554 gen_op_rolw ## SUFFIX ## _T0_T1_cc,\
555 gen_op_rorw ## SUFFIX ## _T0_T1_cc,\
556 gen_op_rclw ## SUFFIX ## _T0_T1_cc,\
557 gen_op_rcrw ## SUFFIX ## _T0_T1_cc,\
558 gen_op_shlw ## SUFFIX ## _T0_T1_cc,\
559 gen_op_shrw ## SUFFIX ## _T0_T1_cc,\
560 gen_op_shlw ## SUFFIX ## _T0_T1_cc,\
561 gen_op_sarw ## SUFFIX ## _T0_T1_cc,\
562 },\
563 {\
564 gen_op_roll ## SUFFIX ## _T0_T1_cc,\
565 gen_op_rorl ## SUFFIX ## _T0_T1_cc,\
566 gen_op_rcll ## SUFFIX ## _T0_T1_cc,\
567 gen_op_rcrl ## SUFFIX ## _T0_T1_cc,\
568 gen_op_shll ## SUFFIX ## _T0_T1_cc,\
569 gen_op_shrl ## SUFFIX ## _T0_T1_cc,\
570 gen_op_shll ## SUFFIX ## _T0_T1_cc,\
571 gen_op_sarl ## SUFFIX ## _T0_T1_cc,\
14ce26e7
FB
572 },\
573 {\
574 X86_64_ONLY(gen_op_rolq ## SUFFIX ## _T0_T1_cc),\
575 X86_64_ONLY(gen_op_rorq ## SUFFIX ## _T0_T1_cc),\
576 X86_64_ONLY(gen_op_rclq ## SUFFIX ## _T0_T1_cc),\
577 X86_64_ONLY(gen_op_rcrq ## SUFFIX ## _T0_T1_cc),\
578 X86_64_ONLY(gen_op_shlq ## SUFFIX ## _T0_T1_cc),\
579 X86_64_ONLY(gen_op_shrq ## SUFFIX ## _T0_T1_cc),\
580 X86_64_ONLY(gen_op_shlq ## SUFFIX ## _T0_T1_cc),\
581 X86_64_ONLY(gen_op_sarq ## SUFFIX ## _T0_T1_cc),\
2c0262af 582 },
4f31916f 583
14ce26e7 584static GenOpFunc *gen_op_shift_T0_T1_cc[4][8] = {
4bb2fcc7 585 DEF_SHIFT( )
2c0262af
FB
586};
587
14ce26e7 588static GenOpFunc *gen_op_shift_mem_T0_T1_cc[3 * 4][8] = {
4f31916f
FB
589 DEF_SHIFT(_raw)
590#ifndef CONFIG_USER_ONLY
591 DEF_SHIFT(_kernel)
592 DEF_SHIFT(_user)
593#endif
2c0262af
FB
594};
595
4f31916f
FB
596#define DEF_SHIFTD(SUFFIX, op)\
597 {\
598 NULL,\
599 NULL,\
600 },\
601 {\
602 gen_op_shldw ## SUFFIX ## _T0_T1_ ## op ## _cc,\
603 gen_op_shrdw ## SUFFIX ## _T0_T1_ ## op ## _cc,\
31313213 604 },\
4f31916f
FB
605 {\
606 gen_op_shldl ## SUFFIX ## _T0_T1_ ## op ## _cc,\
607 gen_op_shrdl ## SUFFIX ## _T0_T1_ ## op ## _cc,\
14ce26e7
FB
608 },\
609 {\
31313213
FB
610X86_64_DEF(gen_op_shldq ## SUFFIX ## _T0_T1_ ## op ## _cc,\
611 gen_op_shrdq ## SUFFIX ## _T0_T1_ ## op ## _cc,)\
2c0262af 612 },
4f31916f 613
14ce26e7 614static GenOpFunc1 *gen_op_shiftd_T0_T1_im_cc[4][2] = {
4f31916f 615 DEF_SHIFTD(, im)
2c0262af
FB
616};
617
14ce26e7 618static GenOpFunc *gen_op_shiftd_T0_T1_ECX_cc[4][2] = {
4f31916f 619 DEF_SHIFTD(, ECX)
2c0262af
FB
620};
621
14ce26e7 622static GenOpFunc1 *gen_op_shiftd_mem_T0_T1_im_cc[3 * 4][2] = {
4f31916f
FB
623 DEF_SHIFTD(_raw, im)
624#ifndef CONFIG_USER_ONLY
625 DEF_SHIFTD(_kernel, im)
626 DEF_SHIFTD(_user, im)
627#endif
2c0262af
FB
628};
629
14ce26e7 630static GenOpFunc *gen_op_shiftd_mem_T0_T1_ECX_cc[3 * 4][2] = {
4f31916f
FB
631 DEF_SHIFTD(_raw, ECX)
632#ifndef CONFIG_USER_ONLY
633 DEF_SHIFTD(_kernel, ECX)
634 DEF_SHIFTD(_user, ECX)
635#endif
2c0262af
FB
636};
637
14ce26e7 638static GenOpFunc *gen_op_btx_T0_T1_cc[3][4] = {
2c0262af
FB
639 [0] = {
640 gen_op_btw_T0_T1_cc,
641 gen_op_btsw_T0_T1_cc,
642 gen_op_btrw_T0_T1_cc,
643 gen_op_btcw_T0_T1_cc,
644 },
645 [1] = {
646 gen_op_btl_T0_T1_cc,
647 gen_op_btsl_T0_T1_cc,
648 gen_op_btrl_T0_T1_cc,
649 gen_op_btcl_T0_T1_cc,
650 },
14ce26e7
FB
651#ifdef TARGET_X86_64
652 [2] = {
653 gen_op_btq_T0_T1_cc,
654 gen_op_btsq_T0_T1_cc,
655 gen_op_btrq_T0_T1_cc,
656 gen_op_btcq_T0_T1_cc,
657 },
658#endif
659};
660
661static GenOpFunc *gen_op_add_bit_A0_T1[3] = {
662 gen_op_add_bitw_A0_T1,
663 gen_op_add_bitl_A0_T1,
664 X86_64_ONLY(gen_op_add_bitq_A0_T1),
2c0262af
FB
665};
666
14ce26e7 667static GenOpFunc *gen_op_bsx_T0_cc[3][2] = {
2c0262af
FB
668 [0] = {
669 gen_op_bsfw_T0_cc,
670 gen_op_bsrw_T0_cc,
671 },
672 [1] = {
673 gen_op_bsfl_T0_cc,
674 gen_op_bsrl_T0_cc,
675 },
14ce26e7
FB
676#ifdef TARGET_X86_64
677 [2] = {
678 gen_op_bsfq_T0_cc,
679 gen_op_bsrq_T0_cc,
680 },
681#endif
2c0262af
FB
682};
683
14ce26e7 684static GenOpFunc *gen_op_lds_T0_A0[3 * 4] = {
61382a50
FB
685 gen_op_ldsb_raw_T0_A0,
686 gen_op_ldsw_raw_T0_A0,
14ce26e7 687 X86_64_ONLY(gen_op_ldsl_raw_T0_A0),
2c0262af 688 NULL,
61382a50 689#ifndef CONFIG_USER_ONLY
2c0262af
FB
690 gen_op_ldsb_kernel_T0_A0,
691 gen_op_ldsw_kernel_T0_A0,
14ce26e7 692 X86_64_ONLY(gen_op_ldsl_kernel_T0_A0),
2c0262af
FB
693 NULL,
694
695 gen_op_ldsb_user_T0_A0,
696 gen_op_ldsw_user_T0_A0,
14ce26e7 697 X86_64_ONLY(gen_op_ldsl_user_T0_A0),
2c0262af 698 NULL,
61382a50 699#endif
2c0262af
FB
700};
701
14ce26e7 702static GenOpFunc *gen_op_ldu_T0_A0[3 * 4] = {
61382a50
FB
703 gen_op_ldub_raw_T0_A0,
704 gen_op_lduw_raw_T0_A0,
2c0262af 705 NULL,
14ce26e7 706 NULL,
2c0262af 707
61382a50 708#ifndef CONFIG_USER_ONLY
2c0262af
FB
709 gen_op_ldub_kernel_T0_A0,
710 gen_op_lduw_kernel_T0_A0,
711 NULL,
14ce26e7 712 NULL,
2c0262af
FB
713
714 gen_op_ldub_user_T0_A0,
715 gen_op_lduw_user_T0_A0,
716 NULL,
14ce26e7 717 NULL,
61382a50 718#endif
2c0262af
FB
719};
720
721/* sign does not matter, except for lidt/lgdt call (TODO: fix it) */
14ce26e7 722static GenOpFunc *gen_op_ld_T0_A0[3 * 4] = {
61382a50
FB
723 gen_op_ldub_raw_T0_A0,
724 gen_op_lduw_raw_T0_A0,
725 gen_op_ldl_raw_T0_A0,
14ce26e7 726 X86_64_ONLY(gen_op_ldq_raw_T0_A0),
2c0262af 727
61382a50 728#ifndef CONFIG_USER_ONLY
2c0262af
FB
729 gen_op_ldub_kernel_T0_A0,
730 gen_op_lduw_kernel_T0_A0,
731 gen_op_ldl_kernel_T0_A0,
14ce26e7 732 X86_64_ONLY(gen_op_ldq_kernel_T0_A0),
2c0262af
FB
733
734 gen_op_ldub_user_T0_A0,
735 gen_op_lduw_user_T0_A0,
736 gen_op_ldl_user_T0_A0,
14ce26e7 737 X86_64_ONLY(gen_op_ldq_user_T0_A0),
61382a50 738#endif
2c0262af
FB
739};
740
14ce26e7 741static GenOpFunc *gen_op_ld_T1_A0[3 * 4] = {
61382a50
FB
742 gen_op_ldub_raw_T1_A0,
743 gen_op_lduw_raw_T1_A0,
744 gen_op_ldl_raw_T1_A0,
14ce26e7 745 X86_64_ONLY(gen_op_ldq_raw_T1_A0),
2c0262af 746
61382a50 747#ifndef CONFIG_USER_ONLY
2c0262af
FB
748 gen_op_ldub_kernel_T1_A0,
749 gen_op_lduw_kernel_T1_A0,
750 gen_op_ldl_kernel_T1_A0,
14ce26e7 751 X86_64_ONLY(gen_op_ldq_kernel_T1_A0),
2c0262af
FB
752
753 gen_op_ldub_user_T1_A0,
754 gen_op_lduw_user_T1_A0,
755 gen_op_ldl_user_T1_A0,
14ce26e7 756 X86_64_ONLY(gen_op_ldq_user_T1_A0),
61382a50 757#endif
2c0262af
FB
758};
759
14ce26e7 760static GenOpFunc *gen_op_st_T0_A0[3 * 4] = {
61382a50
FB
761 gen_op_stb_raw_T0_A0,
762 gen_op_stw_raw_T0_A0,
763 gen_op_stl_raw_T0_A0,
14ce26e7 764 X86_64_ONLY(gen_op_stq_raw_T0_A0),
2c0262af 765
61382a50 766#ifndef CONFIG_USER_ONLY
2c0262af
FB
767 gen_op_stb_kernel_T0_A0,
768 gen_op_stw_kernel_T0_A0,
769 gen_op_stl_kernel_T0_A0,
14ce26e7 770 X86_64_ONLY(gen_op_stq_kernel_T0_A0),
2c0262af
FB
771
772 gen_op_stb_user_T0_A0,
773 gen_op_stw_user_T0_A0,
774 gen_op_stl_user_T0_A0,
14ce26e7 775 X86_64_ONLY(gen_op_stq_user_T0_A0),
61382a50 776#endif
2c0262af
FB
777};
778
14ce26e7 779static GenOpFunc *gen_op_st_T1_A0[3 * 4] = {
4f31916f
FB
780 NULL,
781 gen_op_stw_raw_T1_A0,
782 gen_op_stl_raw_T1_A0,
14ce26e7 783 X86_64_ONLY(gen_op_stq_raw_T1_A0),
4f31916f
FB
784
785#ifndef CONFIG_USER_ONLY
786 NULL,
787 gen_op_stw_kernel_T1_A0,
788 gen_op_stl_kernel_T1_A0,
14ce26e7 789 X86_64_ONLY(gen_op_stq_kernel_T1_A0),
4f31916f
FB
790
791 NULL,
792 gen_op_stw_user_T1_A0,
793 gen_op_stl_user_T1_A0,
14ce26e7 794 X86_64_ONLY(gen_op_stq_user_T1_A0),
4f31916f
FB
795#endif
796};
797
14ce26e7
FB
798static inline void gen_jmp_im(target_ulong pc)
799{
800#ifdef TARGET_X86_64
801 if (pc == (uint32_t)pc) {
802 gen_op_movl_eip_im(pc);
803 } else if (pc == (int32_t)pc) {
804 gen_op_movq_eip_im(pc);
805 } else {
806 gen_op_movq_eip_im64(pc >> 32, pc);
807 }
808#else
809 gen_op_movl_eip_im(pc);
810#endif
811}
812
2c0262af
FB
813static inline void gen_string_movl_A0_ESI(DisasContext *s)
814{
815 int override;
816
817 override = s->override;
14ce26e7
FB
818#ifdef TARGET_X86_64
819 if (s->aflag == 2) {
820 if (override >= 0) {
821 gen_op_movq_A0_seg(offsetof(CPUX86State,segs[override].base));
822 gen_op_addq_A0_reg_sN[0][R_ESI]();
823 } else {
824 gen_op_movq_A0_reg[R_ESI]();
825 }
826 } else
827#endif
2c0262af
FB
828 if (s->aflag) {
829 /* 32 bit address */
830 if (s->addseg && override < 0)
831 override = R_DS;
832 if (override >= 0) {
833 gen_op_movl_A0_seg(offsetof(CPUX86State,segs[override].base));
834 gen_op_addl_A0_reg_sN[0][R_ESI]();
835 } else {
836 gen_op_movl_A0_reg[R_ESI]();
837 }
838 } else {
839 /* 16 address, always override */
840 if (override < 0)
841 override = R_DS;
842 gen_op_movl_A0_reg[R_ESI]();
843 gen_op_andl_A0_ffff();
844 gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base));
845 }
846}
847
848static inline void gen_string_movl_A0_EDI(DisasContext *s)
849{
14ce26e7
FB
850#ifdef TARGET_X86_64
851 if (s->aflag == 2) {
852 gen_op_movq_A0_reg[R_EDI]();
853 } else
854#endif
2c0262af
FB
855 if (s->aflag) {
856 if (s->addseg) {
857 gen_op_movl_A0_seg(offsetof(CPUX86State,segs[R_ES].base));
858 gen_op_addl_A0_reg_sN[0][R_EDI]();
859 } else {
860 gen_op_movl_A0_reg[R_EDI]();
861 }
862 } else {
863 gen_op_movl_A0_reg[R_EDI]();
864 gen_op_andl_A0_ffff();
865 gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_ES].base));
866 }
867}
868
14ce26e7 869static GenOpFunc *gen_op_movl_T0_Dshift[4] = {
2c0262af
FB
870 gen_op_movl_T0_Dshiftb,
871 gen_op_movl_T0_Dshiftw,
872 gen_op_movl_T0_Dshiftl,
14ce26e7 873 X86_64_ONLY(gen_op_movl_T0_Dshiftq),
2c0262af
FB
874};
875
14ce26e7
FB
876static GenOpFunc1 *gen_op_jnz_ecx[3] = {
877 gen_op_jnz_ecxw,
878 gen_op_jnz_ecxl,
879 X86_64_ONLY(gen_op_jnz_ecxq),
2c0262af 880};
3b46e624 881
14ce26e7
FB
882static GenOpFunc1 *gen_op_jz_ecx[3] = {
883 gen_op_jz_ecxw,
884 gen_op_jz_ecxl,
885 X86_64_ONLY(gen_op_jz_ecxq),
2c0262af
FB
886};
887
14ce26e7 888static GenOpFunc *gen_op_dec_ECX[3] = {
2c0262af
FB
889 gen_op_decw_ECX,
890 gen_op_decl_ECX,
14ce26e7 891 X86_64_ONLY(gen_op_decq_ECX),
2c0262af
FB
892};
893
14ce26e7 894static GenOpFunc1 *gen_op_string_jnz_sub[2][4] = {
2c0262af 895 {
14ce26e7
FB
896 gen_op_jnz_subb,
897 gen_op_jnz_subw,
898 gen_op_jnz_subl,
899 X86_64_ONLY(gen_op_jnz_subq),
2c0262af
FB
900 },
901 {
14ce26e7
FB
902 gen_op_jz_subb,
903 gen_op_jz_subw,
904 gen_op_jz_subl,
905 X86_64_ONLY(gen_op_jz_subq),
2c0262af
FB
906 },
907};
908
909static GenOpFunc *gen_op_in_DX_T0[3] = {
910 gen_op_inb_DX_T0,
911 gen_op_inw_DX_T0,
912 gen_op_inl_DX_T0,
913};
914
915static GenOpFunc *gen_op_out_DX_T0[3] = {
916 gen_op_outb_DX_T0,
917 gen_op_outw_DX_T0,
918 gen_op_outl_DX_T0,
919};
920
f115e911
FB
921static GenOpFunc *gen_op_in[3] = {
922 gen_op_inb_T0_T1,
923 gen_op_inw_T0_T1,
924 gen_op_inl_T0_T1,
925};
926
927static GenOpFunc *gen_op_out[3] = {
928 gen_op_outb_T0_T1,
929 gen_op_outw_T0_T1,
930 gen_op_outl_T0_T1,
931};
932
933static GenOpFunc *gen_check_io_T0[3] = {
934 gen_op_check_iob_T0,
935 gen_op_check_iow_T0,
936 gen_op_check_iol_T0,
937};
938
939static GenOpFunc *gen_check_io_DX[3] = {
940 gen_op_check_iob_DX,
941 gen_op_check_iow_DX,
942 gen_op_check_iol_DX,
943};
944
14ce26e7 945static void gen_check_io(DisasContext *s, int ot, int use_dx, target_ulong cur_eip)
f115e911
FB
946{
947 if (s->pe && (s->cpl > s->iopl || s->vm86)) {
948 if (s->cc_op != CC_OP_DYNAMIC)
949 gen_op_set_cc_op(s->cc_op);
14ce26e7 950 gen_jmp_im(cur_eip);
f115e911
FB
951 if (use_dx)
952 gen_check_io_DX[ot]();
953 else
954 gen_check_io_T0[ot]();
955 }
956}
957
2c0262af
FB
958static inline void gen_movs(DisasContext *s, int ot)
959{
960 gen_string_movl_A0_ESI(s);
961 gen_op_ld_T0_A0[ot + s->mem_index]();
962 gen_string_movl_A0_EDI(s);
963 gen_op_st_T0_A0[ot + s->mem_index]();
964 gen_op_movl_T0_Dshift[ot]();
14ce26e7
FB
965#ifdef TARGET_X86_64
966 if (s->aflag == 2) {
967 gen_op_addq_ESI_T0();
968 gen_op_addq_EDI_T0();
5fafdf24 969 } else
14ce26e7 970#endif
2c0262af
FB
971 if (s->aflag) {
972 gen_op_addl_ESI_T0();
973 gen_op_addl_EDI_T0();
974 } else {
975 gen_op_addw_ESI_T0();
976 gen_op_addw_EDI_T0();
977 }
978}
979
980static inline void gen_update_cc_op(DisasContext *s)
981{
982 if (s->cc_op != CC_OP_DYNAMIC) {
983 gen_op_set_cc_op(s->cc_op);
984 s->cc_op = CC_OP_DYNAMIC;
985 }
986}
987
14ce26e7
FB
988/* XXX: does not work with gdbstub "ice" single step - not a
989 serious problem */
990static int gen_jz_ecx_string(DisasContext *s, target_ulong next_eip)
2c0262af 991{
14ce26e7
FB
992 int l1, l2;
993
994 l1 = gen_new_label();
995 l2 = gen_new_label();
996 gen_op_jnz_ecx[s->aflag](l1);
997 gen_set_label(l2);
998 gen_jmp_tb(s, next_eip, 1);
999 gen_set_label(l1);
1000 return l2;
2c0262af
FB
1001}
1002
1003static inline void gen_stos(DisasContext *s, int ot)
1004{
1005 gen_op_mov_TN_reg[OT_LONG][0][R_EAX]();
1006 gen_string_movl_A0_EDI(s);
1007 gen_op_st_T0_A0[ot + s->mem_index]();
1008 gen_op_movl_T0_Dshift[ot]();
14ce26e7
FB
1009#ifdef TARGET_X86_64
1010 if (s->aflag == 2) {
1011 gen_op_addq_EDI_T0();
5fafdf24 1012 } else
14ce26e7 1013#endif
2c0262af
FB
1014 if (s->aflag) {
1015 gen_op_addl_EDI_T0();
1016 } else {
1017 gen_op_addw_EDI_T0();
1018 }
1019}
1020
1021static inline void gen_lods(DisasContext *s, int ot)
1022{
1023 gen_string_movl_A0_ESI(s);
1024 gen_op_ld_T0_A0[ot + s->mem_index]();
1025 gen_op_mov_reg_T0[ot][R_EAX]();
1026 gen_op_movl_T0_Dshift[ot]();
14ce26e7
FB
1027#ifdef TARGET_X86_64
1028 if (s->aflag == 2) {
1029 gen_op_addq_ESI_T0();
5fafdf24 1030 } else
14ce26e7 1031#endif
2c0262af
FB
1032 if (s->aflag) {
1033 gen_op_addl_ESI_T0();
1034 } else {
1035 gen_op_addw_ESI_T0();
1036 }
1037}
1038
1039static inline void gen_scas(DisasContext *s, int ot)
1040{
1041 gen_op_mov_TN_reg[OT_LONG][0][R_EAX]();
1042 gen_string_movl_A0_EDI(s);
1043 gen_op_ld_T1_A0[ot + s->mem_index]();
1044 gen_op_cmpl_T0_T1_cc();
1045 gen_op_movl_T0_Dshift[ot]();
14ce26e7
FB
1046#ifdef TARGET_X86_64
1047 if (s->aflag == 2) {
1048 gen_op_addq_EDI_T0();
5fafdf24 1049 } else
14ce26e7 1050#endif
2c0262af
FB
1051 if (s->aflag) {
1052 gen_op_addl_EDI_T0();
1053 } else {
1054 gen_op_addw_EDI_T0();
1055 }
1056}
1057
1058static inline void gen_cmps(DisasContext *s, int ot)
1059{
1060 gen_string_movl_A0_ESI(s);
1061 gen_op_ld_T0_A0[ot + s->mem_index]();
1062 gen_string_movl_A0_EDI(s);
1063 gen_op_ld_T1_A0[ot + s->mem_index]();
1064 gen_op_cmpl_T0_T1_cc();
1065 gen_op_movl_T0_Dshift[ot]();
14ce26e7
FB
1066#ifdef TARGET_X86_64
1067 if (s->aflag == 2) {
1068 gen_op_addq_ESI_T0();
1069 gen_op_addq_EDI_T0();
5fafdf24 1070 } else
14ce26e7 1071#endif
2c0262af
FB
1072 if (s->aflag) {
1073 gen_op_addl_ESI_T0();
1074 gen_op_addl_EDI_T0();
1075 } else {
1076 gen_op_addw_ESI_T0();
1077 gen_op_addw_EDI_T0();
1078 }
1079}
1080
1081static inline void gen_ins(DisasContext *s, int ot)
1082{
2c0262af 1083 gen_string_movl_A0_EDI(s);
9772c73b
FB
1084 gen_op_movl_T0_0();
1085 gen_op_st_T0_A0[ot + s->mem_index]();
1086 gen_op_in_DX_T0[ot]();
2c0262af
FB
1087 gen_op_st_T0_A0[ot + s->mem_index]();
1088 gen_op_movl_T0_Dshift[ot]();
14ce26e7
FB
1089#ifdef TARGET_X86_64
1090 if (s->aflag == 2) {
1091 gen_op_addq_EDI_T0();
5fafdf24 1092 } else
14ce26e7 1093#endif
2c0262af
FB
1094 if (s->aflag) {
1095 gen_op_addl_EDI_T0();
1096 } else {
1097 gen_op_addw_EDI_T0();
1098 }
1099}
1100
1101static inline void gen_outs(DisasContext *s, int ot)
1102{
1103 gen_string_movl_A0_ESI(s);
1104 gen_op_ld_T0_A0[ot + s->mem_index]();
1105 gen_op_out_DX_T0[ot]();
1106 gen_op_movl_T0_Dshift[ot]();
14ce26e7
FB
1107#ifdef TARGET_X86_64
1108 if (s->aflag == 2) {
1109 gen_op_addq_ESI_T0();
5fafdf24 1110 } else
14ce26e7 1111#endif
2c0262af
FB
1112 if (s->aflag) {
1113 gen_op_addl_ESI_T0();
1114 } else {
1115 gen_op_addw_ESI_T0();
1116 }
1117}
1118
1119/* same method as Valgrind : we generate jumps to current or next
1120 instruction */
1121#define GEN_REPZ(op) \
1122static inline void gen_repz_ ## op(DisasContext *s, int ot, \
14ce26e7 1123 target_ulong cur_eip, target_ulong next_eip) \
2c0262af 1124{ \
14ce26e7 1125 int l2;\
2c0262af 1126 gen_update_cc_op(s); \
14ce26e7 1127 l2 = gen_jz_ecx_string(s, next_eip); \
2c0262af
FB
1128 gen_ ## op(s, ot); \
1129 gen_op_dec_ECX[s->aflag](); \
1130 /* a loop would cause two single step exceptions if ECX = 1 \
1131 before rep string_insn */ \
1132 if (!s->jmp_opt) \
14ce26e7 1133 gen_op_jz_ecx[s->aflag](l2); \
2c0262af
FB
1134 gen_jmp(s, cur_eip); \
1135}
1136
1137#define GEN_REPZ2(op) \
1138static inline void gen_repz_ ## op(DisasContext *s, int ot, \
14ce26e7
FB
1139 target_ulong cur_eip, \
1140 target_ulong next_eip, \
2c0262af
FB
1141 int nz) \
1142{ \
14ce26e7 1143 int l2;\
2c0262af 1144 gen_update_cc_op(s); \
14ce26e7 1145 l2 = gen_jz_ecx_string(s, next_eip); \
2c0262af
FB
1146 gen_ ## op(s, ot); \
1147 gen_op_dec_ECX[s->aflag](); \
1148 gen_op_set_cc_op(CC_OP_SUBB + ot); \
14ce26e7 1149 gen_op_string_jnz_sub[nz][ot](l2);\
2c0262af 1150 if (!s->jmp_opt) \
14ce26e7 1151 gen_op_jz_ecx[s->aflag](l2); \
2c0262af
FB
1152 gen_jmp(s, cur_eip); \
1153}
1154
1155GEN_REPZ(movs)
1156GEN_REPZ(stos)
1157GEN_REPZ(lods)
1158GEN_REPZ(ins)
1159GEN_REPZ(outs)
1160GEN_REPZ2(scas)
1161GEN_REPZ2(cmps)
1162
2c0262af
FB
1163enum {
1164 JCC_O,
1165 JCC_B,
1166 JCC_Z,
1167 JCC_BE,
1168 JCC_S,
1169 JCC_P,
1170 JCC_L,
1171 JCC_LE,
1172};
1173
14ce26e7 1174static GenOpFunc1 *gen_jcc_sub[4][8] = {
2c0262af
FB
1175 [OT_BYTE] = {
1176 NULL,
1177 gen_op_jb_subb,
1178 gen_op_jz_subb,
1179 gen_op_jbe_subb,
1180 gen_op_js_subb,
1181 NULL,
1182 gen_op_jl_subb,
1183 gen_op_jle_subb,
1184 },
1185 [OT_WORD] = {
1186 NULL,
1187 gen_op_jb_subw,
1188 gen_op_jz_subw,
1189 gen_op_jbe_subw,
1190 gen_op_js_subw,
1191 NULL,
1192 gen_op_jl_subw,
1193 gen_op_jle_subw,
1194 },
1195 [OT_LONG] = {
1196 NULL,
1197 gen_op_jb_subl,
1198 gen_op_jz_subl,
1199 gen_op_jbe_subl,
1200 gen_op_js_subl,
1201 NULL,
1202 gen_op_jl_subl,
1203 gen_op_jle_subl,
1204 },
14ce26e7
FB
1205#ifdef TARGET_X86_64
1206 [OT_QUAD] = {
1207 NULL,
1208 BUGGY_64(gen_op_jb_subq),
1209 gen_op_jz_subq,
1210 BUGGY_64(gen_op_jbe_subq),
1211 gen_op_js_subq,
1212 NULL,
1213 BUGGY_64(gen_op_jl_subq),
1214 BUGGY_64(gen_op_jle_subq),
1215 },
1216#endif
2c0262af 1217};
14ce26e7 1218static GenOpFunc1 *gen_op_loop[3][4] = {
2c0262af
FB
1219 [0] = {
1220 gen_op_loopnzw,
1221 gen_op_loopzw,
14ce26e7 1222 gen_op_jnz_ecxw,
2c0262af
FB
1223 },
1224 [1] = {
1225 gen_op_loopnzl,
1226 gen_op_loopzl,
14ce26e7
FB
1227 gen_op_jnz_ecxl,
1228 },
1229#ifdef TARGET_X86_64
1230 [2] = {
1231 gen_op_loopnzq,
1232 gen_op_loopzq,
1233 gen_op_jnz_ecxq,
2c0262af 1234 },
14ce26e7 1235#endif
2c0262af
FB
1236};
1237
1238static GenOpFunc *gen_setcc_slow[8] = {
1239 gen_op_seto_T0_cc,
1240 gen_op_setb_T0_cc,
1241 gen_op_setz_T0_cc,
1242 gen_op_setbe_T0_cc,
1243 gen_op_sets_T0_cc,
1244 gen_op_setp_T0_cc,
1245 gen_op_setl_T0_cc,
1246 gen_op_setle_T0_cc,
1247};
1248
14ce26e7 1249static GenOpFunc *gen_setcc_sub[4][8] = {
2c0262af
FB
1250 [OT_BYTE] = {
1251 NULL,
1252 gen_op_setb_T0_subb,
1253 gen_op_setz_T0_subb,
1254 gen_op_setbe_T0_subb,
1255 gen_op_sets_T0_subb,
1256 NULL,
1257 gen_op_setl_T0_subb,
1258 gen_op_setle_T0_subb,
1259 },
1260 [OT_WORD] = {
1261 NULL,
1262 gen_op_setb_T0_subw,
1263 gen_op_setz_T0_subw,
1264 gen_op_setbe_T0_subw,
1265 gen_op_sets_T0_subw,
1266 NULL,
1267 gen_op_setl_T0_subw,
1268 gen_op_setle_T0_subw,
1269 },
1270 [OT_LONG] = {
1271 NULL,
1272 gen_op_setb_T0_subl,
1273 gen_op_setz_T0_subl,
1274 gen_op_setbe_T0_subl,
1275 gen_op_sets_T0_subl,
1276 NULL,
1277 gen_op_setl_T0_subl,
1278 gen_op_setle_T0_subl,
1279 },
14ce26e7
FB
1280#ifdef TARGET_X86_64
1281 [OT_QUAD] = {
1282 NULL,
1283 gen_op_setb_T0_subq,
1284 gen_op_setz_T0_subq,
1285 gen_op_setbe_T0_subq,
1286 gen_op_sets_T0_subq,
1287 NULL,
1288 gen_op_setl_T0_subq,
1289 gen_op_setle_T0_subq,
1290 },
1291#endif
2c0262af
FB
1292};
1293
1294static GenOpFunc *gen_op_fp_arith_ST0_FT0[8] = {
1295 gen_op_fadd_ST0_FT0,
1296 gen_op_fmul_ST0_FT0,
1297 gen_op_fcom_ST0_FT0,
1298 gen_op_fcom_ST0_FT0,
1299 gen_op_fsub_ST0_FT0,
1300 gen_op_fsubr_ST0_FT0,
1301 gen_op_fdiv_ST0_FT0,
1302 gen_op_fdivr_ST0_FT0,
1303};
1304
1305/* NOTE the exception in "r" op ordering */
1306static GenOpFunc1 *gen_op_fp_arith_STN_ST0[8] = {
1307 gen_op_fadd_STN_ST0,
1308 gen_op_fmul_STN_ST0,
1309 NULL,
1310 NULL,
1311 gen_op_fsubr_STN_ST0,
1312 gen_op_fsub_STN_ST0,
1313 gen_op_fdivr_STN_ST0,
1314 gen_op_fdiv_STN_ST0,
1315};
1316
1317/* if d == OR_TMP0, it means memory operand (address in A0) */
1318static void gen_op(DisasContext *s1, int op, int ot, int d)
1319{
1320 GenOpFunc *gen_update_cc;
3b46e624 1321
2c0262af
FB
1322 if (d != OR_TMP0) {
1323 gen_op_mov_TN_reg[ot][0][d]();
1324 } else {
1325 gen_op_ld_T0_A0[ot + s1->mem_index]();
1326 }
1327 switch(op) {
1328 case OP_ADCL:
1329 case OP_SBBL:
1330 if (s1->cc_op != CC_OP_DYNAMIC)
1331 gen_op_set_cc_op(s1->cc_op);
1332 if (d != OR_TMP0) {
1333 gen_op_arithc_T0_T1_cc[ot][op - OP_ADCL]();
1334 gen_op_mov_reg_T0[ot][d]();
1335 } else {
4f31916f 1336 gen_op_arithc_mem_T0_T1_cc[ot + s1->mem_index][op - OP_ADCL]();
2c0262af
FB
1337 }
1338 s1->cc_op = CC_OP_DYNAMIC;
1339 goto the_end;
1340 case OP_ADDL:
1341 gen_op_addl_T0_T1();
1342 s1->cc_op = CC_OP_ADDB + ot;
1343 gen_update_cc = gen_op_update2_cc;
1344 break;
1345 case OP_SUBL:
1346 gen_op_subl_T0_T1();
1347 s1->cc_op = CC_OP_SUBB + ot;
1348 gen_update_cc = gen_op_update2_cc;
1349 break;
1350 default:
1351 case OP_ANDL:
1352 case OP_ORL:
1353 case OP_XORL:
1354 gen_op_arith_T0_T1_cc[op]();
1355 s1->cc_op = CC_OP_LOGICB + ot;
1356 gen_update_cc = gen_op_update1_cc;
1357 break;
1358 case OP_CMPL:
1359 gen_op_cmpl_T0_T1_cc();
1360 s1->cc_op = CC_OP_SUBB + ot;
1361 gen_update_cc = NULL;
1362 break;
1363 }
1364 if (op != OP_CMPL) {
1365 if (d != OR_TMP0)
1366 gen_op_mov_reg_T0[ot][d]();
1367 else
1368 gen_op_st_T0_A0[ot + s1->mem_index]();
1369 }
1370 /* the flags update must happen after the memory write (precise
1371 exception support) */
1372 if (gen_update_cc)
1373 gen_update_cc();
1374 the_end: ;
1375}
1376
1377/* if d == OR_TMP0, it means memory operand (address in A0) */
1378static void gen_inc(DisasContext *s1, int ot, int d, int c)
1379{
1380 if (d != OR_TMP0)
1381 gen_op_mov_TN_reg[ot][0][d]();
1382 else
1383 gen_op_ld_T0_A0[ot + s1->mem_index]();
1384 if (s1->cc_op != CC_OP_DYNAMIC)
1385 gen_op_set_cc_op(s1->cc_op);
1386 if (c > 0) {
1387 gen_op_incl_T0();
1388 s1->cc_op = CC_OP_INCB + ot;
1389 } else {
1390 gen_op_decl_T0();
1391 s1->cc_op = CC_OP_DECB + ot;
1392 }
1393 if (d != OR_TMP0)
1394 gen_op_mov_reg_T0[ot][d]();
1395 else
1396 gen_op_st_T0_A0[ot + s1->mem_index]();
1397 gen_op_update_inc_cc();
1398}
1399
1400static void gen_shift(DisasContext *s1, int op, int ot, int d, int s)
1401{
1402 if (d != OR_TMP0)
1403 gen_op_mov_TN_reg[ot][0][d]();
1404 else
1405 gen_op_ld_T0_A0[ot + s1->mem_index]();
1406 if (s != OR_TMP1)
1407 gen_op_mov_TN_reg[ot][1][s]();
1408 /* for zero counts, flags are not updated, so must do it dynamically */
1409 if (s1->cc_op != CC_OP_DYNAMIC)
1410 gen_op_set_cc_op(s1->cc_op);
3b46e624 1411
2c0262af
FB
1412 if (d != OR_TMP0)
1413 gen_op_shift_T0_T1_cc[ot][op]();
1414 else
4f31916f 1415 gen_op_shift_mem_T0_T1_cc[ot + s1->mem_index][op]();
2c0262af
FB
1416 if (d != OR_TMP0)
1417 gen_op_mov_reg_T0[ot][d]();
1418 s1->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
1419}
1420
1421static void gen_shifti(DisasContext *s1, int op, int ot, int d, int c)
1422{
1423 /* currently not optimized */
1424 gen_op_movl_T1_im(c);
1425 gen_shift(s1, op, ot, d, OR_TMP1);
1426}
1427
1428static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ptr)
1429{
14ce26e7 1430 target_long disp;
2c0262af 1431 int havesib;
14ce26e7 1432 int base;
2c0262af
FB
1433 int index;
1434 int scale;
1435 int opreg;
1436 int mod, rm, code, override, must_add_seg;
1437
1438 override = s->override;
1439 must_add_seg = s->addseg;
1440 if (override >= 0)
1441 must_add_seg = 1;
1442 mod = (modrm >> 6) & 3;
1443 rm = modrm & 7;
1444
1445 if (s->aflag) {
1446
1447 havesib = 0;
1448 base = rm;
1449 index = 0;
1450 scale = 0;
3b46e624 1451
2c0262af
FB
1452 if (base == 4) {
1453 havesib = 1;
61382a50 1454 code = ldub_code(s->pc++);
2c0262af 1455 scale = (code >> 6) & 3;
14ce26e7
FB
1456 index = ((code >> 3) & 7) | REX_X(s);
1457 base = (code & 7);
2c0262af 1458 }
14ce26e7 1459 base |= REX_B(s);
2c0262af
FB
1460
1461 switch (mod) {
1462 case 0:
14ce26e7 1463 if ((base & 7) == 5) {
2c0262af 1464 base = -1;
14ce26e7 1465 disp = (int32_t)ldl_code(s->pc);
2c0262af 1466 s->pc += 4;
14ce26e7
FB
1467 if (CODE64(s) && !havesib) {
1468 disp += s->pc + s->rip_offset;
1469 }
2c0262af
FB
1470 } else {
1471 disp = 0;
1472 }
1473 break;
1474 case 1:
61382a50 1475 disp = (int8_t)ldub_code(s->pc++);
2c0262af
FB
1476 break;
1477 default:
1478 case 2:
61382a50 1479 disp = ldl_code(s->pc);
2c0262af
FB
1480 s->pc += 4;
1481 break;
1482 }
3b46e624 1483
2c0262af
FB
1484 if (base >= 0) {
1485 /* for correct popl handling with esp */
1486 if (base == 4 && s->popl_esp_hack)
1487 disp += s->popl_esp_hack;
14ce26e7
FB
1488#ifdef TARGET_X86_64
1489 if (s->aflag == 2) {
1490 gen_op_movq_A0_reg[base]();
1491 if (disp != 0) {
1492 if ((int32_t)disp == disp)
1493 gen_op_addq_A0_im(disp);
1494 else
1495 gen_op_addq_A0_im64(disp >> 32, disp);
1496 }
5fafdf24 1497 } else
14ce26e7
FB
1498#endif
1499 {
1500 gen_op_movl_A0_reg[base]();
1501 if (disp != 0)
1502 gen_op_addl_A0_im(disp);
1503 }
2c0262af 1504 } else {
14ce26e7
FB
1505#ifdef TARGET_X86_64
1506 if (s->aflag == 2) {
1507 if ((int32_t)disp == disp)
1508 gen_op_movq_A0_im(disp);
1509 else
1510 gen_op_movq_A0_im64(disp >> 32, disp);
5fafdf24 1511 } else
14ce26e7
FB
1512#endif
1513 {
1514 gen_op_movl_A0_im(disp);
1515 }
2c0262af
FB
1516 }
1517 /* XXX: index == 4 is always invalid */
1518 if (havesib && (index != 4 || scale != 0)) {
14ce26e7
FB
1519#ifdef TARGET_X86_64
1520 if (s->aflag == 2) {
1521 gen_op_addq_A0_reg_sN[scale][index]();
5fafdf24 1522 } else
14ce26e7
FB
1523#endif
1524 {
1525 gen_op_addl_A0_reg_sN[scale][index]();
1526 }
2c0262af
FB
1527 }
1528 if (must_add_seg) {
1529 if (override < 0) {
1530 if (base == R_EBP || base == R_ESP)
1531 override = R_SS;
1532 else
1533 override = R_DS;
1534 }
14ce26e7
FB
1535#ifdef TARGET_X86_64
1536 if (s->aflag == 2) {
1537 gen_op_addq_A0_seg(offsetof(CPUX86State,segs[override].base));
5fafdf24 1538 } else
14ce26e7
FB
1539#endif
1540 {
1541 gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base));
1542 }
2c0262af
FB
1543 }
1544 } else {
1545 switch (mod) {
1546 case 0:
1547 if (rm == 6) {
61382a50 1548 disp = lduw_code(s->pc);
2c0262af
FB
1549 s->pc += 2;
1550 gen_op_movl_A0_im(disp);
1551 rm = 0; /* avoid SS override */
1552 goto no_rm;
1553 } else {
1554 disp = 0;
1555 }
1556 break;
1557 case 1:
61382a50 1558 disp = (int8_t)ldub_code(s->pc++);
2c0262af
FB
1559 break;
1560 default:
1561 case 2:
61382a50 1562 disp = lduw_code(s->pc);
2c0262af
FB
1563 s->pc += 2;
1564 break;
1565 }
1566 switch(rm) {
1567 case 0:
1568 gen_op_movl_A0_reg[R_EBX]();
1569 gen_op_addl_A0_reg_sN[0][R_ESI]();
1570 break;
1571 case 1:
1572 gen_op_movl_A0_reg[R_EBX]();
1573 gen_op_addl_A0_reg_sN[0][R_EDI]();
1574 break;
1575 case 2:
1576 gen_op_movl_A0_reg[R_EBP]();
1577 gen_op_addl_A0_reg_sN[0][R_ESI]();
1578 break;
1579 case 3:
1580 gen_op_movl_A0_reg[R_EBP]();
1581 gen_op_addl_A0_reg_sN[0][R_EDI]();
1582 break;
1583 case 4:
1584 gen_op_movl_A0_reg[R_ESI]();
1585 break;
1586 case 5:
1587 gen_op_movl_A0_reg[R_EDI]();
1588 break;
1589 case 6:
1590 gen_op_movl_A0_reg[R_EBP]();
1591 break;
1592 default:
1593 case 7:
1594 gen_op_movl_A0_reg[R_EBX]();
1595 break;
1596 }
1597 if (disp != 0)
1598 gen_op_addl_A0_im(disp);
1599 gen_op_andl_A0_ffff();
1600 no_rm:
1601 if (must_add_seg) {
1602 if (override < 0) {
1603 if (rm == 2 || rm == 3 || rm == 6)
1604 override = R_SS;
1605 else
1606 override = R_DS;
1607 }
1608 gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base));
1609 }
1610 }
1611
1612 opreg = OR_A0;
1613 disp = 0;
1614 *reg_ptr = opreg;
1615 *offset_ptr = disp;
1616}
1617
e17a36ce
FB
1618static void gen_nop_modrm(DisasContext *s, int modrm)
1619{
1620 int mod, rm, base, code;
1621
1622 mod = (modrm >> 6) & 3;
1623 if (mod == 3)
1624 return;
1625 rm = modrm & 7;
1626
1627 if (s->aflag) {
1628
1629 base = rm;
3b46e624 1630
e17a36ce
FB
1631 if (base == 4) {
1632 code = ldub_code(s->pc++);
1633 base = (code & 7);
1634 }
3b46e624 1635
e17a36ce
FB
1636 switch (mod) {
1637 case 0:
1638 if (base == 5) {
1639 s->pc += 4;
1640 }
1641 break;
1642 case 1:
1643 s->pc++;
1644 break;
1645 default:
1646 case 2:
1647 s->pc += 4;
1648 break;
1649 }
1650 } else {
1651 switch (mod) {
1652 case 0:
1653 if (rm == 6) {
1654 s->pc += 2;
1655 }
1656 break;
1657 case 1:
1658 s->pc++;
1659 break;
1660 default:
1661 case 2:
1662 s->pc += 2;
1663 break;
1664 }
1665 }
1666}
1667
664e0f19
FB
1668/* used for LEA and MOV AX, mem */
1669static void gen_add_A0_ds_seg(DisasContext *s)
1670{
1671 int override, must_add_seg;
1672 must_add_seg = s->addseg;
1673 override = R_DS;
1674 if (s->override >= 0) {
1675 override = s->override;
1676 must_add_seg = 1;
1677 } else {
1678 override = R_DS;
1679 }
1680 if (must_add_seg) {
8f091a59
FB
1681#ifdef TARGET_X86_64
1682 if (CODE64(s)) {
1683 gen_op_addq_A0_seg(offsetof(CPUX86State,segs[override].base));
5fafdf24 1684 } else
8f091a59
FB
1685#endif
1686 {
1687 gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base));
1688 }
664e0f19
FB
1689 }
1690}
1691
2c0262af
FB
1692/* generate modrm memory load or store of 'reg'. TMP0 is used if reg !=
1693 OR_TMP0 */
1694static void gen_ldst_modrm(DisasContext *s, int modrm, int ot, int reg, int is_store)
1695{
1696 int mod, rm, opreg, disp;
1697
1698 mod = (modrm >> 6) & 3;
14ce26e7 1699 rm = (modrm & 7) | REX_B(s);
2c0262af
FB
1700 if (mod == 3) {
1701 if (is_store) {
1702 if (reg != OR_TMP0)
1703 gen_op_mov_TN_reg[ot][0][reg]();
1704 gen_op_mov_reg_T0[ot][rm]();
1705 } else {
1706 gen_op_mov_TN_reg[ot][0][rm]();
1707 if (reg != OR_TMP0)
1708 gen_op_mov_reg_T0[ot][reg]();
1709 }
1710 } else {
1711 gen_lea_modrm(s, modrm, &opreg, &disp);
1712 if (is_store) {
1713 if (reg != OR_TMP0)
1714 gen_op_mov_TN_reg[ot][0][reg]();
1715 gen_op_st_T0_A0[ot + s->mem_index]();
1716 } else {
1717 gen_op_ld_T0_A0[ot + s->mem_index]();
1718 if (reg != OR_TMP0)
1719 gen_op_mov_reg_T0[ot][reg]();
1720 }
1721 }
1722}
1723
1724static inline uint32_t insn_get(DisasContext *s, int ot)
1725{
1726 uint32_t ret;
1727
1728 switch(ot) {
1729 case OT_BYTE:
61382a50 1730 ret = ldub_code(s->pc);
2c0262af
FB
1731 s->pc++;
1732 break;
1733 case OT_WORD:
61382a50 1734 ret = lduw_code(s->pc);
2c0262af
FB
1735 s->pc += 2;
1736 break;
1737 default:
1738 case OT_LONG:
61382a50 1739 ret = ldl_code(s->pc);
2c0262af
FB
1740 s->pc += 4;
1741 break;
1742 }
1743 return ret;
1744}
1745
14ce26e7
FB
1746static inline int insn_const_size(unsigned int ot)
1747{
1748 if (ot <= OT_LONG)
1749 return 1 << ot;
1750 else
1751 return 4;
1752}
1753
6e256c93
FB
1754static inline void gen_goto_tb(DisasContext *s, int tb_num, target_ulong eip)
1755{
1756 TranslationBlock *tb;
1757 target_ulong pc;
1758
1759 pc = s->cs_base + eip;
1760 tb = s->tb;
1761 /* NOTE: we handle the case where the TB spans two pages here */
1762 if ((pc & TARGET_PAGE_MASK) == (tb->pc & TARGET_PAGE_MASK) ||
1763 (pc & TARGET_PAGE_MASK) == ((s->pc - 1) & TARGET_PAGE_MASK)) {
1764 /* jump to same page: we can use a direct jump */
1765 if (tb_num == 0)
1766 gen_op_goto_tb0(TBPARAM(tb));
1767 else
1768 gen_op_goto_tb1(TBPARAM(tb));
1769 gen_jmp_im(eip);
1770 gen_op_movl_T0_im((long)tb + tb_num);
1771 gen_op_exit_tb();
1772 } else {
1773 /* jump to another page: currently not optimized */
1774 gen_jmp_im(eip);
1775 gen_eob(s);
1776 }
1777}
1778
5fafdf24 1779static inline void gen_jcc(DisasContext *s, int b,
14ce26e7 1780 target_ulong val, target_ulong next_eip)
2c0262af
FB
1781{
1782 TranslationBlock *tb;
1783 int inv, jcc_op;
14ce26e7
FB
1784 GenOpFunc1 *func;
1785 target_ulong tmp;
1786 int l1, l2;
2c0262af
FB
1787
1788 inv = b & 1;
1789 jcc_op = (b >> 1) & 7;
3b46e624 1790
2c0262af
FB
1791 if (s->jmp_opt) {
1792 switch(s->cc_op) {
1793 /* we optimize the cmp/jcc case */
1794 case CC_OP_SUBB:
1795 case CC_OP_SUBW:
1796 case CC_OP_SUBL:
14ce26e7 1797 case CC_OP_SUBQ:
2c0262af
FB
1798 func = gen_jcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
1799 break;
3b46e624 1800
2c0262af
FB
1801 /* some jumps are easy to compute */
1802 case CC_OP_ADDB:
1803 case CC_OP_ADDW:
1804 case CC_OP_ADDL:
14ce26e7
FB
1805 case CC_OP_ADDQ:
1806
2c0262af
FB
1807 case CC_OP_ADCB:
1808 case CC_OP_ADCW:
1809 case CC_OP_ADCL:
14ce26e7
FB
1810 case CC_OP_ADCQ:
1811
2c0262af
FB
1812 case CC_OP_SBBB:
1813 case CC_OP_SBBW:
1814 case CC_OP_SBBL:
14ce26e7
FB
1815 case CC_OP_SBBQ:
1816
2c0262af
FB
1817 case CC_OP_LOGICB:
1818 case CC_OP_LOGICW:
1819 case CC_OP_LOGICL:
14ce26e7
FB
1820 case CC_OP_LOGICQ:
1821
2c0262af
FB
1822 case CC_OP_INCB:
1823 case CC_OP_INCW:
1824 case CC_OP_INCL:
14ce26e7
FB
1825 case CC_OP_INCQ:
1826
2c0262af
FB
1827 case CC_OP_DECB:
1828 case CC_OP_DECW:
1829 case CC_OP_DECL:
14ce26e7
FB
1830 case CC_OP_DECQ:
1831
2c0262af
FB
1832 case CC_OP_SHLB:
1833 case CC_OP_SHLW:
1834 case CC_OP_SHLL:
14ce26e7
FB
1835 case CC_OP_SHLQ:
1836
2c0262af
FB
1837 case CC_OP_SARB:
1838 case CC_OP_SARW:
1839 case CC_OP_SARL:
14ce26e7 1840 case CC_OP_SARQ:
2c0262af
FB
1841 switch(jcc_op) {
1842 case JCC_Z:
14ce26e7 1843 func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 4][jcc_op];
2c0262af
FB
1844 break;
1845 case JCC_S:
14ce26e7 1846 func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 4][jcc_op];
2c0262af
FB
1847 break;
1848 default:
1849 func = NULL;
1850 break;
1851 }
1852 break;
1853 default:
1854 func = NULL;
1855 break;
1856 }
1857
6e256c93 1858 if (s->cc_op != CC_OP_DYNAMIC) {
2c0262af 1859 gen_op_set_cc_op(s->cc_op);
6e256c93
FB
1860 s->cc_op = CC_OP_DYNAMIC;
1861 }
2c0262af
FB
1862
1863 if (!func) {
1864 gen_setcc_slow[jcc_op]();
14ce26e7 1865 func = gen_op_jnz_T0_label;
2c0262af 1866 }
3b46e624 1867
14ce26e7
FB
1868 if (inv) {
1869 tmp = val;
1870 val = next_eip;
1871 next_eip = tmp;
2c0262af 1872 }
14ce26e7
FB
1873 tb = s->tb;
1874
1875 l1 = gen_new_label();
1876 func(l1);
1877
6e256c93 1878 gen_goto_tb(s, 0, next_eip);
14ce26e7
FB
1879
1880 gen_set_label(l1);
6e256c93 1881 gen_goto_tb(s, 1, val);
14ce26e7 1882
2c0262af
FB
1883 s->is_jmp = 3;
1884 } else {
14ce26e7 1885
2c0262af
FB
1886 if (s->cc_op != CC_OP_DYNAMIC) {
1887 gen_op_set_cc_op(s->cc_op);
1888 s->cc_op = CC_OP_DYNAMIC;
1889 }
1890 gen_setcc_slow[jcc_op]();
14ce26e7
FB
1891 if (inv) {
1892 tmp = val;
1893 val = next_eip;
1894 next_eip = tmp;
2c0262af 1895 }
14ce26e7
FB
1896 l1 = gen_new_label();
1897 l2 = gen_new_label();
1898 gen_op_jnz_T0_label(l1);
1899 gen_jmp_im(next_eip);
1900 gen_op_jmp_label(l2);
1901 gen_set_label(l1);
1902 gen_jmp_im(val);
1903 gen_set_label(l2);
2c0262af
FB
1904 gen_eob(s);
1905 }
1906}
1907
1908static void gen_setcc(DisasContext *s, int b)
1909{
1910 int inv, jcc_op;
1911 GenOpFunc *func;
1912
1913 inv = b & 1;
1914 jcc_op = (b >> 1) & 7;
1915 switch(s->cc_op) {
1916 /* we optimize the cmp/jcc case */
1917 case CC_OP_SUBB:
1918 case CC_OP_SUBW:
1919 case CC_OP_SUBL:
14ce26e7 1920 case CC_OP_SUBQ:
2c0262af
FB
1921 func = gen_setcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
1922 if (!func)
1923 goto slow_jcc;
1924 break;
3b46e624 1925
2c0262af
FB
1926 /* some jumps are easy to compute */
1927 case CC_OP_ADDB:
1928 case CC_OP_ADDW:
1929 case CC_OP_ADDL:
14ce26e7
FB
1930 case CC_OP_ADDQ:
1931
2c0262af
FB
1932 case CC_OP_LOGICB:
1933 case CC_OP_LOGICW:
1934 case CC_OP_LOGICL:
14ce26e7
FB
1935 case CC_OP_LOGICQ:
1936
2c0262af
FB
1937 case CC_OP_INCB:
1938 case CC_OP_INCW:
1939 case CC_OP_INCL:
14ce26e7
FB
1940 case CC_OP_INCQ:
1941
2c0262af
FB
1942 case CC_OP_DECB:
1943 case CC_OP_DECW:
1944 case CC_OP_DECL:
14ce26e7
FB
1945 case CC_OP_DECQ:
1946
2c0262af
FB
1947 case CC_OP_SHLB:
1948 case CC_OP_SHLW:
1949 case CC_OP_SHLL:
14ce26e7 1950 case CC_OP_SHLQ:
2c0262af
FB
1951 switch(jcc_op) {
1952 case JCC_Z:
14ce26e7 1953 func = gen_setcc_sub[(s->cc_op - CC_OP_ADDB) % 4][jcc_op];
2c0262af
FB
1954 break;
1955 case JCC_S:
14ce26e7 1956 func = gen_setcc_sub[(s->cc_op - CC_OP_ADDB) % 4][jcc_op];
2c0262af
FB
1957 break;
1958 default:
1959 goto slow_jcc;
1960 }
1961 break;
1962 default:
1963 slow_jcc:
1964 if (s->cc_op != CC_OP_DYNAMIC)
1965 gen_op_set_cc_op(s->cc_op);
1966 func = gen_setcc_slow[jcc_op];
1967 break;
1968 }
1969 func();
1970 if (inv) {
1971 gen_op_xor_T0_1();
1972 }
1973}
1974
1975/* move T0 to seg_reg and compute if the CPU state may change. Never
1976 call this function with seg_reg == R_CS */
14ce26e7 1977static void gen_movl_seg_T0(DisasContext *s, int seg_reg, target_ulong cur_eip)
2c0262af 1978{
3415a4dd
FB
1979 if (s->pe && !s->vm86) {
1980 /* XXX: optimize by finding processor state dynamically */
1981 if (s->cc_op != CC_OP_DYNAMIC)
1982 gen_op_set_cc_op(s->cc_op);
14ce26e7 1983 gen_jmp_im(cur_eip);
3415a4dd 1984 gen_op_movl_seg_T0(seg_reg);
dc196a57
FB
1985 /* abort translation because the addseg value may change or
1986 because ss32 may change. For R_SS, translation must always
1987 stop as a special handling must be done to disable hardware
1988 interrupts for the next instruction */
1989 if (seg_reg == R_SS || (s->code32 && seg_reg < R_FS))
1990 s->is_jmp = 3;
3415a4dd 1991 } else {
2c0262af 1992 gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[seg_reg]));
dc196a57
FB
1993 if (seg_reg == R_SS)
1994 s->is_jmp = 3;
3415a4dd 1995 }
2c0262af
FB
1996}
1997
0573fbfc
TS
1998#ifdef TARGET_X86_64
1999#define SVM_movq_T1_im(x) gen_op_movq_T1_im64((x) >> 32, x)
2000#else
2001#define SVM_movq_T1_im(x) gen_op_movl_T1_im(x)
2002#endif
2003
2004static inline int
2005gen_svm_check_io(DisasContext *s, target_ulong pc_start, uint64_t type)
2006{
2007#if !defined(CONFIG_USER_ONLY)
2008 if(s->flags & (1ULL << INTERCEPT_IOIO_PROT)) {
2009 if (s->cc_op != CC_OP_DYNAMIC)
2010 gen_op_set_cc_op(s->cc_op);
2011 SVM_movq_T1_im(s->pc - s->cs_base);
2012 gen_jmp_im(pc_start - s->cs_base);
2013 gen_op_geneflags();
2014 gen_op_svm_check_intercept_io((uint32_t)(type >> 32), (uint32_t)type);
2015 s->cc_op = CC_OP_DYNAMIC;
2016 /* FIXME: maybe we could move the io intercept vector to the TB as well
2017 so we know if this is an EOB or not ... let's assume it's not
2018 for now. */
2019 }
2020#endif
2021 return 0;
2022}
2023
2024static inline int svm_is_rep(int prefixes)
2025{
2026 return ((prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) ? 8 : 0);
2027}
2028
2029static inline int
2030gen_svm_check_intercept_param(DisasContext *s, target_ulong pc_start,
2031 uint64_t type, uint64_t param)
2032{
2033 if(!(s->flags & (INTERCEPT_SVM_MASK)))
2034 /* no SVM activated */
2035 return 0;
2036 switch(type) {
2037 /* CRx and DRx reads/writes */
2038 case SVM_EXIT_READ_CR0 ... SVM_EXIT_EXCP_BASE - 1:
2039 if (s->cc_op != CC_OP_DYNAMIC) {
2040 gen_op_set_cc_op(s->cc_op);
2041 s->cc_op = CC_OP_DYNAMIC;
2042 }
2043 gen_jmp_im(pc_start - s->cs_base);
2044 SVM_movq_T1_im(param);
2045 gen_op_geneflags();
2046 gen_op_svm_check_intercept_param((uint32_t)(type >> 32), (uint32_t)type);
2047 /* this is a special case as we do not know if the interception occurs
2048 so we assume there was none */
2049 return 0;
2050 case SVM_EXIT_MSR:
2051 if(s->flags & (1ULL << INTERCEPT_MSR_PROT)) {
2052 if (s->cc_op != CC_OP_DYNAMIC) {
2053 gen_op_set_cc_op(s->cc_op);
2054 s->cc_op = CC_OP_DYNAMIC;
2055 }
2056 gen_jmp_im(pc_start - s->cs_base);
2057 SVM_movq_T1_im(param);
2058 gen_op_geneflags();
2059 gen_op_svm_check_intercept_param((uint32_t)(type >> 32), (uint32_t)type);
2060 /* this is a special case as we do not know if the interception occurs
2061 so we assume there was none */
2062 return 0;
2063 }
2064 break;
2065 default:
2066 if(s->flags & (1ULL << ((type - SVM_EXIT_INTR) + INTERCEPT_INTR))) {
2067 if (s->cc_op != CC_OP_DYNAMIC) {
2068 gen_op_set_cc_op(s->cc_op);
2069 s->cc_op = CC_OP_EFLAGS;
2070 }
2071 gen_jmp_im(pc_start - s->cs_base);
2072 SVM_movq_T1_im(param);
2073 gen_op_geneflags();
2074 gen_op_svm_vmexit(type >> 32, type);
2075 /* we can optimize this one so TBs don't get longer
2076 than up to vmexit */
2077 gen_eob(s);
2078 return 1;
2079 }
2080 }
2081 return 0;
2082}
2083
2084static inline int
2085gen_svm_check_intercept(DisasContext *s, target_ulong pc_start, uint64_t type)
2086{
2087 return gen_svm_check_intercept_param(s, pc_start, type, 0);
2088}
2089
4f31916f
FB
2090static inline void gen_stack_update(DisasContext *s, int addend)
2091{
14ce26e7
FB
2092#ifdef TARGET_X86_64
2093 if (CODE64(s)) {
2094 if (addend == 8)
2095 gen_op_addq_ESP_8();
5fafdf24 2096 else
14ce26e7
FB
2097 gen_op_addq_ESP_im(addend);
2098 } else
2099#endif
4f31916f
FB
2100 if (s->ss32) {
2101 if (addend == 2)
2102 gen_op_addl_ESP_2();
2103 else if (addend == 4)
2104 gen_op_addl_ESP_4();
5fafdf24 2105 else
4f31916f
FB
2106 gen_op_addl_ESP_im(addend);
2107 } else {
2108 if (addend == 2)
2109 gen_op_addw_ESP_2();
2110 else if (addend == 4)
2111 gen_op_addw_ESP_4();
2112 else
2113 gen_op_addw_ESP_im(addend);
2114 }
2115}
2116
2c0262af
FB
2117/* generate a push. It depends on ss32, addseg and dflag */
2118static void gen_push_T0(DisasContext *s)
2119{
14ce26e7
FB
2120#ifdef TARGET_X86_64
2121 if (CODE64(s)) {
14ce26e7 2122 gen_op_movq_A0_reg[R_ESP]();
8f091a59
FB
2123 if (s->dflag) {
2124 gen_op_subq_A0_8();
2125 gen_op_st_T0_A0[OT_QUAD + s->mem_index]();
2126 } else {
2127 gen_op_subq_A0_2();
2128 gen_op_st_T0_A0[OT_WORD + s->mem_index]();
2129 }
14ce26e7 2130 gen_op_movq_ESP_A0();
5fafdf24 2131 } else
14ce26e7
FB
2132#endif
2133 {
2134 gen_op_movl_A0_reg[R_ESP]();
2135 if (!s->dflag)
2136 gen_op_subl_A0_2();
2137 else
2138 gen_op_subl_A0_4();
2139 if (s->ss32) {
2140 if (s->addseg) {
2141 gen_op_movl_T1_A0();
2142 gen_op_addl_A0_SS();
2143 }
2144 } else {
2145 gen_op_andl_A0_ffff();
4f31916f
FB
2146 gen_op_movl_T1_A0();
2147 gen_op_addl_A0_SS();
2c0262af 2148 }
14ce26e7
FB
2149 gen_op_st_T0_A0[s->dflag + 1 + s->mem_index]();
2150 if (s->ss32 && !s->addseg)
2151 gen_op_movl_ESP_A0();
2152 else
2153 gen_op_mov_reg_T1[s->ss32 + 1][R_ESP]();
2c0262af
FB
2154 }
2155}
2156
4f31916f
FB
2157/* generate a push. It depends on ss32, addseg and dflag */
2158/* slower version for T1, only used for call Ev */
2159static void gen_push_T1(DisasContext *s)
2c0262af 2160{
14ce26e7
FB
2161#ifdef TARGET_X86_64
2162 if (CODE64(s)) {
14ce26e7 2163 gen_op_movq_A0_reg[R_ESP]();
8f091a59
FB
2164 if (s->dflag) {
2165 gen_op_subq_A0_8();
2166 gen_op_st_T1_A0[OT_QUAD + s->mem_index]();
2167 } else {
2168 gen_op_subq_A0_2();
2169 gen_op_st_T0_A0[OT_WORD + s->mem_index]();
2170 }
14ce26e7 2171 gen_op_movq_ESP_A0();
5fafdf24 2172 } else
14ce26e7
FB
2173#endif
2174 {
2175 gen_op_movl_A0_reg[R_ESP]();
2176 if (!s->dflag)
2177 gen_op_subl_A0_2();
2178 else
2179 gen_op_subl_A0_4();
2180 if (s->ss32) {
2181 if (s->addseg) {
2182 gen_op_addl_A0_SS();
2183 }
2184 } else {
2185 gen_op_andl_A0_ffff();
4f31916f 2186 gen_op_addl_A0_SS();
2c0262af 2187 }
14ce26e7 2188 gen_op_st_T1_A0[s->dflag + 1 + s->mem_index]();
3b46e624 2189
14ce26e7
FB
2190 if (s->ss32 && !s->addseg)
2191 gen_op_movl_ESP_A0();
2192 else
2193 gen_stack_update(s, (-2) << s->dflag);
2c0262af
FB
2194 }
2195}
2196
4f31916f
FB
2197/* two step pop is necessary for precise exceptions */
2198static void gen_pop_T0(DisasContext *s)
2c0262af 2199{
14ce26e7
FB
2200#ifdef TARGET_X86_64
2201 if (CODE64(s)) {
14ce26e7 2202 gen_op_movq_A0_reg[R_ESP]();
8f091a59 2203 gen_op_ld_T0_A0[(s->dflag ? OT_QUAD : OT_WORD) + s->mem_index]();
5fafdf24 2204 } else
14ce26e7
FB
2205#endif
2206 {
2207 gen_op_movl_A0_reg[R_ESP]();
2208 if (s->ss32) {
2209 if (s->addseg)
2210 gen_op_addl_A0_SS();
2211 } else {
2212 gen_op_andl_A0_ffff();
4f31916f 2213 gen_op_addl_A0_SS();
14ce26e7
FB
2214 }
2215 gen_op_ld_T0_A0[s->dflag + 1 + s->mem_index]();
2c0262af
FB
2216 }
2217}
2218
2219static void gen_pop_update(DisasContext *s)
2220{
14ce26e7 2221#ifdef TARGET_X86_64
8f091a59 2222 if (CODE64(s) && s->dflag) {
14ce26e7
FB
2223 gen_stack_update(s, 8);
2224 } else
2225#endif
2226 {
2227 gen_stack_update(s, 2 << s->dflag);
2228 }
2c0262af
FB
2229}
2230
2231static void gen_stack_A0(DisasContext *s)
2232{
2233 gen_op_movl_A0_ESP();
2234 if (!s->ss32)
2235 gen_op_andl_A0_ffff();
2236 gen_op_movl_T1_A0();
2237 if (s->addseg)
2238 gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
2239}
2240
2241/* NOTE: wrap around in 16 bit not fully handled */
2242static void gen_pusha(DisasContext *s)
2243{
2244 int i;
2245 gen_op_movl_A0_ESP();
2246 gen_op_addl_A0_im(-16 << s->dflag);
2247 if (!s->ss32)
2248 gen_op_andl_A0_ffff();
2249 gen_op_movl_T1_A0();
2250 if (s->addseg)
2251 gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
2252 for(i = 0;i < 8; i++) {
2253 gen_op_mov_TN_reg[OT_LONG][0][7 - i]();
2254 gen_op_st_T0_A0[OT_WORD + s->dflag + s->mem_index]();
2255 gen_op_addl_A0_im(2 << s->dflag);
2256 }
90f11f95 2257 gen_op_mov_reg_T1[OT_WORD + s->ss32][R_ESP]();
2c0262af
FB
2258}
2259
2260/* NOTE: wrap around in 16 bit not fully handled */
2261static void gen_popa(DisasContext *s)
2262{
2263 int i;
2264 gen_op_movl_A0_ESP();
2265 if (!s->ss32)
2266 gen_op_andl_A0_ffff();
2267 gen_op_movl_T1_A0();
2268 gen_op_addl_T1_im(16 << s->dflag);
2269 if (s->addseg)
2270 gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
2271 for(i = 0;i < 8; i++) {
2272 /* ESP is not reloaded */
2273 if (i != 3) {
2274 gen_op_ld_T0_A0[OT_WORD + s->dflag + s->mem_index]();
2275 gen_op_mov_reg_T0[OT_WORD + s->dflag][7 - i]();
2276 }
2277 gen_op_addl_A0_im(2 << s->dflag);
2278 }
90f11f95 2279 gen_op_mov_reg_T1[OT_WORD + s->ss32][R_ESP]();
2c0262af
FB
2280}
2281
2c0262af
FB
2282static void gen_enter(DisasContext *s, int esp_addend, int level)
2283{
61a8c4ec 2284 int ot, opsize;
2c0262af 2285
2c0262af 2286 level &= 0x1f;
8f091a59
FB
2287#ifdef TARGET_X86_64
2288 if (CODE64(s)) {
2289 ot = s->dflag ? OT_QUAD : OT_WORD;
2290 opsize = 1 << ot;
3b46e624 2291
8f091a59
FB
2292 gen_op_movl_A0_ESP();
2293 gen_op_addq_A0_im(-opsize);
2294 gen_op_movl_T1_A0();
2295
2296 /* push bp */
2297 gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
2298 gen_op_st_T0_A0[ot + s->mem_index]();
2299 if (level) {
2300 gen_op_enter64_level(level, (ot == OT_QUAD));
2301 }
2302 gen_op_mov_reg_T1[ot][R_EBP]();
2303 gen_op_addl_T1_im( -esp_addend + (-opsize * level) );
2304 gen_op_mov_reg_T1[OT_QUAD][R_ESP]();
5fafdf24 2305 } else
8f091a59
FB
2306#endif
2307 {
2308 ot = s->dflag + OT_WORD;
2309 opsize = 2 << s->dflag;
3b46e624 2310
8f091a59
FB
2311 gen_op_movl_A0_ESP();
2312 gen_op_addl_A0_im(-opsize);
2313 if (!s->ss32)
2314 gen_op_andl_A0_ffff();
2315 gen_op_movl_T1_A0();
2316 if (s->addseg)
2317 gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
2318 /* push bp */
2319 gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
2320 gen_op_st_T0_A0[ot + s->mem_index]();
2321 if (level) {
2322 gen_op_enter_level(level, s->dflag);
2323 }
2324 gen_op_mov_reg_T1[ot][R_EBP]();
2325 gen_op_addl_T1_im( -esp_addend + (-opsize * level) );
2326 gen_op_mov_reg_T1[OT_WORD + s->ss32][R_ESP]();
2c0262af 2327 }
2c0262af
FB
2328}
2329
14ce26e7 2330static void gen_exception(DisasContext *s, int trapno, target_ulong cur_eip)
2c0262af
FB
2331{
2332 if (s->cc_op != CC_OP_DYNAMIC)
2333 gen_op_set_cc_op(s->cc_op);
14ce26e7 2334 gen_jmp_im(cur_eip);
2c0262af
FB
2335 gen_op_raise_exception(trapno);
2336 s->is_jmp = 3;
2337}
2338
2339/* an interrupt is different from an exception because of the
7f75ffd3 2340 privilege checks */
5fafdf24 2341static void gen_interrupt(DisasContext *s, int intno,
14ce26e7 2342 target_ulong cur_eip, target_ulong next_eip)
2c0262af
FB
2343{
2344 if (s->cc_op != CC_OP_DYNAMIC)
2345 gen_op_set_cc_op(s->cc_op);
14ce26e7 2346 gen_jmp_im(cur_eip);
a8ede8ba 2347 gen_op_raise_interrupt(intno, (int)(next_eip - cur_eip));
2c0262af
FB
2348 s->is_jmp = 3;
2349}
2350
14ce26e7 2351static void gen_debug(DisasContext *s, target_ulong cur_eip)
2c0262af
FB
2352{
2353 if (s->cc_op != CC_OP_DYNAMIC)
2354 gen_op_set_cc_op(s->cc_op);
14ce26e7 2355 gen_jmp_im(cur_eip);
2c0262af
FB
2356 gen_op_debug();
2357 s->is_jmp = 3;
2358}
2359
2360/* generate a generic end of block. Trace exception is also generated
2361 if needed */
2362static void gen_eob(DisasContext *s)
2363{
2364 if (s->cc_op != CC_OP_DYNAMIC)
2365 gen_op_set_cc_op(s->cc_op);
a2cc3b24
FB
2366 if (s->tb->flags & HF_INHIBIT_IRQ_MASK) {
2367 gen_op_reset_inhibit_irq();
2368 }
34865134
FB
2369 if (s->singlestep_enabled) {
2370 gen_op_debug();
2371 } else if (s->tf) {
88fe8a41 2372 gen_op_single_step();
2c0262af
FB
2373 } else {
2374 gen_op_movl_T0_0();
2375 gen_op_exit_tb();
2376 }
2377 s->is_jmp = 3;
2378}
2379
2380/* generate a jump to eip. No segment change must happen before as a
2381 direct call to the next block may occur */
14ce26e7 2382static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num)
2c0262af 2383{
2c0262af 2384 if (s->jmp_opt) {
6e256c93 2385 if (s->cc_op != CC_OP_DYNAMIC) {
2c0262af 2386 gen_op_set_cc_op(s->cc_op);
6e256c93
FB
2387 s->cc_op = CC_OP_DYNAMIC;
2388 }
2389 gen_goto_tb(s, tb_num, eip);
2c0262af
FB
2390 s->is_jmp = 3;
2391 } else {
14ce26e7 2392 gen_jmp_im(eip);
2c0262af
FB
2393 gen_eob(s);
2394 }
2395}
2396
14ce26e7
FB
2397static void gen_jmp(DisasContext *s, target_ulong eip)
2398{
2399 gen_jmp_tb(s, eip, 0);
2400}
2401
2402static void gen_movtl_T0_im(target_ulong val)
2403{
3b46e624 2404#ifdef TARGET_X86_64
14ce26e7
FB
2405 if ((int32_t)val == val) {
2406 gen_op_movl_T0_im(val);
2407 } else {
2408 gen_op_movq_T0_im64(val >> 32, val);
2409 }
2410#else
2411 gen_op_movl_T0_im(val);
2412#endif
2413}
2414
1ef38687
FB
2415static void gen_movtl_T1_im(target_ulong val)
2416{
3b46e624 2417#ifdef TARGET_X86_64
1ef38687
FB
2418 if ((int32_t)val == val) {
2419 gen_op_movl_T1_im(val);
2420 } else {
2421 gen_op_movq_T1_im64(val >> 32, val);
2422 }
2423#else
2424 gen_op_movl_T1_im(val);
2425#endif
2426}
2427
aba9d61e
FB
2428static void gen_add_A0_im(DisasContext *s, int val)
2429{
2430#ifdef TARGET_X86_64
2431 if (CODE64(s))
2432 gen_op_addq_A0_im(val);
2433 else
2434#endif
2435 gen_op_addl_A0_im(val);
2436}
2437
664e0f19
FB
2438static GenOpFunc1 *gen_ldq_env_A0[3] = {
2439 gen_op_ldq_raw_env_A0,
2440#ifndef CONFIG_USER_ONLY
2441 gen_op_ldq_kernel_env_A0,
2442 gen_op_ldq_user_env_A0,
2443#endif
2444};
2445
2446static GenOpFunc1 *gen_stq_env_A0[3] = {
2447 gen_op_stq_raw_env_A0,
2448#ifndef CONFIG_USER_ONLY
2449 gen_op_stq_kernel_env_A0,
2450 gen_op_stq_user_env_A0,
2451#endif
2452};
2453
14ce26e7
FB
2454static GenOpFunc1 *gen_ldo_env_A0[3] = {
2455 gen_op_ldo_raw_env_A0,
2456#ifndef CONFIG_USER_ONLY
2457 gen_op_ldo_kernel_env_A0,
2458 gen_op_ldo_user_env_A0,
2459#endif
2460};
2461
2462static GenOpFunc1 *gen_sto_env_A0[3] = {
2463 gen_op_sto_raw_env_A0,
2464#ifndef CONFIG_USER_ONLY
2465 gen_op_sto_kernel_env_A0,
2466 gen_op_sto_user_env_A0,
2467#endif
2468};
2469
664e0f19
FB
2470#define SSE_SPECIAL ((GenOpFunc2 *)1)
2471
2472#define MMX_OP2(x) { gen_op_ ## x ## _mmx, gen_op_ ## x ## _xmm }
2473#define SSE_FOP(x) { gen_op_ ## x ## ps, gen_op_ ## x ## pd, \
2474 gen_op_ ## x ## ss, gen_op_ ## x ## sd, }
2475
2476static GenOpFunc2 *sse_op_table1[256][4] = {
2477 /* pure SSE operations */
2478 [0x10] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movups, movupd, movss, movsd */
2479 [0x11] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movups, movupd, movss, movsd */
465e9838 2480 [0x12] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movlps, movlpd, movsldup, movddup */
664e0f19
FB
2481 [0x13] = { SSE_SPECIAL, SSE_SPECIAL }, /* movlps, movlpd */
2482 [0x14] = { gen_op_punpckldq_xmm, gen_op_punpcklqdq_xmm },
2483 [0x15] = { gen_op_punpckhdq_xmm, gen_op_punpckhqdq_xmm },
2484 [0x16] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movhps, movhpd, movshdup */
2485 [0x17] = { SSE_SPECIAL, SSE_SPECIAL }, /* movhps, movhpd */
2486
2487 [0x28] = { SSE_SPECIAL, SSE_SPECIAL }, /* movaps, movapd */
2488 [0x29] = { SSE_SPECIAL, SSE_SPECIAL }, /* movaps, movapd */
2489 [0x2a] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvtpi2ps, cvtpi2pd, cvtsi2ss, cvtsi2sd */
2490 [0x2b] = { SSE_SPECIAL, SSE_SPECIAL }, /* movntps, movntpd */
2491 [0x2c] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvttps2pi, cvttpd2pi, cvttsd2si, cvttss2si */
2492 [0x2d] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvtps2pi, cvtpd2pi, cvtsd2si, cvtss2si */
2493 [0x2e] = { gen_op_ucomiss, gen_op_ucomisd },
2494 [0x2f] = { gen_op_comiss, gen_op_comisd },
2495 [0x50] = { SSE_SPECIAL, SSE_SPECIAL }, /* movmskps, movmskpd */
2496 [0x51] = SSE_FOP(sqrt),
2497 [0x52] = { gen_op_rsqrtps, NULL, gen_op_rsqrtss, NULL },
2498 [0x53] = { gen_op_rcpps, NULL, gen_op_rcpss, NULL },
2499 [0x54] = { gen_op_pand_xmm, gen_op_pand_xmm }, /* andps, andpd */
2500 [0x55] = { gen_op_pandn_xmm, gen_op_pandn_xmm }, /* andnps, andnpd */
2501 [0x56] = { gen_op_por_xmm, gen_op_por_xmm }, /* orps, orpd */
2502 [0x57] = { gen_op_pxor_xmm, gen_op_pxor_xmm }, /* xorps, xorpd */
2503 [0x58] = SSE_FOP(add),
2504 [0x59] = SSE_FOP(mul),
5fafdf24 2505 [0x5a] = { gen_op_cvtps2pd, gen_op_cvtpd2ps,
664e0f19
FB
2506 gen_op_cvtss2sd, gen_op_cvtsd2ss },
2507 [0x5b] = { gen_op_cvtdq2ps, gen_op_cvtps2dq, gen_op_cvttps2dq },
2508 [0x5c] = SSE_FOP(sub),
2509 [0x5d] = SSE_FOP(min),
2510 [0x5e] = SSE_FOP(div),
2511 [0x5f] = SSE_FOP(max),
2512
2513 [0xc2] = SSE_FOP(cmpeq),
d52cf7a6 2514 [0xc6] = { (GenOpFunc2 *)gen_op_shufps, (GenOpFunc2 *)gen_op_shufpd },
664e0f19
FB
2515
2516 /* MMX ops and their SSE extensions */
2517 [0x60] = MMX_OP2(punpcklbw),
2518 [0x61] = MMX_OP2(punpcklwd),
2519 [0x62] = MMX_OP2(punpckldq),
2520 [0x63] = MMX_OP2(packsswb),
2521 [0x64] = MMX_OP2(pcmpgtb),
2522 [0x65] = MMX_OP2(pcmpgtw),
2523 [0x66] = MMX_OP2(pcmpgtl),
2524 [0x67] = MMX_OP2(packuswb),
2525 [0x68] = MMX_OP2(punpckhbw),
2526 [0x69] = MMX_OP2(punpckhwd),
2527 [0x6a] = MMX_OP2(punpckhdq),
2528 [0x6b] = MMX_OP2(packssdw),
2529 [0x6c] = { NULL, gen_op_punpcklqdq_xmm },
2530 [0x6d] = { NULL, gen_op_punpckhqdq_xmm },
2531 [0x6e] = { SSE_SPECIAL, SSE_SPECIAL }, /* movd mm, ea */
2532 [0x6f] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movq, movdqa, , movqdu */
5fafdf24
TS
2533 [0x70] = { (GenOpFunc2 *)gen_op_pshufw_mmx,
2534 (GenOpFunc2 *)gen_op_pshufd_xmm,
2535 (GenOpFunc2 *)gen_op_pshufhw_xmm,
664e0f19
FB
2536 (GenOpFunc2 *)gen_op_pshuflw_xmm },
2537 [0x71] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftw */
2538 [0x72] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftd */
2539 [0x73] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftq */
2540 [0x74] = MMX_OP2(pcmpeqb),
2541 [0x75] = MMX_OP2(pcmpeqw),
2542 [0x76] = MMX_OP2(pcmpeql),
2543 [0x77] = { SSE_SPECIAL }, /* emms */
2544 [0x7c] = { NULL, gen_op_haddpd, NULL, gen_op_haddps },
2545 [0x7d] = { NULL, gen_op_hsubpd, NULL, gen_op_hsubps },
2546 [0x7e] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movd, movd, , movq */
2547 [0x7f] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movq, movdqa, movdqu */
2548 [0xc4] = { SSE_SPECIAL, SSE_SPECIAL }, /* pinsrw */
2549 [0xc5] = { SSE_SPECIAL, SSE_SPECIAL }, /* pextrw */
2550 [0xd0] = { NULL, gen_op_addsubpd, NULL, gen_op_addsubps },
2551 [0xd1] = MMX_OP2(psrlw),
2552 [0xd2] = MMX_OP2(psrld),
2553 [0xd3] = MMX_OP2(psrlq),
2554 [0xd4] = MMX_OP2(paddq),
2555 [0xd5] = MMX_OP2(pmullw),
2556 [0xd6] = { NULL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
2557 [0xd7] = { SSE_SPECIAL, SSE_SPECIAL }, /* pmovmskb */
2558 [0xd8] = MMX_OP2(psubusb),
2559 [0xd9] = MMX_OP2(psubusw),
2560 [0xda] = MMX_OP2(pminub),
2561 [0xdb] = MMX_OP2(pand),
2562 [0xdc] = MMX_OP2(paddusb),
2563 [0xdd] = MMX_OP2(paddusw),
2564 [0xde] = MMX_OP2(pmaxub),
2565 [0xdf] = MMX_OP2(pandn),
2566 [0xe0] = MMX_OP2(pavgb),
2567 [0xe1] = MMX_OP2(psraw),
2568 [0xe2] = MMX_OP2(psrad),
2569 [0xe3] = MMX_OP2(pavgw),
2570 [0xe4] = MMX_OP2(pmulhuw),
2571 [0xe5] = MMX_OP2(pmulhw),
2572 [0xe6] = { NULL, gen_op_cvttpd2dq, gen_op_cvtdq2pd, gen_op_cvtpd2dq },
2573 [0xe7] = { SSE_SPECIAL , SSE_SPECIAL }, /* movntq, movntq */
2574 [0xe8] = MMX_OP2(psubsb),
2575 [0xe9] = MMX_OP2(psubsw),
2576 [0xea] = MMX_OP2(pminsw),
2577 [0xeb] = MMX_OP2(por),
2578 [0xec] = MMX_OP2(paddsb),
2579 [0xed] = MMX_OP2(paddsw),
2580 [0xee] = MMX_OP2(pmaxsw),
2581 [0xef] = MMX_OP2(pxor),
465e9838 2582 [0xf0] = { NULL, NULL, NULL, SSE_SPECIAL }, /* lddqu */
664e0f19
FB
2583 [0xf1] = MMX_OP2(psllw),
2584 [0xf2] = MMX_OP2(pslld),
2585 [0xf3] = MMX_OP2(psllq),
2586 [0xf4] = MMX_OP2(pmuludq),
2587 [0xf5] = MMX_OP2(pmaddwd),
2588 [0xf6] = MMX_OP2(psadbw),
2589 [0xf7] = MMX_OP2(maskmov),
2590 [0xf8] = MMX_OP2(psubb),
2591 [0xf9] = MMX_OP2(psubw),
2592 [0xfa] = MMX_OP2(psubl),
2593 [0xfb] = MMX_OP2(psubq),
2594 [0xfc] = MMX_OP2(paddb),
2595 [0xfd] = MMX_OP2(paddw),
2596 [0xfe] = MMX_OP2(paddl),
2597};
2598
2599static GenOpFunc2 *sse_op_table2[3 * 8][2] = {
2600 [0 + 2] = MMX_OP2(psrlw),
2601 [0 + 4] = MMX_OP2(psraw),
2602 [0 + 6] = MMX_OP2(psllw),
2603 [8 + 2] = MMX_OP2(psrld),
2604 [8 + 4] = MMX_OP2(psrad),
2605 [8 + 6] = MMX_OP2(pslld),
2606 [16 + 2] = MMX_OP2(psrlq),
2607 [16 + 3] = { NULL, gen_op_psrldq_xmm },
2608 [16 + 6] = MMX_OP2(psllq),
2609 [16 + 7] = { NULL, gen_op_pslldq_xmm },
2610};
2611
2612static GenOpFunc1 *sse_op_table3[4 * 3] = {
2613 gen_op_cvtsi2ss,
2614 gen_op_cvtsi2sd,
2615 X86_64_ONLY(gen_op_cvtsq2ss),
2616 X86_64_ONLY(gen_op_cvtsq2sd),
3b46e624 2617
664e0f19
FB
2618 gen_op_cvttss2si,
2619 gen_op_cvttsd2si,
2620 X86_64_ONLY(gen_op_cvttss2sq),
2621 X86_64_ONLY(gen_op_cvttsd2sq),
2622
2623 gen_op_cvtss2si,
2624 gen_op_cvtsd2si,
2625 X86_64_ONLY(gen_op_cvtss2sq),
2626 X86_64_ONLY(gen_op_cvtsd2sq),
2627};
3b46e624 2628
664e0f19
FB
2629static GenOpFunc2 *sse_op_table4[8][4] = {
2630 SSE_FOP(cmpeq),
2631 SSE_FOP(cmplt),
2632 SSE_FOP(cmple),
2633 SSE_FOP(cmpunord),
2634 SSE_FOP(cmpneq),
2635 SSE_FOP(cmpnlt),
2636 SSE_FOP(cmpnle),
2637 SSE_FOP(cmpord),
2638};
3b46e624 2639
664e0f19
FB
2640static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r)
2641{
2642 int b1, op1_offset, op2_offset, is_xmm, val, ot;
2643 int modrm, mod, rm, reg, reg_addr, offset_addr;
2644 GenOpFunc2 *sse_op2;
2645 GenOpFunc3 *sse_op3;
2646
2647 b &= 0xff;
5fafdf24 2648 if (s->prefix & PREFIX_DATA)
664e0f19 2649 b1 = 1;
5fafdf24 2650 else if (s->prefix & PREFIX_REPZ)
664e0f19 2651 b1 = 2;
5fafdf24 2652 else if (s->prefix & PREFIX_REPNZ)
664e0f19
FB
2653 b1 = 3;
2654 else
2655 b1 = 0;
2656 sse_op2 = sse_op_table1[b][b1];
5fafdf24 2657 if (!sse_op2)
664e0f19
FB
2658 goto illegal_op;
2659 if (b <= 0x5f || b == 0xc6 || b == 0xc2) {
2660 is_xmm = 1;
2661 } else {
2662 if (b1 == 0) {
2663 /* MMX case */
2664 is_xmm = 0;
2665 } else {
2666 is_xmm = 1;
2667 }
2668 }
2669 /* simple MMX/SSE operation */
2670 if (s->flags & HF_TS_MASK) {
2671 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
2672 return;
2673 }
2674 if (s->flags & HF_EM_MASK) {
2675 illegal_op:
2676 gen_exception(s, EXCP06_ILLOP, pc_start - s->cs_base);
2677 return;
2678 }
2679 if (is_xmm && !(s->flags & HF_OSFXSR_MASK))
2680 goto illegal_op;
2681 if (b == 0x77) {
2682 /* emms */
2683 gen_op_emms();
2684 return;
2685 }
2686 /* prepare MMX state (XXX: optimize by storing fptt and fptags in
2687 the static cpu state) */
2688 if (!is_xmm) {
2689 gen_op_enter_mmx();
2690 }
2691
2692 modrm = ldub_code(s->pc++);
2693 reg = ((modrm >> 3) & 7);
2694 if (is_xmm)
2695 reg |= rex_r;
2696 mod = (modrm >> 6) & 3;
2697 if (sse_op2 == SSE_SPECIAL) {
2698 b |= (b1 << 8);
2699 switch(b) {
2700 case 0x0e7: /* movntq */
5fafdf24 2701 if (mod == 3)
664e0f19
FB
2702 goto illegal_op;
2703 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2704 gen_stq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,fpregs[reg].mmx));
2705 break;
2706 case 0x1e7: /* movntdq */
2707 case 0x02b: /* movntps */
2708 case 0x12b: /* movntps */
465e9838
FB
2709 case 0x3f0: /* lddqu */
2710 if (mod == 3)
664e0f19
FB
2711 goto illegal_op;
2712 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2713 gen_sto_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg]));
2714 break;
2715 case 0x6e: /* movd mm, ea */
dabd98dd
FB
2716#ifdef TARGET_X86_64
2717 if (s->dflag == 2) {
2718 gen_ldst_modrm(s, modrm, OT_QUAD, OR_TMP0, 0);
2719 gen_op_movq_mm_T0_mmx(offsetof(CPUX86State,fpregs[reg].mmx));
5fafdf24 2720 } else
dabd98dd
FB
2721#endif
2722 {
2723 gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 0);
2724 gen_op_movl_mm_T0_mmx(offsetof(CPUX86State,fpregs[reg].mmx));
2725 }
664e0f19
FB
2726 break;
2727 case 0x16e: /* movd xmm, ea */
dabd98dd
FB
2728#ifdef TARGET_X86_64
2729 if (s->dflag == 2) {
2730 gen_ldst_modrm(s, modrm, OT_QUAD, OR_TMP0, 0);
2731 gen_op_movq_mm_T0_xmm(offsetof(CPUX86State,xmm_regs[reg]));
5fafdf24 2732 } else
dabd98dd
FB
2733#endif
2734 {
2735 gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 0);
2736 gen_op_movl_mm_T0_xmm(offsetof(CPUX86State,xmm_regs[reg]));
2737 }
664e0f19
FB
2738 break;
2739 case 0x6f: /* movq mm, ea */
2740 if (mod != 3) {
2741 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2742 gen_ldq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,fpregs[reg].mmx));
2743 } else {
2744 rm = (modrm & 7);
2745 gen_op_movq(offsetof(CPUX86State,fpregs[reg].mmx),
2746 offsetof(CPUX86State,fpregs[rm].mmx));
2747 }
2748 break;
2749 case 0x010: /* movups */
2750 case 0x110: /* movupd */
2751 case 0x028: /* movaps */
2752 case 0x128: /* movapd */
2753 case 0x16f: /* movdqa xmm, ea */
2754 case 0x26f: /* movdqu xmm, ea */
2755 if (mod != 3) {
2756 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2757 gen_ldo_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg]));
2758 } else {
2759 rm = (modrm & 7) | REX_B(s);
2760 gen_op_movo(offsetof(CPUX86State,xmm_regs[reg]),
2761 offsetof(CPUX86State,xmm_regs[rm]));
2762 }
2763 break;
2764 case 0x210: /* movss xmm, ea */
2765 if (mod != 3) {
2766 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2767 gen_op_ld_T0_A0[OT_LONG + s->mem_index]();
2768 gen_op_movl_env_T0(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
2769 gen_op_movl_T0_0();
2770 gen_op_movl_env_T0(offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)));
2771 gen_op_movl_env_T0(offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)));
2772 gen_op_movl_env_T0(offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)));
2773 } else {
2774 rm = (modrm & 7) | REX_B(s);
2775 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)),
2776 offsetof(CPUX86State,xmm_regs[rm].XMM_L(0)));
2777 }
2778 break;
2779 case 0x310: /* movsd xmm, ea */
2780 if (mod != 3) {
2781 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2782 gen_ldq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
2783 gen_op_movl_T0_0();
2784 gen_op_movl_env_T0(offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)));
2785 gen_op_movl_env_T0(offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)));
2786 } else {
2787 rm = (modrm & 7) | REX_B(s);
2788 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
2789 offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
2790 }
2791 break;
2792 case 0x012: /* movlps */
2793 case 0x112: /* movlpd */
2794 if (mod != 3) {
2795 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2796 gen_ldq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
2797 } else {
2798 /* movhlps */
2799 rm = (modrm & 7) | REX_B(s);
2800 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
2801 offsetof(CPUX86State,xmm_regs[rm].XMM_Q(1)));
2802 }
2803 break;
465e9838
FB
2804 case 0x212: /* movsldup */
2805 if (mod != 3) {
2806 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2807 gen_ldo_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg]));
2808 } else {
2809 rm = (modrm & 7) | REX_B(s);
2810 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)),
2811 offsetof(CPUX86State,xmm_regs[rm].XMM_L(0)));
2812 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)),
2813 offsetof(CPUX86State,xmm_regs[rm].XMM_L(2)));
2814 }
2815 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)),
2816 offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
2817 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)),
2818 offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)));
2819 break;
2820 case 0x312: /* movddup */
2821 if (mod != 3) {
2822 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2823 gen_ldq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
2824 } else {
2825 rm = (modrm & 7) | REX_B(s);
2826 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
2827 offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
2828 }
2829 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)),
ba6526df 2830 offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
465e9838 2831 break;
664e0f19
FB
2832 case 0x016: /* movhps */
2833 case 0x116: /* movhpd */
2834 if (mod != 3) {
2835 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2836 gen_ldq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)));
2837 } else {
2838 /* movlhps */
2839 rm = (modrm & 7) | REX_B(s);
2840 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)),
2841 offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
2842 }
2843 break;
2844 case 0x216: /* movshdup */
2845 if (mod != 3) {
2846 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2847 gen_ldo_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg]));
2848 } else {
2849 rm = (modrm & 7) | REX_B(s);
2850 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)),
2851 offsetof(CPUX86State,xmm_regs[rm].XMM_L(1)));
2852 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)),
2853 offsetof(CPUX86State,xmm_regs[rm].XMM_L(3)));
2854 }
2855 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)),
2856 offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)));
2857 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)),
2858 offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)));
2859 break;
2860 case 0x7e: /* movd ea, mm */
dabd98dd
FB
2861#ifdef TARGET_X86_64
2862 if (s->dflag == 2) {
2863 gen_op_movq_T0_mm_mmx(offsetof(CPUX86State,fpregs[reg].mmx));
2864 gen_ldst_modrm(s, modrm, OT_QUAD, OR_TMP0, 1);
5fafdf24 2865 } else
dabd98dd
FB
2866#endif
2867 {
2868 gen_op_movl_T0_mm_mmx(offsetof(CPUX86State,fpregs[reg].mmx));
2869 gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 1);
2870 }
664e0f19
FB
2871 break;
2872 case 0x17e: /* movd ea, xmm */
dabd98dd
FB
2873#ifdef TARGET_X86_64
2874 if (s->dflag == 2) {
2875 gen_op_movq_T0_mm_xmm(offsetof(CPUX86State,xmm_regs[reg]));
2876 gen_ldst_modrm(s, modrm, OT_QUAD, OR_TMP0, 1);
5fafdf24 2877 } else
dabd98dd
FB
2878#endif
2879 {
2880 gen_op_movl_T0_mm_xmm(offsetof(CPUX86State,xmm_regs[reg]));
2881 gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 1);
2882 }
664e0f19
FB
2883 break;
2884 case 0x27e: /* movq xmm, ea */
2885 if (mod != 3) {
2886 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2887 gen_ldq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
2888 } else {
2889 rm = (modrm & 7) | REX_B(s);
2890 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
2891 offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
2892 }
2893 gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)));
2894 break;
2895 case 0x7f: /* movq ea, mm */
2896 if (mod != 3) {
2897 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2898 gen_stq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,fpregs[reg].mmx));
2899 } else {
2900 rm = (modrm & 7);
2901 gen_op_movq(offsetof(CPUX86State,fpregs[rm].mmx),
2902 offsetof(CPUX86State,fpregs[reg].mmx));
2903 }
2904 break;
2905 case 0x011: /* movups */
2906 case 0x111: /* movupd */
2907 case 0x029: /* movaps */
2908 case 0x129: /* movapd */
2909 case 0x17f: /* movdqa ea, xmm */
2910 case 0x27f: /* movdqu ea, xmm */
2911 if (mod != 3) {
2912 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2913 gen_sto_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg]));
2914 } else {
2915 rm = (modrm & 7) | REX_B(s);
2916 gen_op_movo(offsetof(CPUX86State,xmm_regs[rm]),
2917 offsetof(CPUX86State,xmm_regs[reg]));
2918 }
2919 break;
2920 case 0x211: /* movss ea, xmm */
2921 if (mod != 3) {
2922 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2923 gen_op_movl_T0_env(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
2924 gen_op_st_T0_A0[OT_LONG + s->mem_index]();
2925 } else {
2926 rm = (modrm & 7) | REX_B(s);
2927 gen_op_movl(offsetof(CPUX86State,xmm_regs[rm].XMM_L(0)),
2928 offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
2929 }
2930 break;
2931 case 0x311: /* movsd ea, xmm */
2932 if (mod != 3) {
2933 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2934 gen_stq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
2935 } else {
2936 rm = (modrm & 7) | REX_B(s);
2937 gen_op_movq(offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)),
2938 offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
2939 }
2940 break;
2941 case 0x013: /* movlps */
2942 case 0x113: /* movlpd */
2943 if (mod != 3) {
2944 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2945 gen_stq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
2946 } else {
2947 goto illegal_op;
2948 }
2949 break;
2950 case 0x017: /* movhps */
2951 case 0x117: /* movhpd */
2952 if (mod != 3) {
2953 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2954 gen_stq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)));
2955 } else {
2956 goto illegal_op;
2957 }
2958 break;
2959 case 0x71: /* shift mm, im */
2960 case 0x72:
2961 case 0x73:
2962 case 0x171: /* shift xmm, im */
2963 case 0x172:
2964 case 0x173:
2965 val = ldub_code(s->pc++);
2966 if (is_xmm) {
2967 gen_op_movl_T0_im(val);
2968 gen_op_movl_env_T0(offsetof(CPUX86State,xmm_t0.XMM_L(0)));
2969 gen_op_movl_T0_0();
2970 gen_op_movl_env_T0(offsetof(CPUX86State,xmm_t0.XMM_L(1)));
2971 op1_offset = offsetof(CPUX86State,xmm_t0);
2972 } else {
2973 gen_op_movl_T0_im(val);
2974 gen_op_movl_env_T0(offsetof(CPUX86State,mmx_t0.MMX_L(0)));
2975 gen_op_movl_T0_0();
2976 gen_op_movl_env_T0(offsetof(CPUX86State,mmx_t0.MMX_L(1)));
2977 op1_offset = offsetof(CPUX86State,mmx_t0);
2978 }
2979 sse_op2 = sse_op_table2[((b - 1) & 3) * 8 + (((modrm >> 3)) & 7)][b1];
2980 if (!sse_op2)
2981 goto illegal_op;
2982 if (is_xmm) {
2983 rm = (modrm & 7) | REX_B(s);
2984 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
2985 } else {
2986 rm = (modrm & 7);
2987 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
2988 }
2989 sse_op2(op2_offset, op1_offset);
2990 break;
2991 case 0x050: /* movmskps */
664e0f19 2992 rm = (modrm & 7) | REX_B(s);
31313213
FB
2993 gen_op_movmskps(offsetof(CPUX86State,xmm_regs[rm]));
2994 gen_op_mov_reg_T0[OT_LONG][reg]();
664e0f19
FB
2995 break;
2996 case 0x150: /* movmskpd */
664e0f19 2997 rm = (modrm & 7) | REX_B(s);
31313213
FB
2998 gen_op_movmskpd(offsetof(CPUX86State,xmm_regs[rm]));
2999 gen_op_mov_reg_T0[OT_LONG][reg]();
664e0f19
FB
3000 break;
3001 case 0x02a: /* cvtpi2ps */
3002 case 0x12a: /* cvtpi2pd */
3003 gen_op_enter_mmx();
3004 if (mod != 3) {
3005 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3006 op2_offset = offsetof(CPUX86State,mmx_t0);
3007 gen_ldq_env_A0[s->mem_index >> 2](op2_offset);
3008 } else {
3009 rm = (modrm & 7);
3010 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3011 }
3012 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
3013 switch(b >> 8) {
3014 case 0x0:
3015 gen_op_cvtpi2ps(op1_offset, op2_offset);
3016 break;
3017 default:
3018 case 0x1:
3019 gen_op_cvtpi2pd(op1_offset, op2_offset);
3020 break;
3021 }
3022 break;
3023 case 0x22a: /* cvtsi2ss */
3024 case 0x32a: /* cvtsi2sd */
3025 ot = (s->dflag == 2) ? OT_QUAD : OT_LONG;
3026 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
3027 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
3028 sse_op_table3[(s->dflag == 2) * 2 + ((b >> 8) - 2)](op1_offset);
3029 break;
3030 case 0x02c: /* cvttps2pi */
3031 case 0x12c: /* cvttpd2pi */
3032 case 0x02d: /* cvtps2pi */
3033 case 0x12d: /* cvtpd2pi */
3034 gen_op_enter_mmx();
3035 if (mod != 3) {
3036 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3037 op2_offset = offsetof(CPUX86State,xmm_t0);
3038 gen_ldo_env_A0[s->mem_index >> 2](op2_offset);
3039 } else {
3040 rm = (modrm & 7) | REX_B(s);
3041 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3042 }
3043 op1_offset = offsetof(CPUX86State,fpregs[reg & 7].mmx);
3044 switch(b) {
3045 case 0x02c:
3046 gen_op_cvttps2pi(op1_offset, op2_offset);
3047 break;
3048 case 0x12c:
3049 gen_op_cvttpd2pi(op1_offset, op2_offset);
3050 break;
3051 case 0x02d:
3052 gen_op_cvtps2pi(op1_offset, op2_offset);
3053 break;
3054 case 0x12d:
3055 gen_op_cvtpd2pi(op1_offset, op2_offset);
3056 break;
3057 }
3058 break;
3059 case 0x22c: /* cvttss2si */
3060 case 0x32c: /* cvttsd2si */
3061 case 0x22d: /* cvtss2si */
3062 case 0x32d: /* cvtsd2si */
3063 ot = (s->dflag == 2) ? OT_QUAD : OT_LONG;
31313213
FB
3064 if (mod != 3) {
3065 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3066 if ((b >> 8) & 1) {
3067 gen_ldq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_t0.XMM_Q(0)));
3068 } else {
3069 gen_op_ld_T0_A0[OT_LONG + s->mem_index]();
3070 gen_op_movl_env_T0(offsetof(CPUX86State,xmm_t0.XMM_L(0)));
3071 }
3072 op2_offset = offsetof(CPUX86State,xmm_t0);
3073 } else {
3074 rm = (modrm & 7) | REX_B(s);
3075 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3076 }
5fafdf24 3077 sse_op_table3[(s->dflag == 2) * 2 + ((b >> 8) - 2) + 4 +
31313213
FB
3078 (b & 1) * 4](op2_offset);
3079 gen_op_mov_reg_T0[ot][reg]();
664e0f19
FB
3080 break;
3081 case 0xc4: /* pinsrw */
5fafdf24 3082 case 0x1c4:
d1e42c5c 3083 s->rip_offset = 1;
664e0f19
FB
3084 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
3085 val = ldub_code(s->pc++);
3086 if (b1) {
3087 val &= 7;
3088 gen_op_pinsrw_xmm(offsetof(CPUX86State,xmm_regs[reg]), val);
3089 } else {
3090 val &= 3;
3091 gen_op_pinsrw_mmx(offsetof(CPUX86State,fpregs[reg].mmx), val);
3092 }
3093 break;
3094 case 0xc5: /* pextrw */
5fafdf24 3095 case 0x1c5:
664e0f19
FB
3096 if (mod != 3)
3097 goto illegal_op;
3098 val = ldub_code(s->pc++);
3099 if (b1) {
3100 val &= 7;
3101 rm = (modrm & 7) | REX_B(s);
3102 gen_op_pextrw_xmm(offsetof(CPUX86State,xmm_regs[rm]), val);
3103 } else {
3104 val &= 3;
3105 rm = (modrm & 7);
3106 gen_op_pextrw_mmx(offsetof(CPUX86State,fpregs[rm].mmx), val);
3107 }
3108 reg = ((modrm >> 3) & 7) | rex_r;
3109 gen_op_mov_reg_T0[OT_LONG][reg]();
3110 break;
3111 case 0x1d6: /* movq ea, xmm */
3112 if (mod != 3) {
3113 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3114 gen_stq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
3115 } else {
3116 rm = (modrm & 7) | REX_B(s);
3117 gen_op_movq(offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)),
3118 offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
3119 gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[rm].XMM_Q(1)));
3120 }
3121 break;
3122 case 0x2d6: /* movq2dq */
3123 gen_op_enter_mmx();
480c1cdb
FB
3124 rm = (modrm & 7);
3125 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
3126 offsetof(CPUX86State,fpregs[rm].mmx));
3127 gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)));
664e0f19
FB
3128 break;
3129 case 0x3d6: /* movdq2q */
3130 gen_op_enter_mmx();
480c1cdb
FB
3131 rm = (modrm & 7) | REX_B(s);
3132 gen_op_movq(offsetof(CPUX86State,fpregs[reg & 7].mmx),
3133 offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
664e0f19
FB
3134 break;
3135 case 0xd7: /* pmovmskb */
3136 case 0x1d7:
3137 if (mod != 3)
3138 goto illegal_op;
3139 if (b1) {
3140 rm = (modrm & 7) | REX_B(s);
3141 gen_op_pmovmskb_xmm(offsetof(CPUX86State,xmm_regs[rm]));
3142 } else {
3143 rm = (modrm & 7);
3144 gen_op_pmovmskb_mmx(offsetof(CPUX86State,fpregs[rm].mmx));
3145 }
3146 reg = ((modrm >> 3) & 7) | rex_r;
3147 gen_op_mov_reg_T0[OT_LONG][reg]();
3148 break;
3149 default:
3150 goto illegal_op;
3151 }
3152 } else {
3153 /* generic MMX or SSE operation */
d1e42c5c
FB
3154 switch(b) {
3155 case 0xf7:
664e0f19 3156 /* maskmov : we must prepare A0 */
5fafdf24 3157 if (mod != 3)
664e0f19
FB
3158 goto illegal_op;
3159#ifdef TARGET_X86_64
8f091a59 3160 if (s->aflag == 2) {
664e0f19 3161 gen_op_movq_A0_reg[R_EDI]();
5fafdf24 3162 } else
664e0f19
FB
3163#endif
3164 {
3165 gen_op_movl_A0_reg[R_EDI]();
3166 if (s->aflag == 0)
3167 gen_op_andl_A0_ffff();
3168 }
3169 gen_add_A0_ds_seg(s);
d1e42c5c
FB
3170 break;
3171 case 0x70: /* pshufx insn */
3172 case 0xc6: /* pshufx insn */
3173 case 0xc2: /* compare insns */
3174 s->rip_offset = 1;
3175 break;
3176 default:
3177 break;
664e0f19
FB
3178 }
3179 if (is_xmm) {
3180 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
3181 if (mod != 3) {
3182 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3183 op2_offset = offsetof(CPUX86State,xmm_t0);
480c1cdb 3184 if (b1 >= 2 && ((b >= 0x50 && b <= 0x5f && b != 0x5b) ||
664e0f19
FB
3185 b == 0xc2)) {
3186 /* specific case for SSE single instructions */
3187 if (b1 == 2) {
3188 /* 32 bit access */
3189 gen_op_ld_T0_A0[OT_LONG + s->mem_index]();
3190 gen_op_movl_env_T0(offsetof(CPUX86State,xmm_t0.XMM_L(0)));
3191 } else {
3192 /* 64 bit access */
3193 gen_ldq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_t0.XMM_D(0)));
3194 }
3195 } else {
3196 gen_ldo_env_A0[s->mem_index >> 2](op2_offset);
3197 }
3198 } else {
3199 rm = (modrm & 7) | REX_B(s);
3200 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3201 }
3202 } else {
3203 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
3204 if (mod != 3) {
3205 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3206 op2_offset = offsetof(CPUX86State,mmx_t0);
3207 gen_ldq_env_A0[s->mem_index >> 2](op2_offset);
3208 } else {
3209 rm = (modrm & 7);
3210 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3211 }
3212 }
3213 switch(b) {
3214 case 0x70: /* pshufx insn */
3215 case 0xc6: /* pshufx insn */
3216 val = ldub_code(s->pc++);
3217 sse_op3 = (GenOpFunc3 *)sse_op2;
3218 sse_op3(op1_offset, op2_offset, val);
3219 break;
3220 case 0xc2:
3221 /* compare insns */
3222 val = ldub_code(s->pc++);
3223 if (val >= 8)
3224 goto illegal_op;
3225 sse_op2 = sse_op_table4[val][b1];
3226 sse_op2(op1_offset, op2_offset);
3227 break;
3228 default:
3229 sse_op2(op1_offset, op2_offset);
3230 break;
3231 }
3232 if (b == 0x2e || b == 0x2f) {
3233 s->cc_op = CC_OP_EFLAGS;
3234 }
3235 }
3236}
3237
3238
2c0262af
FB
3239/* convert one instruction. s->is_jmp is set if the translation must
3240 be stopped. Return the next pc value */
14ce26e7 3241static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
2c0262af
FB
3242{
3243 int b, prefixes, aflag, dflag;
3244 int shift, ot;
3245 int modrm, reg, rm, mod, reg_addr, op, opreg, offset_addr, val;
14ce26e7
FB
3246 target_ulong next_eip, tval;
3247 int rex_w, rex_r;
2c0262af
FB
3248
3249 s->pc = pc_start;
3250 prefixes = 0;
3251 aflag = s->code32;
3252 dflag = s->code32;
3253 s->override = -1;
14ce26e7
FB
3254 rex_w = -1;
3255 rex_r = 0;
3256#ifdef TARGET_X86_64
3257 s->rex_x = 0;
3258 s->rex_b = 0;
5fafdf24 3259 x86_64_hregs = 0;
14ce26e7
FB
3260#endif
3261 s->rip_offset = 0; /* for relative ip address */
2c0262af 3262 next_byte:
61382a50 3263 b = ldub_code(s->pc);
2c0262af
FB
3264 s->pc++;
3265 /* check prefixes */
14ce26e7
FB
3266#ifdef TARGET_X86_64
3267 if (CODE64(s)) {
3268 switch (b) {
3269 case 0xf3:
3270 prefixes |= PREFIX_REPZ;
3271 goto next_byte;
3272 case 0xf2:
3273 prefixes |= PREFIX_REPNZ;
3274 goto next_byte;
3275 case 0xf0:
3276 prefixes |= PREFIX_LOCK;
3277 goto next_byte;
3278 case 0x2e:
3279 s->override = R_CS;
3280 goto next_byte;
3281 case 0x36:
3282 s->override = R_SS;
3283 goto next_byte;
3284 case 0x3e:
3285 s->override = R_DS;
3286 goto next_byte;
3287 case 0x26:
3288 s->override = R_ES;
3289 goto next_byte;
3290 case 0x64:
3291 s->override = R_FS;
3292 goto next_byte;
3293 case 0x65:
3294 s->override = R_GS;
3295 goto next_byte;
3296 case 0x66:
3297 prefixes |= PREFIX_DATA;
3298 goto next_byte;
3299 case 0x67:
3300 prefixes |= PREFIX_ADR;
3301 goto next_byte;
3302 case 0x40 ... 0x4f:
3303 /* REX prefix */
3304 rex_w = (b >> 3) & 1;
3305 rex_r = (b & 0x4) << 1;
3306 s->rex_x = (b & 0x2) << 2;
3307 REX_B(s) = (b & 0x1) << 3;
3308 x86_64_hregs = 1; /* select uniform byte register addressing */
3309 goto next_byte;
3310 }
3311 if (rex_w == 1) {
3312 /* 0x66 is ignored if rex.w is set */
3313 dflag = 2;
3314 } else {
3315 if (prefixes & PREFIX_DATA)
3316 dflag ^= 1;
3317 }
3318 if (!(prefixes & PREFIX_ADR))
3319 aflag = 2;
5fafdf24 3320 } else
14ce26e7
FB
3321#endif
3322 {
3323 switch (b) {
3324 case 0xf3:
3325 prefixes |= PREFIX_REPZ;
3326 goto next_byte;
3327 case 0xf2:
3328 prefixes |= PREFIX_REPNZ;
3329 goto next_byte;
3330 case 0xf0:
3331 prefixes |= PREFIX_LOCK;
3332 goto next_byte;
3333 case 0x2e:
3334 s->override = R_CS;
3335 goto next_byte;
3336 case 0x36:
3337 s->override = R_SS;
3338 goto next_byte;
3339 case 0x3e:
3340 s->override = R_DS;
3341 goto next_byte;
3342 case 0x26:
3343 s->override = R_ES;
3344 goto next_byte;
3345 case 0x64:
3346 s->override = R_FS;
3347 goto next_byte;
3348 case 0x65:
3349 s->override = R_GS;
3350 goto next_byte;
3351 case 0x66:
3352 prefixes |= PREFIX_DATA;
3353 goto next_byte;
3354 case 0x67:
3355 prefixes |= PREFIX_ADR;
3356 goto next_byte;
3357 }
3358 if (prefixes & PREFIX_DATA)
3359 dflag ^= 1;
3360 if (prefixes & PREFIX_ADR)
3361 aflag ^= 1;
2c0262af
FB
3362 }
3363
2c0262af
FB
3364 s->prefix = prefixes;
3365 s->aflag = aflag;
3366 s->dflag = dflag;
3367
3368 /* lock generation */
3369 if (prefixes & PREFIX_LOCK)
3370 gen_op_lock();
3371
3372 /* now check op code */
3373 reswitch:
3374 switch(b) {
3375 case 0x0f:
3376 /**************************/
3377 /* extended op code */
61382a50 3378 b = ldub_code(s->pc++) | 0x100;
2c0262af 3379 goto reswitch;
3b46e624 3380
2c0262af
FB
3381 /**************************/
3382 /* arith & logic */
3383 case 0x00 ... 0x05:
3384 case 0x08 ... 0x0d:
3385 case 0x10 ... 0x15:
3386 case 0x18 ... 0x1d:
3387 case 0x20 ... 0x25:
3388 case 0x28 ... 0x2d:
3389 case 0x30 ... 0x35:
3390 case 0x38 ... 0x3d:
3391 {
3392 int op, f, val;
3393 op = (b >> 3) & 7;
3394 f = (b >> 1) & 3;
3395
3396 if ((b & 1) == 0)
3397 ot = OT_BYTE;
3398 else
14ce26e7 3399 ot = dflag + OT_WORD;
3b46e624 3400
2c0262af
FB
3401 switch(f) {
3402 case 0: /* OP Ev, Gv */
61382a50 3403 modrm = ldub_code(s->pc++);
14ce26e7 3404 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af 3405 mod = (modrm >> 6) & 3;
14ce26e7 3406 rm = (modrm & 7) | REX_B(s);
2c0262af
FB
3407 if (mod != 3) {
3408 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3409 opreg = OR_TMP0;
3410 } else if (op == OP_XORL && rm == reg) {
3411 xor_zero:
3412 /* xor reg, reg optimisation */
3413 gen_op_movl_T0_0();
3414 s->cc_op = CC_OP_LOGICB + ot;
3415 gen_op_mov_reg_T0[ot][reg]();
3416 gen_op_update1_cc();
3417 break;
3418 } else {
3419 opreg = rm;
3420 }
3421 gen_op_mov_TN_reg[ot][1][reg]();
3422 gen_op(s, op, ot, opreg);
3423 break;
3424 case 1: /* OP Gv, Ev */
61382a50 3425 modrm = ldub_code(s->pc++);
2c0262af 3426 mod = (modrm >> 6) & 3;
14ce26e7
FB
3427 reg = ((modrm >> 3) & 7) | rex_r;
3428 rm = (modrm & 7) | REX_B(s);
2c0262af
FB
3429 if (mod != 3) {
3430 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3431 gen_op_ld_T1_A0[ot + s->mem_index]();
3432 } else if (op == OP_XORL && rm == reg) {
3433 goto xor_zero;
3434 } else {
3435 gen_op_mov_TN_reg[ot][1][rm]();
3436 }
3437 gen_op(s, op, ot, reg);
3438 break;
3439 case 2: /* OP A, Iv */
3440 val = insn_get(s, ot);
3441 gen_op_movl_T1_im(val);
3442 gen_op(s, op, ot, OR_EAX);
3443 break;
3444 }
3445 }
3446 break;
3447
3448 case 0x80: /* GRP1 */
3449 case 0x81:
d64477af 3450 case 0x82:
2c0262af
FB
3451 case 0x83:
3452 {
3453 int val;
3454
3455 if ((b & 1) == 0)
3456 ot = OT_BYTE;
3457 else
14ce26e7 3458 ot = dflag + OT_WORD;
3b46e624 3459
61382a50 3460 modrm = ldub_code(s->pc++);
2c0262af 3461 mod = (modrm >> 6) & 3;
14ce26e7 3462 rm = (modrm & 7) | REX_B(s);
2c0262af 3463 op = (modrm >> 3) & 7;
3b46e624 3464
2c0262af 3465 if (mod != 3) {
14ce26e7
FB
3466 if (b == 0x83)
3467 s->rip_offset = 1;
3468 else
3469 s->rip_offset = insn_const_size(ot);
2c0262af
FB
3470 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3471 opreg = OR_TMP0;
3472 } else {
14ce26e7 3473 opreg = rm;
2c0262af
FB
3474 }
3475
3476 switch(b) {
3477 default:
3478 case 0x80:
3479 case 0x81:
d64477af 3480 case 0x82:
2c0262af
FB
3481 val = insn_get(s, ot);
3482 break;
3483 case 0x83:
3484 val = (int8_t)insn_get(s, OT_BYTE);
3485 break;
3486 }
3487 gen_op_movl_T1_im(val);
3488 gen_op(s, op, ot, opreg);
3489 }
3490 break;
3491
3492 /**************************/
3493 /* inc, dec, and other misc arith */
3494 case 0x40 ... 0x47: /* inc Gv */
3495 ot = dflag ? OT_LONG : OT_WORD;
3496 gen_inc(s, ot, OR_EAX + (b & 7), 1);
3497 break;
3498 case 0x48 ... 0x4f: /* dec Gv */
3499 ot = dflag ? OT_LONG : OT_WORD;
3500 gen_inc(s, ot, OR_EAX + (b & 7), -1);
3501 break;
3502 case 0xf6: /* GRP3 */
3503 case 0xf7:
3504 if ((b & 1) == 0)
3505 ot = OT_BYTE;
3506 else
14ce26e7 3507 ot = dflag + OT_WORD;
2c0262af 3508
61382a50 3509 modrm = ldub_code(s->pc++);
2c0262af 3510 mod = (modrm >> 6) & 3;
14ce26e7 3511 rm = (modrm & 7) | REX_B(s);
2c0262af
FB
3512 op = (modrm >> 3) & 7;
3513 if (mod != 3) {
14ce26e7
FB
3514 if (op == 0)
3515 s->rip_offset = insn_const_size(ot);
2c0262af
FB
3516 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3517 gen_op_ld_T0_A0[ot + s->mem_index]();
3518 } else {
3519 gen_op_mov_TN_reg[ot][0][rm]();
3520 }
3521
3522 switch(op) {
3523 case 0: /* test */
3524 val = insn_get(s, ot);
3525 gen_op_movl_T1_im(val);
3526 gen_op_testl_T0_T1_cc();
3527 s->cc_op = CC_OP_LOGICB + ot;
3528 break;
3529 case 2: /* not */
3530 gen_op_notl_T0();
3531 if (mod != 3) {
3532 gen_op_st_T0_A0[ot + s->mem_index]();
3533 } else {
3534 gen_op_mov_reg_T0[ot][rm]();
3535 }
3536 break;
3537 case 3: /* neg */
3538 gen_op_negl_T0();
3539 if (mod != 3) {
3540 gen_op_st_T0_A0[ot + s->mem_index]();
3541 } else {
3542 gen_op_mov_reg_T0[ot][rm]();
3543 }
3544 gen_op_update_neg_cc();
3545 s->cc_op = CC_OP_SUBB + ot;
3546 break;
3547 case 4: /* mul */
3548 switch(ot) {
3549 case OT_BYTE:
3550 gen_op_mulb_AL_T0();
d36cd60e 3551 s->cc_op = CC_OP_MULB;
2c0262af
FB
3552 break;
3553 case OT_WORD:
3554 gen_op_mulw_AX_T0();
d36cd60e 3555 s->cc_op = CC_OP_MULW;
2c0262af
FB
3556 break;
3557 default:
3558 case OT_LONG:
3559 gen_op_mull_EAX_T0();
d36cd60e 3560 s->cc_op = CC_OP_MULL;
2c0262af 3561 break;
14ce26e7
FB
3562#ifdef TARGET_X86_64
3563 case OT_QUAD:
3564 gen_op_mulq_EAX_T0();
3565 s->cc_op = CC_OP_MULQ;
3566 break;
3567#endif
2c0262af 3568 }
2c0262af
FB
3569 break;
3570 case 5: /* imul */
3571 switch(ot) {
3572 case OT_BYTE:
3573 gen_op_imulb_AL_T0();
d36cd60e 3574 s->cc_op = CC_OP_MULB;
2c0262af
FB
3575 break;
3576 case OT_WORD:
3577 gen_op_imulw_AX_T0();
d36cd60e 3578 s->cc_op = CC_OP_MULW;
2c0262af
FB
3579 break;
3580 default:
3581 case OT_LONG:
3582 gen_op_imull_EAX_T0();
d36cd60e 3583 s->cc_op = CC_OP_MULL;
2c0262af 3584 break;
14ce26e7
FB
3585#ifdef TARGET_X86_64
3586 case OT_QUAD:
3587 gen_op_imulq_EAX_T0();
3588 s->cc_op = CC_OP_MULQ;
3589 break;
3590#endif
2c0262af 3591 }
2c0262af
FB
3592 break;
3593 case 6: /* div */
3594 switch(ot) {
3595 case OT_BYTE:
14ce26e7
FB
3596 gen_jmp_im(pc_start - s->cs_base);
3597 gen_op_divb_AL_T0();
2c0262af
FB
3598 break;
3599 case OT_WORD:
14ce26e7
FB
3600 gen_jmp_im(pc_start - s->cs_base);
3601 gen_op_divw_AX_T0();
2c0262af
FB
3602 break;
3603 default:
3604 case OT_LONG:
14ce26e7
FB
3605 gen_jmp_im(pc_start - s->cs_base);
3606 gen_op_divl_EAX_T0();
3607 break;
3608#ifdef TARGET_X86_64
3609 case OT_QUAD:
3610 gen_jmp_im(pc_start - s->cs_base);
3611 gen_op_divq_EAX_T0();
2c0262af 3612 break;
14ce26e7 3613#endif
2c0262af
FB
3614 }
3615 break;
3616 case 7: /* idiv */
3617 switch(ot) {
3618 case OT_BYTE:
14ce26e7
FB
3619 gen_jmp_im(pc_start - s->cs_base);
3620 gen_op_idivb_AL_T0();
2c0262af
FB
3621 break;
3622 case OT_WORD:
14ce26e7
FB
3623 gen_jmp_im(pc_start - s->cs_base);
3624 gen_op_idivw_AX_T0();
2c0262af
FB
3625 break;
3626 default:
3627 case OT_LONG:
14ce26e7
FB
3628 gen_jmp_im(pc_start - s->cs_base);
3629 gen_op_idivl_EAX_T0();
3630 break;
3631#ifdef TARGET_X86_64
3632 case OT_QUAD:
3633 gen_jmp_im(pc_start - s->cs_base);
3634 gen_op_idivq_EAX_T0();
2c0262af 3635 break;
14ce26e7 3636#endif
2c0262af
FB
3637 }
3638 break;
3639 default:
3640 goto illegal_op;
3641 }
3642 break;
3643
3644 case 0xfe: /* GRP4 */
3645 case 0xff: /* GRP5 */
3646 if ((b & 1) == 0)
3647 ot = OT_BYTE;
3648 else
14ce26e7 3649 ot = dflag + OT_WORD;
2c0262af 3650
61382a50 3651 modrm = ldub_code(s->pc++);
2c0262af 3652 mod = (modrm >> 6) & 3;
14ce26e7 3653 rm = (modrm & 7) | REX_B(s);
2c0262af
FB
3654 op = (modrm >> 3) & 7;
3655 if (op >= 2 && b == 0xfe) {
3656 goto illegal_op;
3657 }
14ce26e7 3658 if (CODE64(s)) {
aba9d61e 3659 if (op == 2 || op == 4) {
14ce26e7
FB
3660 /* operand size for jumps is 64 bit */
3661 ot = OT_QUAD;
aba9d61e
FB
3662 } else if (op == 3 || op == 5) {
3663 /* for call calls, the operand is 16 or 32 bit, even
3664 in long mode */
3665 ot = dflag ? OT_LONG : OT_WORD;
14ce26e7
FB
3666 } else if (op == 6) {
3667 /* default push size is 64 bit */
3668 ot = dflag ? OT_QUAD : OT_WORD;
3669 }
3670 }
2c0262af
FB
3671 if (mod != 3) {
3672 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3673 if (op >= 2 && op != 3 && op != 5)
3674 gen_op_ld_T0_A0[ot + s->mem_index]();
3675 } else {
3676 gen_op_mov_TN_reg[ot][0][rm]();
3677 }
3678
3679 switch(op) {
3680 case 0: /* inc Ev */
3681 if (mod != 3)
3682 opreg = OR_TMP0;
3683 else
3684 opreg = rm;
3685 gen_inc(s, ot, opreg, 1);
3686 break;
3687 case 1: /* dec Ev */
3688 if (mod != 3)
3689 opreg = OR_TMP0;
3690 else
3691 opreg = rm;
3692 gen_inc(s, ot, opreg, -1);
3693 break;
3694 case 2: /* call Ev */
4f31916f 3695 /* XXX: optimize if memory (no 'and' is necessary) */
2c0262af
FB
3696 if (s->dflag == 0)
3697 gen_op_andl_T0_ffff();
2c0262af 3698 next_eip = s->pc - s->cs_base;
1ef38687 3699 gen_movtl_T1_im(next_eip);
4f31916f
FB
3700 gen_push_T1(s);
3701 gen_op_jmp_T0();
2c0262af
FB
3702 gen_eob(s);
3703 break;
61382a50 3704 case 3: /* lcall Ev */
2c0262af 3705 gen_op_ld_T1_A0[ot + s->mem_index]();
aba9d61e 3706 gen_add_A0_im(s, 1 << (ot - OT_WORD + 1));
61382a50 3707 gen_op_ldu_T0_A0[OT_WORD + s->mem_index]();
2c0262af
FB
3708 do_lcall:
3709 if (s->pe && !s->vm86) {
3710 if (s->cc_op != CC_OP_DYNAMIC)
3711 gen_op_set_cc_op(s->cc_op);
14ce26e7 3712 gen_jmp_im(pc_start - s->cs_base);
aba9d61e 3713 gen_op_lcall_protected_T0_T1(dflag, s->pc - pc_start);
2c0262af
FB
3714 } else {
3715 gen_op_lcall_real_T0_T1(dflag, s->pc - s->cs_base);
3716 }
3717 gen_eob(s);
3718 break;
3719 case 4: /* jmp Ev */
3720 if (s->dflag == 0)
3721 gen_op_andl_T0_ffff();
3722 gen_op_jmp_T0();
3723 gen_eob(s);
3724 break;
3725 case 5: /* ljmp Ev */
3726 gen_op_ld_T1_A0[ot + s->mem_index]();
aba9d61e 3727 gen_add_A0_im(s, 1 << (ot - OT_WORD + 1));
61382a50 3728 gen_op_ldu_T0_A0[OT_WORD + s->mem_index]();
2c0262af
FB
3729 do_ljmp:
3730 if (s->pe && !s->vm86) {
3731 if (s->cc_op != CC_OP_DYNAMIC)
3732 gen_op_set_cc_op(s->cc_op);
14ce26e7 3733 gen_jmp_im(pc_start - s->cs_base);
aba9d61e 3734 gen_op_ljmp_protected_T0_T1(s->pc - pc_start);
2c0262af
FB
3735 } else {
3736 gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[R_CS]));
3737 gen_op_movl_T0_T1();
3738 gen_op_jmp_T0();
3739 }
3740 gen_eob(s);
3741 break;
3742 case 6: /* push Ev */
3743 gen_push_T0(s);
3744 break;
3745 default:
3746 goto illegal_op;
3747 }
3748 break;
3749
3750 case 0x84: /* test Ev, Gv */
5fafdf24 3751 case 0x85:
2c0262af
FB
3752 if ((b & 1) == 0)
3753 ot = OT_BYTE;
3754 else
14ce26e7 3755 ot = dflag + OT_WORD;
2c0262af 3756
61382a50 3757 modrm = ldub_code(s->pc++);
2c0262af 3758 mod = (modrm >> 6) & 3;
14ce26e7
FB
3759 rm = (modrm & 7) | REX_B(s);
3760 reg = ((modrm >> 3) & 7) | rex_r;
3b46e624 3761
2c0262af 3762 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
14ce26e7 3763 gen_op_mov_TN_reg[ot][1][reg]();
2c0262af
FB
3764 gen_op_testl_T0_T1_cc();
3765 s->cc_op = CC_OP_LOGICB + ot;
3766 break;
3b46e624 3767
2c0262af
FB
3768 case 0xa8: /* test eAX, Iv */
3769 case 0xa9:
3770 if ((b & 1) == 0)
3771 ot = OT_BYTE;
3772 else
14ce26e7 3773 ot = dflag + OT_WORD;
2c0262af
FB
3774 val = insn_get(s, ot);
3775
3776 gen_op_mov_TN_reg[ot][0][OR_EAX]();
3777 gen_op_movl_T1_im(val);
3778 gen_op_testl_T0_T1_cc();
3779 s->cc_op = CC_OP_LOGICB + ot;
3780 break;
3b46e624 3781
2c0262af 3782 case 0x98: /* CWDE/CBW */
14ce26e7
FB
3783#ifdef TARGET_X86_64
3784 if (dflag == 2) {
3785 gen_op_movslq_RAX_EAX();
3786 } else
3787#endif
3788 if (dflag == 1)
2c0262af
FB
3789 gen_op_movswl_EAX_AX();
3790 else
3791 gen_op_movsbw_AX_AL();
3792 break;
3793 case 0x99: /* CDQ/CWD */
14ce26e7
FB
3794#ifdef TARGET_X86_64
3795 if (dflag == 2) {
3796 gen_op_movsqo_RDX_RAX();
3797 } else
3798#endif
3799 if (dflag == 1)
2c0262af
FB
3800 gen_op_movslq_EDX_EAX();
3801 else
3802 gen_op_movswl_DX_AX();
3803 break;
3804 case 0x1af: /* imul Gv, Ev */
3805 case 0x69: /* imul Gv, Ev, I */
3806 case 0x6b:
14ce26e7 3807 ot = dflag + OT_WORD;
61382a50 3808 modrm = ldub_code(s->pc++);
14ce26e7
FB
3809 reg = ((modrm >> 3) & 7) | rex_r;
3810 if (b == 0x69)
3811 s->rip_offset = insn_const_size(ot);
3812 else if (b == 0x6b)
3813 s->rip_offset = 1;
2c0262af
FB
3814 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
3815 if (b == 0x69) {
3816 val = insn_get(s, ot);
3817 gen_op_movl_T1_im(val);
3818 } else if (b == 0x6b) {
d64477af 3819 val = (int8_t)insn_get(s, OT_BYTE);
2c0262af
FB
3820 gen_op_movl_T1_im(val);
3821 } else {
3822 gen_op_mov_TN_reg[ot][1][reg]();
3823 }
3824
14ce26e7
FB
3825#ifdef TARGET_X86_64
3826 if (ot == OT_QUAD) {
3827 gen_op_imulq_T0_T1();
3828 } else
3829#endif
2c0262af
FB
3830 if (ot == OT_LONG) {
3831 gen_op_imull_T0_T1();
3832 } else {
3833 gen_op_imulw_T0_T1();
3834 }
3835 gen_op_mov_reg_T0[ot][reg]();
d36cd60e 3836 s->cc_op = CC_OP_MULB + ot;
2c0262af
FB
3837 break;
3838 case 0x1c0:
3839 case 0x1c1: /* xadd Ev, Gv */
3840 if ((b & 1) == 0)
3841 ot = OT_BYTE;
3842 else
14ce26e7 3843 ot = dflag + OT_WORD;
61382a50 3844 modrm = ldub_code(s->pc++);
14ce26e7 3845 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af
FB
3846 mod = (modrm >> 6) & 3;
3847 if (mod == 3) {
14ce26e7 3848 rm = (modrm & 7) | REX_B(s);
2c0262af
FB
3849 gen_op_mov_TN_reg[ot][0][reg]();
3850 gen_op_mov_TN_reg[ot][1][rm]();
3851 gen_op_addl_T0_T1();
2c0262af 3852 gen_op_mov_reg_T1[ot][reg]();
5a1388b6 3853 gen_op_mov_reg_T0[ot][rm]();
2c0262af
FB
3854 } else {
3855 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3856 gen_op_mov_TN_reg[ot][0][reg]();
3857 gen_op_ld_T1_A0[ot + s->mem_index]();
3858 gen_op_addl_T0_T1();
3859 gen_op_st_T0_A0[ot + s->mem_index]();
3860 gen_op_mov_reg_T1[ot][reg]();
3861 }
3862 gen_op_update2_cc();
3863 s->cc_op = CC_OP_ADDB + ot;
3864 break;
3865 case 0x1b0:
3866 case 0x1b1: /* cmpxchg Ev, Gv */
3867 if ((b & 1) == 0)
3868 ot = OT_BYTE;
3869 else
14ce26e7 3870 ot = dflag + OT_WORD;
61382a50 3871 modrm = ldub_code(s->pc++);
14ce26e7 3872 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af
FB
3873 mod = (modrm >> 6) & 3;
3874 gen_op_mov_TN_reg[ot][1][reg]();
3875 if (mod == 3) {
14ce26e7 3876 rm = (modrm & 7) | REX_B(s);
2c0262af
FB
3877 gen_op_mov_TN_reg[ot][0][rm]();
3878 gen_op_cmpxchg_T0_T1_EAX_cc[ot]();
3879 gen_op_mov_reg_T0[ot][rm]();
3880 } else {
3881 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3882 gen_op_ld_T0_A0[ot + s->mem_index]();
4f31916f 3883 gen_op_cmpxchg_mem_T0_T1_EAX_cc[ot + s->mem_index]();
2c0262af
FB
3884 }
3885 s->cc_op = CC_OP_SUBB + ot;
3886 break;
3887 case 0x1c7: /* cmpxchg8b */
61382a50 3888 modrm = ldub_code(s->pc++);
2c0262af
FB
3889 mod = (modrm >> 6) & 3;
3890 if (mod == 3)
3891 goto illegal_op;
2f6ecc62 3892 gen_jmp_im(pc_start - s->cs_base);
2c0262af
FB
3893 if (s->cc_op != CC_OP_DYNAMIC)
3894 gen_op_set_cc_op(s->cc_op);
3895 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3896 gen_op_cmpxchg8b();
3897 s->cc_op = CC_OP_EFLAGS;
3898 break;
3b46e624 3899
2c0262af
FB
3900 /**************************/
3901 /* push/pop */
3902 case 0x50 ... 0x57: /* push */
14ce26e7 3903 gen_op_mov_TN_reg[OT_LONG][0][(b & 7) | REX_B(s)]();
2c0262af
FB
3904 gen_push_T0(s);
3905 break;
3906 case 0x58 ... 0x5f: /* pop */
14ce26e7
FB
3907 if (CODE64(s)) {
3908 ot = dflag ? OT_QUAD : OT_WORD;
3909 } else {
3910 ot = dflag + OT_WORD;
3911 }
2c0262af 3912 gen_pop_T0(s);
77729c24 3913 /* NOTE: order is important for pop %sp */
2c0262af 3914 gen_pop_update(s);
14ce26e7 3915 gen_op_mov_reg_T0[ot][(b & 7) | REX_B(s)]();
2c0262af
FB
3916 break;
3917 case 0x60: /* pusha */
14ce26e7
FB
3918 if (CODE64(s))
3919 goto illegal_op;
2c0262af
FB
3920 gen_pusha(s);
3921 break;
3922 case 0x61: /* popa */
14ce26e7
FB
3923 if (CODE64(s))
3924 goto illegal_op;
2c0262af
FB
3925 gen_popa(s);
3926 break;
3927 case 0x68: /* push Iv */
3928 case 0x6a:
14ce26e7
FB
3929 if (CODE64(s)) {
3930 ot = dflag ? OT_QUAD : OT_WORD;
3931 } else {
3932 ot = dflag + OT_WORD;
3933 }
2c0262af
FB
3934 if (b == 0x68)
3935 val = insn_get(s, ot);
3936 else
3937 val = (int8_t)insn_get(s, OT_BYTE);
3938 gen_op_movl_T0_im(val);
3939 gen_push_T0(s);
3940 break;
3941 case 0x8f: /* pop Ev */
14ce26e7
FB
3942 if (CODE64(s)) {
3943 ot = dflag ? OT_QUAD : OT_WORD;
3944 } else {
3945 ot = dflag + OT_WORD;
3946 }
61382a50 3947 modrm = ldub_code(s->pc++);
77729c24 3948 mod = (modrm >> 6) & 3;
2c0262af 3949 gen_pop_T0(s);
77729c24
FB
3950 if (mod == 3) {
3951 /* NOTE: order is important for pop %sp */
3952 gen_pop_update(s);
14ce26e7 3953 rm = (modrm & 7) | REX_B(s);
77729c24
FB
3954 gen_op_mov_reg_T0[ot][rm]();
3955 } else {
3956 /* NOTE: order is important too for MMU exceptions */
14ce26e7 3957 s->popl_esp_hack = 1 << ot;
77729c24
FB
3958 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
3959 s->popl_esp_hack = 0;
3960 gen_pop_update(s);
3961 }
2c0262af
FB
3962 break;
3963 case 0xc8: /* enter */
3964 {
3965 int level;
61382a50 3966 val = lduw_code(s->pc);
2c0262af 3967 s->pc += 2;
61382a50 3968 level = ldub_code(s->pc++);
2c0262af
FB
3969 gen_enter(s, val, level);
3970 }
3971 break;
3972 case 0xc9: /* leave */
3973 /* XXX: exception not precise (ESP is updated before potential exception) */
14ce26e7
FB
3974 if (CODE64(s)) {
3975 gen_op_mov_TN_reg[OT_QUAD][0][R_EBP]();
3976 gen_op_mov_reg_T0[OT_QUAD][R_ESP]();
3977 } else if (s->ss32) {
2c0262af
FB
3978 gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
3979 gen_op_mov_reg_T0[OT_LONG][R_ESP]();
3980 } else {
3981 gen_op_mov_TN_reg[OT_WORD][0][R_EBP]();
3982 gen_op_mov_reg_T0[OT_WORD][R_ESP]();
3983 }
3984 gen_pop_T0(s);
14ce26e7
FB
3985 if (CODE64(s)) {
3986 ot = dflag ? OT_QUAD : OT_WORD;
3987 } else {
3988 ot = dflag + OT_WORD;
3989 }
2c0262af
FB
3990 gen_op_mov_reg_T0[ot][R_EBP]();
3991 gen_pop_update(s);
3992 break;
3993 case 0x06: /* push es */
3994 case 0x0e: /* push cs */
3995 case 0x16: /* push ss */
3996 case 0x1e: /* push ds */
14ce26e7
FB
3997 if (CODE64(s))
3998 goto illegal_op;
2c0262af
FB
3999 gen_op_movl_T0_seg(b >> 3);
4000 gen_push_T0(s);
4001 break;
4002 case 0x1a0: /* push fs */
4003 case 0x1a8: /* push gs */
4004 gen_op_movl_T0_seg((b >> 3) & 7);
4005 gen_push_T0(s);
4006 break;
4007 case 0x07: /* pop es */
4008 case 0x17: /* pop ss */
4009 case 0x1f: /* pop ds */
14ce26e7
FB
4010 if (CODE64(s))
4011 goto illegal_op;
2c0262af
FB
4012 reg = b >> 3;
4013 gen_pop_T0(s);
4014 gen_movl_seg_T0(s, reg, pc_start - s->cs_base);
4015 gen_pop_update(s);
4016 if (reg == R_SS) {
a2cc3b24
FB
4017 /* if reg == SS, inhibit interrupts/trace. */
4018 /* If several instructions disable interrupts, only the
4019 _first_ does it */
4020 if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
4021 gen_op_set_inhibit_irq();
2c0262af
FB
4022 s->tf = 0;
4023 }
4024 if (s->is_jmp) {
14ce26e7 4025 gen_jmp_im(s->pc - s->cs_base);
2c0262af
FB
4026 gen_eob(s);
4027 }
4028 break;
4029 case 0x1a1: /* pop fs */
4030 case 0x1a9: /* pop gs */
4031 gen_pop_T0(s);
4032 gen_movl_seg_T0(s, (b >> 3) & 7, pc_start - s->cs_base);
4033 gen_pop_update(s);
4034 if (s->is_jmp) {
14ce26e7 4035 gen_jmp_im(s->pc - s->cs_base);
2c0262af
FB
4036 gen_eob(s);
4037 }
4038 break;
4039
4040 /**************************/
4041 /* mov */
4042 case 0x88:
4043 case 0x89: /* mov Gv, Ev */
4044 if ((b & 1) == 0)
4045 ot = OT_BYTE;
4046 else
14ce26e7 4047 ot = dflag + OT_WORD;
61382a50 4048 modrm = ldub_code(s->pc++);
14ce26e7 4049 reg = ((modrm >> 3) & 7) | rex_r;
3b46e624 4050
2c0262af 4051 /* generate a generic store */
14ce26e7 4052 gen_ldst_modrm(s, modrm, ot, reg, 1);
2c0262af
FB
4053 break;
4054 case 0xc6:
4055 case 0xc7: /* mov Ev, Iv */
4056 if ((b & 1) == 0)
4057 ot = OT_BYTE;
4058 else
14ce26e7 4059 ot = dflag + OT_WORD;
61382a50 4060 modrm = ldub_code(s->pc++);
2c0262af 4061 mod = (modrm >> 6) & 3;
14ce26e7
FB
4062 if (mod != 3) {
4063 s->rip_offset = insn_const_size(ot);
2c0262af 4064 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
14ce26e7 4065 }
2c0262af
FB
4066 val = insn_get(s, ot);
4067 gen_op_movl_T0_im(val);
4068 if (mod != 3)
4069 gen_op_st_T0_A0[ot + s->mem_index]();
4070 else
14ce26e7 4071 gen_op_mov_reg_T0[ot][(modrm & 7) | REX_B(s)]();
2c0262af
FB
4072 break;
4073 case 0x8a:
4074 case 0x8b: /* mov Ev, Gv */
4075 if ((b & 1) == 0)
4076 ot = OT_BYTE;
4077 else
14ce26e7 4078 ot = OT_WORD + dflag;
61382a50 4079 modrm = ldub_code(s->pc++);
14ce26e7 4080 reg = ((modrm >> 3) & 7) | rex_r;
3b46e624 4081
2c0262af
FB
4082 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
4083 gen_op_mov_reg_T0[ot][reg]();
4084 break;
4085 case 0x8e: /* mov seg, Gv */
61382a50 4086 modrm = ldub_code(s->pc++);
2c0262af
FB
4087 reg = (modrm >> 3) & 7;
4088 if (reg >= 6 || reg == R_CS)
4089 goto illegal_op;
4090 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
4091 gen_movl_seg_T0(s, reg, pc_start - s->cs_base);
4092 if (reg == R_SS) {
4093 /* if reg == SS, inhibit interrupts/trace */
a2cc3b24
FB
4094 /* If several instructions disable interrupts, only the
4095 _first_ does it */
4096 if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
4097 gen_op_set_inhibit_irq();
2c0262af
FB
4098 s->tf = 0;
4099 }
4100 if (s->is_jmp) {
14ce26e7 4101 gen_jmp_im(s->pc - s->cs_base);
2c0262af
FB
4102 gen_eob(s);
4103 }
4104 break;
4105 case 0x8c: /* mov Gv, seg */
61382a50 4106 modrm = ldub_code(s->pc++);
2c0262af
FB
4107 reg = (modrm >> 3) & 7;
4108 mod = (modrm >> 6) & 3;
4109 if (reg >= 6)
4110 goto illegal_op;
4111 gen_op_movl_T0_seg(reg);
14ce26e7
FB
4112 if (mod == 3)
4113 ot = OT_WORD + dflag;
4114 else
4115 ot = OT_WORD;
2c0262af
FB
4116 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
4117 break;
4118
4119 case 0x1b6: /* movzbS Gv, Eb */
4120 case 0x1b7: /* movzwS Gv, Eb */
4121 case 0x1be: /* movsbS Gv, Eb */
4122 case 0x1bf: /* movswS Gv, Eb */
4123 {
4124 int d_ot;
4125 /* d_ot is the size of destination */
4126 d_ot = dflag + OT_WORD;
4127 /* ot is the size of source */
4128 ot = (b & 1) + OT_BYTE;
61382a50 4129 modrm = ldub_code(s->pc++);
14ce26e7 4130 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af 4131 mod = (modrm >> 6) & 3;
14ce26e7 4132 rm = (modrm & 7) | REX_B(s);
3b46e624 4133
2c0262af
FB
4134 if (mod == 3) {
4135 gen_op_mov_TN_reg[ot][0][rm]();
4136 switch(ot | (b & 8)) {
4137 case OT_BYTE:
4138 gen_op_movzbl_T0_T0();
4139 break;
4140 case OT_BYTE | 8:
4141 gen_op_movsbl_T0_T0();
4142 break;
4143 case OT_WORD:
4144 gen_op_movzwl_T0_T0();
4145 break;
4146 default:
4147 case OT_WORD | 8:
4148 gen_op_movswl_T0_T0();
4149 break;
4150 }
4151 gen_op_mov_reg_T0[d_ot][reg]();
4152 } else {
4153 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4154 if (b & 8) {
4155 gen_op_lds_T0_A0[ot + s->mem_index]();
4156 } else {
4157 gen_op_ldu_T0_A0[ot + s->mem_index]();
4158 }
4159 gen_op_mov_reg_T0[d_ot][reg]();
4160 }
4161 }
4162 break;
4163
4164 case 0x8d: /* lea */
14ce26e7 4165 ot = dflag + OT_WORD;
61382a50 4166 modrm = ldub_code(s->pc++);
3a1d9b8b
FB
4167 mod = (modrm >> 6) & 3;
4168 if (mod == 3)
4169 goto illegal_op;
14ce26e7 4170 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af
FB
4171 /* we must ensure that no segment is added */
4172 s->override = -1;
4173 val = s->addseg;
4174 s->addseg = 0;
4175 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4176 s->addseg = val;
4177 gen_op_mov_reg_A0[ot - OT_WORD][reg]();
4178 break;
3b46e624 4179
2c0262af
FB
4180 case 0xa0: /* mov EAX, Ov */
4181 case 0xa1:
4182 case 0xa2: /* mov Ov, EAX */
4183 case 0xa3:
2c0262af 4184 {
14ce26e7
FB
4185 target_ulong offset_addr;
4186
4187 if ((b & 1) == 0)
4188 ot = OT_BYTE;
4189 else
4190 ot = dflag + OT_WORD;
4191#ifdef TARGET_X86_64
8f091a59 4192 if (s->aflag == 2) {
14ce26e7
FB
4193 offset_addr = ldq_code(s->pc);
4194 s->pc += 8;
4195 if (offset_addr == (int32_t)offset_addr)
4196 gen_op_movq_A0_im(offset_addr);
4197 else
4198 gen_op_movq_A0_im64(offset_addr >> 32, offset_addr);
5fafdf24 4199 } else
14ce26e7
FB
4200#endif
4201 {
4202 if (s->aflag) {
4203 offset_addr = insn_get(s, OT_LONG);
4204 } else {
4205 offset_addr = insn_get(s, OT_WORD);
4206 }
4207 gen_op_movl_A0_im(offset_addr);
4208 }
664e0f19 4209 gen_add_A0_ds_seg(s);
14ce26e7
FB
4210 if ((b & 2) == 0) {
4211 gen_op_ld_T0_A0[ot + s->mem_index]();
4212 gen_op_mov_reg_T0[ot][R_EAX]();
4213 } else {
4214 gen_op_mov_TN_reg[ot][0][R_EAX]();
4215 gen_op_st_T0_A0[ot + s->mem_index]();
2c0262af
FB
4216 }
4217 }
2c0262af
FB
4218 break;
4219 case 0xd7: /* xlat */
14ce26e7 4220#ifdef TARGET_X86_64
8f091a59 4221 if (s->aflag == 2) {
14ce26e7
FB
4222 gen_op_movq_A0_reg[R_EBX]();
4223 gen_op_addq_A0_AL();
5fafdf24 4224 } else
14ce26e7
FB
4225#endif
4226 {
4227 gen_op_movl_A0_reg[R_EBX]();
4228 gen_op_addl_A0_AL();
4229 if (s->aflag == 0)
4230 gen_op_andl_A0_ffff();
4231 }
664e0f19 4232 gen_add_A0_ds_seg(s);
2c0262af
FB
4233 gen_op_ldu_T0_A0[OT_BYTE + s->mem_index]();
4234 gen_op_mov_reg_T0[OT_BYTE][R_EAX]();
4235 break;
4236 case 0xb0 ... 0xb7: /* mov R, Ib */
4237 val = insn_get(s, OT_BYTE);
4238 gen_op_movl_T0_im(val);
14ce26e7 4239 gen_op_mov_reg_T0[OT_BYTE][(b & 7) | REX_B(s)]();
2c0262af
FB
4240 break;
4241 case 0xb8 ... 0xbf: /* mov R, Iv */
14ce26e7
FB
4242#ifdef TARGET_X86_64
4243 if (dflag == 2) {
4244 uint64_t tmp;
4245 /* 64 bit case */
4246 tmp = ldq_code(s->pc);
4247 s->pc += 8;
4248 reg = (b & 7) | REX_B(s);
4249 gen_movtl_T0_im(tmp);
4250 gen_op_mov_reg_T0[OT_QUAD][reg]();
5fafdf24 4251 } else
14ce26e7
FB
4252#endif
4253 {
4254 ot = dflag ? OT_LONG : OT_WORD;
4255 val = insn_get(s, ot);
4256 reg = (b & 7) | REX_B(s);
4257 gen_op_movl_T0_im(val);
4258 gen_op_mov_reg_T0[ot][reg]();
4259 }
2c0262af
FB
4260 break;
4261
4262 case 0x91 ... 0x97: /* xchg R, EAX */
14ce26e7
FB
4263 ot = dflag + OT_WORD;
4264 reg = (b & 7) | REX_B(s);
2c0262af
FB
4265 rm = R_EAX;
4266 goto do_xchg_reg;
4267 case 0x86:
4268 case 0x87: /* xchg Ev, Gv */
4269 if ((b & 1) == 0)
4270 ot = OT_BYTE;
4271 else
14ce26e7 4272 ot = dflag + OT_WORD;
61382a50 4273 modrm = ldub_code(s->pc++);
14ce26e7 4274 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af
FB
4275 mod = (modrm >> 6) & 3;
4276 if (mod == 3) {
14ce26e7 4277 rm = (modrm & 7) | REX_B(s);
2c0262af
FB
4278 do_xchg_reg:
4279 gen_op_mov_TN_reg[ot][0][reg]();
4280 gen_op_mov_TN_reg[ot][1][rm]();
4281 gen_op_mov_reg_T0[ot][rm]();
4282 gen_op_mov_reg_T1[ot][reg]();
4283 } else {
4284 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4285 gen_op_mov_TN_reg[ot][0][reg]();
4286 /* for xchg, lock is implicit */
4287 if (!(prefixes & PREFIX_LOCK))
4288 gen_op_lock();
4289 gen_op_ld_T1_A0[ot + s->mem_index]();
4290 gen_op_st_T0_A0[ot + s->mem_index]();
4291 if (!(prefixes & PREFIX_LOCK))
4292 gen_op_unlock();
4293 gen_op_mov_reg_T1[ot][reg]();
4294 }
4295 break;
4296 case 0xc4: /* les Gv */
14ce26e7
FB
4297 if (CODE64(s))
4298 goto illegal_op;
2c0262af
FB
4299 op = R_ES;
4300 goto do_lxx;
4301 case 0xc5: /* lds Gv */
14ce26e7
FB
4302 if (CODE64(s))
4303 goto illegal_op;
2c0262af
FB
4304 op = R_DS;
4305 goto do_lxx;
4306 case 0x1b2: /* lss Gv */
4307 op = R_SS;
4308 goto do_lxx;
4309 case 0x1b4: /* lfs Gv */
4310 op = R_FS;
4311 goto do_lxx;
4312 case 0x1b5: /* lgs Gv */
4313 op = R_GS;
4314 do_lxx:
4315 ot = dflag ? OT_LONG : OT_WORD;
61382a50 4316 modrm = ldub_code(s->pc++);
14ce26e7 4317 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af
FB
4318 mod = (modrm >> 6) & 3;
4319 if (mod == 3)
4320 goto illegal_op;
4321 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4322 gen_op_ld_T1_A0[ot + s->mem_index]();
aba9d61e 4323 gen_add_A0_im(s, 1 << (ot - OT_WORD + 1));
2c0262af 4324 /* load the segment first to handle exceptions properly */
61382a50 4325 gen_op_ldu_T0_A0[OT_WORD + s->mem_index]();
2c0262af
FB
4326 gen_movl_seg_T0(s, op, pc_start - s->cs_base);
4327 /* then put the data */
4328 gen_op_mov_reg_T1[ot][reg]();
4329 if (s->is_jmp) {
14ce26e7 4330 gen_jmp_im(s->pc - s->cs_base);
2c0262af
FB
4331 gen_eob(s);
4332 }
4333 break;
3b46e624 4334
2c0262af
FB
4335 /************************/
4336 /* shifts */
4337 case 0xc0:
4338 case 0xc1:
4339 /* shift Ev,Ib */
4340 shift = 2;
4341 grp2:
4342 {
4343 if ((b & 1) == 0)
4344 ot = OT_BYTE;
4345 else
14ce26e7 4346 ot = dflag + OT_WORD;
3b46e624 4347
61382a50 4348 modrm = ldub_code(s->pc++);
2c0262af 4349 mod = (modrm >> 6) & 3;
2c0262af 4350 op = (modrm >> 3) & 7;
3b46e624 4351
2c0262af 4352 if (mod != 3) {
14ce26e7
FB
4353 if (shift == 2) {
4354 s->rip_offset = 1;
4355 }
2c0262af
FB
4356 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4357 opreg = OR_TMP0;
4358 } else {
14ce26e7 4359 opreg = (modrm & 7) | REX_B(s);
2c0262af
FB
4360 }
4361
4362 /* simpler op */
4363 if (shift == 0) {
4364 gen_shift(s, op, ot, opreg, OR_ECX);
4365 } else {
4366 if (shift == 2) {
61382a50 4367 shift = ldub_code(s->pc++);
2c0262af
FB
4368 }
4369 gen_shifti(s, op, ot, opreg, shift);
4370 }
4371 }
4372 break;
4373 case 0xd0:
4374 case 0xd1:
4375 /* shift Ev,1 */
4376 shift = 1;
4377 goto grp2;
4378 case 0xd2:
4379 case 0xd3:
4380 /* shift Ev,cl */
4381 shift = 0;
4382 goto grp2;
4383
4384 case 0x1a4: /* shld imm */
4385 op = 0;
4386 shift = 1;
4387 goto do_shiftd;
4388 case 0x1a5: /* shld cl */
4389 op = 0;
4390 shift = 0;
4391 goto do_shiftd;
4392 case 0x1ac: /* shrd imm */
4393 op = 1;
4394 shift = 1;
4395 goto do_shiftd;
4396 case 0x1ad: /* shrd cl */
4397 op = 1;
4398 shift = 0;
4399 do_shiftd:
14ce26e7 4400 ot = dflag + OT_WORD;
61382a50 4401 modrm = ldub_code(s->pc++);
2c0262af 4402 mod = (modrm >> 6) & 3;
14ce26e7
FB
4403 rm = (modrm & 7) | REX_B(s);
4404 reg = ((modrm >> 3) & 7) | rex_r;
3b46e624 4405
2c0262af
FB
4406 if (mod != 3) {
4407 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4408 gen_op_ld_T0_A0[ot + s->mem_index]();
4409 } else {
4410 gen_op_mov_TN_reg[ot][0][rm]();
4411 }
4412 gen_op_mov_TN_reg[ot][1][reg]();
3b46e624 4413
2c0262af 4414 if (shift) {
61382a50 4415 val = ldub_code(s->pc++);
14ce26e7
FB
4416 if (ot == OT_QUAD)
4417 val &= 0x3f;
4418 else
4419 val &= 0x1f;
2c0262af
FB
4420 if (val) {
4421 if (mod == 3)
4f31916f 4422 gen_op_shiftd_T0_T1_im_cc[ot][op](val);
2c0262af 4423 else
4f31916f 4424 gen_op_shiftd_mem_T0_T1_im_cc[ot + s->mem_index][op](val);
2c0262af
FB
4425 if (op == 0 && ot != OT_WORD)
4426 s->cc_op = CC_OP_SHLB + ot;
4427 else
4428 s->cc_op = CC_OP_SARB + ot;
4429 }
4430 } else {
4431 if (s->cc_op != CC_OP_DYNAMIC)
4432 gen_op_set_cc_op(s->cc_op);
4433 if (mod == 3)
4f31916f 4434 gen_op_shiftd_T0_T1_ECX_cc[ot][op]();
2c0262af 4435 else
4f31916f 4436 gen_op_shiftd_mem_T0_T1_ECX_cc[ot + s->mem_index][op]();
2c0262af
FB
4437 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
4438 }
4439 if (mod == 3) {
4440 gen_op_mov_reg_T0[ot][rm]();
4441 }
4442 break;
4443
4444 /************************/
4445 /* floats */
5fafdf24 4446 case 0xd8 ... 0xdf:
7eee2a50
FB
4447 if (s->flags & (HF_EM_MASK | HF_TS_MASK)) {
4448 /* if CR0.EM or CR0.TS are set, generate an FPU exception */
4449 /* XXX: what to do if illegal op ? */
4450 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
4451 break;
4452 }
61382a50 4453 modrm = ldub_code(s->pc++);
2c0262af
FB
4454 mod = (modrm >> 6) & 3;
4455 rm = modrm & 7;
4456 op = ((b & 7) << 3) | ((modrm >> 3) & 7);
2c0262af
FB
4457 if (mod != 3) {
4458 /* memory op */
4459 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4460 switch(op) {
4461 case 0x00 ... 0x07: /* fxxxs */
4462 case 0x10 ... 0x17: /* fixxxl */
4463 case 0x20 ... 0x27: /* fxxxl */
4464 case 0x30 ... 0x37: /* fixxx */
4465 {
4466 int op1;
4467 op1 = op & 7;
4468
4469 switch(op >> 4) {
4470 case 0:
4471 gen_op_flds_FT0_A0();
4472 break;
4473 case 1:
4474 gen_op_fildl_FT0_A0();
4475 break;
4476 case 2:
4477 gen_op_fldl_FT0_A0();
4478 break;
4479 case 3:
4480 default:
4481 gen_op_fild_FT0_A0();
4482 break;
4483 }
3b46e624 4484
2c0262af
FB
4485 gen_op_fp_arith_ST0_FT0[op1]();
4486 if (op1 == 3) {
4487 /* fcomp needs pop */
4488 gen_op_fpop();
4489 }
4490 }
4491 break;
4492 case 0x08: /* flds */
4493 case 0x0a: /* fsts */
4494 case 0x0b: /* fstps */
465e9838
FB
4495 case 0x18 ... 0x1b: /* fildl, fisttpl, fistl, fistpl */
4496 case 0x28 ... 0x2b: /* fldl, fisttpll, fstl, fstpl */
4497 case 0x38 ... 0x3b: /* filds, fisttps, fists, fistps */
2c0262af
FB
4498 switch(op & 7) {
4499 case 0:
4500 switch(op >> 4) {
4501 case 0:
4502 gen_op_flds_ST0_A0();
4503 break;
4504 case 1:
4505 gen_op_fildl_ST0_A0();
4506 break;
4507 case 2:
4508 gen_op_fldl_ST0_A0();
4509 break;
4510 case 3:
4511 default:
4512 gen_op_fild_ST0_A0();
4513 break;
4514 }
4515 break;
465e9838
FB
4516 case 1:
4517 switch(op >> 4) {
4518 case 1:
4519 gen_op_fisttl_ST0_A0();
4520 break;
4521 case 2:
4522 gen_op_fisttll_ST0_A0();
4523 break;
4524 case 3:
4525 default:
4526 gen_op_fistt_ST0_A0();
4527 }
4528 gen_op_fpop();
4529 break;
2c0262af
FB
4530 default:
4531 switch(op >> 4) {
4532 case 0:
4533 gen_op_fsts_ST0_A0();
4534 break;
4535 case 1:
4536 gen_op_fistl_ST0_A0();
4537 break;
4538 case 2:
4539 gen_op_fstl_ST0_A0();
4540 break;
4541 case 3:
4542 default:
4543 gen_op_fist_ST0_A0();
4544 break;
4545 }
4546 if ((op & 7) == 3)
4547 gen_op_fpop();
4548 break;
4549 }
4550 break;
4551 case 0x0c: /* fldenv mem */
4552 gen_op_fldenv_A0(s->dflag);
4553 break;
4554 case 0x0d: /* fldcw mem */
4555 gen_op_fldcw_A0();
4556 break;
4557 case 0x0e: /* fnstenv mem */
4558 gen_op_fnstenv_A0(s->dflag);
4559 break;
4560 case 0x0f: /* fnstcw mem */
4561 gen_op_fnstcw_A0();
4562 break;
4563 case 0x1d: /* fldt mem */
4564 gen_op_fldt_ST0_A0();
4565 break;
4566 case 0x1f: /* fstpt mem */
4567 gen_op_fstt_ST0_A0();
4568 gen_op_fpop();
4569 break;
4570 case 0x2c: /* frstor mem */
4571 gen_op_frstor_A0(s->dflag);
4572 break;
4573 case 0x2e: /* fnsave mem */
4574 gen_op_fnsave_A0(s->dflag);
4575 break;
4576 case 0x2f: /* fnstsw mem */
4577 gen_op_fnstsw_A0();
4578 break;
4579 case 0x3c: /* fbld */
4580 gen_op_fbld_ST0_A0();
4581 break;
4582 case 0x3e: /* fbstp */
4583 gen_op_fbst_ST0_A0();
4584 gen_op_fpop();
4585 break;
4586 case 0x3d: /* fildll */
4587 gen_op_fildll_ST0_A0();
4588 break;
4589 case 0x3f: /* fistpll */
4590 gen_op_fistll_ST0_A0();
4591 gen_op_fpop();
4592 break;
4593 default:
4594 goto illegal_op;
4595 }
4596 } else {
4597 /* register float ops */
4598 opreg = rm;
4599
4600 switch(op) {
4601 case 0x08: /* fld sti */
4602 gen_op_fpush();
4603 gen_op_fmov_ST0_STN((opreg + 1) & 7);
4604 break;
4605 case 0x09: /* fxchg sti */
c169c906
FB
4606 case 0x29: /* fxchg4 sti, undocumented op */
4607 case 0x39: /* fxchg7 sti, undocumented op */
2c0262af
FB
4608 gen_op_fxchg_ST0_STN(opreg);
4609 break;
4610 case 0x0a: /* grp d9/2 */
4611 switch(rm) {
4612 case 0: /* fnop */
023fe10d
FB
4613 /* check exceptions (FreeBSD FPU probe) */
4614 if (s->cc_op != CC_OP_DYNAMIC)
4615 gen_op_set_cc_op(s->cc_op);
14ce26e7 4616 gen_jmp_im(pc_start - s->cs_base);
023fe10d 4617 gen_op_fwait();
2c0262af
FB
4618 break;
4619 default:
4620 goto illegal_op;
4621 }
4622 break;
4623 case 0x0c: /* grp d9/4 */
4624 switch(rm) {
4625 case 0: /* fchs */
4626 gen_op_fchs_ST0();
4627 break;
4628 case 1: /* fabs */
4629 gen_op_fabs_ST0();
4630 break;
4631 case 4: /* ftst */
4632 gen_op_fldz_FT0();
4633 gen_op_fcom_ST0_FT0();
4634 break;
4635 case 5: /* fxam */
4636 gen_op_fxam_ST0();
4637 break;
4638 default:
4639 goto illegal_op;
4640 }
4641 break;
4642 case 0x0d: /* grp d9/5 */
4643 {
4644 switch(rm) {
4645 case 0:
4646 gen_op_fpush();
4647 gen_op_fld1_ST0();
4648 break;
4649 case 1:
4650 gen_op_fpush();
4651 gen_op_fldl2t_ST0();
4652 break;
4653 case 2:
4654 gen_op_fpush();
4655 gen_op_fldl2e_ST0();
4656 break;
4657 case 3:
4658 gen_op_fpush();
4659 gen_op_fldpi_ST0();
4660 break;
4661 case 4:
4662 gen_op_fpush();
4663 gen_op_fldlg2_ST0();
4664 break;
4665 case 5:
4666 gen_op_fpush();
4667 gen_op_fldln2_ST0();
4668 break;
4669 case 6:
4670 gen_op_fpush();
4671 gen_op_fldz_ST0();
4672 break;
4673 default:
4674 goto illegal_op;
4675 }
4676 }
4677 break;
4678 case 0x0e: /* grp d9/6 */
4679 switch(rm) {
4680 case 0: /* f2xm1 */
4681 gen_op_f2xm1();
4682 break;
4683 case 1: /* fyl2x */
4684 gen_op_fyl2x();
4685 break;
4686 case 2: /* fptan */
4687 gen_op_fptan();
4688 break;
4689 case 3: /* fpatan */
4690 gen_op_fpatan();
4691 break;
4692 case 4: /* fxtract */
4693 gen_op_fxtract();
4694 break;
4695 case 5: /* fprem1 */
4696 gen_op_fprem1();
4697 break;
4698 case 6: /* fdecstp */
4699 gen_op_fdecstp();
4700 break;
4701 default:
4702 case 7: /* fincstp */
4703 gen_op_fincstp();
4704 break;
4705 }
4706 break;
4707 case 0x0f: /* grp d9/7 */
4708 switch(rm) {
4709 case 0: /* fprem */
4710 gen_op_fprem();
4711 break;
4712 case 1: /* fyl2xp1 */
4713 gen_op_fyl2xp1();
4714 break;
4715 case 2: /* fsqrt */
4716 gen_op_fsqrt();
4717 break;
4718 case 3: /* fsincos */
4719 gen_op_fsincos();
4720 break;
4721 case 5: /* fscale */
4722 gen_op_fscale();
4723 break;
4724 case 4: /* frndint */
4725 gen_op_frndint();
4726 break;
4727 case 6: /* fsin */
4728 gen_op_fsin();
4729 break;
4730 default:
4731 case 7: /* fcos */
4732 gen_op_fcos();
4733 break;
4734 }
4735 break;
4736 case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
4737 case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
4738 case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
4739 {
4740 int op1;
3b46e624 4741
2c0262af
FB
4742 op1 = op & 7;
4743 if (op >= 0x20) {
4744 gen_op_fp_arith_STN_ST0[op1](opreg);
4745 if (op >= 0x30)
4746 gen_op_fpop();
4747 } else {
4748 gen_op_fmov_FT0_STN(opreg);
4749 gen_op_fp_arith_ST0_FT0[op1]();
4750 }
4751 }
4752 break;
4753 case 0x02: /* fcom */
c169c906 4754 case 0x22: /* fcom2, undocumented op */
2c0262af
FB
4755 gen_op_fmov_FT0_STN(opreg);
4756 gen_op_fcom_ST0_FT0();
4757 break;
4758 case 0x03: /* fcomp */
c169c906
FB
4759 case 0x23: /* fcomp3, undocumented op */
4760 case 0x32: /* fcomp5, undocumented op */
2c0262af
FB
4761 gen_op_fmov_FT0_STN(opreg);
4762 gen_op_fcom_ST0_FT0();
4763 gen_op_fpop();
4764 break;
4765 case 0x15: /* da/5 */
4766 switch(rm) {
4767 case 1: /* fucompp */
4768 gen_op_fmov_FT0_STN(1);
4769 gen_op_fucom_ST0_FT0();
4770 gen_op_fpop();
4771 gen_op_fpop();
4772 break;
4773 default:
4774 goto illegal_op;
4775 }
4776 break;
4777 case 0x1c:
4778 switch(rm) {
4779 case 0: /* feni (287 only, just do nop here) */
4780 break;
4781 case 1: /* fdisi (287 only, just do nop here) */
4782 break;
4783 case 2: /* fclex */
4784 gen_op_fclex();
4785 break;
4786 case 3: /* fninit */
4787 gen_op_fninit();
4788 break;
4789 case 4: /* fsetpm (287 only, just do nop here) */
4790 break;
4791 default:
4792 goto illegal_op;
4793 }
4794 break;
4795 case 0x1d: /* fucomi */
4796 if (s->cc_op != CC_OP_DYNAMIC)
4797 gen_op_set_cc_op(s->cc_op);
4798 gen_op_fmov_FT0_STN(opreg);
4799 gen_op_fucomi_ST0_FT0();
4800 s->cc_op = CC_OP_EFLAGS;
4801 break;
4802 case 0x1e: /* fcomi */
4803 if (s->cc_op != CC_OP_DYNAMIC)
4804 gen_op_set_cc_op(s->cc_op);
4805 gen_op_fmov_FT0_STN(opreg);
4806 gen_op_fcomi_ST0_FT0();
4807 s->cc_op = CC_OP_EFLAGS;
4808 break;
658c8bda
FB
4809 case 0x28: /* ffree sti */
4810 gen_op_ffree_STN(opreg);
5fafdf24 4811 break;
2c0262af
FB
4812 case 0x2a: /* fst sti */
4813 gen_op_fmov_STN_ST0(opreg);
4814 break;
4815 case 0x2b: /* fstp sti */
c169c906
FB
4816 case 0x0b: /* fstp1 sti, undocumented op */
4817 case 0x3a: /* fstp8 sti, undocumented op */
4818 case 0x3b: /* fstp9 sti, undocumented op */
2c0262af
FB
4819 gen_op_fmov_STN_ST0(opreg);
4820 gen_op_fpop();
4821 break;
4822 case 0x2c: /* fucom st(i) */
4823 gen_op_fmov_FT0_STN(opreg);
4824 gen_op_fucom_ST0_FT0();
4825 break;
4826 case 0x2d: /* fucomp st(i) */
4827 gen_op_fmov_FT0_STN(opreg);
4828 gen_op_fucom_ST0_FT0();
4829 gen_op_fpop();
4830 break;
4831 case 0x33: /* de/3 */
4832 switch(rm) {
4833 case 1: /* fcompp */
4834 gen_op_fmov_FT0_STN(1);
4835 gen_op_fcom_ST0_FT0();
4836 gen_op_fpop();
4837 gen_op_fpop();
4838 break;
4839 default:
4840 goto illegal_op;
4841 }
4842 break;
c169c906
FB
4843 case 0x38: /* ffreep sti, undocumented op */
4844 gen_op_ffree_STN(opreg);
4845 gen_op_fpop();
4846 break;
2c0262af
FB
4847 case 0x3c: /* df/4 */
4848 switch(rm) {
4849 case 0:
4850 gen_op_fnstsw_EAX();
4851 break;
4852 default:
4853 goto illegal_op;
4854 }
4855 break;
4856 case 0x3d: /* fucomip */
4857 if (s->cc_op != CC_OP_DYNAMIC)
4858 gen_op_set_cc_op(s->cc_op);
4859 gen_op_fmov_FT0_STN(opreg);
4860 gen_op_fucomi_ST0_FT0();
4861 gen_op_fpop();
4862 s->cc_op = CC_OP_EFLAGS;
4863 break;
4864 case 0x3e: /* fcomip */
4865 if (s->cc_op != CC_OP_DYNAMIC)
4866 gen_op_set_cc_op(s->cc_op);
4867 gen_op_fmov_FT0_STN(opreg);
4868 gen_op_fcomi_ST0_FT0();
4869 gen_op_fpop();
4870 s->cc_op = CC_OP_EFLAGS;
4871 break;
a2cc3b24
FB
4872 case 0x10 ... 0x13: /* fcmovxx */
4873 case 0x18 ... 0x1b:
4874 {
4875 int op1;
4876 const static uint8_t fcmov_cc[8] = {
4877 (JCC_B << 1),
4878 (JCC_Z << 1),
4879 (JCC_BE << 1),
4880 (JCC_P << 1),
4881 };
4882 op1 = fcmov_cc[op & 3] | ((op >> 3) & 1);
4883 gen_setcc(s, op1);
4884 gen_op_fcmov_ST0_STN_T0(opreg);
4885 }
4886 break;
2c0262af
FB
4887 default:
4888 goto illegal_op;
4889 }
4890 }
4891 break;
4892 /************************/
4893 /* string ops */
4894
4895 case 0xa4: /* movsS */
4896 case 0xa5:
4897 if ((b & 1) == 0)
4898 ot = OT_BYTE;
4899 else
14ce26e7 4900 ot = dflag + OT_WORD;
2c0262af
FB
4901
4902 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
4903 gen_repz_movs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
4904 } else {
4905 gen_movs(s, ot);
4906 }
4907 break;
3b46e624 4908
2c0262af
FB
4909 case 0xaa: /* stosS */
4910 case 0xab:
4911 if ((b & 1) == 0)
4912 ot = OT_BYTE;
4913 else
14ce26e7 4914 ot = dflag + OT_WORD;
2c0262af
FB
4915
4916 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
4917 gen_repz_stos(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
4918 } else {
4919 gen_stos(s, ot);
4920 }
4921 break;
4922 case 0xac: /* lodsS */
4923 case 0xad:
4924 if ((b & 1) == 0)
4925 ot = OT_BYTE;
4926 else
14ce26e7 4927 ot = dflag + OT_WORD;
2c0262af
FB
4928 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
4929 gen_repz_lods(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
4930 } else {
4931 gen_lods(s, ot);
4932 }
4933 break;
4934 case 0xae: /* scasS */
4935 case 0xaf:
4936 if ((b & 1) == 0)
4937 ot = OT_BYTE;
4938 else
14ce26e7 4939 ot = dflag + OT_WORD;
2c0262af
FB
4940 if (prefixes & PREFIX_REPNZ) {
4941 gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
4942 } else if (prefixes & PREFIX_REPZ) {
4943 gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
4944 } else {
4945 gen_scas(s, ot);
4946 s->cc_op = CC_OP_SUBB + ot;
4947 }
4948 break;
4949
4950 case 0xa6: /* cmpsS */
4951 case 0xa7:
4952 if ((b & 1) == 0)
4953 ot = OT_BYTE;
4954 else
14ce26e7 4955 ot = dflag + OT_WORD;
2c0262af
FB
4956 if (prefixes & PREFIX_REPNZ) {
4957 gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
4958 } else if (prefixes & PREFIX_REPZ) {
4959 gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
4960 } else {
4961 gen_cmps(s, ot);
4962 s->cc_op = CC_OP_SUBB + ot;
4963 }
4964 break;
4965 case 0x6c: /* insS */
4966 case 0x6d:
f115e911
FB
4967 if ((b & 1) == 0)
4968 ot = OT_BYTE;
4969 else
4970 ot = dflag ? OT_LONG : OT_WORD;
4971 gen_check_io(s, ot, 1, pc_start - s->cs_base);
0573fbfc
TS
4972 gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
4973 gen_op_andl_T0_ffff();
4974 if (gen_svm_check_io(s, pc_start,
4975 SVM_IOIO_TYPE_MASK | (1 << (4+ot)) |
4976 svm_is_rep(prefixes) | 4 | (1 << (7+s->aflag))))
4977 break;
f115e911
FB
4978 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
4979 gen_repz_ins(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
2c0262af 4980 } else {
f115e911 4981 gen_ins(s, ot);
2c0262af
FB
4982 }
4983 break;
4984 case 0x6e: /* outsS */
4985 case 0x6f:
f115e911
FB
4986 if ((b & 1) == 0)
4987 ot = OT_BYTE;
4988 else
4989 ot = dflag ? OT_LONG : OT_WORD;
4990 gen_check_io(s, ot, 1, pc_start - s->cs_base);
0573fbfc
TS
4991 gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
4992 gen_op_andl_T0_ffff();
4993 if (gen_svm_check_io(s, pc_start,
4994 (1 << (4+ot)) | svm_is_rep(prefixes) |
4995 4 | (1 << (7+s->aflag))))
4996 break;
f115e911
FB
4997 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
4998 gen_repz_outs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
2c0262af 4999 } else {
f115e911 5000 gen_outs(s, ot);
2c0262af
FB
5001 }
5002 break;
5003
5004 /************************/
5005 /* port I/O */
0573fbfc 5006
2c0262af
FB
5007 case 0xe4:
5008 case 0xe5:
f115e911
FB
5009 if ((b & 1) == 0)
5010 ot = OT_BYTE;
5011 else
5012 ot = dflag ? OT_LONG : OT_WORD;
5013 val = ldub_code(s->pc++);
5014 gen_op_movl_T0_im(val);
5015 gen_check_io(s, ot, 0, pc_start - s->cs_base);
0573fbfc
TS
5016 if (gen_svm_check_io(s, pc_start,
5017 SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes) |
5018 (1 << (4+ot))))
5019 break;
f115e911
FB
5020 gen_op_in[ot]();
5021 gen_op_mov_reg_T1[ot][R_EAX]();
2c0262af
FB
5022 break;
5023 case 0xe6:
5024 case 0xe7:
f115e911
FB
5025 if ((b & 1) == 0)
5026 ot = OT_BYTE;
5027 else
5028 ot = dflag ? OT_LONG : OT_WORD;
5029 val = ldub_code(s->pc++);
5030 gen_op_movl_T0_im(val);
5031 gen_check_io(s, ot, 0, pc_start - s->cs_base);
0573fbfc
TS
5032 if (gen_svm_check_io(s, pc_start, svm_is_rep(prefixes) |
5033 (1 << (4+ot))))
5034 break;
f115e911
FB
5035 gen_op_mov_TN_reg[ot][1][R_EAX]();
5036 gen_op_out[ot]();
2c0262af
FB
5037 break;
5038 case 0xec:
5039 case 0xed:
f115e911
FB
5040 if ((b & 1) == 0)
5041 ot = OT_BYTE;
5042 else
5043 ot = dflag ? OT_LONG : OT_WORD;
5044 gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
4f31916f 5045 gen_op_andl_T0_ffff();
f115e911 5046 gen_check_io(s, ot, 0, pc_start - s->cs_base);
0573fbfc
TS
5047 if (gen_svm_check_io(s, pc_start,
5048 SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes) |
5049 (1 << (4+ot))))
5050 break;
f115e911
FB
5051 gen_op_in[ot]();
5052 gen_op_mov_reg_T1[ot][R_EAX]();
2c0262af
FB
5053 break;
5054 case 0xee:
5055 case 0xef:
f115e911
FB
5056 if ((b & 1) == 0)
5057 ot = OT_BYTE;
5058 else
5059 ot = dflag ? OT_LONG : OT_WORD;
5060 gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
4f31916f 5061 gen_op_andl_T0_ffff();
f115e911 5062 gen_check_io(s, ot, 0, pc_start - s->cs_base);
0573fbfc
TS
5063 if (gen_svm_check_io(s, pc_start,
5064 svm_is_rep(prefixes) | (1 << (4+ot))))
5065 break;
f115e911
FB
5066 gen_op_mov_TN_reg[ot][1][R_EAX]();
5067 gen_op_out[ot]();
2c0262af
FB
5068 break;
5069
5070 /************************/
5071 /* control */
5072 case 0xc2: /* ret im */
61382a50 5073 val = ldsw_code(s->pc);
2c0262af
FB
5074 s->pc += 2;
5075 gen_pop_T0(s);
8f091a59
FB
5076 if (CODE64(s) && s->dflag)
5077 s->dflag = 2;
2c0262af
FB
5078 gen_stack_update(s, val + (2 << s->dflag));
5079 if (s->dflag == 0)
5080 gen_op_andl_T0_ffff();
5081 gen_op_jmp_T0();
5082 gen_eob(s);
5083 break;
5084 case 0xc3: /* ret */
5085 gen_pop_T0(s);
5086 gen_pop_update(s);
5087 if (s->dflag == 0)
5088 gen_op_andl_T0_ffff();
5089 gen_op_jmp_T0();
5090 gen_eob(s);
5091 break;
5092 case 0xca: /* lret im */
61382a50 5093 val = ldsw_code(s->pc);
2c0262af
FB
5094 s->pc += 2;
5095 do_lret:
5096 if (s->pe && !s->vm86) {
5097 if (s->cc_op != CC_OP_DYNAMIC)
5098 gen_op_set_cc_op(s->cc_op);
14ce26e7 5099 gen_jmp_im(pc_start - s->cs_base);
2c0262af
FB
5100 gen_op_lret_protected(s->dflag, val);
5101 } else {
5102 gen_stack_A0(s);
5103 /* pop offset */
5104 gen_op_ld_T0_A0[1 + s->dflag + s->mem_index]();
5105 if (s->dflag == 0)
5106 gen_op_andl_T0_ffff();
5107 /* NOTE: keeping EIP updated is not a problem in case of
5108 exception */
5109 gen_op_jmp_T0();
5110 /* pop selector */
5111 gen_op_addl_A0_im(2 << s->dflag);
5112 gen_op_ld_T0_A0[1 + s->dflag + s->mem_index]();
5113 gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[R_CS]));
5114 /* add stack offset */
5115 gen_stack_update(s, val + (4 << s->dflag));
5116 }
5117 gen_eob(s);
5118 break;
5119 case 0xcb: /* lret */
5120 val = 0;
5121 goto do_lret;
5122 case 0xcf: /* iret */
0573fbfc
TS
5123 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_IRET))
5124 break;
2c0262af
FB
5125 if (!s->pe) {
5126 /* real mode */
5127 gen_op_iret_real(s->dflag);
5128 s->cc_op = CC_OP_EFLAGS;
f115e911
FB
5129 } else if (s->vm86) {
5130 if (s->iopl != 3) {
5131 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5132 } else {
5133 gen_op_iret_real(s->dflag);
5134 s->cc_op = CC_OP_EFLAGS;
5135 }
2c0262af
FB
5136 } else {
5137 if (s->cc_op != CC_OP_DYNAMIC)
5138 gen_op_set_cc_op(s->cc_op);
14ce26e7 5139 gen_jmp_im(pc_start - s->cs_base);
08cea4ee 5140 gen_op_iret_protected(s->dflag, s->pc - s->cs_base);
2c0262af
FB
5141 s->cc_op = CC_OP_EFLAGS;
5142 }
5143 gen_eob(s);
5144 break;
5145 case 0xe8: /* call im */
5146 {
14ce26e7
FB
5147 if (dflag)
5148 tval = (int32_t)insn_get(s, OT_LONG);
5149 else
5150 tval = (int16_t)insn_get(s, OT_WORD);
2c0262af 5151 next_eip = s->pc - s->cs_base;
14ce26e7 5152 tval += next_eip;
2c0262af 5153 if (s->dflag == 0)
14ce26e7
FB
5154 tval &= 0xffff;
5155 gen_movtl_T0_im(next_eip);
2c0262af 5156 gen_push_T0(s);
14ce26e7 5157 gen_jmp(s, tval);
2c0262af
FB
5158 }
5159 break;
5160 case 0x9a: /* lcall im */
5161 {
5162 unsigned int selector, offset;
3b46e624 5163
14ce26e7
FB
5164 if (CODE64(s))
5165 goto illegal_op;
2c0262af
FB
5166 ot = dflag ? OT_LONG : OT_WORD;
5167 offset = insn_get(s, ot);
5168 selector = insn_get(s, OT_WORD);
3b46e624 5169
2c0262af 5170 gen_op_movl_T0_im(selector);
14ce26e7 5171 gen_op_movl_T1_imu(offset);
2c0262af
FB
5172 }
5173 goto do_lcall;
ecada8a2 5174 case 0xe9: /* jmp im */
14ce26e7
FB
5175 if (dflag)
5176 tval = (int32_t)insn_get(s, OT_LONG);
5177 else
5178 tval = (int16_t)insn_get(s, OT_WORD);
5179 tval += s->pc - s->cs_base;
2c0262af 5180 if (s->dflag == 0)
14ce26e7
FB
5181 tval &= 0xffff;
5182 gen_jmp(s, tval);
2c0262af
FB
5183 break;
5184 case 0xea: /* ljmp im */
5185 {
5186 unsigned int selector, offset;
5187
14ce26e7
FB
5188 if (CODE64(s))
5189 goto illegal_op;
2c0262af
FB
5190 ot = dflag ? OT_LONG : OT_WORD;
5191 offset = insn_get(s, ot);
5192 selector = insn_get(s, OT_WORD);
3b46e624 5193
2c0262af 5194 gen_op_movl_T0_im(selector);
14ce26e7 5195 gen_op_movl_T1_imu(offset);
2c0262af
FB
5196 }
5197 goto do_ljmp;
5198 case 0xeb: /* jmp Jb */
14ce26e7
FB
5199 tval = (int8_t)insn_get(s, OT_BYTE);
5200 tval += s->pc - s->cs_base;
2c0262af 5201 if (s->dflag == 0)
14ce26e7
FB
5202 tval &= 0xffff;
5203 gen_jmp(s, tval);
2c0262af
FB
5204 break;
5205 case 0x70 ... 0x7f: /* jcc Jb */
14ce26e7 5206 tval = (int8_t)insn_get(s, OT_BYTE);
2c0262af
FB
5207 goto do_jcc;
5208 case 0x180 ... 0x18f: /* jcc Jv */
5209 if (dflag) {
14ce26e7 5210 tval = (int32_t)insn_get(s, OT_LONG);
2c0262af 5211 } else {
5fafdf24 5212 tval = (int16_t)insn_get(s, OT_WORD);
2c0262af
FB
5213 }
5214 do_jcc:
5215 next_eip = s->pc - s->cs_base;
14ce26e7 5216 tval += next_eip;
2c0262af 5217 if (s->dflag == 0)
14ce26e7
FB
5218 tval &= 0xffff;
5219 gen_jcc(s, b, tval, next_eip);
2c0262af
FB
5220 break;
5221
5222 case 0x190 ... 0x19f: /* setcc Gv */
61382a50 5223 modrm = ldub_code(s->pc++);
2c0262af
FB
5224 gen_setcc(s, b);
5225 gen_ldst_modrm(s, modrm, OT_BYTE, OR_TMP0, 1);
5226 break;
5227 case 0x140 ... 0x14f: /* cmov Gv, Ev */
14ce26e7 5228 ot = dflag + OT_WORD;
61382a50 5229 modrm = ldub_code(s->pc++);
14ce26e7 5230 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af
FB
5231 mod = (modrm >> 6) & 3;
5232 gen_setcc(s, b);
5233 if (mod != 3) {
5234 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
5235 gen_op_ld_T1_A0[ot + s->mem_index]();
5236 } else {
14ce26e7 5237 rm = (modrm & 7) | REX_B(s);
2c0262af
FB
5238 gen_op_mov_TN_reg[ot][1][rm]();
5239 }
5240 gen_op_cmov_reg_T1_T0[ot - OT_WORD][reg]();
5241 break;
3b46e624 5242
2c0262af
FB
5243 /************************/
5244 /* flags */
5245 case 0x9c: /* pushf */
0573fbfc
TS
5246 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_PUSHF))
5247 break;
2c0262af
FB
5248 if (s->vm86 && s->iopl != 3) {
5249 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5250 } else {
5251 if (s->cc_op != CC_OP_DYNAMIC)
5252 gen_op_set_cc_op(s->cc_op);
5253 gen_op_movl_T0_eflags();
5254 gen_push_T0(s);
5255 }
5256 break;
5257 case 0x9d: /* popf */
0573fbfc
TS
5258 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_POPF))
5259 break;
2c0262af
FB
5260 if (s->vm86 && s->iopl != 3) {
5261 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5262 } else {
5263 gen_pop_T0(s);
5264 if (s->cpl == 0) {
5265 if (s->dflag) {
5266 gen_op_movl_eflags_T0_cpl0();
5267 } else {
5268 gen_op_movw_eflags_T0_cpl0();
5269 }
5270 } else {
4136f33c
FB
5271 if (s->cpl <= s->iopl) {
5272 if (s->dflag) {
5273 gen_op_movl_eflags_T0_io();
5274 } else {
5275 gen_op_movw_eflags_T0_io();
5276 }
2c0262af 5277 } else {
4136f33c
FB
5278 if (s->dflag) {
5279 gen_op_movl_eflags_T0();
5280 } else {
5281 gen_op_movw_eflags_T0();
5282 }
2c0262af
FB
5283 }
5284 }
5285 gen_pop_update(s);
5286 s->cc_op = CC_OP_EFLAGS;
5287 /* abort translation because TF flag may change */
14ce26e7 5288 gen_jmp_im(s->pc - s->cs_base);
2c0262af
FB
5289 gen_eob(s);
5290 }
5291 break;
5292 case 0x9e: /* sahf */
14ce26e7
FB
5293 if (CODE64(s))
5294 goto illegal_op;
2c0262af
FB
5295 gen_op_mov_TN_reg[OT_BYTE][0][R_AH]();
5296 if (s->cc_op != CC_OP_DYNAMIC)
5297 gen_op_set_cc_op(s->cc_op);
5298 gen_op_movb_eflags_T0();
5299 s->cc_op = CC_OP_EFLAGS;
5300 break;
5301 case 0x9f: /* lahf */
14ce26e7
FB
5302 if (CODE64(s))
5303 goto illegal_op;
2c0262af
FB
5304 if (s->cc_op != CC_OP_DYNAMIC)
5305 gen_op_set_cc_op(s->cc_op);
5306 gen_op_movl_T0_eflags();
5307 gen_op_mov_reg_T0[OT_BYTE][R_AH]();
5308 break;
5309 case 0xf5: /* cmc */
5310 if (s->cc_op != CC_OP_DYNAMIC)
5311 gen_op_set_cc_op(s->cc_op);
5312 gen_op_cmc();
5313 s->cc_op = CC_OP_EFLAGS;
5314 break;
5315 case 0xf8: /* clc */
5316 if (s->cc_op != CC_OP_DYNAMIC)
5317 gen_op_set_cc_op(s->cc_op);
5318 gen_op_clc();
5319 s->cc_op = CC_OP_EFLAGS;
5320 break;
5321 case 0xf9: /* stc */
5322 if (s->cc_op != CC_OP_DYNAMIC)
5323 gen_op_set_cc_op(s->cc_op);
5324 gen_op_stc();
5325 s->cc_op = CC_OP_EFLAGS;
5326 break;
5327 case 0xfc: /* cld */
5328 gen_op_cld();
5329 break;
5330 case 0xfd: /* std */
5331 gen_op_std();
5332 break;
5333
5334 /************************/
5335 /* bit operations */
5336 case 0x1ba: /* bt/bts/btr/btc Gv, im */
14ce26e7 5337 ot = dflag + OT_WORD;
61382a50 5338 modrm = ldub_code(s->pc++);
33698e5f 5339 op = (modrm >> 3) & 7;
2c0262af 5340 mod = (modrm >> 6) & 3;
14ce26e7 5341 rm = (modrm & 7) | REX_B(s);
2c0262af 5342 if (mod != 3) {
14ce26e7 5343 s->rip_offset = 1;
2c0262af
FB
5344 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
5345 gen_op_ld_T0_A0[ot + s->mem_index]();
5346 } else {
5347 gen_op_mov_TN_reg[ot][0][rm]();
5348 }
5349 /* load shift */
61382a50 5350 val = ldub_code(s->pc++);
2c0262af
FB
5351 gen_op_movl_T1_im(val);
5352 if (op < 4)
5353 goto illegal_op;
5354 op -= 4;
5355 gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
5356 s->cc_op = CC_OP_SARB + ot;
5357 if (op != 0) {
5358 if (mod != 3)
5359 gen_op_st_T0_A0[ot + s->mem_index]();
5360 else
5361 gen_op_mov_reg_T0[ot][rm]();
5362 gen_op_update_bt_cc();
5363 }
5364 break;
5365 case 0x1a3: /* bt Gv, Ev */
5366 op = 0;
5367 goto do_btx;
5368 case 0x1ab: /* bts */
5369 op = 1;
5370 goto do_btx;
5371 case 0x1b3: /* btr */
5372 op = 2;
5373 goto do_btx;
5374 case 0x1bb: /* btc */
5375 op = 3;
5376 do_btx:
14ce26e7 5377 ot = dflag + OT_WORD;
61382a50 5378 modrm = ldub_code(s->pc++);
14ce26e7 5379 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af 5380 mod = (modrm >> 6) & 3;
14ce26e7 5381 rm = (modrm & 7) | REX_B(s);
2c0262af
FB
5382 gen_op_mov_TN_reg[OT_LONG][1][reg]();
5383 if (mod != 3) {
5384 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
5385 /* specific case: we need to add a displacement */
14ce26e7 5386 gen_op_add_bit_A0_T1[ot - OT_WORD]();
2c0262af
FB
5387 gen_op_ld_T0_A0[ot + s->mem_index]();
5388 } else {
5389 gen_op_mov_TN_reg[ot][0][rm]();
5390 }
5391 gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
5392 s->cc_op = CC_OP_SARB + ot;
5393 if (op != 0) {
5394 if (mod != 3)
5395 gen_op_st_T0_A0[ot + s->mem_index]();
5396 else
5397 gen_op_mov_reg_T0[ot][rm]();
5398 gen_op_update_bt_cc();
5399 }
5400 break;
5401 case 0x1bc: /* bsf */
5402 case 0x1bd: /* bsr */
14ce26e7 5403 ot = dflag + OT_WORD;
61382a50 5404 modrm = ldub_code(s->pc++);
14ce26e7 5405 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af 5406 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
686f3f26
FB
5407 /* NOTE: in order to handle the 0 case, we must load the
5408 result. It could be optimized with a generated jump */
5409 gen_op_mov_TN_reg[ot][1][reg]();
2c0262af 5410 gen_op_bsx_T0_cc[ot - OT_WORD][b & 1]();
686f3f26 5411 gen_op_mov_reg_T1[ot][reg]();
2c0262af
FB
5412 s->cc_op = CC_OP_LOGICB + ot;
5413 break;
5414 /************************/
5415 /* bcd */
5416 case 0x27: /* daa */
14ce26e7
FB
5417 if (CODE64(s))
5418 goto illegal_op;
2c0262af
FB
5419 if (s->cc_op != CC_OP_DYNAMIC)
5420 gen_op_set_cc_op(s->cc_op);
5421 gen_op_daa();
5422 s->cc_op = CC_OP_EFLAGS;
5423 break;
5424 case 0x2f: /* das */
14ce26e7
FB
5425 if (CODE64(s))
5426 goto illegal_op;
2c0262af
FB
5427 if (s->cc_op != CC_OP_DYNAMIC)
5428 gen_op_set_cc_op(s->cc_op);
5429 gen_op_das();
5430 s->cc_op = CC_OP_EFLAGS;
5431 break;
5432 case 0x37: /* aaa */
14ce26e7
FB
5433 if (CODE64(s))
5434 goto illegal_op;
2c0262af
FB
5435 if (s->cc_op != CC_OP_DYNAMIC)
5436 gen_op_set_cc_op(s->cc_op);
5437 gen_op_aaa();
5438 s->cc_op = CC_OP_EFLAGS;
5439 break;
5440 case 0x3f: /* aas */
14ce26e7
FB
5441 if (CODE64(s))
5442 goto illegal_op;
2c0262af
FB
5443 if (s->cc_op != CC_OP_DYNAMIC)
5444 gen_op_set_cc_op(s->cc_op);
5445 gen_op_aas();
5446 s->cc_op = CC_OP_EFLAGS;
5447 break;
5448 case 0xd4: /* aam */
14ce26e7
FB
5449 if (CODE64(s))
5450 goto illegal_op;
61382a50 5451 val = ldub_code(s->pc++);
b6d7c3db
TS
5452 if (val == 0) {
5453 gen_exception(s, EXCP00_DIVZ, pc_start - s->cs_base);
5454 } else {
5455 gen_op_aam(val);
5456 s->cc_op = CC_OP_LOGICB;
5457 }
2c0262af
FB
5458 break;
5459 case 0xd5: /* aad */
14ce26e7
FB
5460 if (CODE64(s))
5461 goto illegal_op;
61382a50 5462 val = ldub_code(s->pc++);
2c0262af
FB
5463 gen_op_aad(val);
5464 s->cc_op = CC_OP_LOGICB;
5465 break;
5466 /************************/
5467 /* misc */
5468 case 0x90: /* nop */
14ce26e7 5469 /* XXX: xchg + rex handling */
ab1f142b
FB
5470 /* XXX: correct lock test for all insn */
5471 if (prefixes & PREFIX_LOCK)
5472 goto illegal_op;
0573fbfc
TS
5473 if (prefixes & PREFIX_REPZ) {
5474 gen_svm_check_intercept(s, pc_start, SVM_EXIT_PAUSE);
5475 }
2c0262af
FB
5476 break;
5477 case 0x9b: /* fwait */
5fafdf24 5478 if ((s->flags & (HF_MP_MASK | HF_TS_MASK)) ==
7eee2a50
FB
5479 (HF_MP_MASK | HF_TS_MASK)) {
5480 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
2ee73ac3
FB
5481 } else {
5482 if (s->cc_op != CC_OP_DYNAMIC)
5483 gen_op_set_cc_op(s->cc_op);
14ce26e7 5484 gen_jmp_im(pc_start - s->cs_base);
2ee73ac3 5485 gen_op_fwait();
7eee2a50 5486 }
2c0262af
FB
5487 break;
5488 case 0xcc: /* int3 */
0573fbfc
TS
5489 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_SWINT))
5490 break;
2c0262af
FB
5491 gen_interrupt(s, EXCP03_INT3, pc_start - s->cs_base, s->pc - s->cs_base);
5492 break;
5493 case 0xcd: /* int N */
61382a50 5494 val = ldub_code(s->pc++);
0573fbfc
TS
5495 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_SWINT))
5496 break;
f115e911 5497 if (s->vm86 && s->iopl != 3) {
5fafdf24 5498 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
f115e911
FB
5499 } else {
5500 gen_interrupt(s, val, pc_start - s->cs_base, s->pc - s->cs_base);
5501 }
2c0262af
FB
5502 break;
5503 case 0xce: /* into */
14ce26e7
FB
5504 if (CODE64(s))
5505 goto illegal_op;
0573fbfc
TS
5506 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_SWINT))
5507 break;
2c0262af
FB
5508 if (s->cc_op != CC_OP_DYNAMIC)
5509 gen_op_set_cc_op(s->cc_op);
a8ede8ba
FB
5510 gen_jmp_im(pc_start - s->cs_base);
5511 gen_op_into(s->pc - pc_start);
2c0262af
FB
5512 break;
5513 case 0xf1: /* icebp (undocumented, exits to external debugger) */
0573fbfc
TS
5514 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_ICEBP))
5515 break;
aba9d61e 5516#if 1
2c0262af 5517 gen_debug(s, pc_start - s->cs_base);
aba9d61e
FB
5518#else
5519 /* start debug */
5520 tb_flush(cpu_single_env);
5521 cpu_set_log(CPU_LOG_INT | CPU_LOG_TB_IN_ASM);
5522#endif
2c0262af
FB
5523 break;
5524 case 0xfa: /* cli */
5525 if (!s->vm86) {
5526 if (s->cpl <= s->iopl) {
5527 gen_op_cli();
5528 } else {
5529 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5530 }
5531 } else {
5532 if (s->iopl == 3) {
5533 gen_op_cli();
5534 } else {
5535 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5536 }
5537 }
5538 break;
5539 case 0xfb: /* sti */
5540 if (!s->vm86) {
5541 if (s->cpl <= s->iopl) {
5542 gen_sti:
5543 gen_op_sti();
5544 /* interruptions are enabled only the first insn after sti */
a2cc3b24
FB
5545 /* If several instructions disable interrupts, only the
5546 _first_ does it */
5547 if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
5548 gen_op_set_inhibit_irq();
2c0262af 5549 /* give a chance to handle pending irqs */
14ce26e7 5550 gen_jmp_im(s->pc - s->cs_base);
2c0262af
FB
5551 gen_eob(s);
5552 } else {
5553 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5554 }
5555 } else {
5556 if (s->iopl == 3) {
5557 goto gen_sti;
5558 } else {
5559 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5560 }
5561 }
5562 break;
5563 case 0x62: /* bound */
14ce26e7
FB
5564 if (CODE64(s))
5565 goto illegal_op;
2c0262af 5566 ot = dflag ? OT_LONG : OT_WORD;
61382a50 5567 modrm = ldub_code(s->pc++);
2c0262af
FB
5568 reg = (modrm >> 3) & 7;
5569 mod = (modrm >> 6) & 3;
5570 if (mod == 3)
5571 goto illegal_op;
cabf23c3 5572 gen_op_mov_TN_reg[ot][0][reg]();
2c0262af 5573 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
14ce26e7 5574 gen_jmp_im(pc_start - s->cs_base);
2c0262af 5575 if (ot == OT_WORD)
14ce26e7 5576 gen_op_boundw();
2c0262af 5577 else
14ce26e7 5578 gen_op_boundl();
2c0262af
FB
5579 break;
5580 case 0x1c8 ... 0x1cf: /* bswap reg */
14ce26e7
FB
5581 reg = (b & 7) | REX_B(s);
5582#ifdef TARGET_X86_64
5583 if (dflag == 2) {
5584 gen_op_mov_TN_reg[OT_QUAD][0][reg]();
5585 gen_op_bswapq_T0();
5586 gen_op_mov_reg_T0[OT_QUAD][reg]();
5fafdf24 5587 } else
14ce26e7
FB
5588#endif
5589 {
5590 gen_op_mov_TN_reg[OT_LONG][0][reg]();
5591 gen_op_bswapl_T0();
5592 gen_op_mov_reg_T0[OT_LONG][reg]();
5593 }
2c0262af
FB
5594 break;
5595 case 0xd6: /* salc */
14ce26e7
FB
5596 if (CODE64(s))
5597 goto illegal_op;
2c0262af
FB
5598 if (s->cc_op != CC_OP_DYNAMIC)
5599 gen_op_set_cc_op(s->cc_op);
5600 gen_op_salc();
5601 break;
5602 case 0xe0: /* loopnz */
5603 case 0xe1: /* loopz */
5604 if (s->cc_op != CC_OP_DYNAMIC)
5605 gen_op_set_cc_op(s->cc_op);
5606 /* FALL THRU */
5607 case 0xe2: /* loop */
5608 case 0xe3: /* jecxz */
14ce26e7
FB
5609 {
5610 int l1, l2;
5611
5612 tval = (int8_t)insn_get(s, OT_BYTE);
5613 next_eip = s->pc - s->cs_base;
5614 tval += next_eip;
5615 if (s->dflag == 0)
5616 tval &= 0xffff;
3b46e624 5617
14ce26e7
FB
5618 l1 = gen_new_label();
5619 l2 = gen_new_label();
5620 b &= 3;
5621 if (b == 3) {
5622 gen_op_jz_ecx[s->aflag](l1);
5623 } else {
5624 gen_op_dec_ECX[s->aflag]();
0b9dc5e4
FB
5625 if (b <= 1)
5626 gen_op_mov_T0_cc();
14ce26e7
FB
5627 gen_op_loop[s->aflag][b](l1);
5628 }
5629
5630 gen_jmp_im(next_eip);
5631 gen_op_jmp_label(l2);
5632 gen_set_label(l1);
5633 gen_jmp_im(tval);
5634 gen_set_label(l2);
5635 gen_eob(s);
5636 }
2c0262af
FB
5637 break;
5638 case 0x130: /* wrmsr */
5639 case 0x132: /* rdmsr */
5640 if (s->cpl != 0) {
5641 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5642 } else {
0573fbfc
TS
5643 int retval = 0;
5644 if (b & 2) {
5645 retval = gen_svm_check_intercept_param(s, pc_start, SVM_EXIT_MSR, 0);
2c0262af 5646 gen_op_rdmsr();
0573fbfc
TS
5647 } else {
5648 retval = gen_svm_check_intercept_param(s, pc_start, SVM_EXIT_MSR, 1);
2c0262af 5649 gen_op_wrmsr();
0573fbfc
TS
5650 }
5651 if(retval)
5652 gen_eob(s);
2c0262af
FB
5653 }
5654 break;
5655 case 0x131: /* rdtsc */
0573fbfc
TS
5656 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_RDTSC))
5657 break;
ecada8a2 5658 gen_jmp_im(pc_start - s->cs_base);
2c0262af
FB
5659 gen_op_rdtsc();
5660 break;
023fe10d 5661 case 0x134: /* sysenter */
14ce26e7
FB
5662 if (CODE64(s))
5663 goto illegal_op;
023fe10d
FB
5664 if (!s->pe) {
5665 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5666 } else {
5667 if (s->cc_op != CC_OP_DYNAMIC) {
5668 gen_op_set_cc_op(s->cc_op);
5669 s->cc_op = CC_OP_DYNAMIC;
5670 }
14ce26e7 5671 gen_jmp_im(pc_start - s->cs_base);
023fe10d
FB
5672 gen_op_sysenter();
5673 gen_eob(s);
5674 }
5675 break;
5676 case 0x135: /* sysexit */
14ce26e7
FB
5677 if (CODE64(s))
5678 goto illegal_op;
023fe10d
FB
5679 if (!s->pe) {
5680 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5681 } else {
5682 if (s->cc_op != CC_OP_DYNAMIC) {
5683 gen_op_set_cc_op(s->cc_op);
5684 s->cc_op = CC_OP_DYNAMIC;
5685 }
14ce26e7 5686 gen_jmp_im(pc_start - s->cs_base);
023fe10d
FB
5687 gen_op_sysexit();
5688 gen_eob(s);
5689 }
5690 break;
14ce26e7
FB
5691#ifdef TARGET_X86_64
5692 case 0x105: /* syscall */
5693 /* XXX: is it usable in real mode ? */
5694 if (s->cc_op != CC_OP_DYNAMIC) {
5695 gen_op_set_cc_op(s->cc_op);
5696 s->cc_op = CC_OP_DYNAMIC;
5697 }
5698 gen_jmp_im(pc_start - s->cs_base);
06c2f506 5699 gen_op_syscall(s->pc - pc_start);
14ce26e7
FB
5700 gen_eob(s);
5701 break;
5702 case 0x107: /* sysret */
5703 if (!s->pe) {
5704 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5705 } else {
5706 if (s->cc_op != CC_OP_DYNAMIC) {
5707 gen_op_set_cc_op(s->cc_op);
5708 s->cc_op = CC_OP_DYNAMIC;
5709 }
5710 gen_jmp_im(pc_start - s->cs_base);
5711 gen_op_sysret(s->dflag);
aba9d61e
FB
5712 /* condition codes are modified only in long mode */
5713 if (s->lma)
5714 s->cc_op = CC_OP_EFLAGS;
14ce26e7
FB
5715 gen_eob(s);
5716 }
5717 break;
5718#endif
2c0262af 5719 case 0x1a2: /* cpuid */
0573fbfc
TS
5720 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_CPUID))
5721 break;
2c0262af
FB
5722 gen_op_cpuid();
5723 break;
5724 case 0xf4: /* hlt */
5725 if (s->cpl != 0) {
5726 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5727 } else {
0573fbfc
TS
5728 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_HLT))
5729 break;
2c0262af
FB
5730 if (s->cc_op != CC_OP_DYNAMIC)
5731 gen_op_set_cc_op(s->cc_op);
14ce26e7 5732 gen_jmp_im(s->pc - s->cs_base);
2c0262af
FB
5733 gen_op_hlt();
5734 s->is_jmp = 3;
5735 }
5736 break;
5737 case 0x100:
61382a50 5738 modrm = ldub_code(s->pc++);
2c0262af
FB
5739 mod = (modrm >> 6) & 3;
5740 op = (modrm >> 3) & 7;
5741 switch(op) {
5742 case 0: /* sldt */
f115e911
FB
5743 if (!s->pe || s->vm86)
5744 goto illegal_op;
0573fbfc
TS
5745 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_READ))
5746 break;
2c0262af
FB
5747 gen_op_movl_T0_env(offsetof(CPUX86State,ldt.selector));
5748 ot = OT_WORD;
5749 if (mod == 3)
5750 ot += s->dflag;
5751 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
5752 break;
5753 case 2: /* lldt */
f115e911
FB
5754 if (!s->pe || s->vm86)
5755 goto illegal_op;
2c0262af
FB
5756 if (s->cpl != 0) {
5757 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5758 } else {
0573fbfc
TS
5759 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_WRITE))
5760 break;
2c0262af 5761 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
14ce26e7 5762 gen_jmp_im(pc_start - s->cs_base);
2c0262af
FB
5763 gen_op_lldt_T0();
5764 }
5765 break;
5766 case 1: /* str */
f115e911
FB
5767 if (!s->pe || s->vm86)
5768 goto illegal_op;
0573fbfc
TS
5769 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_READ))
5770 break;
2c0262af
FB
5771 gen_op_movl_T0_env(offsetof(CPUX86State,tr.selector));
5772 ot = OT_WORD;
5773 if (mod == 3)
5774 ot += s->dflag;
5775 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
5776 break;
5777 case 3: /* ltr */
f115e911
FB
5778 if (!s->pe || s->vm86)
5779 goto illegal_op;
2c0262af
FB
5780 if (s->cpl != 0) {
5781 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5782 } else {
0573fbfc
TS
5783 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_WRITE))
5784 break;
2c0262af 5785 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
14ce26e7 5786 gen_jmp_im(pc_start - s->cs_base);
2c0262af
FB
5787 gen_op_ltr_T0();
5788 }
5789 break;
5790 case 4: /* verr */
5791 case 5: /* verw */
f115e911
FB
5792 if (!s->pe || s->vm86)
5793 goto illegal_op;
5794 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
5795 if (s->cc_op != CC_OP_DYNAMIC)
5796 gen_op_set_cc_op(s->cc_op);
5797 if (op == 4)
5798 gen_op_verr();
5799 else
5800 gen_op_verw();
5801 s->cc_op = CC_OP_EFLAGS;
5802 break;
2c0262af
FB
5803 default:
5804 goto illegal_op;
5805 }
5806 break;
5807 case 0x101:
61382a50 5808 modrm = ldub_code(s->pc++);
2c0262af
FB
5809 mod = (modrm >> 6) & 3;
5810 op = (modrm >> 3) & 7;
3d7374c5 5811 rm = modrm & 7;
2c0262af
FB
5812 switch(op) {
5813 case 0: /* sgdt */
2c0262af
FB
5814 if (mod == 3)
5815 goto illegal_op;
0573fbfc
TS
5816 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_GDTR_READ))
5817 break;
2c0262af 5818 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3d7374c5 5819 gen_op_movl_T0_env(offsetof(CPUX86State, gdt.limit));
2c0262af 5820 gen_op_st_T0_A0[OT_WORD + s->mem_index]();
aba9d61e 5821 gen_add_A0_im(s, 2);
3d7374c5 5822 gen_op_movtl_T0_env(offsetof(CPUX86State, gdt.base));
2c0262af
FB
5823 if (!s->dflag)
5824 gen_op_andl_T0_im(0xffffff);
14ce26e7 5825 gen_op_st_T0_A0[CODE64(s) + OT_LONG + s->mem_index]();
2c0262af 5826 break;
3d7374c5
FB
5827 case 1:
5828 if (mod == 3) {
5829 switch (rm) {
5830 case 0: /* monitor */
5831 if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) ||
5832 s->cpl != 0)
5833 goto illegal_op;
0573fbfc
TS
5834 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_MONITOR))
5835 break;
3d7374c5
FB
5836 gen_jmp_im(pc_start - s->cs_base);
5837#ifdef TARGET_X86_64
5838 if (s->aflag == 2) {
5839 gen_op_movq_A0_reg[R_EBX]();
5840 gen_op_addq_A0_AL();
5fafdf24 5841 } else
3d7374c5
FB
5842#endif
5843 {
5844 gen_op_movl_A0_reg[R_EBX]();
5845 gen_op_addl_A0_AL();
5846 if (s->aflag == 0)
5847 gen_op_andl_A0_ffff();
5848 }
5849 gen_add_A0_ds_seg(s);
5850 gen_op_monitor();
5851 break;
5852 case 1: /* mwait */
5853 if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) ||
5854 s->cpl != 0)
5855 goto illegal_op;
5856 if (s->cc_op != CC_OP_DYNAMIC) {
5857 gen_op_set_cc_op(s->cc_op);
5858 s->cc_op = CC_OP_DYNAMIC;
5859 }
0573fbfc
TS
5860 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_MWAIT))
5861 break;
3d7374c5
FB
5862 gen_jmp_im(s->pc - s->cs_base);
5863 gen_op_mwait();
5864 gen_eob(s);
5865 break;
5866 default:
5867 goto illegal_op;
5868 }
5869 } else { /* sidt */
0573fbfc
TS
5870 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_IDTR_READ))
5871 break;
3d7374c5
FB
5872 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
5873 gen_op_movl_T0_env(offsetof(CPUX86State, idt.limit));
5874 gen_op_st_T0_A0[OT_WORD + s->mem_index]();
5875 gen_add_A0_im(s, 2);
5876 gen_op_movtl_T0_env(offsetof(CPUX86State, idt.base));
5877 if (!s->dflag)
5878 gen_op_andl_T0_im(0xffffff);
5879 gen_op_st_T0_A0[CODE64(s) + OT_LONG + s->mem_index]();
5880 }
5881 break;
2c0262af
FB
5882 case 2: /* lgdt */
5883 case 3: /* lidt */
0573fbfc
TS
5884 if (mod == 3) {
5885 switch(rm) {
5886 case 0: /* VMRUN */
5887 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_VMRUN))
5888 break;
5889 if (s->cc_op != CC_OP_DYNAMIC)
5890 gen_op_set_cc_op(s->cc_op);
5891 gen_jmp_im(s->pc - s->cs_base);
5892 gen_op_vmrun();
5893 s->cc_op = CC_OP_EFLAGS;
5894 gen_eob(s);
5895 break;
5896 case 1: /* VMMCALL */
5897 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_VMMCALL))
5898 break;
5899 /* FIXME: cause #UD if hflags & SVM */
5900 gen_op_vmmcall();
5901 break;
5902 case 2: /* VMLOAD */
5903 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_VMLOAD))
5904 break;
5905 gen_op_vmload();
5906 break;
5907 case 3: /* VMSAVE */
5908 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_VMSAVE))
5909 break;
5910 gen_op_vmsave();
5911 break;
5912 case 4: /* STGI */
5913 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_STGI))
5914 break;
5915 gen_op_stgi();
5916 break;
5917 case 5: /* CLGI */
5918 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_CLGI))
5919 break;
5920 gen_op_clgi();
5921 break;
5922 case 6: /* SKINIT */
5923 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_SKINIT))
5924 break;
5925 gen_op_skinit();
5926 break;
5927 case 7: /* INVLPGA */
5928 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_INVLPGA))
5929 break;
5930 gen_op_invlpga();
5931 break;
5932 default:
5933 goto illegal_op;
5934 }
5935 } else if (s->cpl != 0) {
2c0262af
FB
5936 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5937 } else {
0573fbfc
TS
5938 if (gen_svm_check_intercept(s, pc_start,
5939 op==2 ? SVM_EXIT_GDTR_WRITE : SVM_EXIT_IDTR_WRITE))
5940 break;
2c0262af
FB
5941 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
5942 gen_op_ld_T1_A0[OT_WORD + s->mem_index]();
aba9d61e 5943 gen_add_A0_im(s, 2);
14ce26e7 5944 gen_op_ld_T0_A0[CODE64(s) + OT_LONG + s->mem_index]();
2c0262af
FB
5945 if (!s->dflag)
5946 gen_op_andl_T0_im(0xffffff);
5947 if (op == 2) {
14ce26e7 5948 gen_op_movtl_env_T0(offsetof(CPUX86State,gdt.base));
2c0262af
FB
5949 gen_op_movl_env_T1(offsetof(CPUX86State,gdt.limit));
5950 } else {
14ce26e7 5951 gen_op_movtl_env_T0(offsetof(CPUX86State,idt.base));
2c0262af
FB
5952 gen_op_movl_env_T1(offsetof(CPUX86State,idt.limit));
5953 }
5954 }
5955 break;
5956 case 4: /* smsw */
0573fbfc
TS
5957 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_CR0))
5958 break;
2c0262af
FB
5959 gen_op_movl_T0_env(offsetof(CPUX86State,cr[0]));
5960 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 1);
5961 break;
5962 case 6: /* lmsw */
5963 if (s->cpl != 0) {
5964 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5965 } else {
0573fbfc
TS
5966 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0))
5967 break;
2c0262af
FB
5968 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
5969 gen_op_lmsw_T0();
14ce26e7 5970 gen_jmp_im(s->pc - s->cs_base);
d71b9a8b 5971 gen_eob(s);
2c0262af
FB
5972 }
5973 break;
5974 case 7: /* invlpg */
5975 if (s->cpl != 0) {
5976 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5977 } else {
14ce26e7
FB
5978 if (mod == 3) {
5979#ifdef TARGET_X86_64
3d7374c5 5980 if (CODE64(s) && rm == 0) {
14ce26e7
FB
5981 /* swapgs */
5982 gen_op_movtl_T0_env(offsetof(CPUX86State,segs[R_GS].base));
5983 gen_op_movtl_T1_env(offsetof(CPUX86State,kernelgsbase));
5984 gen_op_movtl_env_T1(offsetof(CPUX86State,segs[R_GS].base));
5985 gen_op_movtl_env_T0(offsetof(CPUX86State,kernelgsbase));
5fafdf24 5986 } else
14ce26e7
FB
5987#endif
5988 {
5989 goto illegal_op;
5990 }
5991 } else {
0573fbfc
TS
5992 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_INVLPG))
5993 break;
14ce26e7
FB
5994 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
5995 gen_op_invlpg_A0();
5996 gen_jmp_im(s->pc - s->cs_base);
5997 gen_eob(s);
5998 }
2c0262af
FB
5999 }
6000 break;
6001 default:
6002 goto illegal_op;
6003 }
6004 break;
3415a4dd
FB
6005 case 0x108: /* invd */
6006 case 0x109: /* wbinvd */
6007 if (s->cpl != 0) {
6008 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6009 } else {
ad848875 6010 if (gen_svm_check_intercept(s, pc_start, (b & 2) ? SVM_EXIT_INVD : SVM_EXIT_WBINVD))
0573fbfc 6011 break;
3415a4dd
FB
6012 /* nothing to do */
6013 }
6014 break;
14ce26e7
FB
6015 case 0x63: /* arpl or movslS (x86_64) */
6016#ifdef TARGET_X86_64
6017 if (CODE64(s)) {
6018 int d_ot;
6019 /* d_ot is the size of destination */
6020 d_ot = dflag + OT_WORD;
6021
6022 modrm = ldub_code(s->pc++);
6023 reg = ((modrm >> 3) & 7) | rex_r;
6024 mod = (modrm >> 6) & 3;
6025 rm = (modrm & 7) | REX_B(s);
3b46e624 6026
14ce26e7
FB
6027 if (mod == 3) {
6028 gen_op_mov_TN_reg[OT_LONG][0][rm]();
6029 /* sign extend */
6030 if (d_ot == OT_QUAD)
6031 gen_op_movslq_T0_T0();
6032 gen_op_mov_reg_T0[d_ot][reg]();
6033 } else {
6034 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
6035 if (d_ot == OT_QUAD) {
6036 gen_op_lds_T0_A0[OT_LONG + s->mem_index]();
6037 } else {
6038 gen_op_ld_T0_A0[OT_LONG + s->mem_index]();
6039 }
6040 gen_op_mov_reg_T0[d_ot][reg]();
6041 }
5fafdf24 6042 } else
14ce26e7
FB
6043#endif
6044 {
6045 if (!s->pe || s->vm86)
6046 goto illegal_op;
6047 ot = dflag ? OT_LONG : OT_WORD;
6048 modrm = ldub_code(s->pc++);
6049 reg = (modrm >> 3) & 7;
6050 mod = (modrm >> 6) & 3;
6051 rm = modrm & 7;
6052 if (mod != 3) {
6053 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
6054 gen_op_ld_T0_A0[ot + s->mem_index]();
6055 } else {
6056 gen_op_mov_TN_reg[ot][0][rm]();
6057 }
6058 if (s->cc_op != CC_OP_DYNAMIC)
6059 gen_op_set_cc_op(s->cc_op);
6060 gen_op_arpl();
6061 s->cc_op = CC_OP_EFLAGS;
6062 if (mod != 3) {
6063 gen_op_st_T0_A0[ot + s->mem_index]();
6064 } else {
6065 gen_op_mov_reg_T0[ot][rm]();
6066 }
6067 gen_op_arpl_update();
f115e911 6068 }
f115e911 6069 break;
2c0262af
FB
6070 case 0x102: /* lar */
6071 case 0x103: /* lsl */
6072 if (!s->pe || s->vm86)
6073 goto illegal_op;
6074 ot = dflag ? OT_LONG : OT_WORD;
61382a50 6075 modrm = ldub_code(s->pc++);
14ce26e7 6076 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af
FB
6077 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
6078 gen_op_mov_TN_reg[ot][1][reg]();
6079 if (s->cc_op != CC_OP_DYNAMIC)
6080 gen_op_set_cc_op(s->cc_op);
6081 if (b == 0x102)
6082 gen_op_lar();
6083 else
6084 gen_op_lsl();
6085 s->cc_op = CC_OP_EFLAGS;
6086 gen_op_mov_reg_T1[ot][reg]();
6087 break;
6088 case 0x118:
61382a50 6089 modrm = ldub_code(s->pc++);
2c0262af
FB
6090 mod = (modrm >> 6) & 3;
6091 op = (modrm >> 3) & 7;
6092 switch(op) {
6093 case 0: /* prefetchnta */
6094 case 1: /* prefetchnt0 */
6095 case 2: /* prefetchnt0 */
6096 case 3: /* prefetchnt0 */
6097 if (mod == 3)
6098 goto illegal_op;
6099 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
6100 /* nothing more to do */
6101 break;
e17a36ce
FB
6102 default: /* nop (multi byte) */
6103 gen_nop_modrm(s, modrm);
6104 break;
2c0262af
FB
6105 }
6106 break;
e17a36ce
FB
6107 case 0x119 ... 0x11f: /* nop (multi byte) */
6108 modrm = ldub_code(s->pc++);
6109 gen_nop_modrm(s, modrm);
6110 break;
2c0262af
FB
6111 case 0x120: /* mov reg, crN */
6112 case 0x122: /* mov crN, reg */
6113 if (s->cpl != 0) {
6114 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6115 } else {
61382a50 6116 modrm = ldub_code(s->pc++);
2c0262af
FB
6117 if ((modrm & 0xc0) != 0xc0)
6118 goto illegal_op;
14ce26e7
FB
6119 rm = (modrm & 7) | REX_B(s);
6120 reg = ((modrm >> 3) & 7) | rex_r;
6121 if (CODE64(s))
6122 ot = OT_QUAD;
6123 else
6124 ot = OT_LONG;
2c0262af
FB
6125 switch(reg) {
6126 case 0:
6127 case 2:
6128 case 3:
6129 case 4:
9230e66e 6130 case 8:
2c0262af 6131 if (b & 2) {
0573fbfc 6132 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0 + reg);
14ce26e7 6133 gen_op_mov_TN_reg[ot][0][rm]();
2c0262af 6134 gen_op_movl_crN_T0(reg);
14ce26e7 6135 gen_jmp_im(s->pc - s->cs_base);
2c0262af
FB
6136 gen_eob(s);
6137 } else {
0573fbfc 6138 gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_CR0 + reg);
5fafdf24 6139#if !defined(CONFIG_USER_ONLY)
9230e66e
FB
6140 if (reg == 8)
6141 gen_op_movtl_T0_cr8();
6142 else
82e41634 6143#endif
9230e66e 6144 gen_op_movtl_T0_env(offsetof(CPUX86State,cr[reg]));
14ce26e7 6145 gen_op_mov_reg_T0[ot][rm]();
2c0262af
FB
6146 }
6147 break;
6148 default:
6149 goto illegal_op;
6150 }
6151 }
6152 break;
6153 case 0x121: /* mov reg, drN */
6154 case 0x123: /* mov drN, reg */
6155 if (s->cpl != 0) {
6156 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6157 } else {
61382a50 6158 modrm = ldub_code(s->pc++);
2c0262af
FB
6159 if ((modrm & 0xc0) != 0xc0)
6160 goto illegal_op;
14ce26e7
FB
6161 rm = (modrm & 7) | REX_B(s);
6162 reg = ((modrm >> 3) & 7) | rex_r;
6163 if (CODE64(s))
6164 ot = OT_QUAD;
6165 else
6166 ot = OT_LONG;
2c0262af 6167 /* XXX: do it dynamically with CR4.DE bit */
14ce26e7 6168 if (reg == 4 || reg == 5 || reg >= 8)
2c0262af
FB
6169 goto illegal_op;
6170 if (b & 2) {
0573fbfc 6171 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_DR0 + reg);
14ce26e7 6172 gen_op_mov_TN_reg[ot][0][rm]();
2c0262af 6173 gen_op_movl_drN_T0(reg);
14ce26e7 6174 gen_jmp_im(s->pc - s->cs_base);
2c0262af
FB
6175 gen_eob(s);
6176 } else {
0573fbfc 6177 gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_DR0 + reg);
14ce26e7
FB
6178 gen_op_movtl_T0_env(offsetof(CPUX86State,dr[reg]));
6179 gen_op_mov_reg_T0[ot][rm]();
2c0262af
FB
6180 }
6181 }
6182 break;
6183 case 0x106: /* clts */
6184 if (s->cpl != 0) {
6185 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6186 } else {
0573fbfc 6187 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0);
2c0262af 6188 gen_op_clts();
7eee2a50 6189 /* abort block because static cpu state changed */
14ce26e7 6190 gen_jmp_im(s->pc - s->cs_base);
7eee2a50 6191 gen_eob(s);
2c0262af
FB
6192 }
6193 break;
664e0f19
FB
6194 /* MMX/SSE/SSE2/PNI support */
6195 case 0x1c3: /* MOVNTI reg, mem */
6196 if (!(s->cpuid_features & CPUID_SSE2))
14ce26e7 6197 goto illegal_op;
664e0f19
FB
6198 ot = s->dflag == 2 ? OT_QUAD : OT_LONG;
6199 modrm = ldub_code(s->pc++);
6200 mod = (modrm >> 6) & 3;
6201 if (mod == 3)
6202 goto illegal_op;
6203 reg = ((modrm >> 3) & 7) | rex_r;
6204 /* generate a generic store */
6205 gen_ldst_modrm(s, modrm, ot, reg, 1);
14ce26e7 6206 break;
664e0f19
FB
6207 case 0x1ae:
6208 modrm = ldub_code(s->pc++);
6209 mod = (modrm >> 6) & 3;
6210 op = (modrm >> 3) & 7;
6211 switch(op) {
6212 case 0: /* fxsave */
5fafdf24 6213 if (mod == 3 || !(s->cpuid_features & CPUID_FXSR) ||
0fd14b72 6214 (s->flags & HF_EM_MASK))
14ce26e7 6215 goto illegal_op;
0fd14b72
FB
6216 if (s->flags & HF_TS_MASK) {
6217 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
6218 break;
6219 }
664e0f19
FB
6220 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
6221 gen_op_fxsave_A0((s->dflag == 2));
6222 break;
6223 case 1: /* fxrstor */
5fafdf24 6224 if (mod == 3 || !(s->cpuid_features & CPUID_FXSR) ||
0fd14b72 6225 (s->flags & HF_EM_MASK))
14ce26e7 6226 goto illegal_op;
0fd14b72
FB
6227 if (s->flags & HF_TS_MASK) {
6228 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
6229 break;
6230 }
664e0f19
FB
6231 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
6232 gen_op_fxrstor_A0((s->dflag == 2));
6233 break;
6234 case 2: /* ldmxcsr */
6235 case 3: /* stmxcsr */
6236 if (s->flags & HF_TS_MASK) {
6237 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
6238 break;
14ce26e7 6239 }
664e0f19
FB
6240 if ((s->flags & HF_EM_MASK) || !(s->flags & HF_OSFXSR_MASK) ||
6241 mod == 3)
14ce26e7 6242 goto illegal_op;
664e0f19
FB
6243 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
6244 if (op == 2) {
6245 gen_op_ld_T0_A0[OT_LONG + s->mem_index]();
6246 gen_op_movl_env_T0(offsetof(CPUX86State, mxcsr));
14ce26e7 6247 } else {
664e0f19
FB
6248 gen_op_movl_T0_env(offsetof(CPUX86State, mxcsr));
6249 gen_op_st_T0_A0[OT_LONG + s->mem_index]();
14ce26e7 6250 }
664e0f19
FB
6251 break;
6252 case 5: /* lfence */
6253 case 6: /* mfence */
664e0f19
FB
6254 if ((modrm & 0xc7) != 0xc0 || !(s->cpuid_features & CPUID_SSE))
6255 goto illegal_op;
6256 break;
8f091a59
FB
6257 case 7: /* sfence / clflush */
6258 if ((modrm & 0xc7) == 0xc0) {
6259 /* sfence */
6260 if (!(s->cpuid_features & CPUID_SSE))
6261 goto illegal_op;
6262 } else {
6263 /* clflush */
6264 if (!(s->cpuid_features & CPUID_CLFLUSH))
6265 goto illegal_op;
6266 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
6267 }
6268 break;
664e0f19 6269 default:
14ce26e7
FB
6270 goto illegal_op;
6271 }
6272 break;
8f091a59
FB
6273 case 0x10d: /* prefetch */
6274 modrm = ldub_code(s->pc++);
6275 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
6276 /* ignore for now */
6277 break;
3b21e03e 6278 case 0x1aa: /* rsm */
0573fbfc
TS
6279 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_RSM))
6280 break;
3b21e03e
FB
6281 if (!(s->flags & HF_SMM_MASK))
6282 goto illegal_op;
6283 if (s->cc_op != CC_OP_DYNAMIC) {
6284 gen_op_set_cc_op(s->cc_op);
6285 s->cc_op = CC_OP_DYNAMIC;
6286 }
6287 gen_jmp_im(s->pc - s->cs_base);
6288 gen_op_rsm();
6289 gen_eob(s);
6290 break;
664e0f19
FB
6291 case 0x110 ... 0x117:
6292 case 0x128 ... 0x12f:
6293 case 0x150 ... 0x177:
6294 case 0x17c ... 0x17f:
6295 case 0x1c2:
6296 case 0x1c4 ... 0x1c6:
6297 case 0x1d0 ... 0x1fe:
6298 gen_sse(s, b, pc_start, rex_r);
6299 break;
2c0262af
FB
6300 default:
6301 goto illegal_op;
6302 }
6303 /* lock generation */
6304 if (s->prefix & PREFIX_LOCK)
6305 gen_op_unlock();
6306 return s->pc;
6307 illegal_op:
ab1f142b
FB
6308 if (s->prefix & PREFIX_LOCK)
6309 gen_op_unlock();
2c0262af
FB
6310 /* XXX: ensure that no lock was generated */
6311 gen_exception(s, EXCP06_ILLOP, pc_start - s->cs_base);
6312 return s->pc;
6313}
6314
6315#define CC_OSZAPC (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C)
6316#define CC_OSZAP (CC_O | CC_S | CC_Z | CC_A | CC_P)
6317
6318/* flags read by an operation */
5fafdf24 6319static uint16_t opc_read_flags[NB_OPS] = {
2c0262af
FB
6320 [INDEX_op_aas] = CC_A,
6321 [INDEX_op_aaa] = CC_A,
6322 [INDEX_op_das] = CC_A | CC_C,
6323 [INDEX_op_daa] = CC_A | CC_C,
6324
2c0262af 6325 /* subtle: due to the incl/decl implementation, C is used */
5fafdf24 6326 [INDEX_op_update_inc_cc] = CC_C,
2c0262af
FB
6327
6328 [INDEX_op_into] = CC_O,
6329
6330 [INDEX_op_jb_subb] = CC_C,
6331 [INDEX_op_jb_subw] = CC_C,
6332 [INDEX_op_jb_subl] = CC_C,
6333
6334 [INDEX_op_jz_subb] = CC_Z,
6335 [INDEX_op_jz_subw] = CC_Z,
6336 [INDEX_op_jz_subl] = CC_Z,
6337
6338 [INDEX_op_jbe_subb] = CC_Z | CC_C,
6339 [INDEX_op_jbe_subw] = CC_Z | CC_C,
6340 [INDEX_op_jbe_subl] = CC_Z | CC_C,
6341
6342 [INDEX_op_js_subb] = CC_S,
6343 [INDEX_op_js_subw] = CC_S,
6344 [INDEX_op_js_subl] = CC_S,
6345
6346 [INDEX_op_jl_subb] = CC_O | CC_S,
6347 [INDEX_op_jl_subw] = CC_O | CC_S,
6348 [INDEX_op_jl_subl] = CC_O | CC_S,
6349
6350 [INDEX_op_jle_subb] = CC_O | CC_S | CC_Z,
6351 [INDEX_op_jle_subw] = CC_O | CC_S | CC_Z,
6352 [INDEX_op_jle_subl] = CC_O | CC_S | CC_Z,
6353
6354 [INDEX_op_loopnzw] = CC_Z,
6355 [INDEX_op_loopnzl] = CC_Z,
6356 [INDEX_op_loopzw] = CC_Z,
6357 [INDEX_op_loopzl] = CC_Z,
6358
6359 [INDEX_op_seto_T0_cc] = CC_O,
6360 [INDEX_op_setb_T0_cc] = CC_C,
6361 [INDEX_op_setz_T0_cc] = CC_Z,
6362 [INDEX_op_setbe_T0_cc] = CC_Z | CC_C,
6363 [INDEX_op_sets_T0_cc] = CC_S,
6364 [INDEX_op_setp_T0_cc] = CC_P,
6365 [INDEX_op_setl_T0_cc] = CC_O | CC_S,
6366 [INDEX_op_setle_T0_cc] = CC_O | CC_S | CC_Z,
6367
6368 [INDEX_op_setb_T0_subb] = CC_C,
6369 [INDEX_op_setb_T0_subw] = CC_C,
6370 [INDEX_op_setb_T0_subl] = CC_C,
6371
6372 [INDEX_op_setz_T0_subb] = CC_Z,
6373 [INDEX_op_setz_T0_subw] = CC_Z,
6374 [INDEX_op_setz_T0_subl] = CC_Z,
6375
6376 [INDEX_op_setbe_T0_subb] = CC_Z | CC_C,
6377 [INDEX_op_setbe_T0_subw] = CC_Z | CC_C,
6378 [INDEX_op_setbe_T0_subl] = CC_Z | CC_C,
6379
6380 [INDEX_op_sets_T0_subb] = CC_S,
6381 [INDEX_op_sets_T0_subw] = CC_S,
6382 [INDEX_op_sets_T0_subl] = CC_S,
6383
6384 [INDEX_op_setl_T0_subb] = CC_O | CC_S,
6385 [INDEX_op_setl_T0_subw] = CC_O | CC_S,
6386 [INDEX_op_setl_T0_subl] = CC_O | CC_S,
6387
6388 [INDEX_op_setle_T0_subb] = CC_O | CC_S | CC_Z,
6389 [INDEX_op_setle_T0_subw] = CC_O | CC_S | CC_Z,
6390 [INDEX_op_setle_T0_subl] = CC_O | CC_S | CC_Z,
6391
6392 [INDEX_op_movl_T0_eflags] = CC_OSZAPC,
6393 [INDEX_op_cmc] = CC_C,
6394 [INDEX_op_salc] = CC_C,
6395
7399c5a9 6396 /* needed for correct flag optimisation before string ops */
14ce26e7
FB
6397 [INDEX_op_jnz_ecxw] = CC_OSZAPC,
6398 [INDEX_op_jnz_ecxl] = CC_OSZAPC,
7399c5a9
FB
6399 [INDEX_op_jz_ecxw] = CC_OSZAPC,
6400 [INDEX_op_jz_ecxl] = CC_OSZAPC,
14ce26e7
FB
6401
6402#ifdef TARGET_X86_64
6403 [INDEX_op_jb_subq] = CC_C,
6404 [INDEX_op_jz_subq] = CC_Z,
6405 [INDEX_op_jbe_subq] = CC_Z | CC_C,
6406 [INDEX_op_js_subq] = CC_S,
6407 [INDEX_op_jl_subq] = CC_O | CC_S,
6408 [INDEX_op_jle_subq] = CC_O | CC_S | CC_Z,
6409
6410 [INDEX_op_loopnzq] = CC_Z,
6411 [INDEX_op_loopzq] = CC_Z,
6412
6413 [INDEX_op_setb_T0_subq] = CC_C,
6414 [INDEX_op_setz_T0_subq] = CC_Z,
6415 [INDEX_op_setbe_T0_subq] = CC_Z | CC_C,
6416 [INDEX_op_sets_T0_subq] = CC_S,
6417 [INDEX_op_setl_T0_subq] = CC_O | CC_S,
6418 [INDEX_op_setle_T0_subq] = CC_O | CC_S | CC_Z,
6419
6420 [INDEX_op_jnz_ecxq] = CC_OSZAPC,
6421 [INDEX_op_jz_ecxq] = CC_OSZAPC,
6422#endif
7399c5a9 6423
4f31916f
FB
6424#define DEF_READF(SUFFIX)\
6425 [INDEX_op_adcb ## SUFFIX ## _T0_T1_cc] = CC_C,\
6426 [INDEX_op_adcw ## SUFFIX ## _T0_T1_cc] = CC_C,\
6427 [INDEX_op_adcl ## SUFFIX ## _T0_T1_cc] = CC_C,\
14ce26e7 6428 X86_64_DEF([INDEX_op_adcq ## SUFFIX ## _T0_T1_cc] = CC_C,)\
4f31916f
FB
6429 [INDEX_op_sbbb ## SUFFIX ## _T0_T1_cc] = CC_C,\
6430 [INDEX_op_sbbw ## SUFFIX ## _T0_T1_cc] = CC_C,\
6431 [INDEX_op_sbbl ## SUFFIX ## _T0_T1_cc] = CC_C,\
14ce26e7 6432 X86_64_DEF([INDEX_op_sbbq ## SUFFIX ## _T0_T1_cc] = CC_C,)\
4f31916f
FB
6433\
6434 [INDEX_op_rclb ## SUFFIX ## _T0_T1_cc] = CC_C,\
6435 [INDEX_op_rclw ## SUFFIX ## _T0_T1_cc] = CC_C,\
6436 [INDEX_op_rcll ## SUFFIX ## _T0_T1_cc] = CC_C,\
14ce26e7 6437 X86_64_DEF([INDEX_op_rclq ## SUFFIX ## _T0_T1_cc] = CC_C,)\
4f31916f
FB
6438 [INDEX_op_rcrb ## SUFFIX ## _T0_T1_cc] = CC_C,\
6439 [INDEX_op_rcrw ## SUFFIX ## _T0_T1_cc] = CC_C,\
14ce26e7
FB
6440 [INDEX_op_rcrl ## SUFFIX ## _T0_T1_cc] = CC_C,\
6441 X86_64_DEF([INDEX_op_rcrq ## SUFFIX ## _T0_T1_cc] = CC_C,)
4f31916f 6442
4bb2fcc7 6443 DEF_READF( )
4f31916f
FB
6444 DEF_READF(_raw)
6445#ifndef CONFIG_USER_ONLY
6446 DEF_READF(_kernel)
6447 DEF_READF(_user)
6448#endif
2c0262af
FB
6449};
6450
6451/* flags written by an operation */
5fafdf24 6452static uint16_t opc_write_flags[NB_OPS] = {
2c0262af
FB
6453 [INDEX_op_update2_cc] = CC_OSZAPC,
6454 [INDEX_op_update1_cc] = CC_OSZAPC,
6455 [INDEX_op_cmpl_T0_T1_cc] = CC_OSZAPC,
6456 [INDEX_op_update_neg_cc] = CC_OSZAPC,
6457 /* subtle: due to the incl/decl implementation, C is used */
5fafdf24 6458 [INDEX_op_update_inc_cc] = CC_OSZAPC,
2c0262af
FB
6459 [INDEX_op_testl_T0_T1_cc] = CC_OSZAPC,
6460
2c0262af 6461 [INDEX_op_mulb_AL_T0] = CC_OSZAPC,
2c0262af 6462 [INDEX_op_mulw_AX_T0] = CC_OSZAPC,
2c0262af 6463 [INDEX_op_mull_EAX_T0] = CC_OSZAPC,
14ce26e7
FB
6464 X86_64_DEF([INDEX_op_mulq_EAX_T0] = CC_OSZAPC,)
6465 [INDEX_op_imulb_AL_T0] = CC_OSZAPC,
6466 [INDEX_op_imulw_AX_T0] = CC_OSZAPC,
2c0262af 6467 [INDEX_op_imull_EAX_T0] = CC_OSZAPC,
14ce26e7 6468 X86_64_DEF([INDEX_op_imulq_EAX_T0] = CC_OSZAPC,)
2c0262af
FB
6469 [INDEX_op_imulw_T0_T1] = CC_OSZAPC,
6470 [INDEX_op_imull_T0_T1] = CC_OSZAPC,
14ce26e7
FB
6471 X86_64_DEF([INDEX_op_imulq_T0_T1] = CC_OSZAPC,)
6472
664e0f19
FB
6473 /* sse */
6474 [INDEX_op_ucomiss] = CC_OSZAPC,
6475 [INDEX_op_ucomisd] = CC_OSZAPC,
6476 [INDEX_op_comiss] = CC_OSZAPC,
6477 [INDEX_op_comisd] = CC_OSZAPC,
6478
2c0262af
FB
6479 /* bcd */
6480 [INDEX_op_aam] = CC_OSZAPC,
6481 [INDEX_op_aad] = CC_OSZAPC,
6482 [INDEX_op_aas] = CC_OSZAPC,
6483 [INDEX_op_aaa] = CC_OSZAPC,
6484 [INDEX_op_das] = CC_OSZAPC,
6485 [INDEX_op_daa] = CC_OSZAPC,
6486
6487 [INDEX_op_movb_eflags_T0] = CC_S | CC_Z | CC_A | CC_P | CC_C,
6488 [INDEX_op_movw_eflags_T0] = CC_OSZAPC,
6489 [INDEX_op_movl_eflags_T0] = CC_OSZAPC,
4136f33c
FB
6490 [INDEX_op_movw_eflags_T0_io] = CC_OSZAPC,
6491 [INDEX_op_movl_eflags_T0_io] = CC_OSZAPC,
6492 [INDEX_op_movw_eflags_T0_cpl0] = CC_OSZAPC,
6493 [INDEX_op_movl_eflags_T0_cpl0] = CC_OSZAPC,
2c0262af
FB
6494 [INDEX_op_clc] = CC_C,
6495 [INDEX_op_stc] = CC_C,
6496 [INDEX_op_cmc] = CC_C,
6497
2c0262af
FB
6498 [INDEX_op_btw_T0_T1_cc] = CC_OSZAPC,
6499 [INDEX_op_btl_T0_T1_cc] = CC_OSZAPC,
14ce26e7 6500 X86_64_DEF([INDEX_op_btq_T0_T1_cc] = CC_OSZAPC,)
2c0262af
FB
6501 [INDEX_op_btsw_T0_T1_cc] = CC_OSZAPC,
6502 [INDEX_op_btsl_T0_T1_cc] = CC_OSZAPC,
14ce26e7 6503 X86_64_DEF([INDEX_op_btsq_T0_T1_cc] = CC_OSZAPC,)
2c0262af
FB
6504 [INDEX_op_btrw_T0_T1_cc] = CC_OSZAPC,
6505 [INDEX_op_btrl_T0_T1_cc] = CC_OSZAPC,
14ce26e7 6506 X86_64_DEF([INDEX_op_btrq_T0_T1_cc] = CC_OSZAPC,)
2c0262af
FB
6507 [INDEX_op_btcw_T0_T1_cc] = CC_OSZAPC,
6508 [INDEX_op_btcl_T0_T1_cc] = CC_OSZAPC,
14ce26e7 6509 X86_64_DEF([INDEX_op_btcq_T0_T1_cc] = CC_OSZAPC,)
2c0262af
FB
6510
6511 [INDEX_op_bsfw_T0_cc] = CC_OSZAPC,
6512 [INDEX_op_bsfl_T0_cc] = CC_OSZAPC,
14ce26e7 6513 X86_64_DEF([INDEX_op_bsfq_T0_cc] = CC_OSZAPC,)
2c0262af
FB
6514 [INDEX_op_bsrw_T0_cc] = CC_OSZAPC,
6515 [INDEX_op_bsrl_T0_cc] = CC_OSZAPC,
14ce26e7 6516 X86_64_DEF([INDEX_op_bsrq_T0_cc] = CC_OSZAPC,)
2c0262af
FB
6517
6518 [INDEX_op_cmpxchgb_T0_T1_EAX_cc] = CC_OSZAPC,
6519 [INDEX_op_cmpxchgw_T0_T1_EAX_cc] = CC_OSZAPC,
6520 [INDEX_op_cmpxchgl_T0_T1_EAX_cc] = CC_OSZAPC,
14ce26e7 6521 X86_64_DEF([INDEX_op_cmpxchgq_T0_T1_EAX_cc] = CC_OSZAPC,)
2c0262af 6522
2c0262af
FB
6523 [INDEX_op_cmpxchg8b] = CC_Z,
6524 [INDEX_op_lar] = CC_Z,
6525 [INDEX_op_lsl] = CC_Z,
cc6f538b
FB
6526 [INDEX_op_verr] = CC_Z,
6527 [INDEX_op_verw] = CC_Z,
2c0262af
FB
6528 [INDEX_op_fcomi_ST0_FT0] = CC_Z | CC_P | CC_C,
6529 [INDEX_op_fucomi_ST0_FT0] = CC_Z | CC_P | CC_C,
4f31916f
FB
6530
6531#define DEF_WRITEF(SUFFIX)\
6532 [INDEX_op_adcb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6533 [INDEX_op_adcw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6534 [INDEX_op_adcl ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
14ce26e7 6535 X86_64_DEF([INDEX_op_adcq ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,)\
4f31916f
FB
6536 [INDEX_op_sbbb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6537 [INDEX_op_sbbw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6538 [INDEX_op_sbbl ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
14ce26e7 6539 X86_64_DEF([INDEX_op_sbbq ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,)\
4f31916f
FB
6540\
6541 [INDEX_op_rolb ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6542 [INDEX_op_rolw ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6543 [INDEX_op_roll ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
14ce26e7 6544 X86_64_DEF([INDEX_op_rolq ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,)\
4f31916f
FB
6545 [INDEX_op_rorb ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6546 [INDEX_op_rorw ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6547 [INDEX_op_rorl ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
14ce26e7 6548 X86_64_DEF([INDEX_op_rorq ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,)\
4f31916f
FB
6549\
6550 [INDEX_op_rclb ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6551 [INDEX_op_rclw ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6552 [INDEX_op_rcll ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
14ce26e7 6553 X86_64_DEF([INDEX_op_rclq ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,)\
4f31916f
FB
6554 [INDEX_op_rcrb ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6555 [INDEX_op_rcrw ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6556 [INDEX_op_rcrl ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
14ce26e7 6557 X86_64_DEF([INDEX_op_rcrq ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,)\
4f31916f
FB
6558\
6559 [INDEX_op_shlb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6560 [INDEX_op_shlw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6561 [INDEX_op_shll ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
14ce26e7 6562 X86_64_DEF([INDEX_op_shlq ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,)\
4f31916f
FB
6563\
6564 [INDEX_op_shrb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6565 [INDEX_op_shrw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6566 [INDEX_op_shrl ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
14ce26e7 6567 X86_64_DEF([INDEX_op_shrq ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,)\
4f31916f
FB
6568\
6569 [INDEX_op_sarb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6570 [INDEX_op_sarw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6571 [INDEX_op_sarl ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
14ce26e7 6572 X86_64_DEF([INDEX_op_sarq ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,)\
4f31916f
FB
6573\
6574 [INDEX_op_shldw ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,\
6575 [INDEX_op_shldl ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,\
14ce26e7 6576 X86_64_DEF([INDEX_op_shldq ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,)\
4f31916f
FB
6577 [INDEX_op_shldw ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,\
6578 [INDEX_op_shldl ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,\
14ce26e7 6579 X86_64_DEF([INDEX_op_shldq ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,)\
4f31916f
FB
6580\
6581 [INDEX_op_shrdw ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,\
6582 [INDEX_op_shrdl ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,\
14ce26e7 6583 X86_64_DEF([INDEX_op_shrdq ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,)\
4f31916f
FB
6584 [INDEX_op_shrdw ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,\
6585 [INDEX_op_shrdl ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,\
14ce26e7 6586 X86_64_DEF([INDEX_op_shrdq ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,)\
4f31916f
FB
6587\
6588 [INDEX_op_cmpxchgb ## SUFFIX ## _T0_T1_EAX_cc] = CC_OSZAPC,\
6589 [INDEX_op_cmpxchgw ## SUFFIX ## _T0_T1_EAX_cc] = CC_OSZAPC,\
14ce26e7
FB
6590 [INDEX_op_cmpxchgl ## SUFFIX ## _T0_T1_EAX_cc] = CC_OSZAPC,\
6591 X86_64_DEF([INDEX_op_cmpxchgq ## SUFFIX ## _T0_T1_EAX_cc] = CC_OSZAPC,)
4f31916f
FB
6592
6593
4bb2fcc7 6594 DEF_WRITEF( )
4f31916f
FB
6595 DEF_WRITEF(_raw)
6596#ifndef CONFIG_USER_ONLY
6597 DEF_WRITEF(_kernel)
6598 DEF_WRITEF(_user)
6599#endif
2c0262af
FB
6600};
6601
6602/* simpler form of an operation if no flags need to be generated */
5fafdf24 6603static uint16_t opc_simpler[NB_OPS] = {
2c0262af
FB
6604 [INDEX_op_update2_cc] = INDEX_op_nop,
6605 [INDEX_op_update1_cc] = INDEX_op_nop,
6606 [INDEX_op_update_neg_cc] = INDEX_op_nop,
6607#if 0
6608 /* broken: CC_OP logic must be rewritten */
6609 [INDEX_op_update_inc_cc] = INDEX_op_nop,
6610#endif
2c0262af
FB
6611
6612 [INDEX_op_shlb_T0_T1_cc] = INDEX_op_shlb_T0_T1,
6613 [INDEX_op_shlw_T0_T1_cc] = INDEX_op_shlw_T0_T1,
6614 [INDEX_op_shll_T0_T1_cc] = INDEX_op_shll_T0_T1,
14ce26e7 6615 X86_64_DEF([INDEX_op_shlq_T0_T1_cc] = INDEX_op_shlq_T0_T1,)
2c0262af
FB
6616
6617 [INDEX_op_shrb_T0_T1_cc] = INDEX_op_shrb_T0_T1,
6618 [INDEX_op_shrw_T0_T1_cc] = INDEX_op_shrw_T0_T1,
6619 [INDEX_op_shrl_T0_T1_cc] = INDEX_op_shrl_T0_T1,
14ce26e7 6620 X86_64_DEF([INDEX_op_shrq_T0_T1_cc] = INDEX_op_shrq_T0_T1,)
2c0262af
FB
6621
6622 [INDEX_op_sarb_T0_T1_cc] = INDEX_op_sarb_T0_T1,
6623 [INDEX_op_sarw_T0_T1_cc] = INDEX_op_sarw_T0_T1,
6624 [INDEX_op_sarl_T0_T1_cc] = INDEX_op_sarl_T0_T1,
14ce26e7 6625 X86_64_DEF([INDEX_op_sarq_T0_T1_cc] = INDEX_op_sarq_T0_T1,)
4f31916f
FB
6626
6627#define DEF_SIMPLER(SUFFIX)\
6628 [INDEX_op_rolb ## SUFFIX ## _T0_T1_cc] = INDEX_op_rolb ## SUFFIX ## _T0_T1,\
6629 [INDEX_op_rolw ## SUFFIX ## _T0_T1_cc] = INDEX_op_rolw ## SUFFIX ## _T0_T1,\
6630 [INDEX_op_roll ## SUFFIX ## _T0_T1_cc] = INDEX_op_roll ## SUFFIX ## _T0_T1,\
14ce26e7 6631 X86_64_DEF([INDEX_op_rolq ## SUFFIX ## _T0_T1_cc] = INDEX_op_rolq ## SUFFIX ## _T0_T1,)\
4f31916f
FB
6632\
6633 [INDEX_op_rorb ## SUFFIX ## _T0_T1_cc] = INDEX_op_rorb ## SUFFIX ## _T0_T1,\
6634 [INDEX_op_rorw ## SUFFIX ## _T0_T1_cc] = INDEX_op_rorw ## SUFFIX ## _T0_T1,\
14ce26e7
FB
6635 [INDEX_op_rorl ## SUFFIX ## _T0_T1_cc] = INDEX_op_rorl ## SUFFIX ## _T0_T1,\
6636 X86_64_DEF([INDEX_op_rorq ## SUFFIX ## _T0_T1_cc] = INDEX_op_rorq ## SUFFIX ## _T0_T1,)
4f31916f 6637
4bb2fcc7 6638 DEF_SIMPLER( )
4f31916f
FB
6639 DEF_SIMPLER(_raw)
6640#ifndef CONFIG_USER_ONLY
6641 DEF_SIMPLER(_kernel)
6642 DEF_SIMPLER(_user)
6643#endif
2c0262af
FB
6644};
6645
6646void optimize_flags_init(void)
6647{
6648 int i;
6649 /* put default values in arrays */
6650 for(i = 0; i < NB_OPS; i++) {
6651 if (opc_simpler[i] == 0)
6652 opc_simpler[i] = i;
6653 }
6654}
6655
6656/* CPU flags computation optimization: we move backward thru the
6657 generated code to see which flags are needed. The operation is
6658 modified if suitable */
6659static void optimize_flags(uint16_t *opc_buf, int opc_buf_len)
6660{
6661 uint16_t *opc_ptr;
6662 int live_flags, write_flags, op;
6663
6664 opc_ptr = opc_buf + opc_buf_len;
6665 /* live_flags contains the flags needed by the next instructions
e91c8a77 6666 in the code. At the end of the block, we consider that all the
2c0262af
FB
6667 flags are live. */
6668 live_flags = CC_OSZAPC;
6669 while (opc_ptr > opc_buf) {
6670 op = *--opc_ptr;
6671 /* if none of the flags written by the instruction is used,
6672 then we can try to find a simpler instruction */
6673 write_flags = opc_write_flags[op];
6674 if ((live_flags & write_flags) == 0) {
6675 *opc_ptr = opc_simpler[op];
6676 }
6677 /* compute the live flags before the instruction */
6678 live_flags &= ~write_flags;
6679 live_flags |= opc_read_flags[op];
6680 }
6681}
6682
6683/* generate intermediate code in gen_opc_buf and gen_opparam_buf for
6684 basic block 'tb'. If search_pc is TRUE, also generate PC
6685 information for each intermediate instruction. */
6686static inline int gen_intermediate_code_internal(CPUState *env,
5fafdf24 6687 TranslationBlock *tb,
2c0262af
FB
6688 int search_pc)
6689{
6690 DisasContext dc1, *dc = &dc1;
14ce26e7 6691 target_ulong pc_ptr;
2c0262af 6692 uint16_t *gen_opc_end;
c068688b
JM
6693 int j, lj, cflags;
6694 uint64_t flags;
14ce26e7
FB
6695 target_ulong pc_start;
6696 target_ulong cs_base;
3b46e624 6697
2c0262af 6698 /* generate intermediate code */
14ce26e7
FB
6699 pc_start = tb->pc;
6700 cs_base = tb->cs_base;
2c0262af 6701 flags = tb->flags;
d720b93d 6702 cflags = tb->cflags;
3a1d9b8b 6703
4f31916f 6704 dc->pe = (flags >> HF_PE_SHIFT) & 1;
2c0262af
FB
6705 dc->code32 = (flags >> HF_CS32_SHIFT) & 1;
6706 dc->ss32 = (flags >> HF_SS32_SHIFT) & 1;
6707 dc->addseg = (flags >> HF_ADDSEG_SHIFT) & 1;
6708 dc->f_st = 0;
6709 dc->vm86 = (flags >> VM_SHIFT) & 1;
6710 dc->cpl = (flags >> HF_CPL_SHIFT) & 3;
6711 dc->iopl = (flags >> IOPL_SHIFT) & 3;
6712 dc->tf = (flags >> TF_SHIFT) & 1;
34865134 6713 dc->singlestep_enabled = env->singlestep_enabled;
2c0262af
FB
6714 dc->cc_op = CC_OP_DYNAMIC;
6715 dc->cs_base = cs_base;
6716 dc->tb = tb;
6717 dc->popl_esp_hack = 0;
6718 /* select memory access functions */
6719 dc->mem_index = 0;
6720 if (flags & HF_SOFTMMU_MASK) {
6721 if (dc->cpl == 3)
14ce26e7 6722 dc->mem_index = 2 * 4;
2c0262af 6723 else
14ce26e7 6724 dc->mem_index = 1 * 4;
2c0262af 6725 }
14ce26e7 6726 dc->cpuid_features = env->cpuid_features;
3d7374c5 6727 dc->cpuid_ext_features = env->cpuid_ext_features;
14ce26e7
FB
6728#ifdef TARGET_X86_64
6729 dc->lma = (flags >> HF_LMA_SHIFT) & 1;
6730 dc->code64 = (flags >> HF_CS64_SHIFT) & 1;
6731#endif
7eee2a50 6732 dc->flags = flags;
a2cc3b24
FB
6733 dc->jmp_opt = !(dc->tf || env->singlestep_enabled ||
6734 (flags & HF_INHIBIT_IRQ_MASK)
415fa2ea 6735#ifndef CONFIG_SOFTMMU
2c0262af
FB
6736 || (flags & HF_SOFTMMU_MASK)
6737#endif
6738 );
4f31916f
FB
6739#if 0
6740 /* check addseg logic */
dc196a57 6741 if (!dc->addseg && (dc->vm86 || !dc->pe || !dc->code32))
4f31916f
FB
6742 printf("ERROR addseg\n");
6743#endif
6744
2c0262af
FB
6745 gen_opc_ptr = gen_opc_buf;
6746 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
6747 gen_opparam_ptr = gen_opparam_buf;
14ce26e7 6748 nb_gen_labels = 0;
2c0262af
FB
6749
6750 dc->is_jmp = DISAS_NEXT;
6751 pc_ptr = pc_start;
6752 lj = -1;
6753
2c0262af
FB
6754 for(;;) {
6755 if (env->nb_breakpoints > 0) {
6756 for(j = 0; j < env->nb_breakpoints; j++) {
14ce26e7 6757 if (env->breakpoints[j] == pc_ptr) {
2c0262af
FB
6758 gen_debug(dc, pc_ptr - dc->cs_base);
6759 break;
6760 }
6761 }
6762 }
6763 if (search_pc) {
6764 j = gen_opc_ptr - gen_opc_buf;
6765 if (lj < j) {
6766 lj++;
6767 while (lj < j)
6768 gen_opc_instr_start[lj++] = 0;
6769 }
14ce26e7 6770 gen_opc_pc[lj] = pc_ptr;
2c0262af
FB
6771 gen_opc_cc_op[lj] = dc->cc_op;
6772 gen_opc_instr_start[lj] = 1;
6773 }
6774 pc_ptr = disas_insn(dc, pc_ptr);
6775 /* stop translation if indicated */
6776 if (dc->is_jmp)
6777 break;
6778 /* if single step mode, we generate only one instruction and
6779 generate an exception */
a2cc3b24
FB
6780 /* if irq were inhibited with HF_INHIBIT_IRQ_MASK, we clear
6781 the flag and abort the translation to give the irqs a
6782 change to be happen */
5fafdf24 6783 if (dc->tf || dc->singlestep_enabled ||
d720b93d
FB
6784 (flags & HF_INHIBIT_IRQ_MASK) ||
6785 (cflags & CF_SINGLE_INSN)) {
14ce26e7 6786 gen_jmp_im(pc_ptr - dc->cs_base);
2c0262af
FB
6787 gen_eob(dc);
6788 break;
6789 }
6790 /* if too long translation, stop generation too */
6791 if (gen_opc_ptr >= gen_opc_end ||
6792 (pc_ptr - pc_start) >= (TARGET_PAGE_SIZE - 32)) {
14ce26e7 6793 gen_jmp_im(pc_ptr - dc->cs_base);
2c0262af
FB
6794 gen_eob(dc);
6795 break;
6796 }
6797 }
6798 *gen_opc_ptr = INDEX_op_end;
6799 /* we don't forget to fill the last values */
6800 if (search_pc) {
6801 j = gen_opc_ptr - gen_opc_buf;
6802 lj++;
6803 while (lj <= j)
6804 gen_opc_instr_start[lj++] = 0;
6805 }
3b46e624 6806
2c0262af 6807#ifdef DEBUG_DISAS
658c8bda 6808 if (loglevel & CPU_LOG_TB_CPU) {
7fe48483 6809 cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
658c8bda 6810 }
e19e89a5 6811 if (loglevel & CPU_LOG_TB_IN_ASM) {
14ce26e7 6812 int disas_flags;
2c0262af
FB
6813 fprintf(logfile, "----------------\n");
6814 fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
14ce26e7
FB
6815#ifdef TARGET_X86_64
6816 if (dc->code64)
6817 disas_flags = 2;
6818 else
6819#endif
6820 disas_flags = !dc->code32;
6821 target_disas(logfile, pc_start, pc_ptr - pc_start, disas_flags);
2c0262af 6822 fprintf(logfile, "\n");
e19e89a5
FB
6823 if (loglevel & CPU_LOG_TB_OP) {
6824 fprintf(logfile, "OP:\n");
6825 dump_ops(gen_opc_buf, gen_opparam_buf);
6826 fprintf(logfile, "\n");
6827 }
2c0262af
FB
6828 }
6829#endif
6830
6831 /* optimize flag computations */
6832 optimize_flags(gen_opc_buf, gen_opc_ptr - gen_opc_buf);
6833
6834#ifdef DEBUG_DISAS
e19e89a5 6835 if (loglevel & CPU_LOG_TB_OP_OPT) {
2c0262af
FB
6836 fprintf(logfile, "AFTER FLAGS OPT:\n");
6837 dump_ops(gen_opc_buf, gen_opparam_buf);
6838 fprintf(logfile, "\n");
6839 }
6840#endif
6841 if (!search_pc)
6842 tb->size = pc_ptr - pc_start;
6843 return 0;
6844}
6845
6846int gen_intermediate_code(CPUState *env, TranslationBlock *tb)
6847{
6848 return gen_intermediate_code_internal(env, tb, 0);
6849}
6850
6851int gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
6852{
6853 return gen_intermediate_code_internal(env, tb, 1);
6854}
6855