]> git.proxmox.com Git - mirror_qemu.git/blame - target-i386/translate.c
find -type f | xargs sed -i 's/[\t ]*$//g' # Yes, again. Note the star in the regex.
[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 */
7eee2a50 98 int 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
4f31916f
FB
1998static inline void gen_stack_update(DisasContext *s, int addend)
1999{
14ce26e7
FB
2000#ifdef TARGET_X86_64
2001 if (CODE64(s)) {
2002 if (addend == 8)
2003 gen_op_addq_ESP_8();
5fafdf24 2004 else
14ce26e7
FB
2005 gen_op_addq_ESP_im(addend);
2006 } else
2007#endif
4f31916f
FB
2008 if (s->ss32) {
2009 if (addend == 2)
2010 gen_op_addl_ESP_2();
2011 else if (addend == 4)
2012 gen_op_addl_ESP_4();
5fafdf24 2013 else
4f31916f
FB
2014 gen_op_addl_ESP_im(addend);
2015 } else {
2016 if (addend == 2)
2017 gen_op_addw_ESP_2();
2018 else if (addend == 4)
2019 gen_op_addw_ESP_4();
2020 else
2021 gen_op_addw_ESP_im(addend);
2022 }
2023}
2024
2c0262af
FB
2025/* generate a push. It depends on ss32, addseg and dflag */
2026static void gen_push_T0(DisasContext *s)
2027{
14ce26e7
FB
2028#ifdef TARGET_X86_64
2029 if (CODE64(s)) {
14ce26e7 2030 gen_op_movq_A0_reg[R_ESP]();
8f091a59
FB
2031 if (s->dflag) {
2032 gen_op_subq_A0_8();
2033 gen_op_st_T0_A0[OT_QUAD + s->mem_index]();
2034 } else {
2035 gen_op_subq_A0_2();
2036 gen_op_st_T0_A0[OT_WORD + s->mem_index]();
2037 }
14ce26e7 2038 gen_op_movq_ESP_A0();
5fafdf24 2039 } else
14ce26e7
FB
2040#endif
2041 {
2042 gen_op_movl_A0_reg[R_ESP]();
2043 if (!s->dflag)
2044 gen_op_subl_A0_2();
2045 else
2046 gen_op_subl_A0_4();
2047 if (s->ss32) {
2048 if (s->addseg) {
2049 gen_op_movl_T1_A0();
2050 gen_op_addl_A0_SS();
2051 }
2052 } else {
2053 gen_op_andl_A0_ffff();
4f31916f
FB
2054 gen_op_movl_T1_A0();
2055 gen_op_addl_A0_SS();
2c0262af 2056 }
14ce26e7
FB
2057 gen_op_st_T0_A0[s->dflag + 1 + s->mem_index]();
2058 if (s->ss32 && !s->addseg)
2059 gen_op_movl_ESP_A0();
2060 else
2061 gen_op_mov_reg_T1[s->ss32 + 1][R_ESP]();
2c0262af
FB
2062 }
2063}
2064
4f31916f
FB
2065/* generate a push. It depends on ss32, addseg and dflag */
2066/* slower version for T1, only used for call Ev */
2067static void gen_push_T1(DisasContext *s)
2c0262af 2068{
14ce26e7
FB
2069#ifdef TARGET_X86_64
2070 if (CODE64(s)) {
14ce26e7 2071 gen_op_movq_A0_reg[R_ESP]();
8f091a59
FB
2072 if (s->dflag) {
2073 gen_op_subq_A0_8();
2074 gen_op_st_T1_A0[OT_QUAD + s->mem_index]();
2075 } else {
2076 gen_op_subq_A0_2();
2077 gen_op_st_T0_A0[OT_WORD + s->mem_index]();
2078 }
14ce26e7 2079 gen_op_movq_ESP_A0();
5fafdf24 2080 } else
14ce26e7
FB
2081#endif
2082 {
2083 gen_op_movl_A0_reg[R_ESP]();
2084 if (!s->dflag)
2085 gen_op_subl_A0_2();
2086 else
2087 gen_op_subl_A0_4();
2088 if (s->ss32) {
2089 if (s->addseg) {
2090 gen_op_addl_A0_SS();
2091 }
2092 } else {
2093 gen_op_andl_A0_ffff();
4f31916f 2094 gen_op_addl_A0_SS();
2c0262af 2095 }
14ce26e7 2096 gen_op_st_T1_A0[s->dflag + 1 + s->mem_index]();
3b46e624 2097
14ce26e7
FB
2098 if (s->ss32 && !s->addseg)
2099 gen_op_movl_ESP_A0();
2100 else
2101 gen_stack_update(s, (-2) << s->dflag);
2c0262af
FB
2102 }
2103}
2104
4f31916f
FB
2105/* two step pop is necessary for precise exceptions */
2106static void gen_pop_T0(DisasContext *s)
2c0262af 2107{
14ce26e7
FB
2108#ifdef TARGET_X86_64
2109 if (CODE64(s)) {
14ce26e7 2110 gen_op_movq_A0_reg[R_ESP]();
8f091a59 2111 gen_op_ld_T0_A0[(s->dflag ? OT_QUAD : OT_WORD) + s->mem_index]();
5fafdf24 2112 } else
14ce26e7
FB
2113#endif
2114 {
2115 gen_op_movl_A0_reg[R_ESP]();
2116 if (s->ss32) {
2117 if (s->addseg)
2118 gen_op_addl_A0_SS();
2119 } else {
2120 gen_op_andl_A0_ffff();
4f31916f 2121 gen_op_addl_A0_SS();
14ce26e7
FB
2122 }
2123 gen_op_ld_T0_A0[s->dflag + 1 + s->mem_index]();
2c0262af
FB
2124 }
2125}
2126
2127static void gen_pop_update(DisasContext *s)
2128{
14ce26e7 2129#ifdef TARGET_X86_64
8f091a59 2130 if (CODE64(s) && s->dflag) {
14ce26e7
FB
2131 gen_stack_update(s, 8);
2132 } else
2133#endif
2134 {
2135 gen_stack_update(s, 2 << s->dflag);
2136 }
2c0262af
FB
2137}
2138
2139static void gen_stack_A0(DisasContext *s)
2140{
2141 gen_op_movl_A0_ESP();
2142 if (!s->ss32)
2143 gen_op_andl_A0_ffff();
2144 gen_op_movl_T1_A0();
2145 if (s->addseg)
2146 gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
2147}
2148
2149/* NOTE: wrap around in 16 bit not fully handled */
2150static void gen_pusha(DisasContext *s)
2151{
2152 int i;
2153 gen_op_movl_A0_ESP();
2154 gen_op_addl_A0_im(-16 << s->dflag);
2155 if (!s->ss32)
2156 gen_op_andl_A0_ffff();
2157 gen_op_movl_T1_A0();
2158 if (s->addseg)
2159 gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
2160 for(i = 0;i < 8; i++) {
2161 gen_op_mov_TN_reg[OT_LONG][0][7 - i]();
2162 gen_op_st_T0_A0[OT_WORD + s->dflag + s->mem_index]();
2163 gen_op_addl_A0_im(2 << s->dflag);
2164 }
90f11f95 2165 gen_op_mov_reg_T1[OT_WORD + s->ss32][R_ESP]();
2c0262af
FB
2166}
2167
2168/* NOTE: wrap around in 16 bit not fully handled */
2169static void gen_popa(DisasContext *s)
2170{
2171 int i;
2172 gen_op_movl_A0_ESP();
2173 if (!s->ss32)
2174 gen_op_andl_A0_ffff();
2175 gen_op_movl_T1_A0();
2176 gen_op_addl_T1_im(16 << s->dflag);
2177 if (s->addseg)
2178 gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
2179 for(i = 0;i < 8; i++) {
2180 /* ESP is not reloaded */
2181 if (i != 3) {
2182 gen_op_ld_T0_A0[OT_WORD + s->dflag + s->mem_index]();
2183 gen_op_mov_reg_T0[OT_WORD + s->dflag][7 - i]();
2184 }
2185 gen_op_addl_A0_im(2 << s->dflag);
2186 }
90f11f95 2187 gen_op_mov_reg_T1[OT_WORD + s->ss32][R_ESP]();
2c0262af
FB
2188}
2189
2c0262af
FB
2190static void gen_enter(DisasContext *s, int esp_addend, int level)
2191{
61a8c4ec 2192 int ot, opsize;
2c0262af 2193
2c0262af 2194 level &= 0x1f;
8f091a59
FB
2195#ifdef TARGET_X86_64
2196 if (CODE64(s)) {
2197 ot = s->dflag ? OT_QUAD : OT_WORD;
2198 opsize = 1 << ot;
3b46e624 2199
8f091a59
FB
2200 gen_op_movl_A0_ESP();
2201 gen_op_addq_A0_im(-opsize);
2202 gen_op_movl_T1_A0();
2203
2204 /* push bp */
2205 gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
2206 gen_op_st_T0_A0[ot + s->mem_index]();
2207 if (level) {
2208 gen_op_enter64_level(level, (ot == OT_QUAD));
2209 }
2210 gen_op_mov_reg_T1[ot][R_EBP]();
2211 gen_op_addl_T1_im( -esp_addend + (-opsize * level) );
2212 gen_op_mov_reg_T1[OT_QUAD][R_ESP]();
5fafdf24 2213 } else
8f091a59
FB
2214#endif
2215 {
2216 ot = s->dflag + OT_WORD;
2217 opsize = 2 << s->dflag;
3b46e624 2218
8f091a59
FB
2219 gen_op_movl_A0_ESP();
2220 gen_op_addl_A0_im(-opsize);
2221 if (!s->ss32)
2222 gen_op_andl_A0_ffff();
2223 gen_op_movl_T1_A0();
2224 if (s->addseg)
2225 gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
2226 /* push bp */
2227 gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
2228 gen_op_st_T0_A0[ot + s->mem_index]();
2229 if (level) {
2230 gen_op_enter_level(level, s->dflag);
2231 }
2232 gen_op_mov_reg_T1[ot][R_EBP]();
2233 gen_op_addl_T1_im( -esp_addend + (-opsize * level) );
2234 gen_op_mov_reg_T1[OT_WORD + s->ss32][R_ESP]();
2c0262af 2235 }
2c0262af
FB
2236}
2237
14ce26e7 2238static void gen_exception(DisasContext *s, int trapno, target_ulong cur_eip)
2c0262af
FB
2239{
2240 if (s->cc_op != CC_OP_DYNAMIC)
2241 gen_op_set_cc_op(s->cc_op);
14ce26e7 2242 gen_jmp_im(cur_eip);
2c0262af
FB
2243 gen_op_raise_exception(trapno);
2244 s->is_jmp = 3;
2245}
2246
2247/* an interrupt is different from an exception because of the
7f75ffd3 2248 privilege checks */
5fafdf24 2249static void gen_interrupt(DisasContext *s, int intno,
14ce26e7 2250 target_ulong cur_eip, target_ulong next_eip)
2c0262af
FB
2251{
2252 if (s->cc_op != CC_OP_DYNAMIC)
2253 gen_op_set_cc_op(s->cc_op);
14ce26e7 2254 gen_jmp_im(cur_eip);
a8ede8ba 2255 gen_op_raise_interrupt(intno, (int)(next_eip - cur_eip));
2c0262af
FB
2256 s->is_jmp = 3;
2257}
2258
14ce26e7 2259static void gen_debug(DisasContext *s, target_ulong cur_eip)
2c0262af
FB
2260{
2261 if (s->cc_op != CC_OP_DYNAMIC)
2262 gen_op_set_cc_op(s->cc_op);
14ce26e7 2263 gen_jmp_im(cur_eip);
2c0262af
FB
2264 gen_op_debug();
2265 s->is_jmp = 3;
2266}
2267
2268/* generate a generic end of block. Trace exception is also generated
2269 if needed */
2270static void gen_eob(DisasContext *s)
2271{
2272 if (s->cc_op != CC_OP_DYNAMIC)
2273 gen_op_set_cc_op(s->cc_op);
a2cc3b24
FB
2274 if (s->tb->flags & HF_INHIBIT_IRQ_MASK) {
2275 gen_op_reset_inhibit_irq();
2276 }
34865134
FB
2277 if (s->singlestep_enabled) {
2278 gen_op_debug();
2279 } else if (s->tf) {
88fe8a41 2280 gen_op_single_step();
2c0262af
FB
2281 } else {
2282 gen_op_movl_T0_0();
2283 gen_op_exit_tb();
2284 }
2285 s->is_jmp = 3;
2286}
2287
2288/* generate a jump to eip. No segment change must happen before as a
2289 direct call to the next block may occur */
14ce26e7 2290static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num)
2c0262af 2291{
2c0262af 2292 if (s->jmp_opt) {
6e256c93 2293 if (s->cc_op != CC_OP_DYNAMIC) {
2c0262af 2294 gen_op_set_cc_op(s->cc_op);
6e256c93
FB
2295 s->cc_op = CC_OP_DYNAMIC;
2296 }
2297 gen_goto_tb(s, tb_num, eip);
2c0262af
FB
2298 s->is_jmp = 3;
2299 } else {
14ce26e7 2300 gen_jmp_im(eip);
2c0262af
FB
2301 gen_eob(s);
2302 }
2303}
2304
14ce26e7
FB
2305static void gen_jmp(DisasContext *s, target_ulong eip)
2306{
2307 gen_jmp_tb(s, eip, 0);
2308}
2309
2310static void gen_movtl_T0_im(target_ulong val)
2311{
3b46e624 2312#ifdef TARGET_X86_64
14ce26e7
FB
2313 if ((int32_t)val == val) {
2314 gen_op_movl_T0_im(val);
2315 } else {
2316 gen_op_movq_T0_im64(val >> 32, val);
2317 }
2318#else
2319 gen_op_movl_T0_im(val);
2320#endif
2321}
2322
1ef38687
FB
2323static void gen_movtl_T1_im(target_ulong val)
2324{
3b46e624 2325#ifdef TARGET_X86_64
1ef38687
FB
2326 if ((int32_t)val == val) {
2327 gen_op_movl_T1_im(val);
2328 } else {
2329 gen_op_movq_T1_im64(val >> 32, val);
2330 }
2331#else
2332 gen_op_movl_T1_im(val);
2333#endif
2334}
2335
aba9d61e
FB
2336static void gen_add_A0_im(DisasContext *s, int val)
2337{
2338#ifdef TARGET_X86_64
2339 if (CODE64(s))
2340 gen_op_addq_A0_im(val);
2341 else
2342#endif
2343 gen_op_addl_A0_im(val);
2344}
2345
664e0f19
FB
2346static GenOpFunc1 *gen_ldq_env_A0[3] = {
2347 gen_op_ldq_raw_env_A0,
2348#ifndef CONFIG_USER_ONLY
2349 gen_op_ldq_kernel_env_A0,
2350 gen_op_ldq_user_env_A0,
2351#endif
2352};
2353
2354static GenOpFunc1 *gen_stq_env_A0[3] = {
2355 gen_op_stq_raw_env_A0,
2356#ifndef CONFIG_USER_ONLY
2357 gen_op_stq_kernel_env_A0,
2358 gen_op_stq_user_env_A0,
2359#endif
2360};
2361
14ce26e7
FB
2362static GenOpFunc1 *gen_ldo_env_A0[3] = {
2363 gen_op_ldo_raw_env_A0,
2364#ifndef CONFIG_USER_ONLY
2365 gen_op_ldo_kernel_env_A0,
2366 gen_op_ldo_user_env_A0,
2367#endif
2368};
2369
2370static GenOpFunc1 *gen_sto_env_A0[3] = {
2371 gen_op_sto_raw_env_A0,
2372#ifndef CONFIG_USER_ONLY
2373 gen_op_sto_kernel_env_A0,
2374 gen_op_sto_user_env_A0,
2375#endif
2376};
2377
664e0f19
FB
2378#define SSE_SPECIAL ((GenOpFunc2 *)1)
2379
2380#define MMX_OP2(x) { gen_op_ ## x ## _mmx, gen_op_ ## x ## _xmm }
2381#define SSE_FOP(x) { gen_op_ ## x ## ps, gen_op_ ## x ## pd, \
2382 gen_op_ ## x ## ss, gen_op_ ## x ## sd, }
2383
2384static GenOpFunc2 *sse_op_table1[256][4] = {
2385 /* pure SSE operations */
2386 [0x10] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movups, movupd, movss, movsd */
2387 [0x11] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movups, movupd, movss, movsd */
465e9838 2388 [0x12] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movlps, movlpd, movsldup, movddup */
664e0f19
FB
2389 [0x13] = { SSE_SPECIAL, SSE_SPECIAL }, /* movlps, movlpd */
2390 [0x14] = { gen_op_punpckldq_xmm, gen_op_punpcklqdq_xmm },
2391 [0x15] = { gen_op_punpckhdq_xmm, gen_op_punpckhqdq_xmm },
2392 [0x16] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movhps, movhpd, movshdup */
2393 [0x17] = { SSE_SPECIAL, SSE_SPECIAL }, /* movhps, movhpd */
2394
2395 [0x28] = { SSE_SPECIAL, SSE_SPECIAL }, /* movaps, movapd */
2396 [0x29] = { SSE_SPECIAL, SSE_SPECIAL }, /* movaps, movapd */
2397 [0x2a] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvtpi2ps, cvtpi2pd, cvtsi2ss, cvtsi2sd */
2398 [0x2b] = { SSE_SPECIAL, SSE_SPECIAL }, /* movntps, movntpd */
2399 [0x2c] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvttps2pi, cvttpd2pi, cvttsd2si, cvttss2si */
2400 [0x2d] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvtps2pi, cvtpd2pi, cvtsd2si, cvtss2si */
2401 [0x2e] = { gen_op_ucomiss, gen_op_ucomisd },
2402 [0x2f] = { gen_op_comiss, gen_op_comisd },
2403 [0x50] = { SSE_SPECIAL, SSE_SPECIAL }, /* movmskps, movmskpd */
2404 [0x51] = SSE_FOP(sqrt),
2405 [0x52] = { gen_op_rsqrtps, NULL, gen_op_rsqrtss, NULL },
2406 [0x53] = { gen_op_rcpps, NULL, gen_op_rcpss, NULL },
2407 [0x54] = { gen_op_pand_xmm, gen_op_pand_xmm }, /* andps, andpd */
2408 [0x55] = { gen_op_pandn_xmm, gen_op_pandn_xmm }, /* andnps, andnpd */
2409 [0x56] = { gen_op_por_xmm, gen_op_por_xmm }, /* orps, orpd */
2410 [0x57] = { gen_op_pxor_xmm, gen_op_pxor_xmm }, /* xorps, xorpd */
2411 [0x58] = SSE_FOP(add),
2412 [0x59] = SSE_FOP(mul),
5fafdf24 2413 [0x5a] = { gen_op_cvtps2pd, gen_op_cvtpd2ps,
664e0f19
FB
2414 gen_op_cvtss2sd, gen_op_cvtsd2ss },
2415 [0x5b] = { gen_op_cvtdq2ps, gen_op_cvtps2dq, gen_op_cvttps2dq },
2416 [0x5c] = SSE_FOP(sub),
2417 [0x5d] = SSE_FOP(min),
2418 [0x5e] = SSE_FOP(div),
2419 [0x5f] = SSE_FOP(max),
2420
2421 [0xc2] = SSE_FOP(cmpeq),
d52cf7a6 2422 [0xc6] = { (GenOpFunc2 *)gen_op_shufps, (GenOpFunc2 *)gen_op_shufpd },
664e0f19
FB
2423
2424 /* MMX ops and their SSE extensions */
2425 [0x60] = MMX_OP2(punpcklbw),
2426 [0x61] = MMX_OP2(punpcklwd),
2427 [0x62] = MMX_OP2(punpckldq),
2428 [0x63] = MMX_OP2(packsswb),
2429 [0x64] = MMX_OP2(pcmpgtb),
2430 [0x65] = MMX_OP2(pcmpgtw),
2431 [0x66] = MMX_OP2(pcmpgtl),
2432 [0x67] = MMX_OP2(packuswb),
2433 [0x68] = MMX_OP2(punpckhbw),
2434 [0x69] = MMX_OP2(punpckhwd),
2435 [0x6a] = MMX_OP2(punpckhdq),
2436 [0x6b] = MMX_OP2(packssdw),
2437 [0x6c] = { NULL, gen_op_punpcklqdq_xmm },
2438 [0x6d] = { NULL, gen_op_punpckhqdq_xmm },
2439 [0x6e] = { SSE_SPECIAL, SSE_SPECIAL }, /* movd mm, ea */
2440 [0x6f] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movq, movdqa, , movqdu */
5fafdf24
TS
2441 [0x70] = { (GenOpFunc2 *)gen_op_pshufw_mmx,
2442 (GenOpFunc2 *)gen_op_pshufd_xmm,
2443 (GenOpFunc2 *)gen_op_pshufhw_xmm,
664e0f19
FB
2444 (GenOpFunc2 *)gen_op_pshuflw_xmm },
2445 [0x71] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftw */
2446 [0x72] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftd */
2447 [0x73] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftq */
2448 [0x74] = MMX_OP2(pcmpeqb),
2449 [0x75] = MMX_OP2(pcmpeqw),
2450 [0x76] = MMX_OP2(pcmpeql),
2451 [0x77] = { SSE_SPECIAL }, /* emms */
2452 [0x7c] = { NULL, gen_op_haddpd, NULL, gen_op_haddps },
2453 [0x7d] = { NULL, gen_op_hsubpd, NULL, gen_op_hsubps },
2454 [0x7e] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movd, movd, , movq */
2455 [0x7f] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movq, movdqa, movdqu */
2456 [0xc4] = { SSE_SPECIAL, SSE_SPECIAL }, /* pinsrw */
2457 [0xc5] = { SSE_SPECIAL, SSE_SPECIAL }, /* pextrw */
2458 [0xd0] = { NULL, gen_op_addsubpd, NULL, gen_op_addsubps },
2459 [0xd1] = MMX_OP2(psrlw),
2460 [0xd2] = MMX_OP2(psrld),
2461 [0xd3] = MMX_OP2(psrlq),
2462 [0xd4] = MMX_OP2(paddq),
2463 [0xd5] = MMX_OP2(pmullw),
2464 [0xd6] = { NULL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
2465 [0xd7] = { SSE_SPECIAL, SSE_SPECIAL }, /* pmovmskb */
2466 [0xd8] = MMX_OP2(psubusb),
2467 [0xd9] = MMX_OP2(psubusw),
2468 [0xda] = MMX_OP2(pminub),
2469 [0xdb] = MMX_OP2(pand),
2470 [0xdc] = MMX_OP2(paddusb),
2471 [0xdd] = MMX_OP2(paddusw),
2472 [0xde] = MMX_OP2(pmaxub),
2473 [0xdf] = MMX_OP2(pandn),
2474 [0xe0] = MMX_OP2(pavgb),
2475 [0xe1] = MMX_OP2(psraw),
2476 [0xe2] = MMX_OP2(psrad),
2477 [0xe3] = MMX_OP2(pavgw),
2478 [0xe4] = MMX_OP2(pmulhuw),
2479 [0xe5] = MMX_OP2(pmulhw),
2480 [0xe6] = { NULL, gen_op_cvttpd2dq, gen_op_cvtdq2pd, gen_op_cvtpd2dq },
2481 [0xe7] = { SSE_SPECIAL , SSE_SPECIAL }, /* movntq, movntq */
2482 [0xe8] = MMX_OP2(psubsb),
2483 [0xe9] = MMX_OP2(psubsw),
2484 [0xea] = MMX_OP2(pminsw),
2485 [0xeb] = MMX_OP2(por),
2486 [0xec] = MMX_OP2(paddsb),
2487 [0xed] = MMX_OP2(paddsw),
2488 [0xee] = MMX_OP2(pmaxsw),
2489 [0xef] = MMX_OP2(pxor),
465e9838 2490 [0xf0] = { NULL, NULL, NULL, SSE_SPECIAL }, /* lddqu */
664e0f19
FB
2491 [0xf1] = MMX_OP2(psllw),
2492 [0xf2] = MMX_OP2(pslld),
2493 [0xf3] = MMX_OP2(psllq),
2494 [0xf4] = MMX_OP2(pmuludq),
2495 [0xf5] = MMX_OP2(pmaddwd),
2496 [0xf6] = MMX_OP2(psadbw),
2497 [0xf7] = MMX_OP2(maskmov),
2498 [0xf8] = MMX_OP2(psubb),
2499 [0xf9] = MMX_OP2(psubw),
2500 [0xfa] = MMX_OP2(psubl),
2501 [0xfb] = MMX_OP2(psubq),
2502 [0xfc] = MMX_OP2(paddb),
2503 [0xfd] = MMX_OP2(paddw),
2504 [0xfe] = MMX_OP2(paddl),
2505};
2506
2507static GenOpFunc2 *sse_op_table2[3 * 8][2] = {
2508 [0 + 2] = MMX_OP2(psrlw),
2509 [0 + 4] = MMX_OP2(psraw),
2510 [0 + 6] = MMX_OP2(psllw),
2511 [8 + 2] = MMX_OP2(psrld),
2512 [8 + 4] = MMX_OP2(psrad),
2513 [8 + 6] = MMX_OP2(pslld),
2514 [16 + 2] = MMX_OP2(psrlq),
2515 [16 + 3] = { NULL, gen_op_psrldq_xmm },
2516 [16 + 6] = MMX_OP2(psllq),
2517 [16 + 7] = { NULL, gen_op_pslldq_xmm },
2518};
2519
2520static GenOpFunc1 *sse_op_table3[4 * 3] = {
2521 gen_op_cvtsi2ss,
2522 gen_op_cvtsi2sd,
2523 X86_64_ONLY(gen_op_cvtsq2ss),
2524 X86_64_ONLY(gen_op_cvtsq2sd),
3b46e624 2525
664e0f19
FB
2526 gen_op_cvttss2si,
2527 gen_op_cvttsd2si,
2528 X86_64_ONLY(gen_op_cvttss2sq),
2529 X86_64_ONLY(gen_op_cvttsd2sq),
2530
2531 gen_op_cvtss2si,
2532 gen_op_cvtsd2si,
2533 X86_64_ONLY(gen_op_cvtss2sq),
2534 X86_64_ONLY(gen_op_cvtsd2sq),
2535};
3b46e624 2536
664e0f19
FB
2537static GenOpFunc2 *sse_op_table4[8][4] = {
2538 SSE_FOP(cmpeq),
2539 SSE_FOP(cmplt),
2540 SSE_FOP(cmple),
2541 SSE_FOP(cmpunord),
2542 SSE_FOP(cmpneq),
2543 SSE_FOP(cmpnlt),
2544 SSE_FOP(cmpnle),
2545 SSE_FOP(cmpord),
2546};
3b46e624 2547
664e0f19
FB
2548static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r)
2549{
2550 int b1, op1_offset, op2_offset, is_xmm, val, ot;
2551 int modrm, mod, rm, reg, reg_addr, offset_addr;
2552 GenOpFunc2 *sse_op2;
2553 GenOpFunc3 *sse_op3;
2554
2555 b &= 0xff;
5fafdf24 2556 if (s->prefix & PREFIX_DATA)
664e0f19 2557 b1 = 1;
5fafdf24 2558 else if (s->prefix & PREFIX_REPZ)
664e0f19 2559 b1 = 2;
5fafdf24 2560 else if (s->prefix & PREFIX_REPNZ)
664e0f19
FB
2561 b1 = 3;
2562 else
2563 b1 = 0;
2564 sse_op2 = sse_op_table1[b][b1];
5fafdf24 2565 if (!sse_op2)
664e0f19
FB
2566 goto illegal_op;
2567 if (b <= 0x5f || b == 0xc6 || b == 0xc2) {
2568 is_xmm = 1;
2569 } else {
2570 if (b1 == 0) {
2571 /* MMX case */
2572 is_xmm = 0;
2573 } else {
2574 is_xmm = 1;
2575 }
2576 }
2577 /* simple MMX/SSE operation */
2578 if (s->flags & HF_TS_MASK) {
2579 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
2580 return;
2581 }
2582 if (s->flags & HF_EM_MASK) {
2583 illegal_op:
2584 gen_exception(s, EXCP06_ILLOP, pc_start - s->cs_base);
2585 return;
2586 }
2587 if (is_xmm && !(s->flags & HF_OSFXSR_MASK))
2588 goto illegal_op;
2589 if (b == 0x77) {
2590 /* emms */
2591 gen_op_emms();
2592 return;
2593 }
2594 /* prepare MMX state (XXX: optimize by storing fptt and fptags in
2595 the static cpu state) */
2596 if (!is_xmm) {
2597 gen_op_enter_mmx();
2598 }
2599
2600 modrm = ldub_code(s->pc++);
2601 reg = ((modrm >> 3) & 7);
2602 if (is_xmm)
2603 reg |= rex_r;
2604 mod = (modrm >> 6) & 3;
2605 if (sse_op2 == SSE_SPECIAL) {
2606 b |= (b1 << 8);
2607 switch(b) {
2608 case 0x0e7: /* movntq */
5fafdf24 2609 if (mod == 3)
664e0f19
FB
2610 goto illegal_op;
2611 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2612 gen_stq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,fpregs[reg].mmx));
2613 break;
2614 case 0x1e7: /* movntdq */
2615 case 0x02b: /* movntps */
2616 case 0x12b: /* movntps */
465e9838
FB
2617 case 0x3f0: /* lddqu */
2618 if (mod == 3)
664e0f19
FB
2619 goto illegal_op;
2620 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2621 gen_sto_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg]));
2622 break;
2623 case 0x6e: /* movd mm, ea */
dabd98dd
FB
2624#ifdef TARGET_X86_64
2625 if (s->dflag == 2) {
2626 gen_ldst_modrm(s, modrm, OT_QUAD, OR_TMP0, 0);
2627 gen_op_movq_mm_T0_mmx(offsetof(CPUX86State,fpregs[reg].mmx));
5fafdf24 2628 } else
dabd98dd
FB
2629#endif
2630 {
2631 gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 0);
2632 gen_op_movl_mm_T0_mmx(offsetof(CPUX86State,fpregs[reg].mmx));
2633 }
664e0f19
FB
2634 break;
2635 case 0x16e: /* movd xmm, ea */
dabd98dd
FB
2636#ifdef TARGET_X86_64
2637 if (s->dflag == 2) {
2638 gen_ldst_modrm(s, modrm, OT_QUAD, OR_TMP0, 0);
2639 gen_op_movq_mm_T0_xmm(offsetof(CPUX86State,xmm_regs[reg]));
5fafdf24 2640 } else
dabd98dd
FB
2641#endif
2642 {
2643 gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 0);
2644 gen_op_movl_mm_T0_xmm(offsetof(CPUX86State,xmm_regs[reg]));
2645 }
664e0f19
FB
2646 break;
2647 case 0x6f: /* movq mm, ea */
2648 if (mod != 3) {
2649 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2650 gen_ldq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,fpregs[reg].mmx));
2651 } else {
2652 rm = (modrm & 7);
2653 gen_op_movq(offsetof(CPUX86State,fpregs[reg].mmx),
2654 offsetof(CPUX86State,fpregs[rm].mmx));
2655 }
2656 break;
2657 case 0x010: /* movups */
2658 case 0x110: /* movupd */
2659 case 0x028: /* movaps */
2660 case 0x128: /* movapd */
2661 case 0x16f: /* movdqa xmm, ea */
2662 case 0x26f: /* movdqu xmm, ea */
2663 if (mod != 3) {
2664 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2665 gen_ldo_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg]));
2666 } else {
2667 rm = (modrm & 7) | REX_B(s);
2668 gen_op_movo(offsetof(CPUX86State,xmm_regs[reg]),
2669 offsetof(CPUX86State,xmm_regs[rm]));
2670 }
2671 break;
2672 case 0x210: /* movss xmm, ea */
2673 if (mod != 3) {
2674 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2675 gen_op_ld_T0_A0[OT_LONG + s->mem_index]();
2676 gen_op_movl_env_T0(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
2677 gen_op_movl_T0_0();
2678 gen_op_movl_env_T0(offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)));
2679 gen_op_movl_env_T0(offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)));
2680 gen_op_movl_env_T0(offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)));
2681 } else {
2682 rm = (modrm & 7) | REX_B(s);
2683 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)),
2684 offsetof(CPUX86State,xmm_regs[rm].XMM_L(0)));
2685 }
2686 break;
2687 case 0x310: /* movsd xmm, ea */
2688 if (mod != 3) {
2689 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2690 gen_ldq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
2691 gen_op_movl_T0_0();
2692 gen_op_movl_env_T0(offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)));
2693 gen_op_movl_env_T0(offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)));
2694 } else {
2695 rm = (modrm & 7) | REX_B(s);
2696 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
2697 offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
2698 }
2699 break;
2700 case 0x012: /* movlps */
2701 case 0x112: /* movlpd */
2702 if (mod != 3) {
2703 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2704 gen_ldq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
2705 } else {
2706 /* movhlps */
2707 rm = (modrm & 7) | REX_B(s);
2708 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
2709 offsetof(CPUX86State,xmm_regs[rm].XMM_Q(1)));
2710 }
2711 break;
465e9838
FB
2712 case 0x212: /* movsldup */
2713 if (mod != 3) {
2714 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2715 gen_ldo_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg]));
2716 } else {
2717 rm = (modrm & 7) | REX_B(s);
2718 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)),
2719 offsetof(CPUX86State,xmm_regs[rm].XMM_L(0)));
2720 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)),
2721 offsetof(CPUX86State,xmm_regs[rm].XMM_L(2)));
2722 }
2723 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)),
2724 offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
2725 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)),
2726 offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)));
2727 break;
2728 case 0x312: /* movddup */
2729 if (mod != 3) {
2730 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2731 gen_ldq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
2732 } else {
2733 rm = (modrm & 7) | REX_B(s);
2734 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
2735 offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
2736 }
2737 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)),
ba6526df 2738 offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
465e9838 2739 break;
664e0f19
FB
2740 case 0x016: /* movhps */
2741 case 0x116: /* movhpd */
2742 if (mod != 3) {
2743 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2744 gen_ldq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)));
2745 } else {
2746 /* movlhps */
2747 rm = (modrm & 7) | REX_B(s);
2748 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)),
2749 offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
2750 }
2751 break;
2752 case 0x216: /* movshdup */
2753 if (mod != 3) {
2754 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2755 gen_ldo_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg]));
2756 } else {
2757 rm = (modrm & 7) | REX_B(s);
2758 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)),
2759 offsetof(CPUX86State,xmm_regs[rm].XMM_L(1)));
2760 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)),
2761 offsetof(CPUX86State,xmm_regs[rm].XMM_L(3)));
2762 }
2763 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)),
2764 offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)));
2765 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)),
2766 offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)));
2767 break;
2768 case 0x7e: /* movd ea, mm */
dabd98dd
FB
2769#ifdef TARGET_X86_64
2770 if (s->dflag == 2) {
2771 gen_op_movq_T0_mm_mmx(offsetof(CPUX86State,fpregs[reg].mmx));
2772 gen_ldst_modrm(s, modrm, OT_QUAD, OR_TMP0, 1);
5fafdf24 2773 } else
dabd98dd
FB
2774#endif
2775 {
2776 gen_op_movl_T0_mm_mmx(offsetof(CPUX86State,fpregs[reg].mmx));
2777 gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 1);
2778 }
664e0f19
FB
2779 break;
2780 case 0x17e: /* movd ea, xmm */
dabd98dd
FB
2781#ifdef TARGET_X86_64
2782 if (s->dflag == 2) {
2783 gen_op_movq_T0_mm_xmm(offsetof(CPUX86State,xmm_regs[reg]));
2784 gen_ldst_modrm(s, modrm, OT_QUAD, OR_TMP0, 1);
5fafdf24 2785 } else
dabd98dd
FB
2786#endif
2787 {
2788 gen_op_movl_T0_mm_xmm(offsetof(CPUX86State,xmm_regs[reg]));
2789 gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 1);
2790 }
664e0f19
FB
2791 break;
2792 case 0x27e: /* movq xmm, ea */
2793 if (mod != 3) {
2794 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2795 gen_ldq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
2796 } else {
2797 rm = (modrm & 7) | REX_B(s);
2798 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
2799 offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
2800 }
2801 gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)));
2802 break;
2803 case 0x7f: /* movq ea, mm */
2804 if (mod != 3) {
2805 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2806 gen_stq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,fpregs[reg].mmx));
2807 } else {
2808 rm = (modrm & 7);
2809 gen_op_movq(offsetof(CPUX86State,fpregs[rm].mmx),
2810 offsetof(CPUX86State,fpregs[reg].mmx));
2811 }
2812 break;
2813 case 0x011: /* movups */
2814 case 0x111: /* movupd */
2815 case 0x029: /* movaps */
2816 case 0x129: /* movapd */
2817 case 0x17f: /* movdqa ea, xmm */
2818 case 0x27f: /* movdqu ea, xmm */
2819 if (mod != 3) {
2820 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2821 gen_sto_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg]));
2822 } else {
2823 rm = (modrm & 7) | REX_B(s);
2824 gen_op_movo(offsetof(CPUX86State,xmm_regs[rm]),
2825 offsetof(CPUX86State,xmm_regs[reg]));
2826 }
2827 break;
2828 case 0x211: /* movss ea, xmm */
2829 if (mod != 3) {
2830 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2831 gen_op_movl_T0_env(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
2832 gen_op_st_T0_A0[OT_LONG + s->mem_index]();
2833 } else {
2834 rm = (modrm & 7) | REX_B(s);
2835 gen_op_movl(offsetof(CPUX86State,xmm_regs[rm].XMM_L(0)),
2836 offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
2837 }
2838 break;
2839 case 0x311: /* movsd ea, xmm */
2840 if (mod != 3) {
2841 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2842 gen_stq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
2843 } else {
2844 rm = (modrm & 7) | REX_B(s);
2845 gen_op_movq(offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)),
2846 offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
2847 }
2848 break;
2849 case 0x013: /* movlps */
2850 case 0x113: /* movlpd */
2851 if (mod != 3) {
2852 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2853 gen_stq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
2854 } else {
2855 goto illegal_op;
2856 }
2857 break;
2858 case 0x017: /* movhps */
2859 case 0x117: /* movhpd */
2860 if (mod != 3) {
2861 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2862 gen_stq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)));
2863 } else {
2864 goto illegal_op;
2865 }
2866 break;
2867 case 0x71: /* shift mm, im */
2868 case 0x72:
2869 case 0x73:
2870 case 0x171: /* shift xmm, im */
2871 case 0x172:
2872 case 0x173:
2873 val = ldub_code(s->pc++);
2874 if (is_xmm) {
2875 gen_op_movl_T0_im(val);
2876 gen_op_movl_env_T0(offsetof(CPUX86State,xmm_t0.XMM_L(0)));
2877 gen_op_movl_T0_0();
2878 gen_op_movl_env_T0(offsetof(CPUX86State,xmm_t0.XMM_L(1)));
2879 op1_offset = offsetof(CPUX86State,xmm_t0);
2880 } else {
2881 gen_op_movl_T0_im(val);
2882 gen_op_movl_env_T0(offsetof(CPUX86State,mmx_t0.MMX_L(0)));
2883 gen_op_movl_T0_0();
2884 gen_op_movl_env_T0(offsetof(CPUX86State,mmx_t0.MMX_L(1)));
2885 op1_offset = offsetof(CPUX86State,mmx_t0);
2886 }
2887 sse_op2 = sse_op_table2[((b - 1) & 3) * 8 + (((modrm >> 3)) & 7)][b1];
2888 if (!sse_op2)
2889 goto illegal_op;
2890 if (is_xmm) {
2891 rm = (modrm & 7) | REX_B(s);
2892 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
2893 } else {
2894 rm = (modrm & 7);
2895 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
2896 }
2897 sse_op2(op2_offset, op1_offset);
2898 break;
2899 case 0x050: /* movmskps */
664e0f19 2900 rm = (modrm & 7) | REX_B(s);
31313213
FB
2901 gen_op_movmskps(offsetof(CPUX86State,xmm_regs[rm]));
2902 gen_op_mov_reg_T0[OT_LONG][reg]();
664e0f19
FB
2903 break;
2904 case 0x150: /* movmskpd */
664e0f19 2905 rm = (modrm & 7) | REX_B(s);
31313213
FB
2906 gen_op_movmskpd(offsetof(CPUX86State,xmm_regs[rm]));
2907 gen_op_mov_reg_T0[OT_LONG][reg]();
664e0f19
FB
2908 break;
2909 case 0x02a: /* cvtpi2ps */
2910 case 0x12a: /* cvtpi2pd */
2911 gen_op_enter_mmx();
2912 if (mod != 3) {
2913 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2914 op2_offset = offsetof(CPUX86State,mmx_t0);
2915 gen_ldq_env_A0[s->mem_index >> 2](op2_offset);
2916 } else {
2917 rm = (modrm & 7);
2918 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
2919 }
2920 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
2921 switch(b >> 8) {
2922 case 0x0:
2923 gen_op_cvtpi2ps(op1_offset, op2_offset);
2924 break;
2925 default:
2926 case 0x1:
2927 gen_op_cvtpi2pd(op1_offset, op2_offset);
2928 break;
2929 }
2930 break;
2931 case 0x22a: /* cvtsi2ss */
2932 case 0x32a: /* cvtsi2sd */
2933 ot = (s->dflag == 2) ? OT_QUAD : OT_LONG;
2934 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
2935 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
2936 sse_op_table3[(s->dflag == 2) * 2 + ((b >> 8) - 2)](op1_offset);
2937 break;
2938 case 0x02c: /* cvttps2pi */
2939 case 0x12c: /* cvttpd2pi */
2940 case 0x02d: /* cvtps2pi */
2941 case 0x12d: /* cvtpd2pi */
2942 gen_op_enter_mmx();
2943 if (mod != 3) {
2944 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2945 op2_offset = offsetof(CPUX86State,xmm_t0);
2946 gen_ldo_env_A0[s->mem_index >> 2](op2_offset);
2947 } else {
2948 rm = (modrm & 7) | REX_B(s);
2949 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
2950 }
2951 op1_offset = offsetof(CPUX86State,fpregs[reg & 7].mmx);
2952 switch(b) {
2953 case 0x02c:
2954 gen_op_cvttps2pi(op1_offset, op2_offset);
2955 break;
2956 case 0x12c:
2957 gen_op_cvttpd2pi(op1_offset, op2_offset);
2958 break;
2959 case 0x02d:
2960 gen_op_cvtps2pi(op1_offset, op2_offset);
2961 break;
2962 case 0x12d:
2963 gen_op_cvtpd2pi(op1_offset, op2_offset);
2964 break;
2965 }
2966 break;
2967 case 0x22c: /* cvttss2si */
2968 case 0x32c: /* cvttsd2si */
2969 case 0x22d: /* cvtss2si */
2970 case 0x32d: /* cvtsd2si */
2971 ot = (s->dflag == 2) ? OT_QUAD : OT_LONG;
31313213
FB
2972 if (mod != 3) {
2973 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2974 if ((b >> 8) & 1) {
2975 gen_ldq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_t0.XMM_Q(0)));
2976 } else {
2977 gen_op_ld_T0_A0[OT_LONG + s->mem_index]();
2978 gen_op_movl_env_T0(offsetof(CPUX86State,xmm_t0.XMM_L(0)));
2979 }
2980 op2_offset = offsetof(CPUX86State,xmm_t0);
2981 } else {
2982 rm = (modrm & 7) | REX_B(s);
2983 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
2984 }
5fafdf24 2985 sse_op_table3[(s->dflag == 2) * 2 + ((b >> 8) - 2) + 4 +
31313213
FB
2986 (b & 1) * 4](op2_offset);
2987 gen_op_mov_reg_T0[ot][reg]();
664e0f19
FB
2988 break;
2989 case 0xc4: /* pinsrw */
5fafdf24 2990 case 0x1c4:
d1e42c5c 2991 s->rip_offset = 1;
664e0f19
FB
2992 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
2993 val = ldub_code(s->pc++);
2994 if (b1) {
2995 val &= 7;
2996 gen_op_pinsrw_xmm(offsetof(CPUX86State,xmm_regs[reg]), val);
2997 } else {
2998 val &= 3;
2999 gen_op_pinsrw_mmx(offsetof(CPUX86State,fpregs[reg].mmx), val);
3000 }
3001 break;
3002 case 0xc5: /* pextrw */
5fafdf24 3003 case 0x1c5:
664e0f19
FB
3004 if (mod != 3)
3005 goto illegal_op;
3006 val = ldub_code(s->pc++);
3007 if (b1) {
3008 val &= 7;
3009 rm = (modrm & 7) | REX_B(s);
3010 gen_op_pextrw_xmm(offsetof(CPUX86State,xmm_regs[rm]), val);
3011 } else {
3012 val &= 3;
3013 rm = (modrm & 7);
3014 gen_op_pextrw_mmx(offsetof(CPUX86State,fpregs[rm].mmx), val);
3015 }
3016 reg = ((modrm >> 3) & 7) | rex_r;
3017 gen_op_mov_reg_T0[OT_LONG][reg]();
3018 break;
3019 case 0x1d6: /* movq ea, xmm */
3020 if (mod != 3) {
3021 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3022 gen_stq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
3023 } else {
3024 rm = (modrm & 7) | REX_B(s);
3025 gen_op_movq(offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)),
3026 offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
3027 gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[rm].XMM_Q(1)));
3028 }
3029 break;
3030 case 0x2d6: /* movq2dq */
3031 gen_op_enter_mmx();
480c1cdb
FB
3032 rm = (modrm & 7);
3033 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
3034 offsetof(CPUX86State,fpregs[rm].mmx));
3035 gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)));
664e0f19
FB
3036 break;
3037 case 0x3d6: /* movdq2q */
3038 gen_op_enter_mmx();
480c1cdb
FB
3039 rm = (modrm & 7) | REX_B(s);
3040 gen_op_movq(offsetof(CPUX86State,fpregs[reg & 7].mmx),
3041 offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
664e0f19
FB
3042 break;
3043 case 0xd7: /* pmovmskb */
3044 case 0x1d7:
3045 if (mod != 3)
3046 goto illegal_op;
3047 if (b1) {
3048 rm = (modrm & 7) | REX_B(s);
3049 gen_op_pmovmskb_xmm(offsetof(CPUX86State,xmm_regs[rm]));
3050 } else {
3051 rm = (modrm & 7);
3052 gen_op_pmovmskb_mmx(offsetof(CPUX86State,fpregs[rm].mmx));
3053 }
3054 reg = ((modrm >> 3) & 7) | rex_r;
3055 gen_op_mov_reg_T0[OT_LONG][reg]();
3056 break;
3057 default:
3058 goto illegal_op;
3059 }
3060 } else {
3061 /* generic MMX or SSE operation */
d1e42c5c
FB
3062 switch(b) {
3063 case 0xf7:
664e0f19 3064 /* maskmov : we must prepare A0 */
5fafdf24 3065 if (mod != 3)
664e0f19
FB
3066 goto illegal_op;
3067#ifdef TARGET_X86_64
8f091a59 3068 if (s->aflag == 2) {
664e0f19 3069 gen_op_movq_A0_reg[R_EDI]();
5fafdf24 3070 } else
664e0f19
FB
3071#endif
3072 {
3073 gen_op_movl_A0_reg[R_EDI]();
3074 if (s->aflag == 0)
3075 gen_op_andl_A0_ffff();
3076 }
3077 gen_add_A0_ds_seg(s);
d1e42c5c
FB
3078 break;
3079 case 0x70: /* pshufx insn */
3080 case 0xc6: /* pshufx insn */
3081 case 0xc2: /* compare insns */
3082 s->rip_offset = 1;
3083 break;
3084 default:
3085 break;
664e0f19
FB
3086 }
3087 if (is_xmm) {
3088 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
3089 if (mod != 3) {
3090 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3091 op2_offset = offsetof(CPUX86State,xmm_t0);
480c1cdb 3092 if (b1 >= 2 && ((b >= 0x50 && b <= 0x5f && b != 0x5b) ||
664e0f19
FB
3093 b == 0xc2)) {
3094 /* specific case for SSE single instructions */
3095 if (b1 == 2) {
3096 /* 32 bit access */
3097 gen_op_ld_T0_A0[OT_LONG + s->mem_index]();
3098 gen_op_movl_env_T0(offsetof(CPUX86State,xmm_t0.XMM_L(0)));
3099 } else {
3100 /* 64 bit access */
3101 gen_ldq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_t0.XMM_D(0)));
3102 }
3103 } else {
3104 gen_ldo_env_A0[s->mem_index >> 2](op2_offset);
3105 }
3106 } else {
3107 rm = (modrm & 7) | REX_B(s);
3108 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3109 }
3110 } else {
3111 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
3112 if (mod != 3) {
3113 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3114 op2_offset = offsetof(CPUX86State,mmx_t0);
3115 gen_ldq_env_A0[s->mem_index >> 2](op2_offset);
3116 } else {
3117 rm = (modrm & 7);
3118 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3119 }
3120 }
3121 switch(b) {
3122 case 0x70: /* pshufx insn */
3123 case 0xc6: /* pshufx insn */
3124 val = ldub_code(s->pc++);
3125 sse_op3 = (GenOpFunc3 *)sse_op2;
3126 sse_op3(op1_offset, op2_offset, val);
3127 break;
3128 case 0xc2:
3129 /* compare insns */
3130 val = ldub_code(s->pc++);
3131 if (val >= 8)
3132 goto illegal_op;
3133 sse_op2 = sse_op_table4[val][b1];
3134 sse_op2(op1_offset, op2_offset);
3135 break;
3136 default:
3137 sse_op2(op1_offset, op2_offset);
3138 break;
3139 }
3140 if (b == 0x2e || b == 0x2f) {
3141 s->cc_op = CC_OP_EFLAGS;
3142 }
3143 }
3144}
3145
3146
2c0262af
FB
3147/* convert one instruction. s->is_jmp is set if the translation must
3148 be stopped. Return the next pc value */
14ce26e7 3149static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
2c0262af
FB
3150{
3151 int b, prefixes, aflag, dflag;
3152 int shift, ot;
3153 int modrm, reg, rm, mod, reg_addr, op, opreg, offset_addr, val;
14ce26e7
FB
3154 target_ulong next_eip, tval;
3155 int rex_w, rex_r;
2c0262af
FB
3156
3157 s->pc = pc_start;
3158 prefixes = 0;
3159 aflag = s->code32;
3160 dflag = s->code32;
3161 s->override = -1;
14ce26e7
FB
3162 rex_w = -1;
3163 rex_r = 0;
3164#ifdef TARGET_X86_64
3165 s->rex_x = 0;
3166 s->rex_b = 0;
5fafdf24 3167 x86_64_hregs = 0;
14ce26e7
FB
3168#endif
3169 s->rip_offset = 0; /* for relative ip address */
2c0262af 3170 next_byte:
61382a50 3171 b = ldub_code(s->pc);
2c0262af
FB
3172 s->pc++;
3173 /* check prefixes */
14ce26e7
FB
3174#ifdef TARGET_X86_64
3175 if (CODE64(s)) {
3176 switch (b) {
3177 case 0xf3:
3178 prefixes |= PREFIX_REPZ;
3179 goto next_byte;
3180 case 0xf2:
3181 prefixes |= PREFIX_REPNZ;
3182 goto next_byte;
3183 case 0xf0:
3184 prefixes |= PREFIX_LOCK;
3185 goto next_byte;
3186 case 0x2e:
3187 s->override = R_CS;
3188 goto next_byte;
3189 case 0x36:
3190 s->override = R_SS;
3191 goto next_byte;
3192 case 0x3e:
3193 s->override = R_DS;
3194 goto next_byte;
3195 case 0x26:
3196 s->override = R_ES;
3197 goto next_byte;
3198 case 0x64:
3199 s->override = R_FS;
3200 goto next_byte;
3201 case 0x65:
3202 s->override = R_GS;
3203 goto next_byte;
3204 case 0x66:
3205 prefixes |= PREFIX_DATA;
3206 goto next_byte;
3207 case 0x67:
3208 prefixes |= PREFIX_ADR;
3209 goto next_byte;
3210 case 0x40 ... 0x4f:
3211 /* REX prefix */
3212 rex_w = (b >> 3) & 1;
3213 rex_r = (b & 0x4) << 1;
3214 s->rex_x = (b & 0x2) << 2;
3215 REX_B(s) = (b & 0x1) << 3;
3216 x86_64_hregs = 1; /* select uniform byte register addressing */
3217 goto next_byte;
3218 }
3219 if (rex_w == 1) {
3220 /* 0x66 is ignored if rex.w is set */
3221 dflag = 2;
3222 } else {
3223 if (prefixes & PREFIX_DATA)
3224 dflag ^= 1;
3225 }
3226 if (!(prefixes & PREFIX_ADR))
3227 aflag = 2;
5fafdf24 3228 } else
14ce26e7
FB
3229#endif
3230 {
3231 switch (b) {
3232 case 0xf3:
3233 prefixes |= PREFIX_REPZ;
3234 goto next_byte;
3235 case 0xf2:
3236 prefixes |= PREFIX_REPNZ;
3237 goto next_byte;
3238 case 0xf0:
3239 prefixes |= PREFIX_LOCK;
3240 goto next_byte;
3241 case 0x2e:
3242 s->override = R_CS;
3243 goto next_byte;
3244 case 0x36:
3245 s->override = R_SS;
3246 goto next_byte;
3247 case 0x3e:
3248 s->override = R_DS;
3249 goto next_byte;
3250 case 0x26:
3251 s->override = R_ES;
3252 goto next_byte;
3253 case 0x64:
3254 s->override = R_FS;
3255 goto next_byte;
3256 case 0x65:
3257 s->override = R_GS;
3258 goto next_byte;
3259 case 0x66:
3260 prefixes |= PREFIX_DATA;
3261 goto next_byte;
3262 case 0x67:
3263 prefixes |= PREFIX_ADR;
3264 goto next_byte;
3265 }
3266 if (prefixes & PREFIX_DATA)
3267 dflag ^= 1;
3268 if (prefixes & PREFIX_ADR)
3269 aflag ^= 1;
2c0262af
FB
3270 }
3271
2c0262af
FB
3272 s->prefix = prefixes;
3273 s->aflag = aflag;
3274 s->dflag = dflag;
3275
3276 /* lock generation */
3277 if (prefixes & PREFIX_LOCK)
3278 gen_op_lock();
3279
3280 /* now check op code */
3281 reswitch:
3282 switch(b) {
3283 case 0x0f:
3284 /**************************/
3285 /* extended op code */
61382a50 3286 b = ldub_code(s->pc++) | 0x100;
2c0262af 3287 goto reswitch;
3b46e624 3288
2c0262af
FB
3289 /**************************/
3290 /* arith & logic */
3291 case 0x00 ... 0x05:
3292 case 0x08 ... 0x0d:
3293 case 0x10 ... 0x15:
3294 case 0x18 ... 0x1d:
3295 case 0x20 ... 0x25:
3296 case 0x28 ... 0x2d:
3297 case 0x30 ... 0x35:
3298 case 0x38 ... 0x3d:
3299 {
3300 int op, f, val;
3301 op = (b >> 3) & 7;
3302 f = (b >> 1) & 3;
3303
3304 if ((b & 1) == 0)
3305 ot = OT_BYTE;
3306 else
14ce26e7 3307 ot = dflag + OT_WORD;
3b46e624 3308
2c0262af
FB
3309 switch(f) {
3310 case 0: /* OP Ev, Gv */
61382a50 3311 modrm = ldub_code(s->pc++);
14ce26e7 3312 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af 3313 mod = (modrm >> 6) & 3;
14ce26e7 3314 rm = (modrm & 7) | REX_B(s);
2c0262af
FB
3315 if (mod != 3) {
3316 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3317 opreg = OR_TMP0;
3318 } else if (op == OP_XORL && rm == reg) {
3319 xor_zero:
3320 /* xor reg, reg optimisation */
3321 gen_op_movl_T0_0();
3322 s->cc_op = CC_OP_LOGICB + ot;
3323 gen_op_mov_reg_T0[ot][reg]();
3324 gen_op_update1_cc();
3325 break;
3326 } else {
3327 opreg = rm;
3328 }
3329 gen_op_mov_TN_reg[ot][1][reg]();
3330 gen_op(s, op, ot, opreg);
3331 break;
3332 case 1: /* OP Gv, Ev */
61382a50 3333 modrm = ldub_code(s->pc++);
2c0262af 3334 mod = (modrm >> 6) & 3;
14ce26e7
FB
3335 reg = ((modrm >> 3) & 7) | rex_r;
3336 rm = (modrm & 7) | REX_B(s);
2c0262af
FB
3337 if (mod != 3) {
3338 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3339 gen_op_ld_T1_A0[ot + s->mem_index]();
3340 } else if (op == OP_XORL && rm == reg) {
3341 goto xor_zero;
3342 } else {
3343 gen_op_mov_TN_reg[ot][1][rm]();
3344 }
3345 gen_op(s, op, ot, reg);
3346 break;
3347 case 2: /* OP A, Iv */
3348 val = insn_get(s, ot);
3349 gen_op_movl_T1_im(val);
3350 gen_op(s, op, ot, OR_EAX);
3351 break;
3352 }
3353 }
3354 break;
3355
3356 case 0x80: /* GRP1 */
3357 case 0x81:
d64477af 3358 case 0x82:
2c0262af
FB
3359 case 0x83:
3360 {
3361 int val;
3362
3363 if ((b & 1) == 0)
3364 ot = OT_BYTE;
3365 else
14ce26e7 3366 ot = dflag + OT_WORD;
3b46e624 3367
61382a50 3368 modrm = ldub_code(s->pc++);
2c0262af 3369 mod = (modrm >> 6) & 3;
14ce26e7 3370 rm = (modrm & 7) | REX_B(s);
2c0262af 3371 op = (modrm >> 3) & 7;
3b46e624 3372
2c0262af 3373 if (mod != 3) {
14ce26e7
FB
3374 if (b == 0x83)
3375 s->rip_offset = 1;
3376 else
3377 s->rip_offset = insn_const_size(ot);
2c0262af
FB
3378 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3379 opreg = OR_TMP0;
3380 } else {
14ce26e7 3381 opreg = rm;
2c0262af
FB
3382 }
3383
3384 switch(b) {
3385 default:
3386 case 0x80:
3387 case 0x81:
d64477af 3388 case 0x82:
2c0262af
FB
3389 val = insn_get(s, ot);
3390 break;
3391 case 0x83:
3392 val = (int8_t)insn_get(s, OT_BYTE);
3393 break;
3394 }
3395 gen_op_movl_T1_im(val);
3396 gen_op(s, op, ot, opreg);
3397 }
3398 break;
3399
3400 /**************************/
3401 /* inc, dec, and other misc arith */
3402 case 0x40 ... 0x47: /* inc Gv */
3403 ot = dflag ? OT_LONG : OT_WORD;
3404 gen_inc(s, ot, OR_EAX + (b & 7), 1);
3405 break;
3406 case 0x48 ... 0x4f: /* dec Gv */
3407 ot = dflag ? OT_LONG : OT_WORD;
3408 gen_inc(s, ot, OR_EAX + (b & 7), -1);
3409 break;
3410 case 0xf6: /* GRP3 */
3411 case 0xf7:
3412 if ((b & 1) == 0)
3413 ot = OT_BYTE;
3414 else
14ce26e7 3415 ot = dflag + OT_WORD;
2c0262af 3416
61382a50 3417 modrm = ldub_code(s->pc++);
2c0262af 3418 mod = (modrm >> 6) & 3;
14ce26e7 3419 rm = (modrm & 7) | REX_B(s);
2c0262af
FB
3420 op = (modrm >> 3) & 7;
3421 if (mod != 3) {
14ce26e7
FB
3422 if (op == 0)
3423 s->rip_offset = insn_const_size(ot);
2c0262af
FB
3424 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3425 gen_op_ld_T0_A0[ot + s->mem_index]();
3426 } else {
3427 gen_op_mov_TN_reg[ot][0][rm]();
3428 }
3429
3430 switch(op) {
3431 case 0: /* test */
3432 val = insn_get(s, ot);
3433 gen_op_movl_T1_im(val);
3434 gen_op_testl_T0_T1_cc();
3435 s->cc_op = CC_OP_LOGICB + ot;
3436 break;
3437 case 2: /* not */
3438 gen_op_notl_T0();
3439 if (mod != 3) {
3440 gen_op_st_T0_A0[ot + s->mem_index]();
3441 } else {
3442 gen_op_mov_reg_T0[ot][rm]();
3443 }
3444 break;
3445 case 3: /* neg */
3446 gen_op_negl_T0();
3447 if (mod != 3) {
3448 gen_op_st_T0_A0[ot + s->mem_index]();
3449 } else {
3450 gen_op_mov_reg_T0[ot][rm]();
3451 }
3452 gen_op_update_neg_cc();
3453 s->cc_op = CC_OP_SUBB + ot;
3454 break;
3455 case 4: /* mul */
3456 switch(ot) {
3457 case OT_BYTE:
3458 gen_op_mulb_AL_T0();
d36cd60e 3459 s->cc_op = CC_OP_MULB;
2c0262af
FB
3460 break;
3461 case OT_WORD:
3462 gen_op_mulw_AX_T0();
d36cd60e 3463 s->cc_op = CC_OP_MULW;
2c0262af
FB
3464 break;
3465 default:
3466 case OT_LONG:
3467 gen_op_mull_EAX_T0();
d36cd60e 3468 s->cc_op = CC_OP_MULL;
2c0262af 3469 break;
14ce26e7
FB
3470#ifdef TARGET_X86_64
3471 case OT_QUAD:
3472 gen_op_mulq_EAX_T0();
3473 s->cc_op = CC_OP_MULQ;
3474 break;
3475#endif
2c0262af 3476 }
2c0262af
FB
3477 break;
3478 case 5: /* imul */
3479 switch(ot) {
3480 case OT_BYTE:
3481 gen_op_imulb_AL_T0();
d36cd60e 3482 s->cc_op = CC_OP_MULB;
2c0262af
FB
3483 break;
3484 case OT_WORD:
3485 gen_op_imulw_AX_T0();
d36cd60e 3486 s->cc_op = CC_OP_MULW;
2c0262af
FB
3487 break;
3488 default:
3489 case OT_LONG:
3490 gen_op_imull_EAX_T0();
d36cd60e 3491 s->cc_op = CC_OP_MULL;
2c0262af 3492 break;
14ce26e7
FB
3493#ifdef TARGET_X86_64
3494 case OT_QUAD:
3495 gen_op_imulq_EAX_T0();
3496 s->cc_op = CC_OP_MULQ;
3497 break;
3498#endif
2c0262af 3499 }
2c0262af
FB
3500 break;
3501 case 6: /* div */
3502 switch(ot) {
3503 case OT_BYTE:
14ce26e7
FB
3504 gen_jmp_im(pc_start - s->cs_base);
3505 gen_op_divb_AL_T0();
2c0262af
FB
3506 break;
3507 case OT_WORD:
14ce26e7
FB
3508 gen_jmp_im(pc_start - s->cs_base);
3509 gen_op_divw_AX_T0();
2c0262af
FB
3510 break;
3511 default:
3512 case OT_LONG:
14ce26e7
FB
3513 gen_jmp_im(pc_start - s->cs_base);
3514 gen_op_divl_EAX_T0();
3515 break;
3516#ifdef TARGET_X86_64
3517 case OT_QUAD:
3518 gen_jmp_im(pc_start - s->cs_base);
3519 gen_op_divq_EAX_T0();
2c0262af 3520 break;
14ce26e7 3521#endif
2c0262af
FB
3522 }
3523 break;
3524 case 7: /* idiv */
3525 switch(ot) {
3526 case OT_BYTE:
14ce26e7
FB
3527 gen_jmp_im(pc_start - s->cs_base);
3528 gen_op_idivb_AL_T0();
2c0262af
FB
3529 break;
3530 case OT_WORD:
14ce26e7
FB
3531 gen_jmp_im(pc_start - s->cs_base);
3532 gen_op_idivw_AX_T0();
2c0262af
FB
3533 break;
3534 default:
3535 case OT_LONG:
14ce26e7
FB
3536 gen_jmp_im(pc_start - s->cs_base);
3537 gen_op_idivl_EAX_T0();
3538 break;
3539#ifdef TARGET_X86_64
3540 case OT_QUAD:
3541 gen_jmp_im(pc_start - s->cs_base);
3542 gen_op_idivq_EAX_T0();
2c0262af 3543 break;
14ce26e7 3544#endif
2c0262af
FB
3545 }
3546 break;
3547 default:
3548 goto illegal_op;
3549 }
3550 break;
3551
3552 case 0xfe: /* GRP4 */
3553 case 0xff: /* GRP5 */
3554 if ((b & 1) == 0)
3555 ot = OT_BYTE;
3556 else
14ce26e7 3557 ot = dflag + OT_WORD;
2c0262af 3558
61382a50 3559 modrm = ldub_code(s->pc++);
2c0262af 3560 mod = (modrm >> 6) & 3;
14ce26e7 3561 rm = (modrm & 7) | REX_B(s);
2c0262af
FB
3562 op = (modrm >> 3) & 7;
3563 if (op >= 2 && b == 0xfe) {
3564 goto illegal_op;
3565 }
14ce26e7 3566 if (CODE64(s)) {
aba9d61e 3567 if (op == 2 || op == 4) {
14ce26e7
FB
3568 /* operand size for jumps is 64 bit */
3569 ot = OT_QUAD;
aba9d61e
FB
3570 } else if (op == 3 || op == 5) {
3571 /* for call calls, the operand is 16 or 32 bit, even
3572 in long mode */
3573 ot = dflag ? OT_LONG : OT_WORD;
14ce26e7
FB
3574 } else if (op == 6) {
3575 /* default push size is 64 bit */
3576 ot = dflag ? OT_QUAD : OT_WORD;
3577 }
3578 }
2c0262af
FB
3579 if (mod != 3) {
3580 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3581 if (op >= 2 && op != 3 && op != 5)
3582 gen_op_ld_T0_A0[ot + s->mem_index]();
3583 } else {
3584 gen_op_mov_TN_reg[ot][0][rm]();
3585 }
3586
3587 switch(op) {
3588 case 0: /* inc Ev */
3589 if (mod != 3)
3590 opreg = OR_TMP0;
3591 else
3592 opreg = rm;
3593 gen_inc(s, ot, opreg, 1);
3594 break;
3595 case 1: /* dec Ev */
3596 if (mod != 3)
3597 opreg = OR_TMP0;
3598 else
3599 opreg = rm;
3600 gen_inc(s, ot, opreg, -1);
3601 break;
3602 case 2: /* call Ev */
4f31916f 3603 /* XXX: optimize if memory (no 'and' is necessary) */
2c0262af
FB
3604 if (s->dflag == 0)
3605 gen_op_andl_T0_ffff();
2c0262af 3606 next_eip = s->pc - s->cs_base;
1ef38687 3607 gen_movtl_T1_im(next_eip);
4f31916f
FB
3608 gen_push_T1(s);
3609 gen_op_jmp_T0();
2c0262af
FB
3610 gen_eob(s);
3611 break;
61382a50 3612 case 3: /* lcall Ev */
2c0262af 3613 gen_op_ld_T1_A0[ot + s->mem_index]();
aba9d61e 3614 gen_add_A0_im(s, 1 << (ot - OT_WORD + 1));
61382a50 3615 gen_op_ldu_T0_A0[OT_WORD + s->mem_index]();
2c0262af
FB
3616 do_lcall:
3617 if (s->pe && !s->vm86) {
3618 if (s->cc_op != CC_OP_DYNAMIC)
3619 gen_op_set_cc_op(s->cc_op);
14ce26e7 3620 gen_jmp_im(pc_start - s->cs_base);
aba9d61e 3621 gen_op_lcall_protected_T0_T1(dflag, s->pc - pc_start);
2c0262af
FB
3622 } else {
3623 gen_op_lcall_real_T0_T1(dflag, s->pc - s->cs_base);
3624 }
3625 gen_eob(s);
3626 break;
3627 case 4: /* jmp Ev */
3628 if (s->dflag == 0)
3629 gen_op_andl_T0_ffff();
3630 gen_op_jmp_T0();
3631 gen_eob(s);
3632 break;
3633 case 5: /* ljmp Ev */
3634 gen_op_ld_T1_A0[ot + s->mem_index]();
aba9d61e 3635 gen_add_A0_im(s, 1 << (ot - OT_WORD + 1));
61382a50 3636 gen_op_ldu_T0_A0[OT_WORD + s->mem_index]();
2c0262af
FB
3637 do_ljmp:
3638 if (s->pe && !s->vm86) {
3639 if (s->cc_op != CC_OP_DYNAMIC)
3640 gen_op_set_cc_op(s->cc_op);
14ce26e7 3641 gen_jmp_im(pc_start - s->cs_base);
aba9d61e 3642 gen_op_ljmp_protected_T0_T1(s->pc - pc_start);
2c0262af
FB
3643 } else {
3644 gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[R_CS]));
3645 gen_op_movl_T0_T1();
3646 gen_op_jmp_T0();
3647 }
3648 gen_eob(s);
3649 break;
3650 case 6: /* push Ev */
3651 gen_push_T0(s);
3652 break;
3653 default:
3654 goto illegal_op;
3655 }
3656 break;
3657
3658 case 0x84: /* test Ev, Gv */
5fafdf24 3659 case 0x85:
2c0262af
FB
3660 if ((b & 1) == 0)
3661 ot = OT_BYTE;
3662 else
14ce26e7 3663 ot = dflag + OT_WORD;
2c0262af 3664
61382a50 3665 modrm = ldub_code(s->pc++);
2c0262af 3666 mod = (modrm >> 6) & 3;
14ce26e7
FB
3667 rm = (modrm & 7) | REX_B(s);
3668 reg = ((modrm >> 3) & 7) | rex_r;
3b46e624 3669
2c0262af 3670 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
14ce26e7 3671 gen_op_mov_TN_reg[ot][1][reg]();
2c0262af
FB
3672 gen_op_testl_T0_T1_cc();
3673 s->cc_op = CC_OP_LOGICB + ot;
3674 break;
3b46e624 3675
2c0262af
FB
3676 case 0xa8: /* test eAX, Iv */
3677 case 0xa9:
3678 if ((b & 1) == 0)
3679 ot = OT_BYTE;
3680 else
14ce26e7 3681 ot = dflag + OT_WORD;
2c0262af
FB
3682 val = insn_get(s, ot);
3683
3684 gen_op_mov_TN_reg[ot][0][OR_EAX]();
3685 gen_op_movl_T1_im(val);
3686 gen_op_testl_T0_T1_cc();
3687 s->cc_op = CC_OP_LOGICB + ot;
3688 break;
3b46e624 3689
2c0262af 3690 case 0x98: /* CWDE/CBW */
14ce26e7
FB
3691#ifdef TARGET_X86_64
3692 if (dflag == 2) {
3693 gen_op_movslq_RAX_EAX();
3694 } else
3695#endif
3696 if (dflag == 1)
2c0262af
FB
3697 gen_op_movswl_EAX_AX();
3698 else
3699 gen_op_movsbw_AX_AL();
3700 break;
3701 case 0x99: /* CDQ/CWD */
14ce26e7
FB
3702#ifdef TARGET_X86_64
3703 if (dflag == 2) {
3704 gen_op_movsqo_RDX_RAX();
3705 } else
3706#endif
3707 if (dflag == 1)
2c0262af
FB
3708 gen_op_movslq_EDX_EAX();
3709 else
3710 gen_op_movswl_DX_AX();
3711 break;
3712 case 0x1af: /* imul Gv, Ev */
3713 case 0x69: /* imul Gv, Ev, I */
3714 case 0x6b:
14ce26e7 3715 ot = dflag + OT_WORD;
61382a50 3716 modrm = ldub_code(s->pc++);
14ce26e7
FB
3717 reg = ((modrm >> 3) & 7) | rex_r;
3718 if (b == 0x69)
3719 s->rip_offset = insn_const_size(ot);
3720 else if (b == 0x6b)
3721 s->rip_offset = 1;
2c0262af
FB
3722 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
3723 if (b == 0x69) {
3724 val = insn_get(s, ot);
3725 gen_op_movl_T1_im(val);
3726 } else if (b == 0x6b) {
d64477af 3727 val = (int8_t)insn_get(s, OT_BYTE);
2c0262af
FB
3728 gen_op_movl_T1_im(val);
3729 } else {
3730 gen_op_mov_TN_reg[ot][1][reg]();
3731 }
3732
14ce26e7
FB
3733#ifdef TARGET_X86_64
3734 if (ot == OT_QUAD) {
3735 gen_op_imulq_T0_T1();
3736 } else
3737#endif
2c0262af
FB
3738 if (ot == OT_LONG) {
3739 gen_op_imull_T0_T1();
3740 } else {
3741 gen_op_imulw_T0_T1();
3742 }
3743 gen_op_mov_reg_T0[ot][reg]();
d36cd60e 3744 s->cc_op = CC_OP_MULB + ot;
2c0262af
FB
3745 break;
3746 case 0x1c0:
3747 case 0x1c1: /* xadd Ev, Gv */
3748 if ((b & 1) == 0)
3749 ot = OT_BYTE;
3750 else
14ce26e7 3751 ot = dflag + OT_WORD;
61382a50 3752 modrm = ldub_code(s->pc++);
14ce26e7 3753 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af
FB
3754 mod = (modrm >> 6) & 3;
3755 if (mod == 3) {
14ce26e7 3756 rm = (modrm & 7) | REX_B(s);
2c0262af
FB
3757 gen_op_mov_TN_reg[ot][0][reg]();
3758 gen_op_mov_TN_reg[ot][1][rm]();
3759 gen_op_addl_T0_T1();
2c0262af 3760 gen_op_mov_reg_T1[ot][reg]();
5a1388b6 3761 gen_op_mov_reg_T0[ot][rm]();
2c0262af
FB
3762 } else {
3763 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3764 gen_op_mov_TN_reg[ot][0][reg]();
3765 gen_op_ld_T1_A0[ot + s->mem_index]();
3766 gen_op_addl_T0_T1();
3767 gen_op_st_T0_A0[ot + s->mem_index]();
3768 gen_op_mov_reg_T1[ot][reg]();
3769 }
3770 gen_op_update2_cc();
3771 s->cc_op = CC_OP_ADDB + ot;
3772 break;
3773 case 0x1b0:
3774 case 0x1b1: /* cmpxchg Ev, Gv */
3775 if ((b & 1) == 0)
3776 ot = OT_BYTE;
3777 else
14ce26e7 3778 ot = dflag + OT_WORD;
61382a50 3779 modrm = ldub_code(s->pc++);
14ce26e7 3780 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af
FB
3781 mod = (modrm >> 6) & 3;
3782 gen_op_mov_TN_reg[ot][1][reg]();
3783 if (mod == 3) {
14ce26e7 3784 rm = (modrm & 7) | REX_B(s);
2c0262af
FB
3785 gen_op_mov_TN_reg[ot][0][rm]();
3786 gen_op_cmpxchg_T0_T1_EAX_cc[ot]();
3787 gen_op_mov_reg_T0[ot][rm]();
3788 } else {
3789 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3790 gen_op_ld_T0_A0[ot + s->mem_index]();
4f31916f 3791 gen_op_cmpxchg_mem_T0_T1_EAX_cc[ot + s->mem_index]();
2c0262af
FB
3792 }
3793 s->cc_op = CC_OP_SUBB + ot;
3794 break;
3795 case 0x1c7: /* cmpxchg8b */
61382a50 3796 modrm = ldub_code(s->pc++);
2c0262af
FB
3797 mod = (modrm >> 6) & 3;
3798 if (mod == 3)
3799 goto illegal_op;
2f6ecc62 3800 gen_jmp_im(pc_start - s->cs_base);
2c0262af
FB
3801 if (s->cc_op != CC_OP_DYNAMIC)
3802 gen_op_set_cc_op(s->cc_op);
3803 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3804 gen_op_cmpxchg8b();
3805 s->cc_op = CC_OP_EFLAGS;
3806 break;
3b46e624 3807
2c0262af
FB
3808 /**************************/
3809 /* push/pop */
3810 case 0x50 ... 0x57: /* push */
14ce26e7 3811 gen_op_mov_TN_reg[OT_LONG][0][(b & 7) | REX_B(s)]();
2c0262af
FB
3812 gen_push_T0(s);
3813 break;
3814 case 0x58 ... 0x5f: /* pop */
14ce26e7
FB
3815 if (CODE64(s)) {
3816 ot = dflag ? OT_QUAD : OT_WORD;
3817 } else {
3818 ot = dflag + OT_WORD;
3819 }
2c0262af 3820 gen_pop_T0(s);
77729c24 3821 /* NOTE: order is important for pop %sp */
2c0262af 3822 gen_pop_update(s);
14ce26e7 3823 gen_op_mov_reg_T0[ot][(b & 7) | REX_B(s)]();
2c0262af
FB
3824 break;
3825 case 0x60: /* pusha */
14ce26e7
FB
3826 if (CODE64(s))
3827 goto illegal_op;
2c0262af
FB
3828 gen_pusha(s);
3829 break;
3830 case 0x61: /* popa */
14ce26e7
FB
3831 if (CODE64(s))
3832 goto illegal_op;
2c0262af
FB
3833 gen_popa(s);
3834 break;
3835 case 0x68: /* push Iv */
3836 case 0x6a:
14ce26e7
FB
3837 if (CODE64(s)) {
3838 ot = dflag ? OT_QUAD : OT_WORD;
3839 } else {
3840 ot = dflag + OT_WORD;
3841 }
2c0262af
FB
3842 if (b == 0x68)
3843 val = insn_get(s, ot);
3844 else
3845 val = (int8_t)insn_get(s, OT_BYTE);
3846 gen_op_movl_T0_im(val);
3847 gen_push_T0(s);
3848 break;
3849 case 0x8f: /* pop Ev */
14ce26e7
FB
3850 if (CODE64(s)) {
3851 ot = dflag ? OT_QUAD : OT_WORD;
3852 } else {
3853 ot = dflag + OT_WORD;
3854 }
61382a50 3855 modrm = ldub_code(s->pc++);
77729c24 3856 mod = (modrm >> 6) & 3;
2c0262af 3857 gen_pop_T0(s);
77729c24
FB
3858 if (mod == 3) {
3859 /* NOTE: order is important for pop %sp */
3860 gen_pop_update(s);
14ce26e7 3861 rm = (modrm & 7) | REX_B(s);
77729c24
FB
3862 gen_op_mov_reg_T0[ot][rm]();
3863 } else {
3864 /* NOTE: order is important too for MMU exceptions */
14ce26e7 3865 s->popl_esp_hack = 1 << ot;
77729c24
FB
3866 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
3867 s->popl_esp_hack = 0;
3868 gen_pop_update(s);
3869 }
2c0262af
FB
3870 break;
3871 case 0xc8: /* enter */
3872 {
3873 int level;
61382a50 3874 val = lduw_code(s->pc);
2c0262af 3875 s->pc += 2;
61382a50 3876 level = ldub_code(s->pc++);
2c0262af
FB
3877 gen_enter(s, val, level);
3878 }
3879 break;
3880 case 0xc9: /* leave */
3881 /* XXX: exception not precise (ESP is updated before potential exception) */
14ce26e7
FB
3882 if (CODE64(s)) {
3883 gen_op_mov_TN_reg[OT_QUAD][0][R_EBP]();
3884 gen_op_mov_reg_T0[OT_QUAD][R_ESP]();
3885 } else if (s->ss32) {
2c0262af
FB
3886 gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
3887 gen_op_mov_reg_T0[OT_LONG][R_ESP]();
3888 } else {
3889 gen_op_mov_TN_reg[OT_WORD][0][R_EBP]();
3890 gen_op_mov_reg_T0[OT_WORD][R_ESP]();
3891 }
3892 gen_pop_T0(s);
14ce26e7
FB
3893 if (CODE64(s)) {
3894 ot = dflag ? OT_QUAD : OT_WORD;
3895 } else {
3896 ot = dflag + OT_WORD;
3897 }
2c0262af
FB
3898 gen_op_mov_reg_T0[ot][R_EBP]();
3899 gen_pop_update(s);
3900 break;
3901 case 0x06: /* push es */
3902 case 0x0e: /* push cs */
3903 case 0x16: /* push ss */
3904 case 0x1e: /* push ds */
14ce26e7
FB
3905 if (CODE64(s))
3906 goto illegal_op;
2c0262af
FB
3907 gen_op_movl_T0_seg(b >> 3);
3908 gen_push_T0(s);
3909 break;
3910 case 0x1a0: /* push fs */
3911 case 0x1a8: /* push gs */
3912 gen_op_movl_T0_seg((b >> 3) & 7);
3913 gen_push_T0(s);
3914 break;
3915 case 0x07: /* pop es */
3916 case 0x17: /* pop ss */
3917 case 0x1f: /* pop ds */
14ce26e7
FB
3918 if (CODE64(s))
3919 goto illegal_op;
2c0262af
FB
3920 reg = b >> 3;
3921 gen_pop_T0(s);
3922 gen_movl_seg_T0(s, reg, pc_start - s->cs_base);
3923 gen_pop_update(s);
3924 if (reg == R_SS) {
a2cc3b24
FB
3925 /* if reg == SS, inhibit interrupts/trace. */
3926 /* If several instructions disable interrupts, only the
3927 _first_ does it */
3928 if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
3929 gen_op_set_inhibit_irq();
2c0262af
FB
3930 s->tf = 0;
3931 }
3932 if (s->is_jmp) {
14ce26e7 3933 gen_jmp_im(s->pc - s->cs_base);
2c0262af
FB
3934 gen_eob(s);
3935 }
3936 break;
3937 case 0x1a1: /* pop fs */
3938 case 0x1a9: /* pop gs */
3939 gen_pop_T0(s);
3940 gen_movl_seg_T0(s, (b >> 3) & 7, pc_start - s->cs_base);
3941 gen_pop_update(s);
3942 if (s->is_jmp) {
14ce26e7 3943 gen_jmp_im(s->pc - s->cs_base);
2c0262af
FB
3944 gen_eob(s);
3945 }
3946 break;
3947
3948 /**************************/
3949 /* mov */
3950 case 0x88:
3951 case 0x89: /* mov Gv, Ev */
3952 if ((b & 1) == 0)
3953 ot = OT_BYTE;
3954 else
14ce26e7 3955 ot = dflag + OT_WORD;
61382a50 3956 modrm = ldub_code(s->pc++);
14ce26e7 3957 reg = ((modrm >> 3) & 7) | rex_r;
3b46e624 3958
2c0262af 3959 /* generate a generic store */
14ce26e7 3960 gen_ldst_modrm(s, modrm, ot, reg, 1);
2c0262af
FB
3961 break;
3962 case 0xc6:
3963 case 0xc7: /* mov Ev, Iv */
3964 if ((b & 1) == 0)
3965 ot = OT_BYTE;
3966 else
14ce26e7 3967 ot = dflag + OT_WORD;
61382a50 3968 modrm = ldub_code(s->pc++);
2c0262af 3969 mod = (modrm >> 6) & 3;
14ce26e7
FB
3970 if (mod != 3) {
3971 s->rip_offset = insn_const_size(ot);
2c0262af 3972 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
14ce26e7 3973 }
2c0262af
FB
3974 val = insn_get(s, ot);
3975 gen_op_movl_T0_im(val);
3976 if (mod != 3)
3977 gen_op_st_T0_A0[ot + s->mem_index]();
3978 else
14ce26e7 3979 gen_op_mov_reg_T0[ot][(modrm & 7) | REX_B(s)]();
2c0262af
FB
3980 break;
3981 case 0x8a:
3982 case 0x8b: /* mov Ev, Gv */
3983 if ((b & 1) == 0)
3984 ot = OT_BYTE;
3985 else
14ce26e7 3986 ot = OT_WORD + dflag;
61382a50 3987 modrm = ldub_code(s->pc++);
14ce26e7 3988 reg = ((modrm >> 3) & 7) | rex_r;
3b46e624 3989
2c0262af
FB
3990 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
3991 gen_op_mov_reg_T0[ot][reg]();
3992 break;
3993 case 0x8e: /* mov seg, Gv */
61382a50 3994 modrm = ldub_code(s->pc++);
2c0262af
FB
3995 reg = (modrm >> 3) & 7;
3996 if (reg >= 6 || reg == R_CS)
3997 goto illegal_op;
3998 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
3999 gen_movl_seg_T0(s, reg, pc_start - s->cs_base);
4000 if (reg == R_SS) {
4001 /* if reg == SS, inhibit interrupts/trace */
a2cc3b24
FB
4002 /* If several instructions disable interrupts, only the
4003 _first_ does it */
4004 if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
4005 gen_op_set_inhibit_irq();
2c0262af
FB
4006 s->tf = 0;
4007 }
4008 if (s->is_jmp) {
14ce26e7 4009 gen_jmp_im(s->pc - s->cs_base);
2c0262af
FB
4010 gen_eob(s);
4011 }
4012 break;
4013 case 0x8c: /* mov Gv, seg */
61382a50 4014 modrm = ldub_code(s->pc++);
2c0262af
FB
4015 reg = (modrm >> 3) & 7;
4016 mod = (modrm >> 6) & 3;
4017 if (reg >= 6)
4018 goto illegal_op;
4019 gen_op_movl_T0_seg(reg);
14ce26e7
FB
4020 if (mod == 3)
4021 ot = OT_WORD + dflag;
4022 else
4023 ot = OT_WORD;
2c0262af
FB
4024 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
4025 break;
4026
4027 case 0x1b6: /* movzbS Gv, Eb */
4028 case 0x1b7: /* movzwS Gv, Eb */
4029 case 0x1be: /* movsbS Gv, Eb */
4030 case 0x1bf: /* movswS Gv, Eb */
4031 {
4032 int d_ot;
4033 /* d_ot is the size of destination */
4034 d_ot = dflag + OT_WORD;
4035 /* ot is the size of source */
4036 ot = (b & 1) + OT_BYTE;
61382a50 4037 modrm = ldub_code(s->pc++);
14ce26e7 4038 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af 4039 mod = (modrm >> 6) & 3;
14ce26e7 4040 rm = (modrm & 7) | REX_B(s);
3b46e624 4041
2c0262af
FB
4042 if (mod == 3) {
4043 gen_op_mov_TN_reg[ot][0][rm]();
4044 switch(ot | (b & 8)) {
4045 case OT_BYTE:
4046 gen_op_movzbl_T0_T0();
4047 break;
4048 case OT_BYTE | 8:
4049 gen_op_movsbl_T0_T0();
4050 break;
4051 case OT_WORD:
4052 gen_op_movzwl_T0_T0();
4053 break;
4054 default:
4055 case OT_WORD | 8:
4056 gen_op_movswl_T0_T0();
4057 break;
4058 }
4059 gen_op_mov_reg_T0[d_ot][reg]();
4060 } else {
4061 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4062 if (b & 8) {
4063 gen_op_lds_T0_A0[ot + s->mem_index]();
4064 } else {
4065 gen_op_ldu_T0_A0[ot + s->mem_index]();
4066 }
4067 gen_op_mov_reg_T0[d_ot][reg]();
4068 }
4069 }
4070 break;
4071
4072 case 0x8d: /* lea */
14ce26e7 4073 ot = dflag + OT_WORD;
61382a50 4074 modrm = ldub_code(s->pc++);
3a1d9b8b
FB
4075 mod = (modrm >> 6) & 3;
4076 if (mod == 3)
4077 goto illegal_op;
14ce26e7 4078 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af
FB
4079 /* we must ensure that no segment is added */
4080 s->override = -1;
4081 val = s->addseg;
4082 s->addseg = 0;
4083 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4084 s->addseg = val;
4085 gen_op_mov_reg_A0[ot - OT_WORD][reg]();
4086 break;
3b46e624 4087
2c0262af
FB
4088 case 0xa0: /* mov EAX, Ov */
4089 case 0xa1:
4090 case 0xa2: /* mov Ov, EAX */
4091 case 0xa3:
2c0262af 4092 {
14ce26e7
FB
4093 target_ulong offset_addr;
4094
4095 if ((b & 1) == 0)
4096 ot = OT_BYTE;
4097 else
4098 ot = dflag + OT_WORD;
4099#ifdef TARGET_X86_64
8f091a59 4100 if (s->aflag == 2) {
14ce26e7
FB
4101 offset_addr = ldq_code(s->pc);
4102 s->pc += 8;
4103 if (offset_addr == (int32_t)offset_addr)
4104 gen_op_movq_A0_im(offset_addr);
4105 else
4106 gen_op_movq_A0_im64(offset_addr >> 32, offset_addr);
5fafdf24 4107 } else
14ce26e7
FB
4108#endif
4109 {
4110 if (s->aflag) {
4111 offset_addr = insn_get(s, OT_LONG);
4112 } else {
4113 offset_addr = insn_get(s, OT_WORD);
4114 }
4115 gen_op_movl_A0_im(offset_addr);
4116 }
664e0f19 4117 gen_add_A0_ds_seg(s);
14ce26e7
FB
4118 if ((b & 2) == 0) {
4119 gen_op_ld_T0_A0[ot + s->mem_index]();
4120 gen_op_mov_reg_T0[ot][R_EAX]();
4121 } else {
4122 gen_op_mov_TN_reg[ot][0][R_EAX]();
4123 gen_op_st_T0_A0[ot + s->mem_index]();
2c0262af
FB
4124 }
4125 }
2c0262af
FB
4126 break;
4127 case 0xd7: /* xlat */
14ce26e7 4128#ifdef TARGET_X86_64
8f091a59 4129 if (s->aflag == 2) {
14ce26e7
FB
4130 gen_op_movq_A0_reg[R_EBX]();
4131 gen_op_addq_A0_AL();
5fafdf24 4132 } else
14ce26e7
FB
4133#endif
4134 {
4135 gen_op_movl_A0_reg[R_EBX]();
4136 gen_op_addl_A0_AL();
4137 if (s->aflag == 0)
4138 gen_op_andl_A0_ffff();
4139 }
664e0f19 4140 gen_add_A0_ds_seg(s);
2c0262af
FB
4141 gen_op_ldu_T0_A0[OT_BYTE + s->mem_index]();
4142 gen_op_mov_reg_T0[OT_BYTE][R_EAX]();
4143 break;
4144 case 0xb0 ... 0xb7: /* mov R, Ib */
4145 val = insn_get(s, OT_BYTE);
4146 gen_op_movl_T0_im(val);
14ce26e7 4147 gen_op_mov_reg_T0[OT_BYTE][(b & 7) | REX_B(s)]();
2c0262af
FB
4148 break;
4149 case 0xb8 ... 0xbf: /* mov R, Iv */
14ce26e7
FB
4150#ifdef TARGET_X86_64
4151 if (dflag == 2) {
4152 uint64_t tmp;
4153 /* 64 bit case */
4154 tmp = ldq_code(s->pc);
4155 s->pc += 8;
4156 reg = (b & 7) | REX_B(s);
4157 gen_movtl_T0_im(tmp);
4158 gen_op_mov_reg_T0[OT_QUAD][reg]();
5fafdf24 4159 } else
14ce26e7
FB
4160#endif
4161 {
4162 ot = dflag ? OT_LONG : OT_WORD;
4163 val = insn_get(s, ot);
4164 reg = (b & 7) | REX_B(s);
4165 gen_op_movl_T0_im(val);
4166 gen_op_mov_reg_T0[ot][reg]();
4167 }
2c0262af
FB
4168 break;
4169
4170 case 0x91 ... 0x97: /* xchg R, EAX */
14ce26e7
FB
4171 ot = dflag + OT_WORD;
4172 reg = (b & 7) | REX_B(s);
2c0262af
FB
4173 rm = R_EAX;
4174 goto do_xchg_reg;
4175 case 0x86:
4176 case 0x87: /* xchg Ev, Gv */
4177 if ((b & 1) == 0)
4178 ot = OT_BYTE;
4179 else
14ce26e7 4180 ot = dflag + OT_WORD;
61382a50 4181 modrm = ldub_code(s->pc++);
14ce26e7 4182 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af
FB
4183 mod = (modrm >> 6) & 3;
4184 if (mod == 3) {
14ce26e7 4185 rm = (modrm & 7) | REX_B(s);
2c0262af
FB
4186 do_xchg_reg:
4187 gen_op_mov_TN_reg[ot][0][reg]();
4188 gen_op_mov_TN_reg[ot][1][rm]();
4189 gen_op_mov_reg_T0[ot][rm]();
4190 gen_op_mov_reg_T1[ot][reg]();
4191 } else {
4192 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4193 gen_op_mov_TN_reg[ot][0][reg]();
4194 /* for xchg, lock is implicit */
4195 if (!(prefixes & PREFIX_LOCK))
4196 gen_op_lock();
4197 gen_op_ld_T1_A0[ot + s->mem_index]();
4198 gen_op_st_T0_A0[ot + s->mem_index]();
4199 if (!(prefixes & PREFIX_LOCK))
4200 gen_op_unlock();
4201 gen_op_mov_reg_T1[ot][reg]();
4202 }
4203 break;
4204 case 0xc4: /* les Gv */
14ce26e7
FB
4205 if (CODE64(s))
4206 goto illegal_op;
2c0262af
FB
4207 op = R_ES;
4208 goto do_lxx;
4209 case 0xc5: /* lds Gv */
14ce26e7
FB
4210 if (CODE64(s))
4211 goto illegal_op;
2c0262af
FB
4212 op = R_DS;
4213 goto do_lxx;
4214 case 0x1b2: /* lss Gv */
4215 op = R_SS;
4216 goto do_lxx;
4217 case 0x1b4: /* lfs Gv */
4218 op = R_FS;
4219 goto do_lxx;
4220 case 0x1b5: /* lgs Gv */
4221 op = R_GS;
4222 do_lxx:
4223 ot = dflag ? OT_LONG : OT_WORD;
61382a50 4224 modrm = ldub_code(s->pc++);
14ce26e7 4225 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af
FB
4226 mod = (modrm >> 6) & 3;
4227 if (mod == 3)
4228 goto illegal_op;
4229 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4230 gen_op_ld_T1_A0[ot + s->mem_index]();
aba9d61e 4231 gen_add_A0_im(s, 1 << (ot - OT_WORD + 1));
2c0262af 4232 /* load the segment first to handle exceptions properly */
61382a50 4233 gen_op_ldu_T0_A0[OT_WORD + s->mem_index]();
2c0262af
FB
4234 gen_movl_seg_T0(s, op, pc_start - s->cs_base);
4235 /* then put the data */
4236 gen_op_mov_reg_T1[ot][reg]();
4237 if (s->is_jmp) {
14ce26e7 4238 gen_jmp_im(s->pc - s->cs_base);
2c0262af
FB
4239 gen_eob(s);
4240 }
4241 break;
3b46e624 4242
2c0262af
FB
4243 /************************/
4244 /* shifts */
4245 case 0xc0:
4246 case 0xc1:
4247 /* shift Ev,Ib */
4248 shift = 2;
4249 grp2:
4250 {
4251 if ((b & 1) == 0)
4252 ot = OT_BYTE;
4253 else
14ce26e7 4254 ot = dflag + OT_WORD;
3b46e624 4255
61382a50 4256 modrm = ldub_code(s->pc++);
2c0262af 4257 mod = (modrm >> 6) & 3;
2c0262af 4258 op = (modrm >> 3) & 7;
3b46e624 4259
2c0262af 4260 if (mod != 3) {
14ce26e7
FB
4261 if (shift == 2) {
4262 s->rip_offset = 1;
4263 }
2c0262af
FB
4264 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4265 opreg = OR_TMP0;
4266 } else {
14ce26e7 4267 opreg = (modrm & 7) | REX_B(s);
2c0262af
FB
4268 }
4269
4270 /* simpler op */
4271 if (shift == 0) {
4272 gen_shift(s, op, ot, opreg, OR_ECX);
4273 } else {
4274 if (shift == 2) {
61382a50 4275 shift = ldub_code(s->pc++);
2c0262af
FB
4276 }
4277 gen_shifti(s, op, ot, opreg, shift);
4278 }
4279 }
4280 break;
4281 case 0xd0:
4282 case 0xd1:
4283 /* shift Ev,1 */
4284 shift = 1;
4285 goto grp2;
4286 case 0xd2:
4287 case 0xd3:
4288 /* shift Ev,cl */
4289 shift = 0;
4290 goto grp2;
4291
4292 case 0x1a4: /* shld imm */
4293 op = 0;
4294 shift = 1;
4295 goto do_shiftd;
4296 case 0x1a5: /* shld cl */
4297 op = 0;
4298 shift = 0;
4299 goto do_shiftd;
4300 case 0x1ac: /* shrd imm */
4301 op = 1;
4302 shift = 1;
4303 goto do_shiftd;
4304 case 0x1ad: /* shrd cl */
4305 op = 1;
4306 shift = 0;
4307 do_shiftd:
14ce26e7 4308 ot = dflag + OT_WORD;
61382a50 4309 modrm = ldub_code(s->pc++);
2c0262af 4310 mod = (modrm >> 6) & 3;
14ce26e7
FB
4311 rm = (modrm & 7) | REX_B(s);
4312 reg = ((modrm >> 3) & 7) | rex_r;
3b46e624 4313
2c0262af
FB
4314 if (mod != 3) {
4315 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4316 gen_op_ld_T0_A0[ot + s->mem_index]();
4317 } else {
4318 gen_op_mov_TN_reg[ot][0][rm]();
4319 }
4320 gen_op_mov_TN_reg[ot][1][reg]();
3b46e624 4321
2c0262af 4322 if (shift) {
61382a50 4323 val = ldub_code(s->pc++);
14ce26e7
FB
4324 if (ot == OT_QUAD)
4325 val &= 0x3f;
4326 else
4327 val &= 0x1f;
2c0262af
FB
4328 if (val) {
4329 if (mod == 3)
4f31916f 4330 gen_op_shiftd_T0_T1_im_cc[ot][op](val);
2c0262af 4331 else
4f31916f 4332 gen_op_shiftd_mem_T0_T1_im_cc[ot + s->mem_index][op](val);
2c0262af
FB
4333 if (op == 0 && ot != OT_WORD)
4334 s->cc_op = CC_OP_SHLB + ot;
4335 else
4336 s->cc_op = CC_OP_SARB + ot;
4337 }
4338 } else {
4339 if (s->cc_op != CC_OP_DYNAMIC)
4340 gen_op_set_cc_op(s->cc_op);
4341 if (mod == 3)
4f31916f 4342 gen_op_shiftd_T0_T1_ECX_cc[ot][op]();
2c0262af 4343 else
4f31916f 4344 gen_op_shiftd_mem_T0_T1_ECX_cc[ot + s->mem_index][op]();
2c0262af
FB
4345 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
4346 }
4347 if (mod == 3) {
4348 gen_op_mov_reg_T0[ot][rm]();
4349 }
4350 break;
4351
4352 /************************/
4353 /* floats */
5fafdf24 4354 case 0xd8 ... 0xdf:
7eee2a50
FB
4355 if (s->flags & (HF_EM_MASK | HF_TS_MASK)) {
4356 /* if CR0.EM or CR0.TS are set, generate an FPU exception */
4357 /* XXX: what to do if illegal op ? */
4358 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
4359 break;
4360 }
61382a50 4361 modrm = ldub_code(s->pc++);
2c0262af
FB
4362 mod = (modrm >> 6) & 3;
4363 rm = modrm & 7;
4364 op = ((b & 7) << 3) | ((modrm >> 3) & 7);
2c0262af
FB
4365 if (mod != 3) {
4366 /* memory op */
4367 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4368 switch(op) {
4369 case 0x00 ... 0x07: /* fxxxs */
4370 case 0x10 ... 0x17: /* fixxxl */
4371 case 0x20 ... 0x27: /* fxxxl */
4372 case 0x30 ... 0x37: /* fixxx */
4373 {
4374 int op1;
4375 op1 = op & 7;
4376
4377 switch(op >> 4) {
4378 case 0:
4379 gen_op_flds_FT0_A0();
4380 break;
4381 case 1:
4382 gen_op_fildl_FT0_A0();
4383 break;
4384 case 2:
4385 gen_op_fldl_FT0_A0();
4386 break;
4387 case 3:
4388 default:
4389 gen_op_fild_FT0_A0();
4390 break;
4391 }
3b46e624 4392
2c0262af
FB
4393 gen_op_fp_arith_ST0_FT0[op1]();
4394 if (op1 == 3) {
4395 /* fcomp needs pop */
4396 gen_op_fpop();
4397 }
4398 }
4399 break;
4400 case 0x08: /* flds */
4401 case 0x0a: /* fsts */
4402 case 0x0b: /* fstps */
465e9838
FB
4403 case 0x18 ... 0x1b: /* fildl, fisttpl, fistl, fistpl */
4404 case 0x28 ... 0x2b: /* fldl, fisttpll, fstl, fstpl */
4405 case 0x38 ... 0x3b: /* filds, fisttps, fists, fistps */
2c0262af
FB
4406 switch(op & 7) {
4407 case 0:
4408 switch(op >> 4) {
4409 case 0:
4410 gen_op_flds_ST0_A0();
4411 break;
4412 case 1:
4413 gen_op_fildl_ST0_A0();
4414 break;
4415 case 2:
4416 gen_op_fldl_ST0_A0();
4417 break;
4418 case 3:
4419 default:
4420 gen_op_fild_ST0_A0();
4421 break;
4422 }
4423 break;
465e9838
FB
4424 case 1:
4425 switch(op >> 4) {
4426 case 1:
4427 gen_op_fisttl_ST0_A0();
4428 break;
4429 case 2:
4430 gen_op_fisttll_ST0_A0();
4431 break;
4432 case 3:
4433 default:
4434 gen_op_fistt_ST0_A0();
4435 }
4436 gen_op_fpop();
4437 break;
2c0262af
FB
4438 default:
4439 switch(op >> 4) {
4440 case 0:
4441 gen_op_fsts_ST0_A0();
4442 break;
4443 case 1:
4444 gen_op_fistl_ST0_A0();
4445 break;
4446 case 2:
4447 gen_op_fstl_ST0_A0();
4448 break;
4449 case 3:
4450 default:
4451 gen_op_fist_ST0_A0();
4452 break;
4453 }
4454 if ((op & 7) == 3)
4455 gen_op_fpop();
4456 break;
4457 }
4458 break;
4459 case 0x0c: /* fldenv mem */
4460 gen_op_fldenv_A0(s->dflag);
4461 break;
4462 case 0x0d: /* fldcw mem */
4463 gen_op_fldcw_A0();
4464 break;
4465 case 0x0e: /* fnstenv mem */
4466 gen_op_fnstenv_A0(s->dflag);
4467 break;
4468 case 0x0f: /* fnstcw mem */
4469 gen_op_fnstcw_A0();
4470 break;
4471 case 0x1d: /* fldt mem */
4472 gen_op_fldt_ST0_A0();
4473 break;
4474 case 0x1f: /* fstpt mem */
4475 gen_op_fstt_ST0_A0();
4476 gen_op_fpop();
4477 break;
4478 case 0x2c: /* frstor mem */
4479 gen_op_frstor_A0(s->dflag);
4480 break;
4481 case 0x2e: /* fnsave mem */
4482 gen_op_fnsave_A0(s->dflag);
4483 break;
4484 case 0x2f: /* fnstsw mem */
4485 gen_op_fnstsw_A0();
4486 break;
4487 case 0x3c: /* fbld */
4488 gen_op_fbld_ST0_A0();
4489 break;
4490 case 0x3e: /* fbstp */
4491 gen_op_fbst_ST0_A0();
4492 gen_op_fpop();
4493 break;
4494 case 0x3d: /* fildll */
4495 gen_op_fildll_ST0_A0();
4496 break;
4497 case 0x3f: /* fistpll */
4498 gen_op_fistll_ST0_A0();
4499 gen_op_fpop();
4500 break;
4501 default:
4502 goto illegal_op;
4503 }
4504 } else {
4505 /* register float ops */
4506 opreg = rm;
4507
4508 switch(op) {
4509 case 0x08: /* fld sti */
4510 gen_op_fpush();
4511 gen_op_fmov_ST0_STN((opreg + 1) & 7);
4512 break;
4513 case 0x09: /* fxchg sti */
c169c906
FB
4514 case 0x29: /* fxchg4 sti, undocumented op */
4515 case 0x39: /* fxchg7 sti, undocumented op */
2c0262af
FB
4516 gen_op_fxchg_ST0_STN(opreg);
4517 break;
4518 case 0x0a: /* grp d9/2 */
4519 switch(rm) {
4520 case 0: /* fnop */
023fe10d
FB
4521 /* check exceptions (FreeBSD FPU probe) */
4522 if (s->cc_op != CC_OP_DYNAMIC)
4523 gen_op_set_cc_op(s->cc_op);
14ce26e7 4524 gen_jmp_im(pc_start - s->cs_base);
023fe10d 4525 gen_op_fwait();
2c0262af
FB
4526 break;
4527 default:
4528 goto illegal_op;
4529 }
4530 break;
4531 case 0x0c: /* grp d9/4 */
4532 switch(rm) {
4533 case 0: /* fchs */
4534 gen_op_fchs_ST0();
4535 break;
4536 case 1: /* fabs */
4537 gen_op_fabs_ST0();
4538 break;
4539 case 4: /* ftst */
4540 gen_op_fldz_FT0();
4541 gen_op_fcom_ST0_FT0();
4542 break;
4543 case 5: /* fxam */
4544 gen_op_fxam_ST0();
4545 break;
4546 default:
4547 goto illegal_op;
4548 }
4549 break;
4550 case 0x0d: /* grp d9/5 */
4551 {
4552 switch(rm) {
4553 case 0:
4554 gen_op_fpush();
4555 gen_op_fld1_ST0();
4556 break;
4557 case 1:
4558 gen_op_fpush();
4559 gen_op_fldl2t_ST0();
4560 break;
4561 case 2:
4562 gen_op_fpush();
4563 gen_op_fldl2e_ST0();
4564 break;
4565 case 3:
4566 gen_op_fpush();
4567 gen_op_fldpi_ST0();
4568 break;
4569 case 4:
4570 gen_op_fpush();
4571 gen_op_fldlg2_ST0();
4572 break;
4573 case 5:
4574 gen_op_fpush();
4575 gen_op_fldln2_ST0();
4576 break;
4577 case 6:
4578 gen_op_fpush();
4579 gen_op_fldz_ST0();
4580 break;
4581 default:
4582 goto illegal_op;
4583 }
4584 }
4585 break;
4586 case 0x0e: /* grp d9/6 */
4587 switch(rm) {
4588 case 0: /* f2xm1 */
4589 gen_op_f2xm1();
4590 break;
4591 case 1: /* fyl2x */
4592 gen_op_fyl2x();
4593 break;
4594 case 2: /* fptan */
4595 gen_op_fptan();
4596 break;
4597 case 3: /* fpatan */
4598 gen_op_fpatan();
4599 break;
4600 case 4: /* fxtract */
4601 gen_op_fxtract();
4602 break;
4603 case 5: /* fprem1 */
4604 gen_op_fprem1();
4605 break;
4606 case 6: /* fdecstp */
4607 gen_op_fdecstp();
4608 break;
4609 default:
4610 case 7: /* fincstp */
4611 gen_op_fincstp();
4612 break;
4613 }
4614 break;
4615 case 0x0f: /* grp d9/7 */
4616 switch(rm) {
4617 case 0: /* fprem */
4618 gen_op_fprem();
4619 break;
4620 case 1: /* fyl2xp1 */
4621 gen_op_fyl2xp1();
4622 break;
4623 case 2: /* fsqrt */
4624 gen_op_fsqrt();
4625 break;
4626 case 3: /* fsincos */
4627 gen_op_fsincos();
4628 break;
4629 case 5: /* fscale */
4630 gen_op_fscale();
4631 break;
4632 case 4: /* frndint */
4633 gen_op_frndint();
4634 break;
4635 case 6: /* fsin */
4636 gen_op_fsin();
4637 break;
4638 default:
4639 case 7: /* fcos */
4640 gen_op_fcos();
4641 break;
4642 }
4643 break;
4644 case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
4645 case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
4646 case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
4647 {
4648 int op1;
3b46e624 4649
2c0262af
FB
4650 op1 = op & 7;
4651 if (op >= 0x20) {
4652 gen_op_fp_arith_STN_ST0[op1](opreg);
4653 if (op >= 0x30)
4654 gen_op_fpop();
4655 } else {
4656 gen_op_fmov_FT0_STN(opreg);
4657 gen_op_fp_arith_ST0_FT0[op1]();
4658 }
4659 }
4660 break;
4661 case 0x02: /* fcom */
c169c906 4662 case 0x22: /* fcom2, undocumented op */
2c0262af
FB
4663 gen_op_fmov_FT0_STN(opreg);
4664 gen_op_fcom_ST0_FT0();
4665 break;
4666 case 0x03: /* fcomp */
c169c906
FB
4667 case 0x23: /* fcomp3, undocumented op */
4668 case 0x32: /* fcomp5, undocumented op */
2c0262af
FB
4669 gen_op_fmov_FT0_STN(opreg);
4670 gen_op_fcom_ST0_FT0();
4671 gen_op_fpop();
4672 break;
4673 case 0x15: /* da/5 */
4674 switch(rm) {
4675 case 1: /* fucompp */
4676 gen_op_fmov_FT0_STN(1);
4677 gen_op_fucom_ST0_FT0();
4678 gen_op_fpop();
4679 gen_op_fpop();
4680 break;
4681 default:
4682 goto illegal_op;
4683 }
4684 break;
4685 case 0x1c:
4686 switch(rm) {
4687 case 0: /* feni (287 only, just do nop here) */
4688 break;
4689 case 1: /* fdisi (287 only, just do nop here) */
4690 break;
4691 case 2: /* fclex */
4692 gen_op_fclex();
4693 break;
4694 case 3: /* fninit */
4695 gen_op_fninit();
4696 break;
4697 case 4: /* fsetpm (287 only, just do nop here) */
4698 break;
4699 default:
4700 goto illegal_op;
4701 }
4702 break;
4703 case 0x1d: /* fucomi */
4704 if (s->cc_op != CC_OP_DYNAMIC)
4705 gen_op_set_cc_op(s->cc_op);
4706 gen_op_fmov_FT0_STN(opreg);
4707 gen_op_fucomi_ST0_FT0();
4708 s->cc_op = CC_OP_EFLAGS;
4709 break;
4710 case 0x1e: /* fcomi */
4711 if (s->cc_op != CC_OP_DYNAMIC)
4712 gen_op_set_cc_op(s->cc_op);
4713 gen_op_fmov_FT0_STN(opreg);
4714 gen_op_fcomi_ST0_FT0();
4715 s->cc_op = CC_OP_EFLAGS;
4716 break;
658c8bda
FB
4717 case 0x28: /* ffree sti */
4718 gen_op_ffree_STN(opreg);
5fafdf24 4719 break;
2c0262af
FB
4720 case 0x2a: /* fst sti */
4721 gen_op_fmov_STN_ST0(opreg);
4722 break;
4723 case 0x2b: /* fstp sti */
c169c906
FB
4724 case 0x0b: /* fstp1 sti, undocumented op */
4725 case 0x3a: /* fstp8 sti, undocumented op */
4726 case 0x3b: /* fstp9 sti, undocumented op */
2c0262af
FB
4727 gen_op_fmov_STN_ST0(opreg);
4728 gen_op_fpop();
4729 break;
4730 case 0x2c: /* fucom st(i) */
4731 gen_op_fmov_FT0_STN(opreg);
4732 gen_op_fucom_ST0_FT0();
4733 break;
4734 case 0x2d: /* fucomp st(i) */
4735 gen_op_fmov_FT0_STN(opreg);
4736 gen_op_fucom_ST0_FT0();
4737 gen_op_fpop();
4738 break;
4739 case 0x33: /* de/3 */
4740 switch(rm) {
4741 case 1: /* fcompp */
4742 gen_op_fmov_FT0_STN(1);
4743 gen_op_fcom_ST0_FT0();
4744 gen_op_fpop();
4745 gen_op_fpop();
4746 break;
4747 default:
4748 goto illegal_op;
4749 }
4750 break;
c169c906
FB
4751 case 0x38: /* ffreep sti, undocumented op */
4752 gen_op_ffree_STN(opreg);
4753 gen_op_fpop();
4754 break;
2c0262af
FB
4755 case 0x3c: /* df/4 */
4756 switch(rm) {
4757 case 0:
4758 gen_op_fnstsw_EAX();
4759 break;
4760 default:
4761 goto illegal_op;
4762 }
4763 break;
4764 case 0x3d: /* fucomip */
4765 if (s->cc_op != CC_OP_DYNAMIC)
4766 gen_op_set_cc_op(s->cc_op);
4767 gen_op_fmov_FT0_STN(opreg);
4768 gen_op_fucomi_ST0_FT0();
4769 gen_op_fpop();
4770 s->cc_op = CC_OP_EFLAGS;
4771 break;
4772 case 0x3e: /* fcomip */
4773 if (s->cc_op != CC_OP_DYNAMIC)
4774 gen_op_set_cc_op(s->cc_op);
4775 gen_op_fmov_FT0_STN(opreg);
4776 gen_op_fcomi_ST0_FT0();
4777 gen_op_fpop();
4778 s->cc_op = CC_OP_EFLAGS;
4779 break;
a2cc3b24
FB
4780 case 0x10 ... 0x13: /* fcmovxx */
4781 case 0x18 ... 0x1b:
4782 {
4783 int op1;
4784 const static uint8_t fcmov_cc[8] = {
4785 (JCC_B << 1),
4786 (JCC_Z << 1),
4787 (JCC_BE << 1),
4788 (JCC_P << 1),
4789 };
4790 op1 = fcmov_cc[op & 3] | ((op >> 3) & 1);
4791 gen_setcc(s, op1);
4792 gen_op_fcmov_ST0_STN_T0(opreg);
4793 }
4794 break;
2c0262af
FB
4795 default:
4796 goto illegal_op;
4797 }
4798 }
7eee2a50
FB
4799#ifdef USE_CODE_COPY
4800 s->tb->cflags |= CF_TB_FP_USED;
4801#endif
2c0262af
FB
4802 break;
4803 /************************/
4804 /* string ops */
4805
4806 case 0xa4: /* movsS */
4807 case 0xa5:
4808 if ((b & 1) == 0)
4809 ot = OT_BYTE;
4810 else
14ce26e7 4811 ot = dflag + OT_WORD;
2c0262af
FB
4812
4813 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
4814 gen_repz_movs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
4815 } else {
4816 gen_movs(s, ot);
4817 }
4818 break;
3b46e624 4819
2c0262af
FB
4820 case 0xaa: /* stosS */
4821 case 0xab:
4822 if ((b & 1) == 0)
4823 ot = OT_BYTE;
4824 else
14ce26e7 4825 ot = dflag + OT_WORD;
2c0262af
FB
4826
4827 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
4828 gen_repz_stos(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
4829 } else {
4830 gen_stos(s, ot);
4831 }
4832 break;
4833 case 0xac: /* lodsS */
4834 case 0xad:
4835 if ((b & 1) == 0)
4836 ot = OT_BYTE;
4837 else
14ce26e7 4838 ot = dflag + OT_WORD;
2c0262af
FB
4839 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
4840 gen_repz_lods(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
4841 } else {
4842 gen_lods(s, ot);
4843 }
4844 break;
4845 case 0xae: /* scasS */
4846 case 0xaf:
4847 if ((b & 1) == 0)
4848 ot = OT_BYTE;
4849 else
14ce26e7 4850 ot = dflag + OT_WORD;
2c0262af
FB
4851 if (prefixes & PREFIX_REPNZ) {
4852 gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
4853 } else if (prefixes & PREFIX_REPZ) {
4854 gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
4855 } else {
4856 gen_scas(s, ot);
4857 s->cc_op = CC_OP_SUBB + ot;
4858 }
4859 break;
4860
4861 case 0xa6: /* cmpsS */
4862 case 0xa7:
4863 if ((b & 1) == 0)
4864 ot = OT_BYTE;
4865 else
14ce26e7 4866 ot = dflag + OT_WORD;
2c0262af
FB
4867 if (prefixes & PREFIX_REPNZ) {
4868 gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
4869 } else if (prefixes & PREFIX_REPZ) {
4870 gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
4871 } else {
4872 gen_cmps(s, ot);
4873 s->cc_op = CC_OP_SUBB + ot;
4874 }
4875 break;
4876 case 0x6c: /* insS */
4877 case 0x6d:
f115e911
FB
4878 if ((b & 1) == 0)
4879 ot = OT_BYTE;
4880 else
4881 ot = dflag ? OT_LONG : OT_WORD;
4882 gen_check_io(s, ot, 1, pc_start - s->cs_base);
4883 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
4884 gen_repz_ins(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
2c0262af 4885 } else {
f115e911 4886 gen_ins(s, ot);
2c0262af
FB
4887 }
4888 break;
4889 case 0x6e: /* outsS */
4890 case 0x6f:
f115e911
FB
4891 if ((b & 1) == 0)
4892 ot = OT_BYTE;
4893 else
4894 ot = dflag ? OT_LONG : OT_WORD;
4895 gen_check_io(s, ot, 1, pc_start - s->cs_base);
4896 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
4897 gen_repz_outs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
2c0262af 4898 } else {
f115e911 4899 gen_outs(s, ot);
2c0262af
FB
4900 }
4901 break;
4902
4903 /************************/
4904 /* port I/O */
4905 case 0xe4:
4906 case 0xe5:
f115e911
FB
4907 if ((b & 1) == 0)
4908 ot = OT_BYTE;
4909 else
4910 ot = dflag ? OT_LONG : OT_WORD;
4911 val = ldub_code(s->pc++);
4912 gen_op_movl_T0_im(val);
4913 gen_check_io(s, ot, 0, pc_start - s->cs_base);
4914 gen_op_in[ot]();
4915 gen_op_mov_reg_T1[ot][R_EAX]();
2c0262af
FB
4916 break;
4917 case 0xe6:
4918 case 0xe7:
f115e911
FB
4919 if ((b & 1) == 0)
4920 ot = OT_BYTE;
4921 else
4922 ot = dflag ? OT_LONG : OT_WORD;
4923 val = ldub_code(s->pc++);
4924 gen_op_movl_T0_im(val);
4925 gen_check_io(s, ot, 0, pc_start - s->cs_base);
4926 gen_op_mov_TN_reg[ot][1][R_EAX]();
4927 gen_op_out[ot]();
2c0262af
FB
4928 break;
4929 case 0xec:
4930 case 0xed:
f115e911
FB
4931 if ((b & 1) == 0)
4932 ot = OT_BYTE;
4933 else
4934 ot = dflag ? OT_LONG : OT_WORD;
4935 gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
4f31916f 4936 gen_op_andl_T0_ffff();
f115e911
FB
4937 gen_check_io(s, ot, 0, pc_start - s->cs_base);
4938 gen_op_in[ot]();
4939 gen_op_mov_reg_T1[ot][R_EAX]();
2c0262af
FB
4940 break;
4941 case 0xee:
4942 case 0xef:
f115e911
FB
4943 if ((b & 1) == 0)
4944 ot = OT_BYTE;
4945 else
4946 ot = dflag ? OT_LONG : OT_WORD;
4947 gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
4f31916f 4948 gen_op_andl_T0_ffff();
f115e911
FB
4949 gen_check_io(s, ot, 0, pc_start - s->cs_base);
4950 gen_op_mov_TN_reg[ot][1][R_EAX]();
4951 gen_op_out[ot]();
2c0262af
FB
4952 break;
4953
4954 /************************/
4955 /* control */
4956 case 0xc2: /* ret im */
61382a50 4957 val = ldsw_code(s->pc);
2c0262af
FB
4958 s->pc += 2;
4959 gen_pop_T0(s);
8f091a59
FB
4960 if (CODE64(s) && s->dflag)
4961 s->dflag = 2;
2c0262af
FB
4962 gen_stack_update(s, val + (2 << s->dflag));
4963 if (s->dflag == 0)
4964 gen_op_andl_T0_ffff();
4965 gen_op_jmp_T0();
4966 gen_eob(s);
4967 break;
4968 case 0xc3: /* ret */
4969 gen_pop_T0(s);
4970 gen_pop_update(s);
4971 if (s->dflag == 0)
4972 gen_op_andl_T0_ffff();
4973 gen_op_jmp_T0();
4974 gen_eob(s);
4975 break;
4976 case 0xca: /* lret im */
61382a50 4977 val = ldsw_code(s->pc);
2c0262af
FB
4978 s->pc += 2;
4979 do_lret:
4980 if (s->pe && !s->vm86) {
4981 if (s->cc_op != CC_OP_DYNAMIC)
4982 gen_op_set_cc_op(s->cc_op);
14ce26e7 4983 gen_jmp_im(pc_start - s->cs_base);
2c0262af
FB
4984 gen_op_lret_protected(s->dflag, val);
4985 } else {
4986 gen_stack_A0(s);
4987 /* pop offset */
4988 gen_op_ld_T0_A0[1 + s->dflag + s->mem_index]();
4989 if (s->dflag == 0)
4990 gen_op_andl_T0_ffff();
4991 /* NOTE: keeping EIP updated is not a problem in case of
4992 exception */
4993 gen_op_jmp_T0();
4994 /* pop selector */
4995 gen_op_addl_A0_im(2 << s->dflag);
4996 gen_op_ld_T0_A0[1 + s->dflag + s->mem_index]();
4997 gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[R_CS]));
4998 /* add stack offset */
4999 gen_stack_update(s, val + (4 << s->dflag));
5000 }
5001 gen_eob(s);
5002 break;
5003 case 0xcb: /* lret */
5004 val = 0;
5005 goto do_lret;
5006 case 0xcf: /* iret */
5007 if (!s->pe) {
5008 /* real mode */
5009 gen_op_iret_real(s->dflag);
5010 s->cc_op = CC_OP_EFLAGS;
f115e911
FB
5011 } else if (s->vm86) {
5012 if (s->iopl != 3) {
5013 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5014 } else {
5015 gen_op_iret_real(s->dflag);
5016 s->cc_op = CC_OP_EFLAGS;
5017 }
2c0262af
FB
5018 } else {
5019 if (s->cc_op != CC_OP_DYNAMIC)
5020 gen_op_set_cc_op(s->cc_op);
14ce26e7 5021 gen_jmp_im(pc_start - s->cs_base);
08cea4ee 5022 gen_op_iret_protected(s->dflag, s->pc - s->cs_base);
2c0262af
FB
5023 s->cc_op = CC_OP_EFLAGS;
5024 }
5025 gen_eob(s);
5026 break;
5027 case 0xe8: /* call im */
5028 {
14ce26e7
FB
5029 if (dflag)
5030 tval = (int32_t)insn_get(s, OT_LONG);
5031 else
5032 tval = (int16_t)insn_get(s, OT_WORD);
2c0262af 5033 next_eip = s->pc - s->cs_base;
14ce26e7 5034 tval += next_eip;
2c0262af 5035 if (s->dflag == 0)
14ce26e7
FB
5036 tval &= 0xffff;
5037 gen_movtl_T0_im(next_eip);
2c0262af 5038 gen_push_T0(s);
14ce26e7 5039 gen_jmp(s, tval);
2c0262af
FB
5040 }
5041 break;
5042 case 0x9a: /* lcall im */
5043 {
5044 unsigned int selector, offset;
3b46e624 5045
14ce26e7
FB
5046 if (CODE64(s))
5047 goto illegal_op;
2c0262af
FB
5048 ot = dflag ? OT_LONG : OT_WORD;
5049 offset = insn_get(s, ot);
5050 selector = insn_get(s, OT_WORD);
3b46e624 5051
2c0262af 5052 gen_op_movl_T0_im(selector);
14ce26e7 5053 gen_op_movl_T1_imu(offset);
2c0262af
FB
5054 }
5055 goto do_lcall;
ecada8a2 5056 case 0xe9: /* jmp im */
14ce26e7
FB
5057 if (dflag)
5058 tval = (int32_t)insn_get(s, OT_LONG);
5059 else
5060 tval = (int16_t)insn_get(s, OT_WORD);
5061 tval += s->pc - s->cs_base;
2c0262af 5062 if (s->dflag == 0)
14ce26e7
FB
5063 tval &= 0xffff;
5064 gen_jmp(s, tval);
2c0262af
FB
5065 break;
5066 case 0xea: /* ljmp im */
5067 {
5068 unsigned int selector, offset;
5069
14ce26e7
FB
5070 if (CODE64(s))
5071 goto illegal_op;
2c0262af
FB
5072 ot = dflag ? OT_LONG : OT_WORD;
5073 offset = insn_get(s, ot);
5074 selector = insn_get(s, OT_WORD);
3b46e624 5075
2c0262af 5076 gen_op_movl_T0_im(selector);
14ce26e7 5077 gen_op_movl_T1_imu(offset);
2c0262af
FB
5078 }
5079 goto do_ljmp;
5080 case 0xeb: /* jmp Jb */
14ce26e7
FB
5081 tval = (int8_t)insn_get(s, OT_BYTE);
5082 tval += s->pc - s->cs_base;
2c0262af 5083 if (s->dflag == 0)
14ce26e7
FB
5084 tval &= 0xffff;
5085 gen_jmp(s, tval);
2c0262af
FB
5086 break;
5087 case 0x70 ... 0x7f: /* jcc Jb */
14ce26e7 5088 tval = (int8_t)insn_get(s, OT_BYTE);
2c0262af
FB
5089 goto do_jcc;
5090 case 0x180 ... 0x18f: /* jcc Jv */
5091 if (dflag) {
14ce26e7 5092 tval = (int32_t)insn_get(s, OT_LONG);
2c0262af 5093 } else {
5fafdf24 5094 tval = (int16_t)insn_get(s, OT_WORD);
2c0262af
FB
5095 }
5096 do_jcc:
5097 next_eip = s->pc - s->cs_base;
14ce26e7 5098 tval += next_eip;
2c0262af 5099 if (s->dflag == 0)
14ce26e7
FB
5100 tval &= 0xffff;
5101 gen_jcc(s, b, tval, next_eip);
2c0262af
FB
5102 break;
5103
5104 case 0x190 ... 0x19f: /* setcc Gv */
61382a50 5105 modrm = ldub_code(s->pc++);
2c0262af
FB
5106 gen_setcc(s, b);
5107 gen_ldst_modrm(s, modrm, OT_BYTE, OR_TMP0, 1);
5108 break;
5109 case 0x140 ... 0x14f: /* cmov Gv, Ev */
14ce26e7 5110 ot = dflag + OT_WORD;
61382a50 5111 modrm = ldub_code(s->pc++);
14ce26e7 5112 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af
FB
5113 mod = (modrm >> 6) & 3;
5114 gen_setcc(s, b);
5115 if (mod != 3) {
5116 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
5117 gen_op_ld_T1_A0[ot + s->mem_index]();
5118 } else {
14ce26e7 5119 rm = (modrm & 7) | REX_B(s);
2c0262af
FB
5120 gen_op_mov_TN_reg[ot][1][rm]();
5121 }
5122 gen_op_cmov_reg_T1_T0[ot - OT_WORD][reg]();
5123 break;
3b46e624 5124
2c0262af
FB
5125 /************************/
5126 /* flags */
5127 case 0x9c: /* pushf */
5128 if (s->vm86 && s->iopl != 3) {
5129 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5130 } else {
5131 if (s->cc_op != CC_OP_DYNAMIC)
5132 gen_op_set_cc_op(s->cc_op);
5133 gen_op_movl_T0_eflags();
5134 gen_push_T0(s);
5135 }
5136 break;
5137 case 0x9d: /* popf */
5138 if (s->vm86 && s->iopl != 3) {
5139 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5140 } else {
5141 gen_pop_T0(s);
5142 if (s->cpl == 0) {
5143 if (s->dflag) {
5144 gen_op_movl_eflags_T0_cpl0();
5145 } else {
5146 gen_op_movw_eflags_T0_cpl0();
5147 }
5148 } else {
4136f33c
FB
5149 if (s->cpl <= s->iopl) {
5150 if (s->dflag) {
5151 gen_op_movl_eflags_T0_io();
5152 } else {
5153 gen_op_movw_eflags_T0_io();
5154 }
2c0262af 5155 } else {
4136f33c
FB
5156 if (s->dflag) {
5157 gen_op_movl_eflags_T0();
5158 } else {
5159 gen_op_movw_eflags_T0();
5160 }
2c0262af
FB
5161 }
5162 }
5163 gen_pop_update(s);
5164 s->cc_op = CC_OP_EFLAGS;
5165 /* abort translation because TF flag may change */
14ce26e7 5166 gen_jmp_im(s->pc - s->cs_base);
2c0262af
FB
5167 gen_eob(s);
5168 }
5169 break;
5170 case 0x9e: /* sahf */
14ce26e7
FB
5171 if (CODE64(s))
5172 goto illegal_op;
2c0262af
FB
5173 gen_op_mov_TN_reg[OT_BYTE][0][R_AH]();
5174 if (s->cc_op != CC_OP_DYNAMIC)
5175 gen_op_set_cc_op(s->cc_op);
5176 gen_op_movb_eflags_T0();
5177 s->cc_op = CC_OP_EFLAGS;
5178 break;
5179 case 0x9f: /* lahf */
14ce26e7
FB
5180 if (CODE64(s))
5181 goto illegal_op;
2c0262af
FB
5182 if (s->cc_op != CC_OP_DYNAMIC)
5183 gen_op_set_cc_op(s->cc_op);
5184 gen_op_movl_T0_eflags();
5185 gen_op_mov_reg_T0[OT_BYTE][R_AH]();
5186 break;
5187 case 0xf5: /* cmc */
5188 if (s->cc_op != CC_OP_DYNAMIC)
5189 gen_op_set_cc_op(s->cc_op);
5190 gen_op_cmc();
5191 s->cc_op = CC_OP_EFLAGS;
5192 break;
5193 case 0xf8: /* clc */
5194 if (s->cc_op != CC_OP_DYNAMIC)
5195 gen_op_set_cc_op(s->cc_op);
5196 gen_op_clc();
5197 s->cc_op = CC_OP_EFLAGS;
5198 break;
5199 case 0xf9: /* stc */
5200 if (s->cc_op != CC_OP_DYNAMIC)
5201 gen_op_set_cc_op(s->cc_op);
5202 gen_op_stc();
5203 s->cc_op = CC_OP_EFLAGS;
5204 break;
5205 case 0xfc: /* cld */
5206 gen_op_cld();
5207 break;
5208 case 0xfd: /* std */
5209 gen_op_std();
5210 break;
5211
5212 /************************/
5213 /* bit operations */
5214 case 0x1ba: /* bt/bts/btr/btc Gv, im */
14ce26e7 5215 ot = dflag + OT_WORD;
61382a50 5216 modrm = ldub_code(s->pc++);
33698e5f 5217 op = (modrm >> 3) & 7;
2c0262af 5218 mod = (modrm >> 6) & 3;
14ce26e7 5219 rm = (modrm & 7) | REX_B(s);
2c0262af 5220 if (mod != 3) {
14ce26e7 5221 s->rip_offset = 1;
2c0262af
FB
5222 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
5223 gen_op_ld_T0_A0[ot + s->mem_index]();
5224 } else {
5225 gen_op_mov_TN_reg[ot][0][rm]();
5226 }
5227 /* load shift */
61382a50 5228 val = ldub_code(s->pc++);
2c0262af
FB
5229 gen_op_movl_T1_im(val);
5230 if (op < 4)
5231 goto illegal_op;
5232 op -= 4;
5233 gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
5234 s->cc_op = CC_OP_SARB + ot;
5235 if (op != 0) {
5236 if (mod != 3)
5237 gen_op_st_T0_A0[ot + s->mem_index]();
5238 else
5239 gen_op_mov_reg_T0[ot][rm]();
5240 gen_op_update_bt_cc();
5241 }
5242 break;
5243 case 0x1a3: /* bt Gv, Ev */
5244 op = 0;
5245 goto do_btx;
5246 case 0x1ab: /* bts */
5247 op = 1;
5248 goto do_btx;
5249 case 0x1b3: /* btr */
5250 op = 2;
5251 goto do_btx;
5252 case 0x1bb: /* btc */
5253 op = 3;
5254 do_btx:
14ce26e7 5255 ot = dflag + OT_WORD;
61382a50 5256 modrm = ldub_code(s->pc++);
14ce26e7 5257 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af 5258 mod = (modrm >> 6) & 3;
14ce26e7 5259 rm = (modrm & 7) | REX_B(s);
2c0262af
FB
5260 gen_op_mov_TN_reg[OT_LONG][1][reg]();
5261 if (mod != 3) {
5262 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
5263 /* specific case: we need to add a displacement */
14ce26e7 5264 gen_op_add_bit_A0_T1[ot - OT_WORD]();
2c0262af
FB
5265 gen_op_ld_T0_A0[ot + s->mem_index]();
5266 } else {
5267 gen_op_mov_TN_reg[ot][0][rm]();
5268 }
5269 gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
5270 s->cc_op = CC_OP_SARB + ot;
5271 if (op != 0) {
5272 if (mod != 3)
5273 gen_op_st_T0_A0[ot + s->mem_index]();
5274 else
5275 gen_op_mov_reg_T0[ot][rm]();
5276 gen_op_update_bt_cc();
5277 }
5278 break;
5279 case 0x1bc: /* bsf */
5280 case 0x1bd: /* bsr */
14ce26e7 5281 ot = dflag + OT_WORD;
61382a50 5282 modrm = ldub_code(s->pc++);
14ce26e7 5283 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af 5284 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
686f3f26
FB
5285 /* NOTE: in order to handle the 0 case, we must load the
5286 result. It could be optimized with a generated jump */
5287 gen_op_mov_TN_reg[ot][1][reg]();
2c0262af 5288 gen_op_bsx_T0_cc[ot - OT_WORD][b & 1]();
686f3f26 5289 gen_op_mov_reg_T1[ot][reg]();
2c0262af
FB
5290 s->cc_op = CC_OP_LOGICB + ot;
5291 break;
5292 /************************/
5293 /* bcd */
5294 case 0x27: /* daa */
14ce26e7
FB
5295 if (CODE64(s))
5296 goto illegal_op;
2c0262af
FB
5297 if (s->cc_op != CC_OP_DYNAMIC)
5298 gen_op_set_cc_op(s->cc_op);
5299 gen_op_daa();
5300 s->cc_op = CC_OP_EFLAGS;
5301 break;
5302 case 0x2f: /* das */
14ce26e7
FB
5303 if (CODE64(s))
5304 goto illegal_op;
2c0262af
FB
5305 if (s->cc_op != CC_OP_DYNAMIC)
5306 gen_op_set_cc_op(s->cc_op);
5307 gen_op_das();
5308 s->cc_op = CC_OP_EFLAGS;
5309 break;
5310 case 0x37: /* aaa */
14ce26e7
FB
5311 if (CODE64(s))
5312 goto illegal_op;
2c0262af
FB
5313 if (s->cc_op != CC_OP_DYNAMIC)
5314 gen_op_set_cc_op(s->cc_op);
5315 gen_op_aaa();
5316 s->cc_op = CC_OP_EFLAGS;
5317 break;
5318 case 0x3f: /* aas */
14ce26e7
FB
5319 if (CODE64(s))
5320 goto illegal_op;
2c0262af
FB
5321 if (s->cc_op != CC_OP_DYNAMIC)
5322 gen_op_set_cc_op(s->cc_op);
5323 gen_op_aas();
5324 s->cc_op = CC_OP_EFLAGS;
5325 break;
5326 case 0xd4: /* aam */
14ce26e7
FB
5327 if (CODE64(s))
5328 goto illegal_op;
61382a50 5329 val = ldub_code(s->pc++);
b6d7c3db
TS
5330 if (val == 0) {
5331 gen_exception(s, EXCP00_DIVZ, pc_start - s->cs_base);
5332 } else {
5333 gen_op_aam(val);
5334 s->cc_op = CC_OP_LOGICB;
5335 }
2c0262af
FB
5336 break;
5337 case 0xd5: /* aad */
14ce26e7
FB
5338 if (CODE64(s))
5339 goto illegal_op;
61382a50 5340 val = ldub_code(s->pc++);
2c0262af
FB
5341 gen_op_aad(val);
5342 s->cc_op = CC_OP_LOGICB;
5343 break;
5344 /************************/
5345 /* misc */
5346 case 0x90: /* nop */
14ce26e7 5347 /* XXX: xchg + rex handling */
ab1f142b
FB
5348 /* XXX: correct lock test for all insn */
5349 if (prefixes & PREFIX_LOCK)
5350 goto illegal_op;
2c0262af
FB
5351 break;
5352 case 0x9b: /* fwait */
5fafdf24 5353 if ((s->flags & (HF_MP_MASK | HF_TS_MASK)) ==
7eee2a50
FB
5354 (HF_MP_MASK | HF_TS_MASK)) {
5355 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
2ee73ac3
FB
5356 } else {
5357 if (s->cc_op != CC_OP_DYNAMIC)
5358 gen_op_set_cc_op(s->cc_op);
14ce26e7 5359 gen_jmp_im(pc_start - s->cs_base);
2ee73ac3 5360 gen_op_fwait();
7eee2a50 5361 }
2c0262af
FB
5362 break;
5363 case 0xcc: /* int3 */
5364 gen_interrupt(s, EXCP03_INT3, pc_start - s->cs_base, s->pc - s->cs_base);
5365 break;
5366 case 0xcd: /* int N */
61382a50 5367 val = ldub_code(s->pc++);
f115e911 5368 if (s->vm86 && s->iopl != 3) {
5fafdf24 5369 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
f115e911
FB
5370 } else {
5371 gen_interrupt(s, val, pc_start - s->cs_base, s->pc - s->cs_base);
5372 }
2c0262af
FB
5373 break;
5374 case 0xce: /* into */
14ce26e7
FB
5375 if (CODE64(s))
5376 goto illegal_op;
2c0262af
FB
5377 if (s->cc_op != CC_OP_DYNAMIC)
5378 gen_op_set_cc_op(s->cc_op);
a8ede8ba
FB
5379 gen_jmp_im(pc_start - s->cs_base);
5380 gen_op_into(s->pc - pc_start);
2c0262af
FB
5381 break;
5382 case 0xf1: /* icebp (undocumented, exits to external debugger) */
aba9d61e 5383#if 1
2c0262af 5384 gen_debug(s, pc_start - s->cs_base);
aba9d61e
FB
5385#else
5386 /* start debug */
5387 tb_flush(cpu_single_env);
5388 cpu_set_log(CPU_LOG_INT | CPU_LOG_TB_IN_ASM);
5389#endif
2c0262af
FB
5390 break;
5391 case 0xfa: /* cli */
5392 if (!s->vm86) {
5393 if (s->cpl <= s->iopl) {
5394 gen_op_cli();
5395 } else {
5396 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5397 }
5398 } else {
5399 if (s->iopl == 3) {
5400 gen_op_cli();
5401 } else {
5402 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5403 }
5404 }
5405 break;
5406 case 0xfb: /* sti */
5407 if (!s->vm86) {
5408 if (s->cpl <= s->iopl) {
5409 gen_sti:
5410 gen_op_sti();
5411 /* interruptions are enabled only the first insn after sti */
a2cc3b24
FB
5412 /* If several instructions disable interrupts, only the
5413 _first_ does it */
5414 if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
5415 gen_op_set_inhibit_irq();
2c0262af 5416 /* give a chance to handle pending irqs */
14ce26e7 5417 gen_jmp_im(s->pc - s->cs_base);
2c0262af
FB
5418 gen_eob(s);
5419 } else {
5420 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5421 }
5422 } else {
5423 if (s->iopl == 3) {
5424 goto gen_sti;
5425 } else {
5426 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5427 }
5428 }
5429 break;
5430 case 0x62: /* bound */
14ce26e7
FB
5431 if (CODE64(s))
5432 goto illegal_op;
2c0262af 5433 ot = dflag ? OT_LONG : OT_WORD;
61382a50 5434 modrm = ldub_code(s->pc++);
2c0262af
FB
5435 reg = (modrm >> 3) & 7;
5436 mod = (modrm >> 6) & 3;
5437 if (mod == 3)
5438 goto illegal_op;
cabf23c3 5439 gen_op_mov_TN_reg[ot][0][reg]();
2c0262af 5440 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
14ce26e7 5441 gen_jmp_im(pc_start - s->cs_base);
2c0262af 5442 if (ot == OT_WORD)
14ce26e7 5443 gen_op_boundw();
2c0262af 5444 else
14ce26e7 5445 gen_op_boundl();
2c0262af
FB
5446 break;
5447 case 0x1c8 ... 0x1cf: /* bswap reg */
14ce26e7
FB
5448 reg = (b & 7) | REX_B(s);
5449#ifdef TARGET_X86_64
5450 if (dflag == 2) {
5451 gen_op_mov_TN_reg[OT_QUAD][0][reg]();
5452 gen_op_bswapq_T0();
5453 gen_op_mov_reg_T0[OT_QUAD][reg]();
5fafdf24 5454 } else
14ce26e7
FB
5455#endif
5456 {
5457 gen_op_mov_TN_reg[OT_LONG][0][reg]();
5458 gen_op_bswapl_T0();
5459 gen_op_mov_reg_T0[OT_LONG][reg]();
5460 }
2c0262af
FB
5461 break;
5462 case 0xd6: /* salc */
14ce26e7
FB
5463 if (CODE64(s))
5464 goto illegal_op;
2c0262af
FB
5465 if (s->cc_op != CC_OP_DYNAMIC)
5466 gen_op_set_cc_op(s->cc_op);
5467 gen_op_salc();
5468 break;
5469 case 0xe0: /* loopnz */
5470 case 0xe1: /* loopz */
5471 if (s->cc_op != CC_OP_DYNAMIC)
5472 gen_op_set_cc_op(s->cc_op);
5473 /* FALL THRU */
5474 case 0xe2: /* loop */
5475 case 0xe3: /* jecxz */
14ce26e7
FB
5476 {
5477 int l1, l2;
5478
5479 tval = (int8_t)insn_get(s, OT_BYTE);
5480 next_eip = s->pc - s->cs_base;
5481 tval += next_eip;
5482 if (s->dflag == 0)
5483 tval &= 0xffff;
3b46e624 5484
14ce26e7
FB
5485 l1 = gen_new_label();
5486 l2 = gen_new_label();
5487 b &= 3;
5488 if (b == 3) {
5489 gen_op_jz_ecx[s->aflag](l1);
5490 } else {
5491 gen_op_dec_ECX[s->aflag]();
0b9dc5e4
FB
5492 if (b <= 1)
5493 gen_op_mov_T0_cc();
14ce26e7
FB
5494 gen_op_loop[s->aflag][b](l1);
5495 }
5496
5497 gen_jmp_im(next_eip);
5498 gen_op_jmp_label(l2);
5499 gen_set_label(l1);
5500 gen_jmp_im(tval);
5501 gen_set_label(l2);
5502 gen_eob(s);
5503 }
2c0262af
FB
5504 break;
5505 case 0x130: /* wrmsr */
5506 case 0x132: /* rdmsr */
5507 if (s->cpl != 0) {
5508 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5509 } else {
5510 if (b & 2)
5511 gen_op_rdmsr();
5512 else
5513 gen_op_wrmsr();
5514 }
5515 break;
5516 case 0x131: /* rdtsc */
ecada8a2 5517 gen_jmp_im(pc_start - s->cs_base);
2c0262af
FB
5518 gen_op_rdtsc();
5519 break;
023fe10d 5520 case 0x134: /* sysenter */
14ce26e7
FB
5521 if (CODE64(s))
5522 goto illegal_op;
023fe10d
FB
5523 if (!s->pe) {
5524 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5525 } else {
5526 if (s->cc_op != CC_OP_DYNAMIC) {
5527 gen_op_set_cc_op(s->cc_op);
5528 s->cc_op = CC_OP_DYNAMIC;
5529 }
14ce26e7 5530 gen_jmp_im(pc_start - s->cs_base);
023fe10d
FB
5531 gen_op_sysenter();
5532 gen_eob(s);
5533 }
5534 break;
5535 case 0x135: /* sysexit */
14ce26e7
FB
5536 if (CODE64(s))
5537 goto illegal_op;
023fe10d
FB
5538 if (!s->pe) {
5539 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5540 } else {
5541 if (s->cc_op != CC_OP_DYNAMIC) {
5542 gen_op_set_cc_op(s->cc_op);
5543 s->cc_op = CC_OP_DYNAMIC;
5544 }
14ce26e7 5545 gen_jmp_im(pc_start - s->cs_base);
023fe10d
FB
5546 gen_op_sysexit();
5547 gen_eob(s);
5548 }
5549 break;
14ce26e7
FB
5550#ifdef TARGET_X86_64
5551 case 0x105: /* syscall */
5552 /* XXX: is it usable in real mode ? */
5553 if (s->cc_op != CC_OP_DYNAMIC) {
5554 gen_op_set_cc_op(s->cc_op);
5555 s->cc_op = CC_OP_DYNAMIC;
5556 }
5557 gen_jmp_im(pc_start - s->cs_base);
06c2f506 5558 gen_op_syscall(s->pc - pc_start);
14ce26e7
FB
5559 gen_eob(s);
5560 break;
5561 case 0x107: /* sysret */
5562 if (!s->pe) {
5563 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5564 } else {
5565 if (s->cc_op != CC_OP_DYNAMIC) {
5566 gen_op_set_cc_op(s->cc_op);
5567 s->cc_op = CC_OP_DYNAMIC;
5568 }
5569 gen_jmp_im(pc_start - s->cs_base);
5570 gen_op_sysret(s->dflag);
aba9d61e
FB
5571 /* condition codes are modified only in long mode */
5572 if (s->lma)
5573 s->cc_op = CC_OP_EFLAGS;
14ce26e7
FB
5574 gen_eob(s);
5575 }
5576 break;
5577#endif
2c0262af
FB
5578 case 0x1a2: /* cpuid */
5579 gen_op_cpuid();
5580 break;
5581 case 0xf4: /* hlt */
5582 if (s->cpl != 0) {
5583 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5584 } else {
5585 if (s->cc_op != CC_OP_DYNAMIC)
5586 gen_op_set_cc_op(s->cc_op);
14ce26e7 5587 gen_jmp_im(s->pc - s->cs_base);
2c0262af
FB
5588 gen_op_hlt();
5589 s->is_jmp = 3;
5590 }
5591 break;
5592 case 0x100:
61382a50 5593 modrm = ldub_code(s->pc++);
2c0262af
FB
5594 mod = (modrm >> 6) & 3;
5595 op = (modrm >> 3) & 7;
5596 switch(op) {
5597 case 0: /* sldt */
f115e911
FB
5598 if (!s->pe || s->vm86)
5599 goto illegal_op;
2c0262af
FB
5600 gen_op_movl_T0_env(offsetof(CPUX86State,ldt.selector));
5601 ot = OT_WORD;
5602 if (mod == 3)
5603 ot += s->dflag;
5604 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
5605 break;
5606 case 2: /* lldt */
f115e911
FB
5607 if (!s->pe || s->vm86)
5608 goto illegal_op;
2c0262af
FB
5609 if (s->cpl != 0) {
5610 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5611 } else {
5612 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
14ce26e7 5613 gen_jmp_im(pc_start - s->cs_base);
2c0262af
FB
5614 gen_op_lldt_T0();
5615 }
5616 break;
5617 case 1: /* str */
f115e911
FB
5618 if (!s->pe || s->vm86)
5619 goto illegal_op;
2c0262af
FB
5620 gen_op_movl_T0_env(offsetof(CPUX86State,tr.selector));
5621 ot = OT_WORD;
5622 if (mod == 3)
5623 ot += s->dflag;
5624 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
5625 break;
5626 case 3: /* ltr */
f115e911
FB
5627 if (!s->pe || s->vm86)
5628 goto illegal_op;
2c0262af
FB
5629 if (s->cpl != 0) {
5630 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5631 } else {
5632 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
14ce26e7 5633 gen_jmp_im(pc_start - s->cs_base);
2c0262af
FB
5634 gen_op_ltr_T0();
5635 }
5636 break;
5637 case 4: /* verr */
5638 case 5: /* verw */
f115e911
FB
5639 if (!s->pe || s->vm86)
5640 goto illegal_op;
5641 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
5642 if (s->cc_op != CC_OP_DYNAMIC)
5643 gen_op_set_cc_op(s->cc_op);
5644 if (op == 4)
5645 gen_op_verr();
5646 else
5647 gen_op_verw();
5648 s->cc_op = CC_OP_EFLAGS;
5649 break;
2c0262af
FB
5650 default:
5651 goto illegal_op;
5652 }
5653 break;
5654 case 0x101:
61382a50 5655 modrm = ldub_code(s->pc++);
2c0262af
FB
5656 mod = (modrm >> 6) & 3;
5657 op = (modrm >> 3) & 7;
3d7374c5 5658 rm = modrm & 7;
2c0262af
FB
5659 switch(op) {
5660 case 0: /* sgdt */
2c0262af
FB
5661 if (mod == 3)
5662 goto illegal_op;
5663 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3d7374c5 5664 gen_op_movl_T0_env(offsetof(CPUX86State, gdt.limit));
2c0262af 5665 gen_op_st_T0_A0[OT_WORD + s->mem_index]();
aba9d61e 5666 gen_add_A0_im(s, 2);
3d7374c5 5667 gen_op_movtl_T0_env(offsetof(CPUX86State, gdt.base));
2c0262af
FB
5668 if (!s->dflag)
5669 gen_op_andl_T0_im(0xffffff);
14ce26e7 5670 gen_op_st_T0_A0[CODE64(s) + OT_LONG + s->mem_index]();
2c0262af 5671 break;
3d7374c5
FB
5672 case 1:
5673 if (mod == 3) {
5674 switch (rm) {
5675 case 0: /* monitor */
5676 if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) ||
5677 s->cpl != 0)
5678 goto illegal_op;
5679 gen_jmp_im(pc_start - s->cs_base);
5680#ifdef TARGET_X86_64
5681 if (s->aflag == 2) {
5682 gen_op_movq_A0_reg[R_EBX]();
5683 gen_op_addq_A0_AL();
5fafdf24 5684 } else
3d7374c5
FB
5685#endif
5686 {
5687 gen_op_movl_A0_reg[R_EBX]();
5688 gen_op_addl_A0_AL();
5689 if (s->aflag == 0)
5690 gen_op_andl_A0_ffff();
5691 }
5692 gen_add_A0_ds_seg(s);
5693 gen_op_monitor();
5694 break;
5695 case 1: /* mwait */
5696 if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) ||
5697 s->cpl != 0)
5698 goto illegal_op;
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(s->pc - s->cs_base);
5704 gen_op_mwait();
5705 gen_eob(s);
5706 break;
5707 default:
5708 goto illegal_op;
5709 }
5710 } else { /* sidt */
5711 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
5712 gen_op_movl_T0_env(offsetof(CPUX86State, idt.limit));
5713 gen_op_st_T0_A0[OT_WORD + s->mem_index]();
5714 gen_add_A0_im(s, 2);
5715 gen_op_movtl_T0_env(offsetof(CPUX86State, idt.base));
5716 if (!s->dflag)
5717 gen_op_andl_T0_im(0xffffff);
5718 gen_op_st_T0_A0[CODE64(s) + OT_LONG + s->mem_index]();
5719 }
5720 break;
2c0262af
FB
5721 case 2: /* lgdt */
5722 case 3: /* lidt */
5723 if (mod == 3)
5724 goto illegal_op;
5725 if (s->cpl != 0) {
5726 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5727 } else {
5728 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
5729 gen_op_ld_T1_A0[OT_WORD + s->mem_index]();
aba9d61e 5730 gen_add_A0_im(s, 2);
14ce26e7 5731 gen_op_ld_T0_A0[CODE64(s) + OT_LONG + s->mem_index]();
2c0262af
FB
5732 if (!s->dflag)
5733 gen_op_andl_T0_im(0xffffff);
5734 if (op == 2) {
14ce26e7 5735 gen_op_movtl_env_T0(offsetof(CPUX86State,gdt.base));
2c0262af
FB
5736 gen_op_movl_env_T1(offsetof(CPUX86State,gdt.limit));
5737 } else {
14ce26e7 5738 gen_op_movtl_env_T0(offsetof(CPUX86State,idt.base));
2c0262af
FB
5739 gen_op_movl_env_T1(offsetof(CPUX86State,idt.limit));
5740 }
5741 }
5742 break;
5743 case 4: /* smsw */
5744 gen_op_movl_T0_env(offsetof(CPUX86State,cr[0]));
5745 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 1);
5746 break;
5747 case 6: /* lmsw */
5748 if (s->cpl != 0) {
5749 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5750 } else {
5751 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
5752 gen_op_lmsw_T0();
14ce26e7 5753 gen_jmp_im(s->pc - s->cs_base);
d71b9a8b 5754 gen_eob(s);
2c0262af
FB
5755 }
5756 break;
5757 case 7: /* invlpg */
5758 if (s->cpl != 0) {
5759 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5760 } else {
14ce26e7
FB
5761 if (mod == 3) {
5762#ifdef TARGET_X86_64
3d7374c5 5763 if (CODE64(s) && rm == 0) {
14ce26e7
FB
5764 /* swapgs */
5765 gen_op_movtl_T0_env(offsetof(CPUX86State,segs[R_GS].base));
5766 gen_op_movtl_T1_env(offsetof(CPUX86State,kernelgsbase));
5767 gen_op_movtl_env_T1(offsetof(CPUX86State,segs[R_GS].base));
5768 gen_op_movtl_env_T0(offsetof(CPUX86State,kernelgsbase));
5fafdf24 5769 } else
14ce26e7
FB
5770#endif
5771 {
5772 goto illegal_op;
5773 }
5774 } else {
5775 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
5776 gen_op_invlpg_A0();
5777 gen_jmp_im(s->pc - s->cs_base);
5778 gen_eob(s);
5779 }
2c0262af
FB
5780 }
5781 break;
5782 default:
5783 goto illegal_op;
5784 }
5785 break;
3415a4dd
FB
5786 case 0x108: /* invd */
5787 case 0x109: /* wbinvd */
5788 if (s->cpl != 0) {
5789 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5790 } else {
5791 /* nothing to do */
5792 }
5793 break;
14ce26e7
FB
5794 case 0x63: /* arpl or movslS (x86_64) */
5795#ifdef TARGET_X86_64
5796 if (CODE64(s)) {
5797 int d_ot;
5798 /* d_ot is the size of destination */
5799 d_ot = dflag + OT_WORD;
5800
5801 modrm = ldub_code(s->pc++);
5802 reg = ((modrm >> 3) & 7) | rex_r;
5803 mod = (modrm >> 6) & 3;
5804 rm = (modrm & 7) | REX_B(s);
3b46e624 5805
14ce26e7
FB
5806 if (mod == 3) {
5807 gen_op_mov_TN_reg[OT_LONG][0][rm]();
5808 /* sign extend */
5809 if (d_ot == OT_QUAD)
5810 gen_op_movslq_T0_T0();
5811 gen_op_mov_reg_T0[d_ot][reg]();
5812 } else {
5813 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
5814 if (d_ot == OT_QUAD) {
5815 gen_op_lds_T0_A0[OT_LONG + s->mem_index]();
5816 } else {
5817 gen_op_ld_T0_A0[OT_LONG + s->mem_index]();
5818 }
5819 gen_op_mov_reg_T0[d_ot][reg]();
5820 }
5fafdf24 5821 } else
14ce26e7
FB
5822#endif
5823 {
5824 if (!s->pe || s->vm86)
5825 goto illegal_op;
5826 ot = dflag ? OT_LONG : OT_WORD;
5827 modrm = ldub_code(s->pc++);
5828 reg = (modrm >> 3) & 7;
5829 mod = (modrm >> 6) & 3;
5830 rm = modrm & 7;
5831 if (mod != 3) {
5832 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
5833 gen_op_ld_T0_A0[ot + s->mem_index]();
5834 } else {
5835 gen_op_mov_TN_reg[ot][0][rm]();
5836 }
5837 if (s->cc_op != CC_OP_DYNAMIC)
5838 gen_op_set_cc_op(s->cc_op);
5839 gen_op_arpl();
5840 s->cc_op = CC_OP_EFLAGS;
5841 if (mod != 3) {
5842 gen_op_st_T0_A0[ot + s->mem_index]();
5843 } else {
5844 gen_op_mov_reg_T0[ot][rm]();
5845 }
5846 gen_op_arpl_update();
f115e911 5847 }
f115e911 5848 break;
2c0262af
FB
5849 case 0x102: /* lar */
5850 case 0x103: /* lsl */
5851 if (!s->pe || s->vm86)
5852 goto illegal_op;
5853 ot = dflag ? OT_LONG : OT_WORD;
61382a50 5854 modrm = ldub_code(s->pc++);
14ce26e7 5855 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af
FB
5856 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
5857 gen_op_mov_TN_reg[ot][1][reg]();
5858 if (s->cc_op != CC_OP_DYNAMIC)
5859 gen_op_set_cc_op(s->cc_op);
5860 if (b == 0x102)
5861 gen_op_lar();
5862 else
5863 gen_op_lsl();
5864 s->cc_op = CC_OP_EFLAGS;
5865 gen_op_mov_reg_T1[ot][reg]();
5866 break;
5867 case 0x118:
61382a50 5868 modrm = ldub_code(s->pc++);
2c0262af
FB
5869 mod = (modrm >> 6) & 3;
5870 op = (modrm >> 3) & 7;
5871 switch(op) {
5872 case 0: /* prefetchnta */
5873 case 1: /* prefetchnt0 */
5874 case 2: /* prefetchnt0 */
5875 case 3: /* prefetchnt0 */
5876 if (mod == 3)
5877 goto illegal_op;
5878 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
5879 /* nothing more to do */
5880 break;
e17a36ce
FB
5881 default: /* nop (multi byte) */
5882 gen_nop_modrm(s, modrm);
5883 break;
2c0262af
FB
5884 }
5885 break;
e17a36ce
FB
5886 case 0x119 ... 0x11f: /* nop (multi byte) */
5887 modrm = ldub_code(s->pc++);
5888 gen_nop_modrm(s, modrm);
5889 break;
2c0262af
FB
5890 case 0x120: /* mov reg, crN */
5891 case 0x122: /* mov crN, reg */
5892 if (s->cpl != 0) {
5893 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5894 } else {
61382a50 5895 modrm = ldub_code(s->pc++);
2c0262af
FB
5896 if ((modrm & 0xc0) != 0xc0)
5897 goto illegal_op;
14ce26e7
FB
5898 rm = (modrm & 7) | REX_B(s);
5899 reg = ((modrm >> 3) & 7) | rex_r;
5900 if (CODE64(s))
5901 ot = OT_QUAD;
5902 else
5903 ot = OT_LONG;
2c0262af
FB
5904 switch(reg) {
5905 case 0:
5906 case 2:
5907 case 3:
5908 case 4:
9230e66e 5909 case 8:
2c0262af 5910 if (b & 2) {
14ce26e7 5911 gen_op_mov_TN_reg[ot][0][rm]();
2c0262af 5912 gen_op_movl_crN_T0(reg);
14ce26e7 5913 gen_jmp_im(s->pc - s->cs_base);
2c0262af
FB
5914 gen_eob(s);
5915 } else {
5fafdf24 5916#if !defined(CONFIG_USER_ONLY)
9230e66e
FB
5917 if (reg == 8)
5918 gen_op_movtl_T0_cr8();
5919 else
82e41634 5920#endif
9230e66e 5921 gen_op_movtl_T0_env(offsetof(CPUX86State,cr[reg]));
14ce26e7 5922 gen_op_mov_reg_T0[ot][rm]();
2c0262af
FB
5923 }
5924 break;
5925 default:
5926 goto illegal_op;
5927 }
5928 }
5929 break;
5930 case 0x121: /* mov reg, drN */
5931 case 0x123: /* mov drN, reg */
5932 if (s->cpl != 0) {
5933 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5934 } else {
61382a50 5935 modrm = ldub_code(s->pc++);
2c0262af
FB
5936 if ((modrm & 0xc0) != 0xc0)
5937 goto illegal_op;
14ce26e7
FB
5938 rm = (modrm & 7) | REX_B(s);
5939 reg = ((modrm >> 3) & 7) | rex_r;
5940 if (CODE64(s))
5941 ot = OT_QUAD;
5942 else
5943 ot = OT_LONG;
2c0262af 5944 /* XXX: do it dynamically with CR4.DE bit */
14ce26e7 5945 if (reg == 4 || reg == 5 || reg >= 8)
2c0262af
FB
5946 goto illegal_op;
5947 if (b & 2) {
14ce26e7 5948 gen_op_mov_TN_reg[ot][0][rm]();
2c0262af 5949 gen_op_movl_drN_T0(reg);
14ce26e7 5950 gen_jmp_im(s->pc - s->cs_base);
2c0262af
FB
5951 gen_eob(s);
5952 } else {
14ce26e7
FB
5953 gen_op_movtl_T0_env(offsetof(CPUX86State,dr[reg]));
5954 gen_op_mov_reg_T0[ot][rm]();
2c0262af
FB
5955 }
5956 }
5957 break;
5958 case 0x106: /* clts */
5959 if (s->cpl != 0) {
5960 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5961 } else {
5962 gen_op_clts();
7eee2a50 5963 /* abort block because static cpu state changed */
14ce26e7 5964 gen_jmp_im(s->pc - s->cs_base);
7eee2a50 5965 gen_eob(s);
2c0262af
FB
5966 }
5967 break;
664e0f19
FB
5968 /* MMX/SSE/SSE2/PNI support */
5969 case 0x1c3: /* MOVNTI reg, mem */
5970 if (!(s->cpuid_features & CPUID_SSE2))
14ce26e7 5971 goto illegal_op;
664e0f19
FB
5972 ot = s->dflag == 2 ? OT_QUAD : OT_LONG;
5973 modrm = ldub_code(s->pc++);
5974 mod = (modrm >> 6) & 3;
5975 if (mod == 3)
5976 goto illegal_op;
5977 reg = ((modrm >> 3) & 7) | rex_r;
5978 /* generate a generic store */
5979 gen_ldst_modrm(s, modrm, ot, reg, 1);
14ce26e7 5980 break;
664e0f19
FB
5981 case 0x1ae:
5982 modrm = ldub_code(s->pc++);
5983 mod = (modrm >> 6) & 3;
5984 op = (modrm >> 3) & 7;
5985 switch(op) {
5986 case 0: /* fxsave */
5fafdf24 5987 if (mod == 3 || !(s->cpuid_features & CPUID_FXSR) ||
0fd14b72 5988 (s->flags & HF_EM_MASK))
14ce26e7 5989 goto illegal_op;
0fd14b72
FB
5990 if (s->flags & HF_TS_MASK) {
5991 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
5992 break;
5993 }
664e0f19
FB
5994 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
5995 gen_op_fxsave_A0((s->dflag == 2));
5996 break;
5997 case 1: /* fxrstor */
5fafdf24 5998 if (mod == 3 || !(s->cpuid_features & CPUID_FXSR) ||
0fd14b72 5999 (s->flags & HF_EM_MASK))
14ce26e7 6000 goto illegal_op;
0fd14b72
FB
6001 if (s->flags & HF_TS_MASK) {
6002 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
6003 break;
6004 }
664e0f19
FB
6005 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
6006 gen_op_fxrstor_A0((s->dflag == 2));
6007 break;
6008 case 2: /* ldmxcsr */
6009 case 3: /* stmxcsr */
6010 if (s->flags & HF_TS_MASK) {
6011 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
6012 break;
14ce26e7 6013 }
664e0f19
FB
6014 if ((s->flags & HF_EM_MASK) || !(s->flags & HF_OSFXSR_MASK) ||
6015 mod == 3)
14ce26e7 6016 goto illegal_op;
664e0f19
FB
6017 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
6018 if (op == 2) {
6019 gen_op_ld_T0_A0[OT_LONG + s->mem_index]();
6020 gen_op_movl_env_T0(offsetof(CPUX86State, mxcsr));
14ce26e7 6021 } else {
664e0f19
FB
6022 gen_op_movl_T0_env(offsetof(CPUX86State, mxcsr));
6023 gen_op_st_T0_A0[OT_LONG + s->mem_index]();
14ce26e7 6024 }
664e0f19
FB
6025 break;
6026 case 5: /* lfence */
6027 case 6: /* mfence */
664e0f19
FB
6028 if ((modrm & 0xc7) != 0xc0 || !(s->cpuid_features & CPUID_SSE))
6029 goto illegal_op;
6030 break;
8f091a59
FB
6031 case 7: /* sfence / clflush */
6032 if ((modrm & 0xc7) == 0xc0) {
6033 /* sfence */
6034 if (!(s->cpuid_features & CPUID_SSE))
6035 goto illegal_op;
6036 } else {
6037 /* clflush */
6038 if (!(s->cpuid_features & CPUID_CLFLUSH))
6039 goto illegal_op;
6040 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
6041 }
6042 break;
664e0f19 6043 default:
14ce26e7
FB
6044 goto illegal_op;
6045 }
6046 break;
8f091a59
FB
6047 case 0x10d: /* prefetch */
6048 modrm = ldub_code(s->pc++);
6049 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
6050 /* ignore for now */
6051 break;
3b21e03e
FB
6052 case 0x1aa: /* rsm */
6053 if (!(s->flags & HF_SMM_MASK))
6054 goto illegal_op;
6055 if (s->cc_op != CC_OP_DYNAMIC) {
6056 gen_op_set_cc_op(s->cc_op);
6057 s->cc_op = CC_OP_DYNAMIC;
6058 }
6059 gen_jmp_im(s->pc - s->cs_base);
6060 gen_op_rsm();
6061 gen_eob(s);
6062 break;
664e0f19
FB
6063 case 0x110 ... 0x117:
6064 case 0x128 ... 0x12f:
6065 case 0x150 ... 0x177:
6066 case 0x17c ... 0x17f:
6067 case 0x1c2:
6068 case 0x1c4 ... 0x1c6:
6069 case 0x1d0 ... 0x1fe:
6070 gen_sse(s, b, pc_start, rex_r);
6071 break;
2c0262af
FB
6072 default:
6073 goto illegal_op;
6074 }
6075 /* lock generation */
6076 if (s->prefix & PREFIX_LOCK)
6077 gen_op_unlock();
6078 return s->pc;
6079 illegal_op:
ab1f142b
FB
6080 if (s->prefix & PREFIX_LOCK)
6081 gen_op_unlock();
2c0262af
FB
6082 /* XXX: ensure that no lock was generated */
6083 gen_exception(s, EXCP06_ILLOP, pc_start - s->cs_base);
6084 return s->pc;
6085}
6086
6087#define CC_OSZAPC (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C)
6088#define CC_OSZAP (CC_O | CC_S | CC_Z | CC_A | CC_P)
6089
6090/* flags read by an operation */
5fafdf24 6091static uint16_t opc_read_flags[NB_OPS] = {
2c0262af
FB
6092 [INDEX_op_aas] = CC_A,
6093 [INDEX_op_aaa] = CC_A,
6094 [INDEX_op_das] = CC_A | CC_C,
6095 [INDEX_op_daa] = CC_A | CC_C,
6096
2c0262af 6097 /* subtle: due to the incl/decl implementation, C is used */
5fafdf24 6098 [INDEX_op_update_inc_cc] = CC_C,
2c0262af
FB
6099
6100 [INDEX_op_into] = CC_O,
6101
6102 [INDEX_op_jb_subb] = CC_C,
6103 [INDEX_op_jb_subw] = CC_C,
6104 [INDEX_op_jb_subl] = CC_C,
6105
6106 [INDEX_op_jz_subb] = CC_Z,
6107 [INDEX_op_jz_subw] = CC_Z,
6108 [INDEX_op_jz_subl] = CC_Z,
6109
6110 [INDEX_op_jbe_subb] = CC_Z | CC_C,
6111 [INDEX_op_jbe_subw] = CC_Z | CC_C,
6112 [INDEX_op_jbe_subl] = CC_Z | CC_C,
6113
6114 [INDEX_op_js_subb] = CC_S,
6115 [INDEX_op_js_subw] = CC_S,
6116 [INDEX_op_js_subl] = CC_S,
6117
6118 [INDEX_op_jl_subb] = CC_O | CC_S,
6119 [INDEX_op_jl_subw] = CC_O | CC_S,
6120 [INDEX_op_jl_subl] = CC_O | CC_S,
6121
6122 [INDEX_op_jle_subb] = CC_O | CC_S | CC_Z,
6123 [INDEX_op_jle_subw] = CC_O | CC_S | CC_Z,
6124 [INDEX_op_jle_subl] = CC_O | CC_S | CC_Z,
6125
6126 [INDEX_op_loopnzw] = CC_Z,
6127 [INDEX_op_loopnzl] = CC_Z,
6128 [INDEX_op_loopzw] = CC_Z,
6129 [INDEX_op_loopzl] = CC_Z,
6130
6131 [INDEX_op_seto_T0_cc] = CC_O,
6132 [INDEX_op_setb_T0_cc] = CC_C,
6133 [INDEX_op_setz_T0_cc] = CC_Z,
6134 [INDEX_op_setbe_T0_cc] = CC_Z | CC_C,
6135 [INDEX_op_sets_T0_cc] = CC_S,
6136 [INDEX_op_setp_T0_cc] = CC_P,
6137 [INDEX_op_setl_T0_cc] = CC_O | CC_S,
6138 [INDEX_op_setle_T0_cc] = CC_O | CC_S | CC_Z,
6139
6140 [INDEX_op_setb_T0_subb] = CC_C,
6141 [INDEX_op_setb_T0_subw] = CC_C,
6142 [INDEX_op_setb_T0_subl] = CC_C,
6143
6144 [INDEX_op_setz_T0_subb] = CC_Z,
6145 [INDEX_op_setz_T0_subw] = CC_Z,
6146 [INDEX_op_setz_T0_subl] = CC_Z,
6147
6148 [INDEX_op_setbe_T0_subb] = CC_Z | CC_C,
6149 [INDEX_op_setbe_T0_subw] = CC_Z | CC_C,
6150 [INDEX_op_setbe_T0_subl] = CC_Z | CC_C,
6151
6152 [INDEX_op_sets_T0_subb] = CC_S,
6153 [INDEX_op_sets_T0_subw] = CC_S,
6154 [INDEX_op_sets_T0_subl] = CC_S,
6155
6156 [INDEX_op_setl_T0_subb] = CC_O | CC_S,
6157 [INDEX_op_setl_T0_subw] = CC_O | CC_S,
6158 [INDEX_op_setl_T0_subl] = CC_O | CC_S,
6159
6160 [INDEX_op_setle_T0_subb] = CC_O | CC_S | CC_Z,
6161 [INDEX_op_setle_T0_subw] = CC_O | CC_S | CC_Z,
6162 [INDEX_op_setle_T0_subl] = CC_O | CC_S | CC_Z,
6163
6164 [INDEX_op_movl_T0_eflags] = CC_OSZAPC,
6165 [INDEX_op_cmc] = CC_C,
6166 [INDEX_op_salc] = CC_C,
6167
7399c5a9 6168 /* needed for correct flag optimisation before string ops */
14ce26e7
FB
6169 [INDEX_op_jnz_ecxw] = CC_OSZAPC,
6170 [INDEX_op_jnz_ecxl] = CC_OSZAPC,
7399c5a9
FB
6171 [INDEX_op_jz_ecxw] = CC_OSZAPC,
6172 [INDEX_op_jz_ecxl] = CC_OSZAPC,
14ce26e7
FB
6173
6174#ifdef TARGET_X86_64
6175 [INDEX_op_jb_subq] = CC_C,
6176 [INDEX_op_jz_subq] = CC_Z,
6177 [INDEX_op_jbe_subq] = CC_Z | CC_C,
6178 [INDEX_op_js_subq] = CC_S,
6179 [INDEX_op_jl_subq] = CC_O | CC_S,
6180 [INDEX_op_jle_subq] = CC_O | CC_S | CC_Z,
6181
6182 [INDEX_op_loopnzq] = CC_Z,
6183 [INDEX_op_loopzq] = CC_Z,
6184
6185 [INDEX_op_setb_T0_subq] = CC_C,
6186 [INDEX_op_setz_T0_subq] = CC_Z,
6187 [INDEX_op_setbe_T0_subq] = CC_Z | CC_C,
6188 [INDEX_op_sets_T0_subq] = CC_S,
6189 [INDEX_op_setl_T0_subq] = CC_O | CC_S,
6190 [INDEX_op_setle_T0_subq] = CC_O | CC_S | CC_Z,
6191
6192 [INDEX_op_jnz_ecxq] = CC_OSZAPC,
6193 [INDEX_op_jz_ecxq] = CC_OSZAPC,
6194#endif
7399c5a9 6195
4f31916f
FB
6196#define DEF_READF(SUFFIX)\
6197 [INDEX_op_adcb ## SUFFIX ## _T0_T1_cc] = CC_C,\
6198 [INDEX_op_adcw ## SUFFIX ## _T0_T1_cc] = CC_C,\
6199 [INDEX_op_adcl ## SUFFIX ## _T0_T1_cc] = CC_C,\
14ce26e7 6200 X86_64_DEF([INDEX_op_adcq ## SUFFIX ## _T0_T1_cc] = CC_C,)\
4f31916f
FB
6201 [INDEX_op_sbbb ## SUFFIX ## _T0_T1_cc] = CC_C,\
6202 [INDEX_op_sbbw ## SUFFIX ## _T0_T1_cc] = CC_C,\
6203 [INDEX_op_sbbl ## SUFFIX ## _T0_T1_cc] = CC_C,\
14ce26e7 6204 X86_64_DEF([INDEX_op_sbbq ## SUFFIX ## _T0_T1_cc] = CC_C,)\
4f31916f
FB
6205\
6206 [INDEX_op_rclb ## SUFFIX ## _T0_T1_cc] = CC_C,\
6207 [INDEX_op_rclw ## SUFFIX ## _T0_T1_cc] = CC_C,\
6208 [INDEX_op_rcll ## SUFFIX ## _T0_T1_cc] = CC_C,\
14ce26e7 6209 X86_64_DEF([INDEX_op_rclq ## SUFFIX ## _T0_T1_cc] = CC_C,)\
4f31916f
FB
6210 [INDEX_op_rcrb ## SUFFIX ## _T0_T1_cc] = CC_C,\
6211 [INDEX_op_rcrw ## SUFFIX ## _T0_T1_cc] = CC_C,\
14ce26e7
FB
6212 [INDEX_op_rcrl ## SUFFIX ## _T0_T1_cc] = CC_C,\
6213 X86_64_DEF([INDEX_op_rcrq ## SUFFIX ## _T0_T1_cc] = CC_C,)
4f31916f 6214
4bb2fcc7 6215 DEF_READF( )
4f31916f
FB
6216 DEF_READF(_raw)
6217#ifndef CONFIG_USER_ONLY
6218 DEF_READF(_kernel)
6219 DEF_READF(_user)
6220#endif
2c0262af
FB
6221};
6222
6223/* flags written by an operation */
5fafdf24 6224static uint16_t opc_write_flags[NB_OPS] = {
2c0262af
FB
6225 [INDEX_op_update2_cc] = CC_OSZAPC,
6226 [INDEX_op_update1_cc] = CC_OSZAPC,
6227 [INDEX_op_cmpl_T0_T1_cc] = CC_OSZAPC,
6228 [INDEX_op_update_neg_cc] = CC_OSZAPC,
6229 /* subtle: due to the incl/decl implementation, C is used */
5fafdf24 6230 [INDEX_op_update_inc_cc] = CC_OSZAPC,
2c0262af
FB
6231 [INDEX_op_testl_T0_T1_cc] = CC_OSZAPC,
6232
2c0262af 6233 [INDEX_op_mulb_AL_T0] = CC_OSZAPC,
2c0262af 6234 [INDEX_op_mulw_AX_T0] = CC_OSZAPC,
2c0262af 6235 [INDEX_op_mull_EAX_T0] = CC_OSZAPC,
14ce26e7
FB
6236 X86_64_DEF([INDEX_op_mulq_EAX_T0] = CC_OSZAPC,)
6237 [INDEX_op_imulb_AL_T0] = CC_OSZAPC,
6238 [INDEX_op_imulw_AX_T0] = CC_OSZAPC,
2c0262af 6239 [INDEX_op_imull_EAX_T0] = CC_OSZAPC,
14ce26e7 6240 X86_64_DEF([INDEX_op_imulq_EAX_T0] = CC_OSZAPC,)
2c0262af
FB
6241 [INDEX_op_imulw_T0_T1] = CC_OSZAPC,
6242 [INDEX_op_imull_T0_T1] = CC_OSZAPC,
14ce26e7
FB
6243 X86_64_DEF([INDEX_op_imulq_T0_T1] = CC_OSZAPC,)
6244
664e0f19
FB
6245 /* sse */
6246 [INDEX_op_ucomiss] = CC_OSZAPC,
6247 [INDEX_op_ucomisd] = CC_OSZAPC,
6248 [INDEX_op_comiss] = CC_OSZAPC,
6249 [INDEX_op_comisd] = CC_OSZAPC,
6250
2c0262af
FB
6251 /* bcd */
6252 [INDEX_op_aam] = CC_OSZAPC,
6253 [INDEX_op_aad] = CC_OSZAPC,
6254 [INDEX_op_aas] = CC_OSZAPC,
6255 [INDEX_op_aaa] = CC_OSZAPC,
6256 [INDEX_op_das] = CC_OSZAPC,
6257 [INDEX_op_daa] = CC_OSZAPC,
6258
6259 [INDEX_op_movb_eflags_T0] = CC_S | CC_Z | CC_A | CC_P | CC_C,
6260 [INDEX_op_movw_eflags_T0] = CC_OSZAPC,
6261 [INDEX_op_movl_eflags_T0] = CC_OSZAPC,
4136f33c
FB
6262 [INDEX_op_movw_eflags_T0_io] = CC_OSZAPC,
6263 [INDEX_op_movl_eflags_T0_io] = CC_OSZAPC,
6264 [INDEX_op_movw_eflags_T0_cpl0] = CC_OSZAPC,
6265 [INDEX_op_movl_eflags_T0_cpl0] = CC_OSZAPC,
2c0262af
FB
6266 [INDEX_op_clc] = CC_C,
6267 [INDEX_op_stc] = CC_C,
6268 [INDEX_op_cmc] = CC_C,
6269
2c0262af
FB
6270 [INDEX_op_btw_T0_T1_cc] = CC_OSZAPC,
6271 [INDEX_op_btl_T0_T1_cc] = CC_OSZAPC,
14ce26e7 6272 X86_64_DEF([INDEX_op_btq_T0_T1_cc] = CC_OSZAPC,)
2c0262af
FB
6273 [INDEX_op_btsw_T0_T1_cc] = CC_OSZAPC,
6274 [INDEX_op_btsl_T0_T1_cc] = CC_OSZAPC,
14ce26e7 6275 X86_64_DEF([INDEX_op_btsq_T0_T1_cc] = CC_OSZAPC,)
2c0262af
FB
6276 [INDEX_op_btrw_T0_T1_cc] = CC_OSZAPC,
6277 [INDEX_op_btrl_T0_T1_cc] = CC_OSZAPC,
14ce26e7 6278 X86_64_DEF([INDEX_op_btrq_T0_T1_cc] = CC_OSZAPC,)
2c0262af
FB
6279 [INDEX_op_btcw_T0_T1_cc] = CC_OSZAPC,
6280 [INDEX_op_btcl_T0_T1_cc] = CC_OSZAPC,
14ce26e7 6281 X86_64_DEF([INDEX_op_btcq_T0_T1_cc] = CC_OSZAPC,)
2c0262af
FB
6282
6283 [INDEX_op_bsfw_T0_cc] = CC_OSZAPC,
6284 [INDEX_op_bsfl_T0_cc] = CC_OSZAPC,
14ce26e7 6285 X86_64_DEF([INDEX_op_bsfq_T0_cc] = CC_OSZAPC,)
2c0262af
FB
6286 [INDEX_op_bsrw_T0_cc] = CC_OSZAPC,
6287 [INDEX_op_bsrl_T0_cc] = CC_OSZAPC,
14ce26e7 6288 X86_64_DEF([INDEX_op_bsrq_T0_cc] = CC_OSZAPC,)
2c0262af
FB
6289
6290 [INDEX_op_cmpxchgb_T0_T1_EAX_cc] = CC_OSZAPC,
6291 [INDEX_op_cmpxchgw_T0_T1_EAX_cc] = CC_OSZAPC,
6292 [INDEX_op_cmpxchgl_T0_T1_EAX_cc] = CC_OSZAPC,
14ce26e7 6293 X86_64_DEF([INDEX_op_cmpxchgq_T0_T1_EAX_cc] = CC_OSZAPC,)
2c0262af 6294
2c0262af
FB
6295 [INDEX_op_cmpxchg8b] = CC_Z,
6296 [INDEX_op_lar] = CC_Z,
6297 [INDEX_op_lsl] = CC_Z,
cc6f538b
FB
6298 [INDEX_op_verr] = CC_Z,
6299 [INDEX_op_verw] = CC_Z,
2c0262af
FB
6300 [INDEX_op_fcomi_ST0_FT0] = CC_Z | CC_P | CC_C,
6301 [INDEX_op_fucomi_ST0_FT0] = CC_Z | CC_P | CC_C,
4f31916f
FB
6302
6303#define DEF_WRITEF(SUFFIX)\
6304 [INDEX_op_adcb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6305 [INDEX_op_adcw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6306 [INDEX_op_adcl ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
14ce26e7 6307 X86_64_DEF([INDEX_op_adcq ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,)\
4f31916f
FB
6308 [INDEX_op_sbbb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6309 [INDEX_op_sbbw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6310 [INDEX_op_sbbl ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
14ce26e7 6311 X86_64_DEF([INDEX_op_sbbq ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,)\
4f31916f
FB
6312\
6313 [INDEX_op_rolb ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6314 [INDEX_op_rolw ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6315 [INDEX_op_roll ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
14ce26e7 6316 X86_64_DEF([INDEX_op_rolq ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,)\
4f31916f
FB
6317 [INDEX_op_rorb ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6318 [INDEX_op_rorw ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6319 [INDEX_op_rorl ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
14ce26e7 6320 X86_64_DEF([INDEX_op_rorq ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,)\
4f31916f
FB
6321\
6322 [INDEX_op_rclb ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6323 [INDEX_op_rclw ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6324 [INDEX_op_rcll ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
14ce26e7 6325 X86_64_DEF([INDEX_op_rclq ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,)\
4f31916f
FB
6326 [INDEX_op_rcrb ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6327 [INDEX_op_rcrw ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6328 [INDEX_op_rcrl ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
14ce26e7 6329 X86_64_DEF([INDEX_op_rcrq ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,)\
4f31916f
FB
6330\
6331 [INDEX_op_shlb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6332 [INDEX_op_shlw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6333 [INDEX_op_shll ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
14ce26e7 6334 X86_64_DEF([INDEX_op_shlq ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,)\
4f31916f
FB
6335\
6336 [INDEX_op_shrb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6337 [INDEX_op_shrw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6338 [INDEX_op_shrl ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
14ce26e7 6339 X86_64_DEF([INDEX_op_shrq ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,)\
4f31916f
FB
6340\
6341 [INDEX_op_sarb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6342 [INDEX_op_sarw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6343 [INDEX_op_sarl ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
14ce26e7 6344 X86_64_DEF([INDEX_op_sarq ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,)\
4f31916f
FB
6345\
6346 [INDEX_op_shldw ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,\
6347 [INDEX_op_shldl ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,\
14ce26e7 6348 X86_64_DEF([INDEX_op_shldq ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,)\
4f31916f
FB
6349 [INDEX_op_shldw ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,\
6350 [INDEX_op_shldl ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,\
14ce26e7 6351 X86_64_DEF([INDEX_op_shldq ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,)\
4f31916f
FB
6352\
6353 [INDEX_op_shrdw ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,\
6354 [INDEX_op_shrdl ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,\
14ce26e7 6355 X86_64_DEF([INDEX_op_shrdq ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,)\
4f31916f
FB
6356 [INDEX_op_shrdw ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,\
6357 [INDEX_op_shrdl ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,\
14ce26e7 6358 X86_64_DEF([INDEX_op_shrdq ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,)\
4f31916f
FB
6359\
6360 [INDEX_op_cmpxchgb ## SUFFIX ## _T0_T1_EAX_cc] = CC_OSZAPC,\
6361 [INDEX_op_cmpxchgw ## SUFFIX ## _T0_T1_EAX_cc] = CC_OSZAPC,\
14ce26e7
FB
6362 [INDEX_op_cmpxchgl ## SUFFIX ## _T0_T1_EAX_cc] = CC_OSZAPC,\
6363 X86_64_DEF([INDEX_op_cmpxchgq ## SUFFIX ## _T0_T1_EAX_cc] = CC_OSZAPC,)
4f31916f
FB
6364
6365
4bb2fcc7 6366 DEF_WRITEF( )
4f31916f
FB
6367 DEF_WRITEF(_raw)
6368#ifndef CONFIG_USER_ONLY
6369 DEF_WRITEF(_kernel)
6370 DEF_WRITEF(_user)
6371#endif
2c0262af
FB
6372};
6373
6374/* simpler form of an operation if no flags need to be generated */
5fafdf24 6375static uint16_t opc_simpler[NB_OPS] = {
2c0262af
FB
6376 [INDEX_op_update2_cc] = INDEX_op_nop,
6377 [INDEX_op_update1_cc] = INDEX_op_nop,
6378 [INDEX_op_update_neg_cc] = INDEX_op_nop,
6379#if 0
6380 /* broken: CC_OP logic must be rewritten */
6381 [INDEX_op_update_inc_cc] = INDEX_op_nop,
6382#endif
2c0262af
FB
6383
6384 [INDEX_op_shlb_T0_T1_cc] = INDEX_op_shlb_T0_T1,
6385 [INDEX_op_shlw_T0_T1_cc] = INDEX_op_shlw_T0_T1,
6386 [INDEX_op_shll_T0_T1_cc] = INDEX_op_shll_T0_T1,
14ce26e7 6387 X86_64_DEF([INDEX_op_shlq_T0_T1_cc] = INDEX_op_shlq_T0_T1,)
2c0262af
FB
6388
6389 [INDEX_op_shrb_T0_T1_cc] = INDEX_op_shrb_T0_T1,
6390 [INDEX_op_shrw_T0_T1_cc] = INDEX_op_shrw_T0_T1,
6391 [INDEX_op_shrl_T0_T1_cc] = INDEX_op_shrl_T0_T1,
14ce26e7 6392 X86_64_DEF([INDEX_op_shrq_T0_T1_cc] = INDEX_op_shrq_T0_T1,)
2c0262af
FB
6393
6394 [INDEX_op_sarb_T0_T1_cc] = INDEX_op_sarb_T0_T1,
6395 [INDEX_op_sarw_T0_T1_cc] = INDEX_op_sarw_T0_T1,
6396 [INDEX_op_sarl_T0_T1_cc] = INDEX_op_sarl_T0_T1,
14ce26e7 6397 X86_64_DEF([INDEX_op_sarq_T0_T1_cc] = INDEX_op_sarq_T0_T1,)
4f31916f
FB
6398
6399#define DEF_SIMPLER(SUFFIX)\
6400 [INDEX_op_rolb ## SUFFIX ## _T0_T1_cc] = INDEX_op_rolb ## SUFFIX ## _T0_T1,\
6401 [INDEX_op_rolw ## SUFFIX ## _T0_T1_cc] = INDEX_op_rolw ## SUFFIX ## _T0_T1,\
6402 [INDEX_op_roll ## SUFFIX ## _T0_T1_cc] = INDEX_op_roll ## SUFFIX ## _T0_T1,\
14ce26e7 6403 X86_64_DEF([INDEX_op_rolq ## SUFFIX ## _T0_T1_cc] = INDEX_op_rolq ## SUFFIX ## _T0_T1,)\
4f31916f
FB
6404\
6405 [INDEX_op_rorb ## SUFFIX ## _T0_T1_cc] = INDEX_op_rorb ## SUFFIX ## _T0_T1,\
6406 [INDEX_op_rorw ## SUFFIX ## _T0_T1_cc] = INDEX_op_rorw ## SUFFIX ## _T0_T1,\
14ce26e7
FB
6407 [INDEX_op_rorl ## SUFFIX ## _T0_T1_cc] = INDEX_op_rorl ## SUFFIX ## _T0_T1,\
6408 X86_64_DEF([INDEX_op_rorq ## SUFFIX ## _T0_T1_cc] = INDEX_op_rorq ## SUFFIX ## _T0_T1,)
4f31916f 6409
4bb2fcc7 6410 DEF_SIMPLER( )
4f31916f
FB
6411 DEF_SIMPLER(_raw)
6412#ifndef CONFIG_USER_ONLY
6413 DEF_SIMPLER(_kernel)
6414 DEF_SIMPLER(_user)
6415#endif
2c0262af
FB
6416};
6417
6418void optimize_flags_init(void)
6419{
6420 int i;
6421 /* put default values in arrays */
6422 for(i = 0; i < NB_OPS; i++) {
6423 if (opc_simpler[i] == 0)
6424 opc_simpler[i] = i;
6425 }
6426}
6427
6428/* CPU flags computation optimization: we move backward thru the
6429 generated code to see which flags are needed. The operation is
6430 modified if suitable */
6431static void optimize_flags(uint16_t *opc_buf, int opc_buf_len)
6432{
6433 uint16_t *opc_ptr;
6434 int live_flags, write_flags, op;
6435
6436 opc_ptr = opc_buf + opc_buf_len;
6437 /* live_flags contains the flags needed by the next instructions
e91c8a77 6438 in the code. At the end of the block, we consider that all the
2c0262af
FB
6439 flags are live. */
6440 live_flags = CC_OSZAPC;
6441 while (opc_ptr > opc_buf) {
6442 op = *--opc_ptr;
6443 /* if none of the flags written by the instruction is used,
6444 then we can try to find a simpler instruction */
6445 write_flags = opc_write_flags[op];
6446 if ((live_flags & write_flags) == 0) {
6447 *opc_ptr = opc_simpler[op];
6448 }
6449 /* compute the live flags before the instruction */
6450 live_flags &= ~write_flags;
6451 live_flags |= opc_read_flags[op];
6452 }
6453}
6454
6455/* generate intermediate code in gen_opc_buf and gen_opparam_buf for
6456 basic block 'tb'. If search_pc is TRUE, also generate PC
6457 information for each intermediate instruction. */
6458static inline int gen_intermediate_code_internal(CPUState *env,
5fafdf24 6459 TranslationBlock *tb,
2c0262af
FB
6460 int search_pc)
6461{
6462 DisasContext dc1, *dc = &dc1;
14ce26e7 6463 target_ulong pc_ptr;
2c0262af 6464 uint16_t *gen_opc_end;
d720b93d 6465 int flags, j, lj, cflags;
14ce26e7
FB
6466 target_ulong pc_start;
6467 target_ulong cs_base;
3b46e624 6468
2c0262af 6469 /* generate intermediate code */
14ce26e7
FB
6470 pc_start = tb->pc;
6471 cs_base = tb->cs_base;
2c0262af 6472 flags = tb->flags;
d720b93d 6473 cflags = tb->cflags;
3a1d9b8b 6474
4f31916f 6475 dc->pe = (flags >> HF_PE_SHIFT) & 1;
2c0262af
FB
6476 dc->code32 = (flags >> HF_CS32_SHIFT) & 1;
6477 dc->ss32 = (flags >> HF_SS32_SHIFT) & 1;
6478 dc->addseg = (flags >> HF_ADDSEG_SHIFT) & 1;
6479 dc->f_st = 0;
6480 dc->vm86 = (flags >> VM_SHIFT) & 1;
6481 dc->cpl = (flags >> HF_CPL_SHIFT) & 3;
6482 dc->iopl = (flags >> IOPL_SHIFT) & 3;
6483 dc->tf = (flags >> TF_SHIFT) & 1;
34865134 6484 dc->singlestep_enabled = env->singlestep_enabled;
2c0262af
FB
6485 dc->cc_op = CC_OP_DYNAMIC;
6486 dc->cs_base = cs_base;
6487 dc->tb = tb;
6488 dc->popl_esp_hack = 0;
6489 /* select memory access functions */
6490 dc->mem_index = 0;
6491 if (flags & HF_SOFTMMU_MASK) {
6492 if (dc->cpl == 3)
14ce26e7 6493 dc->mem_index = 2 * 4;
2c0262af 6494 else
14ce26e7 6495 dc->mem_index = 1 * 4;
2c0262af 6496 }
14ce26e7 6497 dc->cpuid_features = env->cpuid_features;
3d7374c5 6498 dc->cpuid_ext_features = env->cpuid_ext_features;
14ce26e7
FB
6499#ifdef TARGET_X86_64
6500 dc->lma = (flags >> HF_LMA_SHIFT) & 1;
6501 dc->code64 = (flags >> HF_CS64_SHIFT) & 1;
6502#endif
7eee2a50 6503 dc->flags = flags;
a2cc3b24
FB
6504 dc->jmp_opt = !(dc->tf || env->singlestep_enabled ||
6505 (flags & HF_INHIBIT_IRQ_MASK)
415fa2ea 6506#ifndef CONFIG_SOFTMMU
2c0262af
FB
6507 || (flags & HF_SOFTMMU_MASK)
6508#endif
6509 );
4f31916f
FB
6510#if 0
6511 /* check addseg logic */
dc196a57 6512 if (!dc->addseg && (dc->vm86 || !dc->pe || !dc->code32))
4f31916f
FB
6513 printf("ERROR addseg\n");
6514#endif
6515
2c0262af
FB
6516 gen_opc_ptr = gen_opc_buf;
6517 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
6518 gen_opparam_ptr = gen_opparam_buf;
14ce26e7 6519 nb_gen_labels = 0;
2c0262af
FB
6520
6521 dc->is_jmp = DISAS_NEXT;
6522 pc_ptr = pc_start;
6523 lj = -1;
6524
2c0262af
FB
6525 for(;;) {
6526 if (env->nb_breakpoints > 0) {
6527 for(j = 0; j < env->nb_breakpoints; j++) {
14ce26e7 6528 if (env->breakpoints[j] == pc_ptr) {
2c0262af
FB
6529 gen_debug(dc, pc_ptr - dc->cs_base);
6530 break;
6531 }
6532 }
6533 }
6534 if (search_pc) {
6535 j = gen_opc_ptr - gen_opc_buf;
6536 if (lj < j) {
6537 lj++;
6538 while (lj < j)
6539 gen_opc_instr_start[lj++] = 0;
6540 }
14ce26e7 6541 gen_opc_pc[lj] = pc_ptr;
2c0262af
FB
6542 gen_opc_cc_op[lj] = dc->cc_op;
6543 gen_opc_instr_start[lj] = 1;
6544 }
6545 pc_ptr = disas_insn(dc, pc_ptr);
6546 /* stop translation if indicated */
6547 if (dc->is_jmp)
6548 break;
6549 /* if single step mode, we generate only one instruction and
6550 generate an exception */
a2cc3b24
FB
6551 /* if irq were inhibited with HF_INHIBIT_IRQ_MASK, we clear
6552 the flag and abort the translation to give the irqs a
6553 change to be happen */
5fafdf24 6554 if (dc->tf || dc->singlestep_enabled ||
d720b93d
FB
6555 (flags & HF_INHIBIT_IRQ_MASK) ||
6556 (cflags & CF_SINGLE_INSN)) {
14ce26e7 6557 gen_jmp_im(pc_ptr - dc->cs_base);
2c0262af
FB
6558 gen_eob(dc);
6559 break;
6560 }
6561 /* if too long translation, stop generation too */
6562 if (gen_opc_ptr >= gen_opc_end ||
6563 (pc_ptr - pc_start) >= (TARGET_PAGE_SIZE - 32)) {
14ce26e7 6564 gen_jmp_im(pc_ptr - dc->cs_base);
2c0262af
FB
6565 gen_eob(dc);
6566 break;
6567 }
6568 }
6569 *gen_opc_ptr = INDEX_op_end;
6570 /* we don't forget to fill the last values */
6571 if (search_pc) {
6572 j = gen_opc_ptr - gen_opc_buf;
6573 lj++;
6574 while (lj <= j)
6575 gen_opc_instr_start[lj++] = 0;
6576 }
3b46e624 6577
2c0262af 6578#ifdef DEBUG_DISAS
658c8bda 6579 if (loglevel & CPU_LOG_TB_CPU) {
7fe48483 6580 cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
658c8bda 6581 }
e19e89a5 6582 if (loglevel & CPU_LOG_TB_IN_ASM) {
14ce26e7 6583 int disas_flags;
2c0262af
FB
6584 fprintf(logfile, "----------------\n");
6585 fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
14ce26e7
FB
6586#ifdef TARGET_X86_64
6587 if (dc->code64)
6588 disas_flags = 2;
6589 else
6590#endif
6591 disas_flags = !dc->code32;
6592 target_disas(logfile, pc_start, pc_ptr - pc_start, disas_flags);
2c0262af 6593 fprintf(logfile, "\n");
e19e89a5
FB
6594 if (loglevel & CPU_LOG_TB_OP) {
6595 fprintf(logfile, "OP:\n");
6596 dump_ops(gen_opc_buf, gen_opparam_buf);
6597 fprintf(logfile, "\n");
6598 }
2c0262af
FB
6599 }
6600#endif
6601
6602 /* optimize flag computations */
6603 optimize_flags(gen_opc_buf, gen_opc_ptr - gen_opc_buf);
6604
6605#ifdef DEBUG_DISAS
e19e89a5 6606 if (loglevel & CPU_LOG_TB_OP_OPT) {
2c0262af
FB
6607 fprintf(logfile, "AFTER FLAGS OPT:\n");
6608 dump_ops(gen_opc_buf, gen_opparam_buf);
6609 fprintf(logfile, "\n");
6610 }
6611#endif
6612 if (!search_pc)
6613 tb->size = pc_ptr - pc_start;
6614 return 0;
6615}
6616
6617int gen_intermediate_code(CPUState *env, TranslationBlock *tb)
6618{
6619 return gen_intermediate_code_internal(env, tb, 0);
6620}
6621
6622int gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
6623{
6624 return gen_intermediate_code_internal(env, tb, 1);
6625}
6626