]> git.proxmox.com Git - mirror_qemu.git/blame - target-i386/translate.c
SVM Support, by Alexander Graf.
[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 }
7eee2a50
FB
4891#ifdef USE_CODE_COPY
4892 s->tb->cflags |= CF_TB_FP_USED;
4893#endif
2c0262af
FB
4894 break;
4895 /************************/
4896 /* string ops */
4897
4898 case 0xa4: /* movsS */
4899 case 0xa5:
4900 if ((b & 1) == 0)
4901 ot = OT_BYTE;
4902 else
14ce26e7 4903 ot = dflag + OT_WORD;
2c0262af
FB
4904
4905 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
4906 gen_repz_movs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
4907 } else {
4908 gen_movs(s, ot);
4909 }
4910 break;
3b46e624 4911
2c0262af
FB
4912 case 0xaa: /* stosS */
4913 case 0xab:
4914 if ((b & 1) == 0)
4915 ot = OT_BYTE;
4916 else
14ce26e7 4917 ot = dflag + OT_WORD;
2c0262af
FB
4918
4919 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
4920 gen_repz_stos(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
4921 } else {
4922 gen_stos(s, ot);
4923 }
4924 break;
4925 case 0xac: /* lodsS */
4926 case 0xad:
4927 if ((b & 1) == 0)
4928 ot = OT_BYTE;
4929 else
14ce26e7 4930 ot = dflag + OT_WORD;
2c0262af
FB
4931 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
4932 gen_repz_lods(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
4933 } else {
4934 gen_lods(s, ot);
4935 }
4936 break;
4937 case 0xae: /* scasS */
4938 case 0xaf:
4939 if ((b & 1) == 0)
4940 ot = OT_BYTE;
4941 else
14ce26e7 4942 ot = dflag + OT_WORD;
2c0262af
FB
4943 if (prefixes & PREFIX_REPNZ) {
4944 gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
4945 } else if (prefixes & PREFIX_REPZ) {
4946 gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
4947 } else {
4948 gen_scas(s, ot);
4949 s->cc_op = CC_OP_SUBB + ot;
4950 }
4951 break;
4952
4953 case 0xa6: /* cmpsS */
4954 case 0xa7:
4955 if ((b & 1) == 0)
4956 ot = OT_BYTE;
4957 else
14ce26e7 4958 ot = dflag + OT_WORD;
2c0262af
FB
4959 if (prefixes & PREFIX_REPNZ) {
4960 gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
4961 } else if (prefixes & PREFIX_REPZ) {
4962 gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
4963 } else {
4964 gen_cmps(s, ot);
4965 s->cc_op = CC_OP_SUBB + ot;
4966 }
4967 break;
4968 case 0x6c: /* insS */
4969 case 0x6d:
f115e911
FB
4970 if ((b & 1) == 0)
4971 ot = OT_BYTE;
4972 else
4973 ot = dflag ? OT_LONG : OT_WORD;
4974 gen_check_io(s, ot, 1, pc_start - s->cs_base);
0573fbfc
TS
4975 gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
4976 gen_op_andl_T0_ffff();
4977 if (gen_svm_check_io(s, pc_start,
4978 SVM_IOIO_TYPE_MASK | (1 << (4+ot)) |
4979 svm_is_rep(prefixes) | 4 | (1 << (7+s->aflag))))
4980 break;
f115e911
FB
4981 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
4982 gen_repz_ins(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
2c0262af 4983 } else {
f115e911 4984 gen_ins(s, ot);
2c0262af
FB
4985 }
4986 break;
4987 case 0x6e: /* outsS */
4988 case 0x6f:
f115e911
FB
4989 if ((b & 1) == 0)
4990 ot = OT_BYTE;
4991 else
4992 ot = dflag ? OT_LONG : OT_WORD;
4993 gen_check_io(s, ot, 1, pc_start - s->cs_base);
0573fbfc
TS
4994 gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
4995 gen_op_andl_T0_ffff();
4996 if (gen_svm_check_io(s, pc_start,
4997 (1 << (4+ot)) | svm_is_rep(prefixes) |
4998 4 | (1 << (7+s->aflag))))
4999 break;
f115e911
FB
5000 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
5001 gen_repz_outs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
2c0262af 5002 } else {
f115e911 5003 gen_outs(s, ot);
2c0262af
FB
5004 }
5005 break;
5006
5007 /************************/
5008 /* port I/O */
0573fbfc 5009
2c0262af
FB
5010 case 0xe4:
5011 case 0xe5:
f115e911
FB
5012 if ((b & 1) == 0)
5013 ot = OT_BYTE;
5014 else
5015 ot = dflag ? OT_LONG : OT_WORD;
5016 val = ldub_code(s->pc++);
5017 gen_op_movl_T0_im(val);
5018 gen_check_io(s, ot, 0, pc_start - s->cs_base);
0573fbfc
TS
5019 if (gen_svm_check_io(s, pc_start,
5020 SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes) |
5021 (1 << (4+ot))))
5022 break;
f115e911
FB
5023 gen_op_in[ot]();
5024 gen_op_mov_reg_T1[ot][R_EAX]();
2c0262af
FB
5025 break;
5026 case 0xe6:
5027 case 0xe7:
f115e911
FB
5028 if ((b & 1) == 0)
5029 ot = OT_BYTE;
5030 else
5031 ot = dflag ? OT_LONG : OT_WORD;
5032 val = ldub_code(s->pc++);
5033 gen_op_movl_T0_im(val);
5034 gen_check_io(s, ot, 0, pc_start - s->cs_base);
0573fbfc
TS
5035 if (gen_svm_check_io(s, pc_start, svm_is_rep(prefixes) |
5036 (1 << (4+ot))))
5037 break;
f115e911
FB
5038 gen_op_mov_TN_reg[ot][1][R_EAX]();
5039 gen_op_out[ot]();
2c0262af
FB
5040 break;
5041 case 0xec:
5042 case 0xed:
f115e911
FB
5043 if ((b & 1) == 0)
5044 ot = OT_BYTE;
5045 else
5046 ot = dflag ? OT_LONG : OT_WORD;
5047 gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
4f31916f 5048 gen_op_andl_T0_ffff();
f115e911 5049 gen_check_io(s, ot, 0, pc_start - s->cs_base);
0573fbfc
TS
5050 if (gen_svm_check_io(s, pc_start,
5051 SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes) |
5052 (1 << (4+ot))))
5053 break;
f115e911
FB
5054 gen_op_in[ot]();
5055 gen_op_mov_reg_T1[ot][R_EAX]();
2c0262af
FB
5056 break;
5057 case 0xee:
5058 case 0xef:
f115e911
FB
5059 if ((b & 1) == 0)
5060 ot = OT_BYTE;
5061 else
5062 ot = dflag ? OT_LONG : OT_WORD;
5063 gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
4f31916f 5064 gen_op_andl_T0_ffff();
f115e911 5065 gen_check_io(s, ot, 0, pc_start - s->cs_base);
0573fbfc
TS
5066 if (gen_svm_check_io(s, pc_start,
5067 svm_is_rep(prefixes) | (1 << (4+ot))))
5068 break;
f115e911
FB
5069 gen_op_mov_TN_reg[ot][1][R_EAX]();
5070 gen_op_out[ot]();
2c0262af
FB
5071 break;
5072
5073 /************************/
5074 /* control */
5075 case 0xc2: /* ret im */
61382a50 5076 val = ldsw_code(s->pc);
2c0262af
FB
5077 s->pc += 2;
5078 gen_pop_T0(s);
8f091a59
FB
5079 if (CODE64(s) && s->dflag)
5080 s->dflag = 2;
2c0262af
FB
5081 gen_stack_update(s, val + (2 << s->dflag));
5082 if (s->dflag == 0)
5083 gen_op_andl_T0_ffff();
5084 gen_op_jmp_T0();
5085 gen_eob(s);
5086 break;
5087 case 0xc3: /* ret */
5088 gen_pop_T0(s);
5089 gen_pop_update(s);
5090 if (s->dflag == 0)
5091 gen_op_andl_T0_ffff();
5092 gen_op_jmp_T0();
5093 gen_eob(s);
5094 break;
5095 case 0xca: /* lret im */
61382a50 5096 val = ldsw_code(s->pc);
2c0262af
FB
5097 s->pc += 2;
5098 do_lret:
5099 if (s->pe && !s->vm86) {
5100 if (s->cc_op != CC_OP_DYNAMIC)
5101 gen_op_set_cc_op(s->cc_op);
14ce26e7 5102 gen_jmp_im(pc_start - s->cs_base);
2c0262af
FB
5103 gen_op_lret_protected(s->dflag, val);
5104 } else {
5105 gen_stack_A0(s);
5106 /* pop offset */
5107 gen_op_ld_T0_A0[1 + s->dflag + s->mem_index]();
5108 if (s->dflag == 0)
5109 gen_op_andl_T0_ffff();
5110 /* NOTE: keeping EIP updated is not a problem in case of
5111 exception */
5112 gen_op_jmp_T0();
5113 /* pop selector */
5114 gen_op_addl_A0_im(2 << s->dflag);
5115 gen_op_ld_T0_A0[1 + s->dflag + s->mem_index]();
5116 gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[R_CS]));
5117 /* add stack offset */
5118 gen_stack_update(s, val + (4 << s->dflag));
5119 }
5120 gen_eob(s);
5121 break;
5122 case 0xcb: /* lret */
5123 val = 0;
5124 goto do_lret;
5125 case 0xcf: /* iret */
0573fbfc
TS
5126 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_IRET))
5127 break;
2c0262af
FB
5128 if (!s->pe) {
5129 /* real mode */
5130 gen_op_iret_real(s->dflag);
5131 s->cc_op = CC_OP_EFLAGS;
f115e911
FB
5132 } else if (s->vm86) {
5133 if (s->iopl != 3) {
5134 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5135 } else {
5136 gen_op_iret_real(s->dflag);
5137 s->cc_op = CC_OP_EFLAGS;
5138 }
2c0262af
FB
5139 } else {
5140 if (s->cc_op != CC_OP_DYNAMIC)
5141 gen_op_set_cc_op(s->cc_op);
14ce26e7 5142 gen_jmp_im(pc_start - s->cs_base);
08cea4ee 5143 gen_op_iret_protected(s->dflag, s->pc - s->cs_base);
2c0262af
FB
5144 s->cc_op = CC_OP_EFLAGS;
5145 }
5146 gen_eob(s);
5147 break;
5148 case 0xe8: /* call im */
5149 {
14ce26e7
FB
5150 if (dflag)
5151 tval = (int32_t)insn_get(s, OT_LONG);
5152 else
5153 tval = (int16_t)insn_get(s, OT_WORD);
2c0262af 5154 next_eip = s->pc - s->cs_base;
14ce26e7 5155 tval += next_eip;
2c0262af 5156 if (s->dflag == 0)
14ce26e7
FB
5157 tval &= 0xffff;
5158 gen_movtl_T0_im(next_eip);
2c0262af 5159 gen_push_T0(s);
14ce26e7 5160 gen_jmp(s, tval);
2c0262af
FB
5161 }
5162 break;
5163 case 0x9a: /* lcall im */
5164 {
5165 unsigned int selector, offset;
3b46e624 5166
14ce26e7
FB
5167 if (CODE64(s))
5168 goto illegal_op;
2c0262af
FB
5169 ot = dflag ? OT_LONG : OT_WORD;
5170 offset = insn_get(s, ot);
5171 selector = insn_get(s, OT_WORD);
3b46e624 5172
2c0262af 5173 gen_op_movl_T0_im(selector);
14ce26e7 5174 gen_op_movl_T1_imu(offset);
2c0262af
FB
5175 }
5176 goto do_lcall;
ecada8a2 5177 case 0xe9: /* jmp im */
14ce26e7
FB
5178 if (dflag)
5179 tval = (int32_t)insn_get(s, OT_LONG);
5180 else
5181 tval = (int16_t)insn_get(s, OT_WORD);
5182 tval += s->pc - s->cs_base;
2c0262af 5183 if (s->dflag == 0)
14ce26e7
FB
5184 tval &= 0xffff;
5185 gen_jmp(s, tval);
2c0262af
FB
5186 break;
5187 case 0xea: /* ljmp im */
5188 {
5189 unsigned int selector, offset;
5190
14ce26e7
FB
5191 if (CODE64(s))
5192 goto illegal_op;
2c0262af
FB
5193 ot = dflag ? OT_LONG : OT_WORD;
5194 offset = insn_get(s, ot);
5195 selector = insn_get(s, OT_WORD);
3b46e624 5196
2c0262af 5197 gen_op_movl_T0_im(selector);
14ce26e7 5198 gen_op_movl_T1_imu(offset);
2c0262af
FB
5199 }
5200 goto do_ljmp;
5201 case 0xeb: /* jmp Jb */
14ce26e7
FB
5202 tval = (int8_t)insn_get(s, OT_BYTE);
5203 tval += s->pc - s->cs_base;
2c0262af 5204 if (s->dflag == 0)
14ce26e7
FB
5205 tval &= 0xffff;
5206 gen_jmp(s, tval);
2c0262af
FB
5207 break;
5208 case 0x70 ... 0x7f: /* jcc Jb */
14ce26e7 5209 tval = (int8_t)insn_get(s, OT_BYTE);
2c0262af
FB
5210 goto do_jcc;
5211 case 0x180 ... 0x18f: /* jcc Jv */
5212 if (dflag) {
14ce26e7 5213 tval = (int32_t)insn_get(s, OT_LONG);
2c0262af 5214 } else {
5fafdf24 5215 tval = (int16_t)insn_get(s, OT_WORD);
2c0262af
FB
5216 }
5217 do_jcc:
5218 next_eip = s->pc - s->cs_base;
14ce26e7 5219 tval += next_eip;
2c0262af 5220 if (s->dflag == 0)
14ce26e7
FB
5221 tval &= 0xffff;
5222 gen_jcc(s, b, tval, next_eip);
2c0262af
FB
5223 break;
5224
5225 case 0x190 ... 0x19f: /* setcc Gv */
61382a50 5226 modrm = ldub_code(s->pc++);
2c0262af
FB
5227 gen_setcc(s, b);
5228 gen_ldst_modrm(s, modrm, OT_BYTE, OR_TMP0, 1);
5229 break;
5230 case 0x140 ... 0x14f: /* cmov Gv, Ev */
14ce26e7 5231 ot = dflag + OT_WORD;
61382a50 5232 modrm = ldub_code(s->pc++);
14ce26e7 5233 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af
FB
5234 mod = (modrm >> 6) & 3;
5235 gen_setcc(s, b);
5236 if (mod != 3) {
5237 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
5238 gen_op_ld_T1_A0[ot + s->mem_index]();
5239 } else {
14ce26e7 5240 rm = (modrm & 7) | REX_B(s);
2c0262af
FB
5241 gen_op_mov_TN_reg[ot][1][rm]();
5242 }
5243 gen_op_cmov_reg_T1_T0[ot - OT_WORD][reg]();
5244 break;
3b46e624 5245
2c0262af
FB
5246 /************************/
5247 /* flags */
5248 case 0x9c: /* pushf */
0573fbfc
TS
5249 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_PUSHF))
5250 break;
2c0262af
FB
5251 if (s->vm86 && s->iopl != 3) {
5252 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5253 } else {
5254 if (s->cc_op != CC_OP_DYNAMIC)
5255 gen_op_set_cc_op(s->cc_op);
5256 gen_op_movl_T0_eflags();
5257 gen_push_T0(s);
5258 }
5259 break;
5260 case 0x9d: /* popf */
0573fbfc
TS
5261 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_POPF))
5262 break;
2c0262af
FB
5263 if (s->vm86 && s->iopl != 3) {
5264 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5265 } else {
5266 gen_pop_T0(s);
5267 if (s->cpl == 0) {
5268 if (s->dflag) {
5269 gen_op_movl_eflags_T0_cpl0();
5270 } else {
5271 gen_op_movw_eflags_T0_cpl0();
5272 }
5273 } else {
4136f33c
FB
5274 if (s->cpl <= s->iopl) {
5275 if (s->dflag) {
5276 gen_op_movl_eflags_T0_io();
5277 } else {
5278 gen_op_movw_eflags_T0_io();
5279 }
2c0262af 5280 } else {
4136f33c
FB
5281 if (s->dflag) {
5282 gen_op_movl_eflags_T0();
5283 } else {
5284 gen_op_movw_eflags_T0();
5285 }
2c0262af
FB
5286 }
5287 }
5288 gen_pop_update(s);
5289 s->cc_op = CC_OP_EFLAGS;
5290 /* abort translation because TF flag may change */
14ce26e7 5291 gen_jmp_im(s->pc - s->cs_base);
2c0262af
FB
5292 gen_eob(s);
5293 }
5294 break;
5295 case 0x9e: /* sahf */
14ce26e7
FB
5296 if (CODE64(s))
5297 goto illegal_op;
2c0262af
FB
5298 gen_op_mov_TN_reg[OT_BYTE][0][R_AH]();
5299 if (s->cc_op != CC_OP_DYNAMIC)
5300 gen_op_set_cc_op(s->cc_op);
5301 gen_op_movb_eflags_T0();
5302 s->cc_op = CC_OP_EFLAGS;
5303 break;
5304 case 0x9f: /* lahf */
14ce26e7
FB
5305 if (CODE64(s))
5306 goto illegal_op;
2c0262af
FB
5307 if (s->cc_op != CC_OP_DYNAMIC)
5308 gen_op_set_cc_op(s->cc_op);
5309 gen_op_movl_T0_eflags();
5310 gen_op_mov_reg_T0[OT_BYTE][R_AH]();
5311 break;
5312 case 0xf5: /* cmc */
5313 if (s->cc_op != CC_OP_DYNAMIC)
5314 gen_op_set_cc_op(s->cc_op);
5315 gen_op_cmc();
5316 s->cc_op = CC_OP_EFLAGS;
5317 break;
5318 case 0xf8: /* clc */
5319 if (s->cc_op != CC_OP_DYNAMIC)
5320 gen_op_set_cc_op(s->cc_op);
5321 gen_op_clc();
5322 s->cc_op = CC_OP_EFLAGS;
5323 break;
5324 case 0xf9: /* stc */
5325 if (s->cc_op != CC_OP_DYNAMIC)
5326 gen_op_set_cc_op(s->cc_op);
5327 gen_op_stc();
5328 s->cc_op = CC_OP_EFLAGS;
5329 break;
5330 case 0xfc: /* cld */
5331 gen_op_cld();
5332 break;
5333 case 0xfd: /* std */
5334 gen_op_std();
5335 break;
5336
5337 /************************/
5338 /* bit operations */
5339 case 0x1ba: /* bt/bts/btr/btc Gv, im */
14ce26e7 5340 ot = dflag + OT_WORD;
61382a50 5341 modrm = ldub_code(s->pc++);
33698e5f 5342 op = (modrm >> 3) & 7;
2c0262af 5343 mod = (modrm >> 6) & 3;
14ce26e7 5344 rm = (modrm & 7) | REX_B(s);
2c0262af 5345 if (mod != 3) {
14ce26e7 5346 s->rip_offset = 1;
2c0262af
FB
5347 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
5348 gen_op_ld_T0_A0[ot + s->mem_index]();
5349 } else {
5350 gen_op_mov_TN_reg[ot][0][rm]();
5351 }
5352 /* load shift */
61382a50 5353 val = ldub_code(s->pc++);
2c0262af
FB
5354 gen_op_movl_T1_im(val);
5355 if (op < 4)
5356 goto illegal_op;
5357 op -= 4;
5358 gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
5359 s->cc_op = CC_OP_SARB + ot;
5360 if (op != 0) {
5361 if (mod != 3)
5362 gen_op_st_T0_A0[ot + s->mem_index]();
5363 else
5364 gen_op_mov_reg_T0[ot][rm]();
5365 gen_op_update_bt_cc();
5366 }
5367 break;
5368 case 0x1a3: /* bt Gv, Ev */
5369 op = 0;
5370 goto do_btx;
5371 case 0x1ab: /* bts */
5372 op = 1;
5373 goto do_btx;
5374 case 0x1b3: /* btr */
5375 op = 2;
5376 goto do_btx;
5377 case 0x1bb: /* btc */
5378 op = 3;
5379 do_btx:
14ce26e7 5380 ot = dflag + OT_WORD;
61382a50 5381 modrm = ldub_code(s->pc++);
14ce26e7 5382 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af 5383 mod = (modrm >> 6) & 3;
14ce26e7 5384 rm = (modrm & 7) | REX_B(s);
2c0262af
FB
5385 gen_op_mov_TN_reg[OT_LONG][1][reg]();
5386 if (mod != 3) {
5387 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
5388 /* specific case: we need to add a displacement */
14ce26e7 5389 gen_op_add_bit_A0_T1[ot - OT_WORD]();
2c0262af
FB
5390 gen_op_ld_T0_A0[ot + s->mem_index]();
5391 } else {
5392 gen_op_mov_TN_reg[ot][0][rm]();
5393 }
5394 gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
5395 s->cc_op = CC_OP_SARB + ot;
5396 if (op != 0) {
5397 if (mod != 3)
5398 gen_op_st_T0_A0[ot + s->mem_index]();
5399 else
5400 gen_op_mov_reg_T0[ot][rm]();
5401 gen_op_update_bt_cc();
5402 }
5403 break;
5404 case 0x1bc: /* bsf */
5405 case 0x1bd: /* bsr */
14ce26e7 5406 ot = dflag + OT_WORD;
61382a50 5407 modrm = ldub_code(s->pc++);
14ce26e7 5408 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af 5409 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
686f3f26
FB
5410 /* NOTE: in order to handle the 0 case, we must load the
5411 result. It could be optimized with a generated jump */
5412 gen_op_mov_TN_reg[ot][1][reg]();
2c0262af 5413 gen_op_bsx_T0_cc[ot - OT_WORD][b & 1]();
686f3f26 5414 gen_op_mov_reg_T1[ot][reg]();
2c0262af
FB
5415 s->cc_op = CC_OP_LOGICB + ot;
5416 break;
5417 /************************/
5418 /* bcd */
5419 case 0x27: /* daa */
14ce26e7
FB
5420 if (CODE64(s))
5421 goto illegal_op;
2c0262af
FB
5422 if (s->cc_op != CC_OP_DYNAMIC)
5423 gen_op_set_cc_op(s->cc_op);
5424 gen_op_daa();
5425 s->cc_op = CC_OP_EFLAGS;
5426 break;
5427 case 0x2f: /* das */
14ce26e7
FB
5428 if (CODE64(s))
5429 goto illegal_op;
2c0262af
FB
5430 if (s->cc_op != CC_OP_DYNAMIC)
5431 gen_op_set_cc_op(s->cc_op);
5432 gen_op_das();
5433 s->cc_op = CC_OP_EFLAGS;
5434 break;
5435 case 0x37: /* aaa */
14ce26e7
FB
5436 if (CODE64(s))
5437 goto illegal_op;
2c0262af
FB
5438 if (s->cc_op != CC_OP_DYNAMIC)
5439 gen_op_set_cc_op(s->cc_op);
5440 gen_op_aaa();
5441 s->cc_op = CC_OP_EFLAGS;
5442 break;
5443 case 0x3f: /* aas */
14ce26e7
FB
5444 if (CODE64(s))
5445 goto illegal_op;
2c0262af
FB
5446 if (s->cc_op != CC_OP_DYNAMIC)
5447 gen_op_set_cc_op(s->cc_op);
5448 gen_op_aas();
5449 s->cc_op = CC_OP_EFLAGS;
5450 break;
5451 case 0xd4: /* aam */
14ce26e7
FB
5452 if (CODE64(s))
5453 goto illegal_op;
61382a50 5454 val = ldub_code(s->pc++);
b6d7c3db
TS
5455 if (val == 0) {
5456 gen_exception(s, EXCP00_DIVZ, pc_start - s->cs_base);
5457 } else {
5458 gen_op_aam(val);
5459 s->cc_op = CC_OP_LOGICB;
5460 }
2c0262af
FB
5461 break;
5462 case 0xd5: /* aad */
14ce26e7
FB
5463 if (CODE64(s))
5464 goto illegal_op;
61382a50 5465 val = ldub_code(s->pc++);
2c0262af
FB
5466 gen_op_aad(val);
5467 s->cc_op = CC_OP_LOGICB;
5468 break;
5469 /************************/
5470 /* misc */
5471 case 0x90: /* nop */
14ce26e7 5472 /* XXX: xchg + rex handling */
ab1f142b
FB
5473 /* XXX: correct lock test for all insn */
5474 if (prefixes & PREFIX_LOCK)
5475 goto illegal_op;
0573fbfc
TS
5476 if (prefixes & PREFIX_REPZ) {
5477 gen_svm_check_intercept(s, pc_start, SVM_EXIT_PAUSE);
5478 }
2c0262af
FB
5479 break;
5480 case 0x9b: /* fwait */
5fafdf24 5481 if ((s->flags & (HF_MP_MASK | HF_TS_MASK)) ==
7eee2a50
FB
5482 (HF_MP_MASK | HF_TS_MASK)) {
5483 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
2ee73ac3
FB
5484 } else {
5485 if (s->cc_op != CC_OP_DYNAMIC)
5486 gen_op_set_cc_op(s->cc_op);
14ce26e7 5487 gen_jmp_im(pc_start - s->cs_base);
2ee73ac3 5488 gen_op_fwait();
7eee2a50 5489 }
2c0262af
FB
5490 break;
5491 case 0xcc: /* int3 */
0573fbfc
TS
5492 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_SWINT))
5493 break;
2c0262af
FB
5494 gen_interrupt(s, EXCP03_INT3, pc_start - s->cs_base, s->pc - s->cs_base);
5495 break;
5496 case 0xcd: /* int N */
61382a50 5497 val = ldub_code(s->pc++);
0573fbfc
TS
5498 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_SWINT))
5499 break;
f115e911 5500 if (s->vm86 && s->iopl != 3) {
5fafdf24 5501 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
f115e911
FB
5502 } else {
5503 gen_interrupt(s, val, pc_start - s->cs_base, s->pc - s->cs_base);
5504 }
2c0262af
FB
5505 break;
5506 case 0xce: /* into */
14ce26e7
FB
5507 if (CODE64(s))
5508 goto illegal_op;
0573fbfc
TS
5509 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_SWINT))
5510 break;
2c0262af
FB
5511 if (s->cc_op != CC_OP_DYNAMIC)
5512 gen_op_set_cc_op(s->cc_op);
a8ede8ba
FB
5513 gen_jmp_im(pc_start - s->cs_base);
5514 gen_op_into(s->pc - pc_start);
2c0262af
FB
5515 break;
5516 case 0xf1: /* icebp (undocumented, exits to external debugger) */
0573fbfc
TS
5517 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_ICEBP))
5518 break;
aba9d61e 5519#if 1
2c0262af 5520 gen_debug(s, pc_start - s->cs_base);
aba9d61e
FB
5521#else
5522 /* start debug */
5523 tb_flush(cpu_single_env);
5524 cpu_set_log(CPU_LOG_INT | CPU_LOG_TB_IN_ASM);
5525#endif
2c0262af
FB
5526 break;
5527 case 0xfa: /* cli */
5528 if (!s->vm86) {
5529 if (s->cpl <= s->iopl) {
5530 gen_op_cli();
5531 } else {
5532 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5533 }
5534 } else {
5535 if (s->iopl == 3) {
5536 gen_op_cli();
5537 } else {
5538 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5539 }
5540 }
5541 break;
5542 case 0xfb: /* sti */
5543 if (!s->vm86) {
5544 if (s->cpl <= s->iopl) {
5545 gen_sti:
5546 gen_op_sti();
5547 /* interruptions are enabled only the first insn after sti */
a2cc3b24
FB
5548 /* If several instructions disable interrupts, only the
5549 _first_ does it */
5550 if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
5551 gen_op_set_inhibit_irq();
2c0262af 5552 /* give a chance to handle pending irqs */
14ce26e7 5553 gen_jmp_im(s->pc - s->cs_base);
0573fbfc
TS
5554 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_VINTR))
5555 break;
2c0262af
FB
5556 gen_eob(s);
5557 } else {
5558 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5559 }
5560 } else {
5561 if (s->iopl == 3) {
5562 goto gen_sti;
5563 } else {
5564 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5565 }
5566 }
5567 break;
5568 case 0x62: /* bound */
14ce26e7
FB
5569 if (CODE64(s))
5570 goto illegal_op;
2c0262af 5571 ot = dflag ? OT_LONG : OT_WORD;
61382a50 5572 modrm = ldub_code(s->pc++);
2c0262af
FB
5573 reg = (modrm >> 3) & 7;
5574 mod = (modrm >> 6) & 3;
5575 if (mod == 3)
5576 goto illegal_op;
cabf23c3 5577 gen_op_mov_TN_reg[ot][0][reg]();
2c0262af 5578 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
14ce26e7 5579 gen_jmp_im(pc_start - s->cs_base);
2c0262af 5580 if (ot == OT_WORD)
14ce26e7 5581 gen_op_boundw();
2c0262af 5582 else
14ce26e7 5583 gen_op_boundl();
2c0262af
FB
5584 break;
5585 case 0x1c8 ... 0x1cf: /* bswap reg */
14ce26e7
FB
5586 reg = (b & 7) | REX_B(s);
5587#ifdef TARGET_X86_64
5588 if (dflag == 2) {
5589 gen_op_mov_TN_reg[OT_QUAD][0][reg]();
5590 gen_op_bswapq_T0();
5591 gen_op_mov_reg_T0[OT_QUAD][reg]();
5fafdf24 5592 } else
14ce26e7
FB
5593#endif
5594 {
5595 gen_op_mov_TN_reg[OT_LONG][0][reg]();
5596 gen_op_bswapl_T0();
5597 gen_op_mov_reg_T0[OT_LONG][reg]();
5598 }
2c0262af
FB
5599 break;
5600 case 0xd6: /* salc */
14ce26e7
FB
5601 if (CODE64(s))
5602 goto illegal_op;
2c0262af
FB
5603 if (s->cc_op != CC_OP_DYNAMIC)
5604 gen_op_set_cc_op(s->cc_op);
5605 gen_op_salc();
5606 break;
5607 case 0xe0: /* loopnz */
5608 case 0xe1: /* loopz */
5609 if (s->cc_op != CC_OP_DYNAMIC)
5610 gen_op_set_cc_op(s->cc_op);
5611 /* FALL THRU */
5612 case 0xe2: /* loop */
5613 case 0xe3: /* jecxz */
14ce26e7
FB
5614 {
5615 int l1, l2;
5616
5617 tval = (int8_t)insn_get(s, OT_BYTE);
5618 next_eip = s->pc - s->cs_base;
5619 tval += next_eip;
5620 if (s->dflag == 0)
5621 tval &= 0xffff;
3b46e624 5622
14ce26e7
FB
5623 l1 = gen_new_label();
5624 l2 = gen_new_label();
5625 b &= 3;
5626 if (b == 3) {
5627 gen_op_jz_ecx[s->aflag](l1);
5628 } else {
5629 gen_op_dec_ECX[s->aflag]();
0b9dc5e4
FB
5630 if (b <= 1)
5631 gen_op_mov_T0_cc();
14ce26e7
FB
5632 gen_op_loop[s->aflag][b](l1);
5633 }
5634
5635 gen_jmp_im(next_eip);
5636 gen_op_jmp_label(l2);
5637 gen_set_label(l1);
5638 gen_jmp_im(tval);
5639 gen_set_label(l2);
5640 gen_eob(s);
5641 }
2c0262af
FB
5642 break;
5643 case 0x130: /* wrmsr */
5644 case 0x132: /* rdmsr */
5645 if (s->cpl != 0) {
5646 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5647 } else {
0573fbfc
TS
5648 int retval = 0;
5649 if (b & 2) {
5650 retval = gen_svm_check_intercept_param(s, pc_start, SVM_EXIT_MSR, 0);
2c0262af 5651 gen_op_rdmsr();
0573fbfc
TS
5652 } else {
5653 retval = gen_svm_check_intercept_param(s, pc_start, SVM_EXIT_MSR, 1);
2c0262af 5654 gen_op_wrmsr();
0573fbfc
TS
5655 }
5656 if(retval)
5657 gen_eob(s);
2c0262af
FB
5658 }
5659 break;
5660 case 0x131: /* rdtsc */
0573fbfc
TS
5661 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_RDTSC))
5662 break;
ecada8a2 5663 gen_jmp_im(pc_start - s->cs_base);
2c0262af
FB
5664 gen_op_rdtsc();
5665 break;
023fe10d 5666 case 0x134: /* sysenter */
14ce26e7
FB
5667 if (CODE64(s))
5668 goto illegal_op;
023fe10d
FB
5669 if (!s->pe) {
5670 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5671 } else {
5672 if (s->cc_op != CC_OP_DYNAMIC) {
5673 gen_op_set_cc_op(s->cc_op);
5674 s->cc_op = CC_OP_DYNAMIC;
5675 }
14ce26e7 5676 gen_jmp_im(pc_start - s->cs_base);
023fe10d
FB
5677 gen_op_sysenter();
5678 gen_eob(s);
5679 }
5680 break;
5681 case 0x135: /* sysexit */
14ce26e7
FB
5682 if (CODE64(s))
5683 goto illegal_op;
023fe10d
FB
5684 if (!s->pe) {
5685 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5686 } else {
5687 if (s->cc_op != CC_OP_DYNAMIC) {
5688 gen_op_set_cc_op(s->cc_op);
5689 s->cc_op = CC_OP_DYNAMIC;
5690 }
14ce26e7 5691 gen_jmp_im(pc_start - s->cs_base);
023fe10d
FB
5692 gen_op_sysexit();
5693 gen_eob(s);
5694 }
5695 break;
14ce26e7
FB
5696#ifdef TARGET_X86_64
5697 case 0x105: /* syscall */
5698 /* XXX: is it usable in real mode ? */
5699 if (s->cc_op != CC_OP_DYNAMIC) {
5700 gen_op_set_cc_op(s->cc_op);
5701 s->cc_op = CC_OP_DYNAMIC;
5702 }
5703 gen_jmp_im(pc_start - s->cs_base);
06c2f506 5704 gen_op_syscall(s->pc - pc_start);
14ce26e7
FB
5705 gen_eob(s);
5706 break;
5707 case 0x107: /* sysret */
5708 if (!s->pe) {
5709 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5710 } else {
5711 if (s->cc_op != CC_OP_DYNAMIC) {
5712 gen_op_set_cc_op(s->cc_op);
5713 s->cc_op = CC_OP_DYNAMIC;
5714 }
5715 gen_jmp_im(pc_start - s->cs_base);
5716 gen_op_sysret(s->dflag);
aba9d61e
FB
5717 /* condition codes are modified only in long mode */
5718 if (s->lma)
5719 s->cc_op = CC_OP_EFLAGS;
14ce26e7
FB
5720 gen_eob(s);
5721 }
5722 break;
5723#endif
2c0262af 5724 case 0x1a2: /* cpuid */
0573fbfc
TS
5725 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_CPUID))
5726 break;
2c0262af
FB
5727 gen_op_cpuid();
5728 break;
5729 case 0xf4: /* hlt */
5730 if (s->cpl != 0) {
5731 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5732 } else {
0573fbfc
TS
5733 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_HLT))
5734 break;
2c0262af
FB
5735 if (s->cc_op != CC_OP_DYNAMIC)
5736 gen_op_set_cc_op(s->cc_op);
14ce26e7 5737 gen_jmp_im(s->pc - s->cs_base);
2c0262af
FB
5738 gen_op_hlt();
5739 s->is_jmp = 3;
5740 }
5741 break;
5742 case 0x100:
61382a50 5743 modrm = ldub_code(s->pc++);
2c0262af
FB
5744 mod = (modrm >> 6) & 3;
5745 op = (modrm >> 3) & 7;
5746 switch(op) {
5747 case 0: /* sldt */
f115e911
FB
5748 if (!s->pe || s->vm86)
5749 goto illegal_op;
0573fbfc
TS
5750 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_READ))
5751 break;
2c0262af
FB
5752 gen_op_movl_T0_env(offsetof(CPUX86State,ldt.selector));
5753 ot = OT_WORD;
5754 if (mod == 3)
5755 ot += s->dflag;
5756 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
5757 break;
5758 case 2: /* lldt */
f115e911
FB
5759 if (!s->pe || s->vm86)
5760 goto illegal_op;
2c0262af
FB
5761 if (s->cpl != 0) {
5762 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5763 } else {
0573fbfc
TS
5764 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_WRITE))
5765 break;
2c0262af 5766 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
14ce26e7 5767 gen_jmp_im(pc_start - s->cs_base);
2c0262af
FB
5768 gen_op_lldt_T0();
5769 }
5770 break;
5771 case 1: /* str */
f115e911
FB
5772 if (!s->pe || s->vm86)
5773 goto illegal_op;
0573fbfc
TS
5774 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_READ))
5775 break;
2c0262af
FB
5776 gen_op_movl_T0_env(offsetof(CPUX86State,tr.selector));
5777 ot = OT_WORD;
5778 if (mod == 3)
5779 ot += s->dflag;
5780 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
5781 break;
5782 case 3: /* ltr */
f115e911
FB
5783 if (!s->pe || s->vm86)
5784 goto illegal_op;
2c0262af
FB
5785 if (s->cpl != 0) {
5786 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5787 } else {
0573fbfc
TS
5788 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_WRITE))
5789 break;
2c0262af 5790 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
14ce26e7 5791 gen_jmp_im(pc_start - s->cs_base);
2c0262af
FB
5792 gen_op_ltr_T0();
5793 }
5794 break;
5795 case 4: /* verr */
5796 case 5: /* verw */
f115e911
FB
5797 if (!s->pe || s->vm86)
5798 goto illegal_op;
5799 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
5800 if (s->cc_op != CC_OP_DYNAMIC)
5801 gen_op_set_cc_op(s->cc_op);
5802 if (op == 4)
5803 gen_op_verr();
5804 else
5805 gen_op_verw();
5806 s->cc_op = CC_OP_EFLAGS;
5807 break;
2c0262af
FB
5808 default:
5809 goto illegal_op;
5810 }
5811 break;
5812 case 0x101:
61382a50 5813 modrm = ldub_code(s->pc++);
2c0262af
FB
5814 mod = (modrm >> 6) & 3;
5815 op = (modrm >> 3) & 7;
3d7374c5 5816 rm = modrm & 7;
2c0262af
FB
5817 switch(op) {
5818 case 0: /* sgdt */
2c0262af
FB
5819 if (mod == 3)
5820 goto illegal_op;
0573fbfc
TS
5821 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_GDTR_READ))
5822 break;
2c0262af 5823 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3d7374c5 5824 gen_op_movl_T0_env(offsetof(CPUX86State, gdt.limit));
2c0262af 5825 gen_op_st_T0_A0[OT_WORD + s->mem_index]();
aba9d61e 5826 gen_add_A0_im(s, 2);
3d7374c5 5827 gen_op_movtl_T0_env(offsetof(CPUX86State, gdt.base));
2c0262af
FB
5828 if (!s->dflag)
5829 gen_op_andl_T0_im(0xffffff);
14ce26e7 5830 gen_op_st_T0_A0[CODE64(s) + OT_LONG + s->mem_index]();
2c0262af 5831 break;
3d7374c5
FB
5832 case 1:
5833 if (mod == 3) {
5834 switch (rm) {
5835 case 0: /* monitor */
5836 if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) ||
5837 s->cpl != 0)
5838 goto illegal_op;
0573fbfc
TS
5839 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_MONITOR))
5840 break;
3d7374c5
FB
5841 gen_jmp_im(pc_start - s->cs_base);
5842#ifdef TARGET_X86_64
5843 if (s->aflag == 2) {
5844 gen_op_movq_A0_reg[R_EBX]();
5845 gen_op_addq_A0_AL();
5fafdf24 5846 } else
3d7374c5
FB
5847#endif
5848 {
5849 gen_op_movl_A0_reg[R_EBX]();
5850 gen_op_addl_A0_AL();
5851 if (s->aflag == 0)
5852 gen_op_andl_A0_ffff();
5853 }
5854 gen_add_A0_ds_seg(s);
5855 gen_op_monitor();
5856 break;
5857 case 1: /* mwait */
5858 if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) ||
5859 s->cpl != 0)
5860 goto illegal_op;
5861 if (s->cc_op != CC_OP_DYNAMIC) {
5862 gen_op_set_cc_op(s->cc_op);
5863 s->cc_op = CC_OP_DYNAMIC;
5864 }
0573fbfc
TS
5865 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_MWAIT))
5866 break;
3d7374c5
FB
5867 gen_jmp_im(s->pc - s->cs_base);
5868 gen_op_mwait();
5869 gen_eob(s);
5870 break;
5871 default:
5872 goto illegal_op;
5873 }
5874 } else { /* sidt */
0573fbfc
TS
5875 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_IDTR_READ))
5876 break;
3d7374c5
FB
5877 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
5878 gen_op_movl_T0_env(offsetof(CPUX86State, idt.limit));
5879 gen_op_st_T0_A0[OT_WORD + s->mem_index]();
5880 gen_add_A0_im(s, 2);
5881 gen_op_movtl_T0_env(offsetof(CPUX86State, idt.base));
5882 if (!s->dflag)
5883 gen_op_andl_T0_im(0xffffff);
5884 gen_op_st_T0_A0[CODE64(s) + OT_LONG + s->mem_index]();
5885 }
5886 break;
2c0262af
FB
5887 case 2: /* lgdt */
5888 case 3: /* lidt */
0573fbfc
TS
5889 if (mod == 3) {
5890 switch(rm) {
5891 case 0: /* VMRUN */
5892 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_VMRUN))
5893 break;
5894 if (s->cc_op != CC_OP_DYNAMIC)
5895 gen_op_set_cc_op(s->cc_op);
5896 gen_jmp_im(s->pc - s->cs_base);
5897 gen_op_vmrun();
5898 s->cc_op = CC_OP_EFLAGS;
5899 gen_eob(s);
5900 break;
5901 case 1: /* VMMCALL */
5902 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_VMMCALL))
5903 break;
5904 /* FIXME: cause #UD if hflags & SVM */
5905 gen_op_vmmcall();
5906 break;
5907 case 2: /* VMLOAD */
5908 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_VMLOAD))
5909 break;
5910 gen_op_vmload();
5911 break;
5912 case 3: /* VMSAVE */
5913 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_VMSAVE))
5914 break;
5915 gen_op_vmsave();
5916 break;
5917 case 4: /* STGI */
5918 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_STGI))
5919 break;
5920 gen_op_stgi();
5921 break;
5922 case 5: /* CLGI */
5923 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_CLGI))
5924 break;
5925 gen_op_clgi();
5926 break;
5927 case 6: /* SKINIT */
5928 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_SKINIT))
5929 break;
5930 gen_op_skinit();
5931 break;
5932 case 7: /* INVLPGA */
5933 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_INVLPGA))
5934 break;
5935 gen_op_invlpga();
5936 break;
5937 default:
5938 goto illegal_op;
5939 }
5940 } else if (s->cpl != 0) {
2c0262af
FB
5941 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5942 } else {
0573fbfc
TS
5943 if (gen_svm_check_intercept(s, pc_start,
5944 op==2 ? SVM_EXIT_GDTR_WRITE : SVM_EXIT_IDTR_WRITE))
5945 break;
2c0262af
FB
5946 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
5947 gen_op_ld_T1_A0[OT_WORD + s->mem_index]();
aba9d61e 5948 gen_add_A0_im(s, 2);
14ce26e7 5949 gen_op_ld_T0_A0[CODE64(s) + OT_LONG + s->mem_index]();
2c0262af
FB
5950 if (!s->dflag)
5951 gen_op_andl_T0_im(0xffffff);
5952 if (op == 2) {
14ce26e7 5953 gen_op_movtl_env_T0(offsetof(CPUX86State,gdt.base));
2c0262af
FB
5954 gen_op_movl_env_T1(offsetof(CPUX86State,gdt.limit));
5955 } else {
14ce26e7 5956 gen_op_movtl_env_T0(offsetof(CPUX86State,idt.base));
2c0262af
FB
5957 gen_op_movl_env_T1(offsetof(CPUX86State,idt.limit));
5958 }
5959 }
5960 break;
5961 case 4: /* smsw */
0573fbfc
TS
5962 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_CR0))
5963 break;
2c0262af
FB
5964 gen_op_movl_T0_env(offsetof(CPUX86State,cr[0]));
5965 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 1);
5966 break;
5967 case 6: /* lmsw */
5968 if (s->cpl != 0) {
5969 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5970 } else {
0573fbfc
TS
5971 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0))
5972 break;
2c0262af
FB
5973 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
5974 gen_op_lmsw_T0();
14ce26e7 5975 gen_jmp_im(s->pc - s->cs_base);
d71b9a8b 5976 gen_eob(s);
2c0262af
FB
5977 }
5978 break;
5979 case 7: /* invlpg */
5980 if (s->cpl != 0) {
5981 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5982 } else {
14ce26e7
FB
5983 if (mod == 3) {
5984#ifdef TARGET_X86_64
3d7374c5 5985 if (CODE64(s) && rm == 0) {
14ce26e7
FB
5986 /* swapgs */
5987 gen_op_movtl_T0_env(offsetof(CPUX86State,segs[R_GS].base));
5988 gen_op_movtl_T1_env(offsetof(CPUX86State,kernelgsbase));
5989 gen_op_movtl_env_T1(offsetof(CPUX86State,segs[R_GS].base));
5990 gen_op_movtl_env_T0(offsetof(CPUX86State,kernelgsbase));
5fafdf24 5991 } else
14ce26e7
FB
5992#endif
5993 {
5994 goto illegal_op;
5995 }
5996 } else {
0573fbfc
TS
5997 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_INVLPG))
5998 break;
14ce26e7
FB
5999 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
6000 gen_op_invlpg_A0();
6001 gen_jmp_im(s->pc - s->cs_base);
6002 gen_eob(s);
6003 }
2c0262af
FB
6004 }
6005 break;
6006 default:
6007 goto illegal_op;
6008 }
6009 break;
3415a4dd
FB
6010 case 0x108: /* invd */
6011 case 0x109: /* wbinvd */
6012 if (s->cpl != 0) {
6013 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6014 } else {
0573fbfc
TS
6015 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_INVD))
6016 break;
3415a4dd
FB
6017 /* nothing to do */
6018 }
6019 break;
14ce26e7
FB
6020 case 0x63: /* arpl or movslS (x86_64) */
6021#ifdef TARGET_X86_64
6022 if (CODE64(s)) {
6023 int d_ot;
6024 /* d_ot is the size of destination */
6025 d_ot = dflag + OT_WORD;
6026
6027 modrm = ldub_code(s->pc++);
6028 reg = ((modrm >> 3) & 7) | rex_r;
6029 mod = (modrm >> 6) & 3;
6030 rm = (modrm & 7) | REX_B(s);
3b46e624 6031
14ce26e7
FB
6032 if (mod == 3) {
6033 gen_op_mov_TN_reg[OT_LONG][0][rm]();
6034 /* sign extend */
6035 if (d_ot == OT_QUAD)
6036 gen_op_movslq_T0_T0();
6037 gen_op_mov_reg_T0[d_ot][reg]();
6038 } else {
6039 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
6040 if (d_ot == OT_QUAD) {
6041 gen_op_lds_T0_A0[OT_LONG + s->mem_index]();
6042 } else {
6043 gen_op_ld_T0_A0[OT_LONG + s->mem_index]();
6044 }
6045 gen_op_mov_reg_T0[d_ot][reg]();
6046 }
5fafdf24 6047 } else
14ce26e7
FB
6048#endif
6049 {
6050 if (!s->pe || s->vm86)
6051 goto illegal_op;
6052 ot = dflag ? OT_LONG : OT_WORD;
6053 modrm = ldub_code(s->pc++);
6054 reg = (modrm >> 3) & 7;
6055 mod = (modrm >> 6) & 3;
6056 rm = modrm & 7;
6057 if (mod != 3) {
6058 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
6059 gen_op_ld_T0_A0[ot + s->mem_index]();
6060 } else {
6061 gen_op_mov_TN_reg[ot][0][rm]();
6062 }
6063 if (s->cc_op != CC_OP_DYNAMIC)
6064 gen_op_set_cc_op(s->cc_op);
6065 gen_op_arpl();
6066 s->cc_op = CC_OP_EFLAGS;
6067 if (mod != 3) {
6068 gen_op_st_T0_A0[ot + s->mem_index]();
6069 } else {
6070 gen_op_mov_reg_T0[ot][rm]();
6071 }
6072 gen_op_arpl_update();
f115e911 6073 }
f115e911 6074 break;
2c0262af
FB
6075 case 0x102: /* lar */
6076 case 0x103: /* lsl */
6077 if (!s->pe || s->vm86)
6078 goto illegal_op;
6079 ot = dflag ? OT_LONG : OT_WORD;
61382a50 6080 modrm = ldub_code(s->pc++);
14ce26e7 6081 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af
FB
6082 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
6083 gen_op_mov_TN_reg[ot][1][reg]();
6084 if (s->cc_op != CC_OP_DYNAMIC)
6085 gen_op_set_cc_op(s->cc_op);
6086 if (b == 0x102)
6087 gen_op_lar();
6088 else
6089 gen_op_lsl();
6090 s->cc_op = CC_OP_EFLAGS;
6091 gen_op_mov_reg_T1[ot][reg]();
6092 break;
6093 case 0x118:
61382a50 6094 modrm = ldub_code(s->pc++);
2c0262af
FB
6095 mod = (modrm >> 6) & 3;
6096 op = (modrm >> 3) & 7;
6097 switch(op) {
6098 case 0: /* prefetchnta */
6099 case 1: /* prefetchnt0 */
6100 case 2: /* prefetchnt0 */
6101 case 3: /* prefetchnt0 */
6102 if (mod == 3)
6103 goto illegal_op;
6104 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
6105 /* nothing more to do */
6106 break;
e17a36ce
FB
6107 default: /* nop (multi byte) */
6108 gen_nop_modrm(s, modrm);
6109 break;
2c0262af
FB
6110 }
6111 break;
e17a36ce
FB
6112 case 0x119 ... 0x11f: /* nop (multi byte) */
6113 modrm = ldub_code(s->pc++);
6114 gen_nop_modrm(s, modrm);
6115 break;
2c0262af
FB
6116 case 0x120: /* mov reg, crN */
6117 case 0x122: /* mov crN, reg */
6118 if (s->cpl != 0) {
6119 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6120 } else {
61382a50 6121 modrm = ldub_code(s->pc++);
2c0262af
FB
6122 if ((modrm & 0xc0) != 0xc0)
6123 goto illegal_op;
14ce26e7
FB
6124 rm = (modrm & 7) | REX_B(s);
6125 reg = ((modrm >> 3) & 7) | rex_r;
6126 if (CODE64(s))
6127 ot = OT_QUAD;
6128 else
6129 ot = OT_LONG;
2c0262af
FB
6130 switch(reg) {
6131 case 0:
6132 case 2:
6133 case 3:
6134 case 4:
9230e66e 6135 case 8:
2c0262af 6136 if (b & 2) {
0573fbfc 6137 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0 + reg);
14ce26e7 6138 gen_op_mov_TN_reg[ot][0][rm]();
2c0262af 6139 gen_op_movl_crN_T0(reg);
14ce26e7 6140 gen_jmp_im(s->pc - s->cs_base);
2c0262af
FB
6141 gen_eob(s);
6142 } else {
0573fbfc 6143 gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_CR0 + reg);
5fafdf24 6144#if !defined(CONFIG_USER_ONLY)
9230e66e
FB
6145 if (reg == 8)
6146 gen_op_movtl_T0_cr8();
6147 else
82e41634 6148#endif
9230e66e 6149 gen_op_movtl_T0_env(offsetof(CPUX86State,cr[reg]));
14ce26e7 6150 gen_op_mov_reg_T0[ot][rm]();
2c0262af
FB
6151 }
6152 break;
6153 default:
6154 goto illegal_op;
6155 }
6156 }
6157 break;
6158 case 0x121: /* mov reg, drN */
6159 case 0x123: /* mov drN, reg */
6160 if (s->cpl != 0) {
6161 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6162 } else {
61382a50 6163 modrm = ldub_code(s->pc++);
2c0262af
FB
6164 if ((modrm & 0xc0) != 0xc0)
6165 goto illegal_op;
14ce26e7
FB
6166 rm = (modrm & 7) | REX_B(s);
6167 reg = ((modrm >> 3) & 7) | rex_r;
6168 if (CODE64(s))
6169 ot = OT_QUAD;
6170 else
6171 ot = OT_LONG;
2c0262af 6172 /* XXX: do it dynamically with CR4.DE bit */
14ce26e7 6173 if (reg == 4 || reg == 5 || reg >= 8)
2c0262af
FB
6174 goto illegal_op;
6175 if (b & 2) {
0573fbfc 6176 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_DR0 + reg);
14ce26e7 6177 gen_op_mov_TN_reg[ot][0][rm]();
2c0262af 6178 gen_op_movl_drN_T0(reg);
14ce26e7 6179 gen_jmp_im(s->pc - s->cs_base);
2c0262af
FB
6180 gen_eob(s);
6181 } else {
0573fbfc 6182 gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_DR0 + reg);
14ce26e7
FB
6183 gen_op_movtl_T0_env(offsetof(CPUX86State,dr[reg]));
6184 gen_op_mov_reg_T0[ot][rm]();
2c0262af
FB
6185 }
6186 }
6187 break;
6188 case 0x106: /* clts */
6189 if (s->cpl != 0) {
6190 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6191 } else {
0573fbfc 6192 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0);
2c0262af 6193 gen_op_clts();
7eee2a50 6194 /* abort block because static cpu state changed */
14ce26e7 6195 gen_jmp_im(s->pc - s->cs_base);
7eee2a50 6196 gen_eob(s);
2c0262af
FB
6197 }
6198 break;
664e0f19
FB
6199 /* MMX/SSE/SSE2/PNI support */
6200 case 0x1c3: /* MOVNTI reg, mem */
6201 if (!(s->cpuid_features & CPUID_SSE2))
14ce26e7 6202 goto illegal_op;
664e0f19
FB
6203 ot = s->dflag == 2 ? OT_QUAD : OT_LONG;
6204 modrm = ldub_code(s->pc++);
6205 mod = (modrm >> 6) & 3;
6206 if (mod == 3)
6207 goto illegal_op;
6208 reg = ((modrm >> 3) & 7) | rex_r;
6209 /* generate a generic store */
6210 gen_ldst_modrm(s, modrm, ot, reg, 1);
14ce26e7 6211 break;
664e0f19
FB
6212 case 0x1ae:
6213 modrm = ldub_code(s->pc++);
6214 mod = (modrm >> 6) & 3;
6215 op = (modrm >> 3) & 7;
6216 switch(op) {
6217 case 0: /* fxsave */
5fafdf24 6218 if (mod == 3 || !(s->cpuid_features & CPUID_FXSR) ||
0fd14b72 6219 (s->flags & HF_EM_MASK))
14ce26e7 6220 goto illegal_op;
0fd14b72
FB
6221 if (s->flags & HF_TS_MASK) {
6222 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
6223 break;
6224 }
664e0f19
FB
6225 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
6226 gen_op_fxsave_A0((s->dflag == 2));
6227 break;
6228 case 1: /* fxrstor */
5fafdf24 6229 if (mod == 3 || !(s->cpuid_features & CPUID_FXSR) ||
0fd14b72 6230 (s->flags & HF_EM_MASK))
14ce26e7 6231 goto illegal_op;
0fd14b72
FB
6232 if (s->flags & HF_TS_MASK) {
6233 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
6234 break;
6235 }
664e0f19
FB
6236 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
6237 gen_op_fxrstor_A0((s->dflag == 2));
6238 break;
6239 case 2: /* ldmxcsr */
6240 case 3: /* stmxcsr */
6241 if (s->flags & HF_TS_MASK) {
6242 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
6243 break;
14ce26e7 6244 }
664e0f19
FB
6245 if ((s->flags & HF_EM_MASK) || !(s->flags & HF_OSFXSR_MASK) ||
6246 mod == 3)
14ce26e7 6247 goto illegal_op;
664e0f19
FB
6248 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
6249 if (op == 2) {
6250 gen_op_ld_T0_A0[OT_LONG + s->mem_index]();
6251 gen_op_movl_env_T0(offsetof(CPUX86State, mxcsr));
14ce26e7 6252 } else {
664e0f19
FB
6253 gen_op_movl_T0_env(offsetof(CPUX86State, mxcsr));
6254 gen_op_st_T0_A0[OT_LONG + s->mem_index]();
14ce26e7 6255 }
664e0f19
FB
6256 break;
6257 case 5: /* lfence */
6258 case 6: /* mfence */
664e0f19
FB
6259 if ((modrm & 0xc7) != 0xc0 || !(s->cpuid_features & CPUID_SSE))
6260 goto illegal_op;
6261 break;
8f091a59
FB
6262 case 7: /* sfence / clflush */
6263 if ((modrm & 0xc7) == 0xc0) {
6264 /* sfence */
6265 if (!(s->cpuid_features & CPUID_SSE))
6266 goto illegal_op;
6267 } else {
6268 /* clflush */
6269 if (!(s->cpuid_features & CPUID_CLFLUSH))
6270 goto illegal_op;
6271 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
6272 }
6273 break;
664e0f19 6274 default:
14ce26e7
FB
6275 goto illegal_op;
6276 }
6277 break;
8f091a59
FB
6278 case 0x10d: /* prefetch */
6279 modrm = ldub_code(s->pc++);
6280 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
6281 /* ignore for now */
6282 break;
3b21e03e 6283 case 0x1aa: /* rsm */
0573fbfc
TS
6284 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_RSM))
6285 break;
3b21e03e
FB
6286 if (!(s->flags & HF_SMM_MASK))
6287 goto illegal_op;
6288 if (s->cc_op != CC_OP_DYNAMIC) {
6289 gen_op_set_cc_op(s->cc_op);
6290 s->cc_op = CC_OP_DYNAMIC;
6291 }
6292 gen_jmp_im(s->pc - s->cs_base);
6293 gen_op_rsm();
6294 gen_eob(s);
6295 break;
664e0f19
FB
6296 case 0x110 ... 0x117:
6297 case 0x128 ... 0x12f:
6298 case 0x150 ... 0x177:
6299 case 0x17c ... 0x17f:
6300 case 0x1c2:
6301 case 0x1c4 ... 0x1c6:
6302 case 0x1d0 ... 0x1fe:
6303 gen_sse(s, b, pc_start, rex_r);
6304 break;
2c0262af
FB
6305 default:
6306 goto illegal_op;
6307 }
6308 /* lock generation */
6309 if (s->prefix & PREFIX_LOCK)
6310 gen_op_unlock();
6311 return s->pc;
6312 illegal_op:
ab1f142b
FB
6313 if (s->prefix & PREFIX_LOCK)
6314 gen_op_unlock();
2c0262af
FB
6315 /* XXX: ensure that no lock was generated */
6316 gen_exception(s, EXCP06_ILLOP, pc_start - s->cs_base);
6317 return s->pc;
6318}
6319
6320#define CC_OSZAPC (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C)
6321#define CC_OSZAP (CC_O | CC_S | CC_Z | CC_A | CC_P)
6322
6323/* flags read by an operation */
5fafdf24 6324static uint16_t opc_read_flags[NB_OPS] = {
2c0262af
FB
6325 [INDEX_op_aas] = CC_A,
6326 [INDEX_op_aaa] = CC_A,
6327 [INDEX_op_das] = CC_A | CC_C,
6328 [INDEX_op_daa] = CC_A | CC_C,
6329
2c0262af 6330 /* subtle: due to the incl/decl implementation, C is used */
5fafdf24 6331 [INDEX_op_update_inc_cc] = CC_C,
2c0262af
FB
6332
6333 [INDEX_op_into] = CC_O,
6334
6335 [INDEX_op_jb_subb] = CC_C,
6336 [INDEX_op_jb_subw] = CC_C,
6337 [INDEX_op_jb_subl] = CC_C,
6338
6339 [INDEX_op_jz_subb] = CC_Z,
6340 [INDEX_op_jz_subw] = CC_Z,
6341 [INDEX_op_jz_subl] = CC_Z,
6342
6343 [INDEX_op_jbe_subb] = CC_Z | CC_C,
6344 [INDEX_op_jbe_subw] = CC_Z | CC_C,
6345 [INDEX_op_jbe_subl] = CC_Z | CC_C,
6346
6347 [INDEX_op_js_subb] = CC_S,
6348 [INDEX_op_js_subw] = CC_S,
6349 [INDEX_op_js_subl] = CC_S,
6350
6351 [INDEX_op_jl_subb] = CC_O | CC_S,
6352 [INDEX_op_jl_subw] = CC_O | CC_S,
6353 [INDEX_op_jl_subl] = CC_O | CC_S,
6354
6355 [INDEX_op_jle_subb] = CC_O | CC_S | CC_Z,
6356 [INDEX_op_jle_subw] = CC_O | CC_S | CC_Z,
6357 [INDEX_op_jle_subl] = CC_O | CC_S | CC_Z,
6358
6359 [INDEX_op_loopnzw] = CC_Z,
6360 [INDEX_op_loopnzl] = CC_Z,
6361 [INDEX_op_loopzw] = CC_Z,
6362 [INDEX_op_loopzl] = CC_Z,
6363
6364 [INDEX_op_seto_T0_cc] = CC_O,
6365 [INDEX_op_setb_T0_cc] = CC_C,
6366 [INDEX_op_setz_T0_cc] = CC_Z,
6367 [INDEX_op_setbe_T0_cc] = CC_Z | CC_C,
6368 [INDEX_op_sets_T0_cc] = CC_S,
6369 [INDEX_op_setp_T0_cc] = CC_P,
6370 [INDEX_op_setl_T0_cc] = CC_O | CC_S,
6371 [INDEX_op_setle_T0_cc] = CC_O | CC_S | CC_Z,
6372
6373 [INDEX_op_setb_T0_subb] = CC_C,
6374 [INDEX_op_setb_T0_subw] = CC_C,
6375 [INDEX_op_setb_T0_subl] = CC_C,
6376
6377 [INDEX_op_setz_T0_subb] = CC_Z,
6378 [INDEX_op_setz_T0_subw] = CC_Z,
6379 [INDEX_op_setz_T0_subl] = CC_Z,
6380
6381 [INDEX_op_setbe_T0_subb] = CC_Z | CC_C,
6382 [INDEX_op_setbe_T0_subw] = CC_Z | CC_C,
6383 [INDEX_op_setbe_T0_subl] = CC_Z | CC_C,
6384
6385 [INDEX_op_sets_T0_subb] = CC_S,
6386 [INDEX_op_sets_T0_subw] = CC_S,
6387 [INDEX_op_sets_T0_subl] = CC_S,
6388
6389 [INDEX_op_setl_T0_subb] = CC_O | CC_S,
6390 [INDEX_op_setl_T0_subw] = CC_O | CC_S,
6391 [INDEX_op_setl_T0_subl] = CC_O | CC_S,
6392
6393 [INDEX_op_setle_T0_subb] = CC_O | CC_S | CC_Z,
6394 [INDEX_op_setle_T0_subw] = CC_O | CC_S | CC_Z,
6395 [INDEX_op_setle_T0_subl] = CC_O | CC_S | CC_Z,
6396
6397 [INDEX_op_movl_T0_eflags] = CC_OSZAPC,
6398 [INDEX_op_cmc] = CC_C,
6399 [INDEX_op_salc] = CC_C,
6400
7399c5a9 6401 /* needed for correct flag optimisation before string ops */
14ce26e7
FB
6402 [INDEX_op_jnz_ecxw] = CC_OSZAPC,
6403 [INDEX_op_jnz_ecxl] = CC_OSZAPC,
7399c5a9
FB
6404 [INDEX_op_jz_ecxw] = CC_OSZAPC,
6405 [INDEX_op_jz_ecxl] = CC_OSZAPC,
14ce26e7
FB
6406
6407#ifdef TARGET_X86_64
6408 [INDEX_op_jb_subq] = CC_C,
6409 [INDEX_op_jz_subq] = CC_Z,
6410 [INDEX_op_jbe_subq] = CC_Z | CC_C,
6411 [INDEX_op_js_subq] = CC_S,
6412 [INDEX_op_jl_subq] = CC_O | CC_S,
6413 [INDEX_op_jle_subq] = CC_O | CC_S | CC_Z,
6414
6415 [INDEX_op_loopnzq] = CC_Z,
6416 [INDEX_op_loopzq] = CC_Z,
6417
6418 [INDEX_op_setb_T0_subq] = CC_C,
6419 [INDEX_op_setz_T0_subq] = CC_Z,
6420 [INDEX_op_setbe_T0_subq] = CC_Z | CC_C,
6421 [INDEX_op_sets_T0_subq] = CC_S,
6422 [INDEX_op_setl_T0_subq] = CC_O | CC_S,
6423 [INDEX_op_setle_T0_subq] = CC_O | CC_S | CC_Z,
6424
6425 [INDEX_op_jnz_ecxq] = CC_OSZAPC,
6426 [INDEX_op_jz_ecxq] = CC_OSZAPC,
6427#endif
7399c5a9 6428
4f31916f
FB
6429#define DEF_READF(SUFFIX)\
6430 [INDEX_op_adcb ## SUFFIX ## _T0_T1_cc] = CC_C,\
6431 [INDEX_op_adcw ## SUFFIX ## _T0_T1_cc] = CC_C,\
6432 [INDEX_op_adcl ## SUFFIX ## _T0_T1_cc] = CC_C,\
14ce26e7 6433 X86_64_DEF([INDEX_op_adcq ## SUFFIX ## _T0_T1_cc] = CC_C,)\
4f31916f
FB
6434 [INDEX_op_sbbb ## SUFFIX ## _T0_T1_cc] = CC_C,\
6435 [INDEX_op_sbbw ## SUFFIX ## _T0_T1_cc] = CC_C,\
6436 [INDEX_op_sbbl ## SUFFIX ## _T0_T1_cc] = CC_C,\
14ce26e7 6437 X86_64_DEF([INDEX_op_sbbq ## SUFFIX ## _T0_T1_cc] = CC_C,)\
4f31916f
FB
6438\
6439 [INDEX_op_rclb ## SUFFIX ## _T0_T1_cc] = CC_C,\
6440 [INDEX_op_rclw ## SUFFIX ## _T0_T1_cc] = CC_C,\
6441 [INDEX_op_rcll ## SUFFIX ## _T0_T1_cc] = CC_C,\
14ce26e7 6442 X86_64_DEF([INDEX_op_rclq ## SUFFIX ## _T0_T1_cc] = CC_C,)\
4f31916f
FB
6443 [INDEX_op_rcrb ## SUFFIX ## _T0_T1_cc] = CC_C,\
6444 [INDEX_op_rcrw ## SUFFIX ## _T0_T1_cc] = CC_C,\
14ce26e7
FB
6445 [INDEX_op_rcrl ## SUFFIX ## _T0_T1_cc] = CC_C,\
6446 X86_64_DEF([INDEX_op_rcrq ## SUFFIX ## _T0_T1_cc] = CC_C,)
4f31916f 6447
4bb2fcc7 6448 DEF_READF( )
4f31916f
FB
6449 DEF_READF(_raw)
6450#ifndef CONFIG_USER_ONLY
6451 DEF_READF(_kernel)
6452 DEF_READF(_user)
6453#endif
2c0262af
FB
6454};
6455
6456/* flags written by an operation */
5fafdf24 6457static uint16_t opc_write_flags[NB_OPS] = {
2c0262af
FB
6458 [INDEX_op_update2_cc] = CC_OSZAPC,
6459 [INDEX_op_update1_cc] = CC_OSZAPC,
6460 [INDEX_op_cmpl_T0_T1_cc] = CC_OSZAPC,
6461 [INDEX_op_update_neg_cc] = CC_OSZAPC,
6462 /* subtle: due to the incl/decl implementation, C is used */
5fafdf24 6463 [INDEX_op_update_inc_cc] = CC_OSZAPC,
2c0262af
FB
6464 [INDEX_op_testl_T0_T1_cc] = CC_OSZAPC,
6465
2c0262af 6466 [INDEX_op_mulb_AL_T0] = CC_OSZAPC,
2c0262af 6467 [INDEX_op_mulw_AX_T0] = CC_OSZAPC,
2c0262af 6468 [INDEX_op_mull_EAX_T0] = CC_OSZAPC,
14ce26e7
FB
6469 X86_64_DEF([INDEX_op_mulq_EAX_T0] = CC_OSZAPC,)
6470 [INDEX_op_imulb_AL_T0] = CC_OSZAPC,
6471 [INDEX_op_imulw_AX_T0] = CC_OSZAPC,
2c0262af 6472 [INDEX_op_imull_EAX_T0] = CC_OSZAPC,
14ce26e7 6473 X86_64_DEF([INDEX_op_imulq_EAX_T0] = CC_OSZAPC,)
2c0262af
FB
6474 [INDEX_op_imulw_T0_T1] = CC_OSZAPC,
6475 [INDEX_op_imull_T0_T1] = CC_OSZAPC,
14ce26e7
FB
6476 X86_64_DEF([INDEX_op_imulq_T0_T1] = CC_OSZAPC,)
6477
664e0f19
FB
6478 /* sse */
6479 [INDEX_op_ucomiss] = CC_OSZAPC,
6480 [INDEX_op_ucomisd] = CC_OSZAPC,
6481 [INDEX_op_comiss] = CC_OSZAPC,
6482 [INDEX_op_comisd] = CC_OSZAPC,
6483
2c0262af
FB
6484 /* bcd */
6485 [INDEX_op_aam] = CC_OSZAPC,
6486 [INDEX_op_aad] = CC_OSZAPC,
6487 [INDEX_op_aas] = CC_OSZAPC,
6488 [INDEX_op_aaa] = CC_OSZAPC,
6489 [INDEX_op_das] = CC_OSZAPC,
6490 [INDEX_op_daa] = CC_OSZAPC,
6491
6492 [INDEX_op_movb_eflags_T0] = CC_S | CC_Z | CC_A | CC_P | CC_C,
6493 [INDEX_op_movw_eflags_T0] = CC_OSZAPC,
6494 [INDEX_op_movl_eflags_T0] = CC_OSZAPC,
4136f33c
FB
6495 [INDEX_op_movw_eflags_T0_io] = CC_OSZAPC,
6496 [INDEX_op_movl_eflags_T0_io] = CC_OSZAPC,
6497 [INDEX_op_movw_eflags_T0_cpl0] = CC_OSZAPC,
6498 [INDEX_op_movl_eflags_T0_cpl0] = CC_OSZAPC,
2c0262af
FB
6499 [INDEX_op_clc] = CC_C,
6500 [INDEX_op_stc] = CC_C,
6501 [INDEX_op_cmc] = CC_C,
6502
2c0262af
FB
6503 [INDEX_op_btw_T0_T1_cc] = CC_OSZAPC,
6504 [INDEX_op_btl_T0_T1_cc] = CC_OSZAPC,
14ce26e7 6505 X86_64_DEF([INDEX_op_btq_T0_T1_cc] = CC_OSZAPC,)
2c0262af
FB
6506 [INDEX_op_btsw_T0_T1_cc] = CC_OSZAPC,
6507 [INDEX_op_btsl_T0_T1_cc] = CC_OSZAPC,
14ce26e7 6508 X86_64_DEF([INDEX_op_btsq_T0_T1_cc] = CC_OSZAPC,)
2c0262af
FB
6509 [INDEX_op_btrw_T0_T1_cc] = CC_OSZAPC,
6510 [INDEX_op_btrl_T0_T1_cc] = CC_OSZAPC,
14ce26e7 6511 X86_64_DEF([INDEX_op_btrq_T0_T1_cc] = CC_OSZAPC,)
2c0262af
FB
6512 [INDEX_op_btcw_T0_T1_cc] = CC_OSZAPC,
6513 [INDEX_op_btcl_T0_T1_cc] = CC_OSZAPC,
14ce26e7 6514 X86_64_DEF([INDEX_op_btcq_T0_T1_cc] = CC_OSZAPC,)
2c0262af
FB
6515
6516 [INDEX_op_bsfw_T0_cc] = CC_OSZAPC,
6517 [INDEX_op_bsfl_T0_cc] = CC_OSZAPC,
14ce26e7 6518 X86_64_DEF([INDEX_op_bsfq_T0_cc] = CC_OSZAPC,)
2c0262af
FB
6519 [INDEX_op_bsrw_T0_cc] = CC_OSZAPC,
6520 [INDEX_op_bsrl_T0_cc] = CC_OSZAPC,
14ce26e7 6521 X86_64_DEF([INDEX_op_bsrq_T0_cc] = CC_OSZAPC,)
2c0262af
FB
6522
6523 [INDEX_op_cmpxchgb_T0_T1_EAX_cc] = CC_OSZAPC,
6524 [INDEX_op_cmpxchgw_T0_T1_EAX_cc] = CC_OSZAPC,
6525 [INDEX_op_cmpxchgl_T0_T1_EAX_cc] = CC_OSZAPC,
14ce26e7 6526 X86_64_DEF([INDEX_op_cmpxchgq_T0_T1_EAX_cc] = CC_OSZAPC,)
2c0262af 6527
2c0262af
FB
6528 [INDEX_op_cmpxchg8b] = CC_Z,
6529 [INDEX_op_lar] = CC_Z,
6530 [INDEX_op_lsl] = CC_Z,
cc6f538b
FB
6531 [INDEX_op_verr] = CC_Z,
6532 [INDEX_op_verw] = CC_Z,
2c0262af
FB
6533 [INDEX_op_fcomi_ST0_FT0] = CC_Z | CC_P | CC_C,
6534 [INDEX_op_fucomi_ST0_FT0] = CC_Z | CC_P | CC_C,
4f31916f
FB
6535
6536#define DEF_WRITEF(SUFFIX)\
6537 [INDEX_op_adcb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6538 [INDEX_op_adcw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6539 [INDEX_op_adcl ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
14ce26e7 6540 X86_64_DEF([INDEX_op_adcq ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,)\
4f31916f
FB
6541 [INDEX_op_sbbb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6542 [INDEX_op_sbbw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6543 [INDEX_op_sbbl ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
14ce26e7 6544 X86_64_DEF([INDEX_op_sbbq ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,)\
4f31916f
FB
6545\
6546 [INDEX_op_rolb ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6547 [INDEX_op_rolw ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6548 [INDEX_op_roll ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
14ce26e7 6549 X86_64_DEF([INDEX_op_rolq ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,)\
4f31916f
FB
6550 [INDEX_op_rorb ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6551 [INDEX_op_rorw ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6552 [INDEX_op_rorl ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
14ce26e7 6553 X86_64_DEF([INDEX_op_rorq ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,)\
4f31916f
FB
6554\
6555 [INDEX_op_rclb ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6556 [INDEX_op_rclw ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6557 [INDEX_op_rcll ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
14ce26e7 6558 X86_64_DEF([INDEX_op_rclq ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,)\
4f31916f
FB
6559 [INDEX_op_rcrb ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6560 [INDEX_op_rcrw ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6561 [INDEX_op_rcrl ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
14ce26e7 6562 X86_64_DEF([INDEX_op_rcrq ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,)\
4f31916f
FB
6563\
6564 [INDEX_op_shlb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6565 [INDEX_op_shlw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6566 [INDEX_op_shll ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
14ce26e7 6567 X86_64_DEF([INDEX_op_shlq ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,)\
4f31916f
FB
6568\
6569 [INDEX_op_shrb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6570 [INDEX_op_shrw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6571 [INDEX_op_shrl ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
14ce26e7 6572 X86_64_DEF([INDEX_op_shrq ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,)\
4f31916f
FB
6573\
6574 [INDEX_op_sarb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6575 [INDEX_op_sarw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6576 [INDEX_op_sarl ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
14ce26e7 6577 X86_64_DEF([INDEX_op_sarq ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,)\
4f31916f
FB
6578\
6579 [INDEX_op_shldw ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,\
6580 [INDEX_op_shldl ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,\
14ce26e7 6581 X86_64_DEF([INDEX_op_shldq ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,)\
4f31916f
FB
6582 [INDEX_op_shldw ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,\
6583 [INDEX_op_shldl ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,\
14ce26e7 6584 X86_64_DEF([INDEX_op_shldq ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,)\
4f31916f
FB
6585\
6586 [INDEX_op_shrdw ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,\
6587 [INDEX_op_shrdl ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,\
14ce26e7 6588 X86_64_DEF([INDEX_op_shrdq ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,)\
4f31916f
FB
6589 [INDEX_op_shrdw ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,\
6590 [INDEX_op_shrdl ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,\
14ce26e7 6591 X86_64_DEF([INDEX_op_shrdq ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,)\
4f31916f
FB
6592\
6593 [INDEX_op_cmpxchgb ## SUFFIX ## _T0_T1_EAX_cc] = CC_OSZAPC,\
6594 [INDEX_op_cmpxchgw ## SUFFIX ## _T0_T1_EAX_cc] = CC_OSZAPC,\
14ce26e7
FB
6595 [INDEX_op_cmpxchgl ## SUFFIX ## _T0_T1_EAX_cc] = CC_OSZAPC,\
6596 X86_64_DEF([INDEX_op_cmpxchgq ## SUFFIX ## _T0_T1_EAX_cc] = CC_OSZAPC,)
4f31916f
FB
6597
6598
4bb2fcc7 6599 DEF_WRITEF( )
4f31916f
FB
6600 DEF_WRITEF(_raw)
6601#ifndef CONFIG_USER_ONLY
6602 DEF_WRITEF(_kernel)
6603 DEF_WRITEF(_user)
6604#endif
2c0262af
FB
6605};
6606
6607/* simpler form of an operation if no flags need to be generated */
5fafdf24 6608static uint16_t opc_simpler[NB_OPS] = {
2c0262af
FB
6609 [INDEX_op_update2_cc] = INDEX_op_nop,
6610 [INDEX_op_update1_cc] = INDEX_op_nop,
6611 [INDEX_op_update_neg_cc] = INDEX_op_nop,
6612#if 0
6613 /* broken: CC_OP logic must be rewritten */
6614 [INDEX_op_update_inc_cc] = INDEX_op_nop,
6615#endif
2c0262af
FB
6616
6617 [INDEX_op_shlb_T0_T1_cc] = INDEX_op_shlb_T0_T1,
6618 [INDEX_op_shlw_T0_T1_cc] = INDEX_op_shlw_T0_T1,
6619 [INDEX_op_shll_T0_T1_cc] = INDEX_op_shll_T0_T1,
14ce26e7 6620 X86_64_DEF([INDEX_op_shlq_T0_T1_cc] = INDEX_op_shlq_T0_T1,)
2c0262af
FB
6621
6622 [INDEX_op_shrb_T0_T1_cc] = INDEX_op_shrb_T0_T1,
6623 [INDEX_op_shrw_T0_T1_cc] = INDEX_op_shrw_T0_T1,
6624 [INDEX_op_shrl_T0_T1_cc] = INDEX_op_shrl_T0_T1,
14ce26e7 6625 X86_64_DEF([INDEX_op_shrq_T0_T1_cc] = INDEX_op_shrq_T0_T1,)
2c0262af
FB
6626
6627 [INDEX_op_sarb_T0_T1_cc] = INDEX_op_sarb_T0_T1,
6628 [INDEX_op_sarw_T0_T1_cc] = INDEX_op_sarw_T0_T1,
6629 [INDEX_op_sarl_T0_T1_cc] = INDEX_op_sarl_T0_T1,
14ce26e7 6630 X86_64_DEF([INDEX_op_sarq_T0_T1_cc] = INDEX_op_sarq_T0_T1,)
4f31916f
FB
6631
6632#define DEF_SIMPLER(SUFFIX)\
6633 [INDEX_op_rolb ## SUFFIX ## _T0_T1_cc] = INDEX_op_rolb ## SUFFIX ## _T0_T1,\
6634 [INDEX_op_rolw ## SUFFIX ## _T0_T1_cc] = INDEX_op_rolw ## SUFFIX ## _T0_T1,\
6635 [INDEX_op_roll ## SUFFIX ## _T0_T1_cc] = INDEX_op_roll ## SUFFIX ## _T0_T1,\
14ce26e7 6636 X86_64_DEF([INDEX_op_rolq ## SUFFIX ## _T0_T1_cc] = INDEX_op_rolq ## SUFFIX ## _T0_T1,)\
4f31916f
FB
6637\
6638 [INDEX_op_rorb ## SUFFIX ## _T0_T1_cc] = INDEX_op_rorb ## SUFFIX ## _T0_T1,\
6639 [INDEX_op_rorw ## SUFFIX ## _T0_T1_cc] = INDEX_op_rorw ## SUFFIX ## _T0_T1,\
14ce26e7
FB
6640 [INDEX_op_rorl ## SUFFIX ## _T0_T1_cc] = INDEX_op_rorl ## SUFFIX ## _T0_T1,\
6641 X86_64_DEF([INDEX_op_rorq ## SUFFIX ## _T0_T1_cc] = INDEX_op_rorq ## SUFFIX ## _T0_T1,)
4f31916f 6642
4bb2fcc7 6643 DEF_SIMPLER( )
4f31916f
FB
6644 DEF_SIMPLER(_raw)
6645#ifndef CONFIG_USER_ONLY
6646 DEF_SIMPLER(_kernel)
6647 DEF_SIMPLER(_user)
6648#endif
2c0262af
FB
6649};
6650
6651void optimize_flags_init(void)
6652{
6653 int i;
6654 /* put default values in arrays */
6655 for(i = 0; i < NB_OPS; i++) {
6656 if (opc_simpler[i] == 0)
6657 opc_simpler[i] = i;
6658 }
6659}
6660
6661/* CPU flags computation optimization: we move backward thru the
6662 generated code to see which flags are needed. The operation is
6663 modified if suitable */
6664static void optimize_flags(uint16_t *opc_buf, int opc_buf_len)
6665{
6666 uint16_t *opc_ptr;
6667 int live_flags, write_flags, op;
6668
6669 opc_ptr = opc_buf + opc_buf_len;
6670 /* live_flags contains the flags needed by the next instructions
e91c8a77 6671 in the code. At the end of the block, we consider that all the
2c0262af
FB
6672 flags are live. */
6673 live_flags = CC_OSZAPC;
6674 while (opc_ptr > opc_buf) {
6675 op = *--opc_ptr;
6676 /* if none of the flags written by the instruction is used,
6677 then we can try to find a simpler instruction */
6678 write_flags = opc_write_flags[op];
6679 if ((live_flags & write_flags) == 0) {
6680 *opc_ptr = opc_simpler[op];
6681 }
6682 /* compute the live flags before the instruction */
6683 live_flags &= ~write_flags;
6684 live_flags |= opc_read_flags[op];
6685 }
6686}
6687
6688/* generate intermediate code in gen_opc_buf and gen_opparam_buf for
6689 basic block 'tb'. If search_pc is TRUE, also generate PC
6690 information for each intermediate instruction. */
6691static inline int gen_intermediate_code_internal(CPUState *env,
5fafdf24 6692 TranslationBlock *tb,
2c0262af
FB
6693 int search_pc)
6694{
6695 DisasContext dc1, *dc = &dc1;
14ce26e7 6696 target_ulong pc_ptr;
2c0262af 6697 uint16_t *gen_opc_end;
c068688b
JM
6698 int j, lj, cflags;
6699 uint64_t flags;
14ce26e7
FB
6700 target_ulong pc_start;
6701 target_ulong cs_base;
3b46e624 6702
2c0262af 6703 /* generate intermediate code */
14ce26e7
FB
6704 pc_start = tb->pc;
6705 cs_base = tb->cs_base;
2c0262af 6706 flags = tb->flags;
d720b93d 6707 cflags = tb->cflags;
3a1d9b8b 6708
4f31916f 6709 dc->pe = (flags >> HF_PE_SHIFT) & 1;
2c0262af
FB
6710 dc->code32 = (flags >> HF_CS32_SHIFT) & 1;
6711 dc->ss32 = (flags >> HF_SS32_SHIFT) & 1;
6712 dc->addseg = (flags >> HF_ADDSEG_SHIFT) & 1;
6713 dc->f_st = 0;
6714 dc->vm86 = (flags >> VM_SHIFT) & 1;
6715 dc->cpl = (flags >> HF_CPL_SHIFT) & 3;
6716 dc->iopl = (flags >> IOPL_SHIFT) & 3;
6717 dc->tf = (flags >> TF_SHIFT) & 1;
34865134 6718 dc->singlestep_enabled = env->singlestep_enabled;
2c0262af
FB
6719 dc->cc_op = CC_OP_DYNAMIC;
6720 dc->cs_base = cs_base;
6721 dc->tb = tb;
6722 dc->popl_esp_hack = 0;
6723 /* select memory access functions */
6724 dc->mem_index = 0;
6725 if (flags & HF_SOFTMMU_MASK) {
6726 if (dc->cpl == 3)
14ce26e7 6727 dc->mem_index = 2 * 4;
2c0262af 6728 else
14ce26e7 6729 dc->mem_index = 1 * 4;
2c0262af 6730 }
14ce26e7 6731 dc->cpuid_features = env->cpuid_features;
3d7374c5 6732 dc->cpuid_ext_features = env->cpuid_ext_features;
14ce26e7
FB
6733#ifdef TARGET_X86_64
6734 dc->lma = (flags >> HF_LMA_SHIFT) & 1;
6735 dc->code64 = (flags >> HF_CS64_SHIFT) & 1;
6736#endif
7eee2a50 6737 dc->flags = flags;
a2cc3b24
FB
6738 dc->jmp_opt = !(dc->tf || env->singlestep_enabled ||
6739 (flags & HF_INHIBIT_IRQ_MASK)
415fa2ea 6740#ifndef CONFIG_SOFTMMU
2c0262af
FB
6741 || (flags & HF_SOFTMMU_MASK)
6742#endif
6743 );
4f31916f
FB
6744#if 0
6745 /* check addseg logic */
dc196a57 6746 if (!dc->addseg && (dc->vm86 || !dc->pe || !dc->code32))
4f31916f
FB
6747 printf("ERROR addseg\n");
6748#endif
6749
2c0262af
FB
6750 gen_opc_ptr = gen_opc_buf;
6751 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
6752 gen_opparam_ptr = gen_opparam_buf;
14ce26e7 6753 nb_gen_labels = 0;
2c0262af
FB
6754
6755 dc->is_jmp = DISAS_NEXT;
6756 pc_ptr = pc_start;
6757 lj = -1;
6758
2c0262af
FB
6759 for(;;) {
6760 if (env->nb_breakpoints > 0) {
6761 for(j = 0; j < env->nb_breakpoints; j++) {
14ce26e7 6762 if (env->breakpoints[j] == pc_ptr) {
2c0262af
FB
6763 gen_debug(dc, pc_ptr - dc->cs_base);
6764 break;
6765 }
6766 }
6767 }
6768 if (search_pc) {
6769 j = gen_opc_ptr - gen_opc_buf;
6770 if (lj < j) {
6771 lj++;
6772 while (lj < j)
6773 gen_opc_instr_start[lj++] = 0;
6774 }
14ce26e7 6775 gen_opc_pc[lj] = pc_ptr;
2c0262af
FB
6776 gen_opc_cc_op[lj] = dc->cc_op;
6777 gen_opc_instr_start[lj] = 1;
6778 }
6779 pc_ptr = disas_insn(dc, pc_ptr);
6780 /* stop translation if indicated */
6781 if (dc->is_jmp)
6782 break;
6783 /* if single step mode, we generate only one instruction and
6784 generate an exception */
a2cc3b24
FB
6785 /* if irq were inhibited with HF_INHIBIT_IRQ_MASK, we clear
6786 the flag and abort the translation to give the irqs a
6787 change to be happen */
5fafdf24 6788 if (dc->tf || dc->singlestep_enabled ||
d720b93d
FB
6789 (flags & HF_INHIBIT_IRQ_MASK) ||
6790 (cflags & CF_SINGLE_INSN)) {
14ce26e7 6791 gen_jmp_im(pc_ptr - dc->cs_base);
2c0262af
FB
6792 gen_eob(dc);
6793 break;
6794 }
6795 /* if too long translation, stop generation too */
6796 if (gen_opc_ptr >= gen_opc_end ||
6797 (pc_ptr - pc_start) >= (TARGET_PAGE_SIZE - 32)) {
14ce26e7 6798 gen_jmp_im(pc_ptr - dc->cs_base);
2c0262af
FB
6799 gen_eob(dc);
6800 break;
6801 }
6802 }
6803 *gen_opc_ptr = INDEX_op_end;
6804 /* we don't forget to fill the last values */
6805 if (search_pc) {
6806 j = gen_opc_ptr - gen_opc_buf;
6807 lj++;
6808 while (lj <= j)
6809 gen_opc_instr_start[lj++] = 0;
6810 }
3b46e624 6811
2c0262af 6812#ifdef DEBUG_DISAS
658c8bda 6813 if (loglevel & CPU_LOG_TB_CPU) {
7fe48483 6814 cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
658c8bda 6815 }
e19e89a5 6816 if (loglevel & CPU_LOG_TB_IN_ASM) {
14ce26e7 6817 int disas_flags;
2c0262af
FB
6818 fprintf(logfile, "----------------\n");
6819 fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
14ce26e7
FB
6820#ifdef TARGET_X86_64
6821 if (dc->code64)
6822 disas_flags = 2;
6823 else
6824#endif
6825 disas_flags = !dc->code32;
6826 target_disas(logfile, pc_start, pc_ptr - pc_start, disas_flags);
2c0262af 6827 fprintf(logfile, "\n");
e19e89a5
FB
6828 if (loglevel & CPU_LOG_TB_OP) {
6829 fprintf(logfile, "OP:\n");
6830 dump_ops(gen_opc_buf, gen_opparam_buf);
6831 fprintf(logfile, "\n");
6832 }
2c0262af
FB
6833 }
6834#endif
6835
6836 /* optimize flag computations */
6837 optimize_flags(gen_opc_buf, gen_opc_ptr - gen_opc_buf);
6838
6839#ifdef DEBUG_DISAS
e19e89a5 6840 if (loglevel & CPU_LOG_TB_OP_OPT) {
2c0262af
FB
6841 fprintf(logfile, "AFTER FLAGS OPT:\n");
6842 dump_ops(gen_opc_buf, gen_opparam_buf);
6843 fprintf(logfile, "\n");
6844 }
6845#endif
6846 if (!search_pc)
6847 tb->size = pc_ptr - pc_start;
6848 return 0;
6849}
6850
6851int gen_intermediate_code(CPUState *env, TranslationBlock *tb)
6852{
6853 return gen_intermediate_code_internal(env, tb, 0);
6854}
6855
6856int gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
6857{
6858 return gen_intermediate_code_internal(env, tb, 1);
6859}
6860