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