]> git.proxmox.com Git - mirror_qemu.git/blame - target-i386/translate.c
big endian SSE fix
[mirror_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
1609/* generate modrm memory load or store of 'reg'. TMP0 is used if reg !=
1610 OR_TMP0 */
1611static void gen_ldst_modrm(DisasContext *s, int modrm, int ot, int reg, int is_store)
1612{
1613 int mod, rm, opreg, disp;
1614
1615 mod = (modrm >> 6) & 3;
14ce26e7 1616 rm = (modrm & 7) | REX_B(s);
2c0262af
FB
1617 if (mod == 3) {
1618 if (is_store) {
1619 if (reg != OR_TMP0)
1620 gen_op_mov_TN_reg[ot][0][reg]();
1621 gen_op_mov_reg_T0[ot][rm]();
1622 } else {
1623 gen_op_mov_TN_reg[ot][0][rm]();
1624 if (reg != OR_TMP0)
1625 gen_op_mov_reg_T0[ot][reg]();
1626 }
1627 } else {
1628 gen_lea_modrm(s, modrm, &opreg, &disp);
1629 if (is_store) {
1630 if (reg != OR_TMP0)
1631 gen_op_mov_TN_reg[ot][0][reg]();
1632 gen_op_st_T0_A0[ot + s->mem_index]();
1633 } else {
1634 gen_op_ld_T0_A0[ot + s->mem_index]();
1635 if (reg != OR_TMP0)
1636 gen_op_mov_reg_T0[ot][reg]();
1637 }
1638 }
1639}
1640
1641static inline uint32_t insn_get(DisasContext *s, int ot)
1642{
1643 uint32_t ret;
1644
1645 switch(ot) {
1646 case OT_BYTE:
61382a50 1647 ret = ldub_code(s->pc);
2c0262af
FB
1648 s->pc++;
1649 break;
1650 case OT_WORD:
61382a50 1651 ret = lduw_code(s->pc);
2c0262af
FB
1652 s->pc += 2;
1653 break;
1654 default:
1655 case OT_LONG:
61382a50 1656 ret = ldl_code(s->pc);
2c0262af
FB
1657 s->pc += 4;
1658 break;
1659 }
1660 return ret;
1661}
1662
14ce26e7
FB
1663static inline int insn_const_size(unsigned int ot)
1664{
1665 if (ot <= OT_LONG)
1666 return 1 << ot;
1667 else
1668 return 4;
1669}
1670
1671static inline void gen_jcc(DisasContext *s, int b,
1672 target_ulong val, target_ulong next_eip)
2c0262af
FB
1673{
1674 TranslationBlock *tb;
1675 int inv, jcc_op;
14ce26e7
FB
1676 GenOpFunc1 *func;
1677 target_ulong tmp;
1678 int l1, l2;
2c0262af
FB
1679
1680 inv = b & 1;
1681 jcc_op = (b >> 1) & 7;
1682
1683 if (s->jmp_opt) {
1684 switch(s->cc_op) {
1685 /* we optimize the cmp/jcc case */
1686 case CC_OP_SUBB:
1687 case CC_OP_SUBW:
1688 case CC_OP_SUBL:
14ce26e7 1689 case CC_OP_SUBQ:
2c0262af
FB
1690 func = gen_jcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
1691 break;
1692
1693 /* some jumps are easy to compute */
1694 case CC_OP_ADDB:
1695 case CC_OP_ADDW:
1696 case CC_OP_ADDL:
14ce26e7
FB
1697 case CC_OP_ADDQ:
1698
2c0262af
FB
1699 case CC_OP_ADCB:
1700 case CC_OP_ADCW:
1701 case CC_OP_ADCL:
14ce26e7
FB
1702 case CC_OP_ADCQ:
1703
2c0262af
FB
1704 case CC_OP_SBBB:
1705 case CC_OP_SBBW:
1706 case CC_OP_SBBL:
14ce26e7
FB
1707 case CC_OP_SBBQ:
1708
2c0262af
FB
1709 case CC_OP_LOGICB:
1710 case CC_OP_LOGICW:
1711 case CC_OP_LOGICL:
14ce26e7
FB
1712 case CC_OP_LOGICQ:
1713
2c0262af
FB
1714 case CC_OP_INCB:
1715 case CC_OP_INCW:
1716 case CC_OP_INCL:
14ce26e7
FB
1717 case CC_OP_INCQ:
1718
2c0262af
FB
1719 case CC_OP_DECB:
1720 case CC_OP_DECW:
1721 case CC_OP_DECL:
14ce26e7
FB
1722 case CC_OP_DECQ:
1723
2c0262af
FB
1724 case CC_OP_SHLB:
1725 case CC_OP_SHLW:
1726 case CC_OP_SHLL:
14ce26e7
FB
1727 case CC_OP_SHLQ:
1728
2c0262af
FB
1729 case CC_OP_SARB:
1730 case CC_OP_SARW:
1731 case CC_OP_SARL:
14ce26e7 1732 case CC_OP_SARQ:
2c0262af
FB
1733 switch(jcc_op) {
1734 case JCC_Z:
14ce26e7 1735 func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 4][jcc_op];
2c0262af
FB
1736 break;
1737 case JCC_S:
14ce26e7 1738 func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 4][jcc_op];
2c0262af
FB
1739 break;
1740 default:
1741 func = NULL;
1742 break;
1743 }
1744 break;
1745 default:
1746 func = NULL;
1747 break;
1748 }
1749
1750 if (s->cc_op != CC_OP_DYNAMIC)
1751 gen_op_set_cc_op(s->cc_op);
1752
1753 if (!func) {
1754 gen_setcc_slow[jcc_op]();
14ce26e7 1755 func = gen_op_jnz_T0_label;
2c0262af
FB
1756 }
1757
14ce26e7
FB
1758 if (inv) {
1759 tmp = val;
1760 val = next_eip;
1761 next_eip = tmp;
2c0262af 1762 }
14ce26e7
FB
1763 tb = s->tb;
1764
1765 l1 = gen_new_label();
1766 func(l1);
1767
1768 gen_op_goto_tb0();
1769 gen_jmp_im(next_eip);
1770 gen_op_movl_T0_im((long)tb + 0);
1771 gen_op_exit_tb();
1772
1773 gen_set_label(l1);
1774 gen_op_goto_tb1();
1775 gen_jmp_im(val);
1776 gen_op_movl_T0_im((long)tb + 1);
1777 gen_op_exit_tb();
1778
2c0262af
FB
1779 s->is_jmp = 3;
1780 } else {
14ce26e7 1781
2c0262af
FB
1782 if (s->cc_op != CC_OP_DYNAMIC) {
1783 gen_op_set_cc_op(s->cc_op);
1784 s->cc_op = CC_OP_DYNAMIC;
1785 }
1786 gen_setcc_slow[jcc_op]();
14ce26e7
FB
1787 if (inv) {
1788 tmp = val;
1789 val = next_eip;
1790 next_eip = tmp;
2c0262af 1791 }
14ce26e7
FB
1792 l1 = gen_new_label();
1793 l2 = gen_new_label();
1794 gen_op_jnz_T0_label(l1);
1795 gen_jmp_im(next_eip);
1796 gen_op_jmp_label(l2);
1797 gen_set_label(l1);
1798 gen_jmp_im(val);
1799 gen_set_label(l2);
2c0262af
FB
1800 gen_eob(s);
1801 }
1802}
1803
1804static void gen_setcc(DisasContext *s, int b)
1805{
1806 int inv, jcc_op;
1807 GenOpFunc *func;
1808
1809 inv = b & 1;
1810 jcc_op = (b >> 1) & 7;
1811 switch(s->cc_op) {
1812 /* we optimize the cmp/jcc case */
1813 case CC_OP_SUBB:
1814 case CC_OP_SUBW:
1815 case CC_OP_SUBL:
14ce26e7 1816 case CC_OP_SUBQ:
2c0262af
FB
1817 func = gen_setcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
1818 if (!func)
1819 goto slow_jcc;
1820 break;
1821
1822 /* some jumps are easy to compute */
1823 case CC_OP_ADDB:
1824 case CC_OP_ADDW:
1825 case CC_OP_ADDL:
14ce26e7
FB
1826 case CC_OP_ADDQ:
1827
2c0262af
FB
1828 case CC_OP_LOGICB:
1829 case CC_OP_LOGICW:
1830 case CC_OP_LOGICL:
14ce26e7
FB
1831 case CC_OP_LOGICQ:
1832
2c0262af
FB
1833 case CC_OP_INCB:
1834 case CC_OP_INCW:
1835 case CC_OP_INCL:
14ce26e7
FB
1836 case CC_OP_INCQ:
1837
2c0262af
FB
1838 case CC_OP_DECB:
1839 case CC_OP_DECW:
1840 case CC_OP_DECL:
14ce26e7
FB
1841 case CC_OP_DECQ:
1842
2c0262af
FB
1843 case CC_OP_SHLB:
1844 case CC_OP_SHLW:
1845 case CC_OP_SHLL:
14ce26e7 1846 case CC_OP_SHLQ:
2c0262af
FB
1847 switch(jcc_op) {
1848 case JCC_Z:
14ce26e7 1849 func = gen_setcc_sub[(s->cc_op - CC_OP_ADDB) % 4][jcc_op];
2c0262af
FB
1850 break;
1851 case JCC_S:
14ce26e7 1852 func = gen_setcc_sub[(s->cc_op - CC_OP_ADDB) % 4][jcc_op];
2c0262af
FB
1853 break;
1854 default:
1855 goto slow_jcc;
1856 }
1857 break;
1858 default:
1859 slow_jcc:
1860 if (s->cc_op != CC_OP_DYNAMIC)
1861 gen_op_set_cc_op(s->cc_op);
1862 func = gen_setcc_slow[jcc_op];
1863 break;
1864 }
1865 func();
1866 if (inv) {
1867 gen_op_xor_T0_1();
1868 }
1869}
1870
1871/* move T0 to seg_reg and compute if the CPU state may change. Never
1872 call this function with seg_reg == R_CS */
14ce26e7 1873static void gen_movl_seg_T0(DisasContext *s, int seg_reg, target_ulong cur_eip)
2c0262af 1874{
3415a4dd
FB
1875 if (s->pe && !s->vm86) {
1876 /* XXX: optimize by finding processor state dynamically */
1877 if (s->cc_op != CC_OP_DYNAMIC)
1878 gen_op_set_cc_op(s->cc_op);
14ce26e7 1879 gen_jmp_im(cur_eip);
3415a4dd 1880 gen_op_movl_seg_T0(seg_reg);
dc196a57
FB
1881 /* abort translation because the addseg value may change or
1882 because ss32 may change. For R_SS, translation must always
1883 stop as a special handling must be done to disable hardware
1884 interrupts for the next instruction */
1885 if (seg_reg == R_SS || (s->code32 && seg_reg < R_FS))
1886 s->is_jmp = 3;
3415a4dd 1887 } else {
2c0262af 1888 gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[seg_reg]));
dc196a57
FB
1889 if (seg_reg == R_SS)
1890 s->is_jmp = 3;
3415a4dd 1891 }
2c0262af
FB
1892}
1893
4f31916f
FB
1894static inline void gen_stack_update(DisasContext *s, int addend)
1895{
14ce26e7
FB
1896#ifdef TARGET_X86_64
1897 if (CODE64(s)) {
1898 if (addend == 8)
1899 gen_op_addq_ESP_8();
1900 else
1901 gen_op_addq_ESP_im(addend);
1902 } else
1903#endif
4f31916f
FB
1904 if (s->ss32) {
1905 if (addend == 2)
1906 gen_op_addl_ESP_2();
1907 else if (addend == 4)
1908 gen_op_addl_ESP_4();
1909 else
1910 gen_op_addl_ESP_im(addend);
1911 } else {
1912 if (addend == 2)
1913 gen_op_addw_ESP_2();
1914 else if (addend == 4)
1915 gen_op_addw_ESP_4();
1916 else
1917 gen_op_addw_ESP_im(addend);
1918 }
1919}
1920
2c0262af
FB
1921/* generate a push. It depends on ss32, addseg and dflag */
1922static void gen_push_T0(DisasContext *s)
1923{
14ce26e7
FB
1924#ifdef TARGET_X86_64
1925 if (CODE64(s)) {
1926 /* XXX: check 16 bit behaviour */
1927 gen_op_movq_A0_reg[R_ESP]();
1928 gen_op_subq_A0_8();
1929 gen_op_st_T0_A0[OT_QUAD + s->mem_index]();
1930 gen_op_movq_ESP_A0();
1931 } else
1932#endif
1933 {
1934 gen_op_movl_A0_reg[R_ESP]();
1935 if (!s->dflag)
1936 gen_op_subl_A0_2();
1937 else
1938 gen_op_subl_A0_4();
1939 if (s->ss32) {
1940 if (s->addseg) {
1941 gen_op_movl_T1_A0();
1942 gen_op_addl_A0_SS();
1943 }
1944 } else {
1945 gen_op_andl_A0_ffff();
4f31916f
FB
1946 gen_op_movl_T1_A0();
1947 gen_op_addl_A0_SS();
2c0262af 1948 }
14ce26e7
FB
1949 gen_op_st_T0_A0[s->dflag + 1 + s->mem_index]();
1950 if (s->ss32 && !s->addseg)
1951 gen_op_movl_ESP_A0();
1952 else
1953 gen_op_mov_reg_T1[s->ss32 + 1][R_ESP]();
2c0262af
FB
1954 }
1955}
1956
4f31916f
FB
1957/* generate a push. It depends on ss32, addseg and dflag */
1958/* slower version for T1, only used for call Ev */
1959static void gen_push_T1(DisasContext *s)
2c0262af 1960{
14ce26e7
FB
1961#ifdef TARGET_X86_64
1962 if (CODE64(s)) {
1963 /* XXX: check 16 bit behaviour */
1964 gen_op_movq_A0_reg[R_ESP]();
1965 gen_op_subq_A0_8();
1966 gen_op_st_T1_A0[OT_QUAD + s->mem_index]();
1967 gen_op_movq_ESP_A0();
1968 } else
1969#endif
1970 {
1971 gen_op_movl_A0_reg[R_ESP]();
1972 if (!s->dflag)
1973 gen_op_subl_A0_2();
1974 else
1975 gen_op_subl_A0_4();
1976 if (s->ss32) {
1977 if (s->addseg) {
1978 gen_op_addl_A0_SS();
1979 }
1980 } else {
1981 gen_op_andl_A0_ffff();
4f31916f 1982 gen_op_addl_A0_SS();
2c0262af 1983 }
14ce26e7
FB
1984 gen_op_st_T1_A0[s->dflag + 1 + s->mem_index]();
1985
1986 if (s->ss32 && !s->addseg)
1987 gen_op_movl_ESP_A0();
1988 else
1989 gen_stack_update(s, (-2) << s->dflag);
2c0262af
FB
1990 }
1991}
1992
4f31916f
FB
1993/* two step pop is necessary for precise exceptions */
1994static void gen_pop_T0(DisasContext *s)
2c0262af 1995{
14ce26e7
FB
1996#ifdef TARGET_X86_64
1997 if (CODE64(s)) {
1998 /* XXX: check 16 bit behaviour */
1999 gen_op_movq_A0_reg[R_ESP]();
2000 gen_op_ld_T0_A0[OT_QUAD + s->mem_index]();
2001 } else
2002#endif
2003 {
2004 gen_op_movl_A0_reg[R_ESP]();
2005 if (s->ss32) {
2006 if (s->addseg)
2007 gen_op_addl_A0_SS();
2008 } else {
2009 gen_op_andl_A0_ffff();
4f31916f 2010 gen_op_addl_A0_SS();
14ce26e7
FB
2011 }
2012 gen_op_ld_T0_A0[s->dflag + 1 + s->mem_index]();
2c0262af
FB
2013 }
2014}
2015
2016static void gen_pop_update(DisasContext *s)
2017{
14ce26e7
FB
2018#ifdef TARGET_X86_64
2019 if (CODE64(s)) {
2020 gen_stack_update(s, 8);
2021 } else
2022#endif
2023 {
2024 gen_stack_update(s, 2 << s->dflag);
2025 }
2c0262af
FB
2026}
2027
2028static void gen_stack_A0(DisasContext *s)
2029{
2030 gen_op_movl_A0_ESP();
2031 if (!s->ss32)
2032 gen_op_andl_A0_ffff();
2033 gen_op_movl_T1_A0();
2034 if (s->addseg)
2035 gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
2036}
2037
2038/* NOTE: wrap around in 16 bit not fully handled */
2039static void gen_pusha(DisasContext *s)
2040{
2041 int i;
2042 gen_op_movl_A0_ESP();
2043 gen_op_addl_A0_im(-16 << s->dflag);
2044 if (!s->ss32)
2045 gen_op_andl_A0_ffff();
2046 gen_op_movl_T1_A0();
2047 if (s->addseg)
2048 gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
2049 for(i = 0;i < 8; i++) {
2050 gen_op_mov_TN_reg[OT_LONG][0][7 - i]();
2051 gen_op_st_T0_A0[OT_WORD + s->dflag + s->mem_index]();
2052 gen_op_addl_A0_im(2 << s->dflag);
2053 }
2054 gen_op_mov_reg_T1[OT_WORD + s->dflag][R_ESP]();
2055}
2056
2057/* NOTE: wrap around in 16 bit not fully handled */
2058static void gen_popa(DisasContext *s)
2059{
2060 int i;
2061 gen_op_movl_A0_ESP();
2062 if (!s->ss32)
2063 gen_op_andl_A0_ffff();
2064 gen_op_movl_T1_A0();
2065 gen_op_addl_T1_im(16 << s->dflag);
2066 if (s->addseg)
2067 gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
2068 for(i = 0;i < 8; i++) {
2069 /* ESP is not reloaded */
2070 if (i != 3) {
2071 gen_op_ld_T0_A0[OT_WORD + s->dflag + s->mem_index]();
2072 gen_op_mov_reg_T0[OT_WORD + s->dflag][7 - i]();
2073 }
2074 gen_op_addl_A0_im(2 << s->dflag);
2075 }
2076 gen_op_mov_reg_T1[OT_WORD + s->dflag][R_ESP]();
2077}
2078
2c0262af
FB
2079static void gen_enter(DisasContext *s, int esp_addend, int level)
2080{
61a8c4ec 2081 int ot, opsize;
2c0262af
FB
2082
2083 ot = s->dflag + OT_WORD;
2084 level &= 0x1f;
2c0262af
FB
2085 opsize = 2 << s->dflag;
2086
2087 gen_op_movl_A0_ESP();
2088 gen_op_addl_A0_im(-opsize);
2089 if (!s->ss32)
2090 gen_op_andl_A0_ffff();
2091 gen_op_movl_T1_A0();
2092 if (s->addseg)
2093 gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
2094 /* push bp */
2095 gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
2096 gen_op_st_T0_A0[ot + s->mem_index]();
2097 if (level) {
61a8c4ec 2098 gen_op_enter_level(level, s->dflag);
2c0262af
FB
2099 }
2100 gen_op_mov_reg_T1[ot][R_EBP]();
61a8c4ec 2101 gen_op_addl_T1_im( -esp_addend + (-opsize * level) );
2c0262af
FB
2102 gen_op_mov_reg_T1[ot][R_ESP]();
2103}
2104
14ce26e7 2105static void gen_exception(DisasContext *s, int trapno, target_ulong cur_eip)
2c0262af
FB
2106{
2107 if (s->cc_op != CC_OP_DYNAMIC)
2108 gen_op_set_cc_op(s->cc_op);
14ce26e7 2109 gen_jmp_im(cur_eip);
2c0262af
FB
2110 gen_op_raise_exception(trapno);
2111 s->is_jmp = 3;
2112}
2113
2114/* an interrupt is different from an exception because of the
2115 priviledge checks */
2116static void gen_interrupt(DisasContext *s, int intno,
14ce26e7 2117 target_ulong cur_eip, target_ulong next_eip)
2c0262af
FB
2118{
2119 if (s->cc_op != CC_OP_DYNAMIC)
2120 gen_op_set_cc_op(s->cc_op);
14ce26e7 2121 gen_jmp_im(cur_eip);
2c0262af
FB
2122 gen_op_raise_interrupt(intno, next_eip);
2123 s->is_jmp = 3;
2124}
2125
14ce26e7 2126static void gen_debug(DisasContext *s, target_ulong cur_eip)
2c0262af
FB
2127{
2128 if (s->cc_op != CC_OP_DYNAMIC)
2129 gen_op_set_cc_op(s->cc_op);
14ce26e7 2130 gen_jmp_im(cur_eip);
2c0262af
FB
2131 gen_op_debug();
2132 s->is_jmp = 3;
2133}
2134
2135/* generate a generic end of block. Trace exception is also generated
2136 if needed */
2137static void gen_eob(DisasContext *s)
2138{
2139 if (s->cc_op != CC_OP_DYNAMIC)
2140 gen_op_set_cc_op(s->cc_op);
a2cc3b24
FB
2141 if (s->tb->flags & HF_INHIBIT_IRQ_MASK) {
2142 gen_op_reset_inhibit_irq();
2143 }
34865134
FB
2144 if (s->singlestep_enabled) {
2145 gen_op_debug();
2146 } else if (s->tf) {
2c0262af
FB
2147 gen_op_raise_exception(EXCP01_SSTP);
2148 } else {
2149 gen_op_movl_T0_0();
2150 gen_op_exit_tb();
2151 }
2152 s->is_jmp = 3;
2153}
2154
2155/* generate a jump to eip. No segment change must happen before as a
2156 direct call to the next block may occur */
14ce26e7 2157static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num)
2c0262af
FB
2158{
2159 TranslationBlock *tb = s->tb;
2160
2161 if (s->jmp_opt) {
2162 if (s->cc_op != CC_OP_DYNAMIC)
2163 gen_op_set_cc_op(s->cc_op);
14ce26e7
FB
2164 if (tb_num)
2165 gen_op_goto_tb1();
2166 else
2167 gen_op_goto_tb0();
2168 gen_jmp_im(eip);
2169 gen_op_movl_T0_im((long)tb + tb_num);
2170 gen_op_exit_tb();
2c0262af
FB
2171 s->is_jmp = 3;
2172 } else {
14ce26e7 2173 gen_jmp_im(eip);
2c0262af
FB
2174 gen_eob(s);
2175 }
2176}
2177
14ce26e7
FB
2178static void gen_jmp(DisasContext *s, target_ulong eip)
2179{
2180 gen_jmp_tb(s, eip, 0);
2181}
2182
2183static void gen_movtl_T0_im(target_ulong val)
2184{
2185#ifdef TARGET_X86_64
2186 if ((int32_t)val == val) {
2187 gen_op_movl_T0_im(val);
2188 } else {
2189 gen_op_movq_T0_im64(val >> 32, val);
2190 }
2191#else
2192 gen_op_movl_T0_im(val);
2193#endif
2194}
2195
2196static GenOpFunc1 *gen_ldo_env_A0[3] = {
2197 gen_op_ldo_raw_env_A0,
2198#ifndef CONFIG_USER_ONLY
2199 gen_op_ldo_kernel_env_A0,
2200 gen_op_ldo_user_env_A0,
2201#endif
2202};
2203
2204static GenOpFunc1 *gen_sto_env_A0[3] = {
2205 gen_op_sto_raw_env_A0,
2206#ifndef CONFIG_USER_ONLY
2207 gen_op_sto_kernel_env_A0,
2208 gen_op_sto_user_env_A0,
2209#endif
2210};
2211
2c0262af
FB
2212/* convert one instruction. s->is_jmp is set if the translation must
2213 be stopped. Return the next pc value */
14ce26e7 2214static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
2c0262af
FB
2215{
2216 int b, prefixes, aflag, dflag;
2217 int shift, ot;
2218 int modrm, reg, rm, mod, reg_addr, op, opreg, offset_addr, val;
14ce26e7
FB
2219 target_ulong next_eip, tval;
2220 int rex_w, rex_r;
2c0262af
FB
2221
2222 s->pc = pc_start;
2223 prefixes = 0;
2224 aflag = s->code32;
2225 dflag = s->code32;
2226 s->override = -1;
14ce26e7
FB
2227 rex_w = -1;
2228 rex_r = 0;
2229#ifdef TARGET_X86_64
2230 s->rex_x = 0;
2231 s->rex_b = 0;
2232 x86_64_hregs = 0;
2233#endif
2234 s->rip_offset = 0; /* for relative ip address */
2c0262af 2235 next_byte:
61382a50 2236 b = ldub_code(s->pc);
2c0262af
FB
2237 s->pc++;
2238 /* check prefixes */
14ce26e7
FB
2239#ifdef TARGET_X86_64
2240 if (CODE64(s)) {
2241 switch (b) {
2242 case 0xf3:
2243 prefixes |= PREFIX_REPZ;
2244 goto next_byte;
2245 case 0xf2:
2246 prefixes |= PREFIX_REPNZ;
2247 goto next_byte;
2248 case 0xf0:
2249 prefixes |= PREFIX_LOCK;
2250 goto next_byte;
2251 case 0x2e:
2252 s->override = R_CS;
2253 goto next_byte;
2254 case 0x36:
2255 s->override = R_SS;
2256 goto next_byte;
2257 case 0x3e:
2258 s->override = R_DS;
2259 goto next_byte;
2260 case 0x26:
2261 s->override = R_ES;
2262 goto next_byte;
2263 case 0x64:
2264 s->override = R_FS;
2265 goto next_byte;
2266 case 0x65:
2267 s->override = R_GS;
2268 goto next_byte;
2269 case 0x66:
2270 prefixes |= PREFIX_DATA;
2271 goto next_byte;
2272 case 0x67:
2273 prefixes |= PREFIX_ADR;
2274 goto next_byte;
2275 case 0x40 ... 0x4f:
2276 /* REX prefix */
2277 rex_w = (b >> 3) & 1;
2278 rex_r = (b & 0x4) << 1;
2279 s->rex_x = (b & 0x2) << 2;
2280 REX_B(s) = (b & 0x1) << 3;
2281 x86_64_hregs = 1; /* select uniform byte register addressing */
2282 goto next_byte;
2283 }
2284 if (rex_w == 1) {
2285 /* 0x66 is ignored if rex.w is set */
2286 dflag = 2;
2287 } else {
2288 if (prefixes & PREFIX_DATA)
2289 dflag ^= 1;
2290 }
2291 if (!(prefixes & PREFIX_ADR))
2292 aflag = 2;
2293 } else
2294#endif
2295 {
2296 switch (b) {
2297 case 0xf3:
2298 prefixes |= PREFIX_REPZ;
2299 goto next_byte;
2300 case 0xf2:
2301 prefixes |= PREFIX_REPNZ;
2302 goto next_byte;
2303 case 0xf0:
2304 prefixes |= PREFIX_LOCK;
2305 goto next_byte;
2306 case 0x2e:
2307 s->override = R_CS;
2308 goto next_byte;
2309 case 0x36:
2310 s->override = R_SS;
2311 goto next_byte;
2312 case 0x3e:
2313 s->override = R_DS;
2314 goto next_byte;
2315 case 0x26:
2316 s->override = R_ES;
2317 goto next_byte;
2318 case 0x64:
2319 s->override = R_FS;
2320 goto next_byte;
2321 case 0x65:
2322 s->override = R_GS;
2323 goto next_byte;
2324 case 0x66:
2325 prefixes |= PREFIX_DATA;
2326 goto next_byte;
2327 case 0x67:
2328 prefixes |= PREFIX_ADR;
2329 goto next_byte;
2330 }
2331 if (prefixes & PREFIX_DATA)
2332 dflag ^= 1;
2333 if (prefixes & PREFIX_ADR)
2334 aflag ^= 1;
2c0262af
FB
2335 }
2336
2c0262af
FB
2337 s->prefix = prefixes;
2338 s->aflag = aflag;
2339 s->dflag = dflag;
2340
2341 /* lock generation */
2342 if (prefixes & PREFIX_LOCK)
2343 gen_op_lock();
2344
2345 /* now check op code */
2346 reswitch:
2347 switch(b) {
2348 case 0x0f:
2349 /**************************/
2350 /* extended op code */
61382a50 2351 b = ldub_code(s->pc++) | 0x100;
2c0262af
FB
2352 goto reswitch;
2353
2354 /**************************/
2355 /* arith & logic */
2356 case 0x00 ... 0x05:
2357 case 0x08 ... 0x0d:
2358 case 0x10 ... 0x15:
2359 case 0x18 ... 0x1d:
2360 case 0x20 ... 0x25:
2361 case 0x28 ... 0x2d:
2362 case 0x30 ... 0x35:
2363 case 0x38 ... 0x3d:
2364 {
2365 int op, f, val;
2366 op = (b >> 3) & 7;
2367 f = (b >> 1) & 3;
2368
2369 if ((b & 1) == 0)
2370 ot = OT_BYTE;
2371 else
14ce26e7 2372 ot = dflag + OT_WORD;
2c0262af
FB
2373
2374 switch(f) {
2375 case 0: /* OP Ev, Gv */
61382a50 2376 modrm = ldub_code(s->pc++);
14ce26e7 2377 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af 2378 mod = (modrm >> 6) & 3;
14ce26e7 2379 rm = (modrm & 7) | REX_B(s);
2c0262af
FB
2380 if (mod != 3) {
2381 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2382 opreg = OR_TMP0;
2383 } else if (op == OP_XORL && rm == reg) {
2384 xor_zero:
2385 /* xor reg, reg optimisation */
2386 gen_op_movl_T0_0();
2387 s->cc_op = CC_OP_LOGICB + ot;
2388 gen_op_mov_reg_T0[ot][reg]();
2389 gen_op_update1_cc();
2390 break;
2391 } else {
2392 opreg = rm;
2393 }
2394 gen_op_mov_TN_reg[ot][1][reg]();
2395 gen_op(s, op, ot, opreg);
2396 break;
2397 case 1: /* OP Gv, Ev */
61382a50 2398 modrm = ldub_code(s->pc++);
2c0262af 2399 mod = (modrm >> 6) & 3;
14ce26e7
FB
2400 reg = ((modrm >> 3) & 7) | rex_r;
2401 rm = (modrm & 7) | REX_B(s);
2c0262af
FB
2402 if (mod != 3) {
2403 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2404 gen_op_ld_T1_A0[ot + s->mem_index]();
2405 } else if (op == OP_XORL && rm == reg) {
2406 goto xor_zero;
2407 } else {
2408 gen_op_mov_TN_reg[ot][1][rm]();
2409 }
2410 gen_op(s, op, ot, reg);
2411 break;
2412 case 2: /* OP A, Iv */
2413 val = insn_get(s, ot);
2414 gen_op_movl_T1_im(val);
2415 gen_op(s, op, ot, OR_EAX);
2416 break;
2417 }
2418 }
2419 break;
2420
2421 case 0x80: /* GRP1 */
2422 case 0x81:
d64477af 2423 case 0x82:
2c0262af
FB
2424 case 0x83:
2425 {
2426 int val;
2427
2428 if ((b & 1) == 0)
2429 ot = OT_BYTE;
2430 else
14ce26e7 2431 ot = dflag + OT_WORD;
2c0262af 2432
61382a50 2433 modrm = ldub_code(s->pc++);
2c0262af 2434 mod = (modrm >> 6) & 3;
14ce26e7 2435 rm = (modrm & 7) | REX_B(s);
2c0262af
FB
2436 op = (modrm >> 3) & 7;
2437
2438 if (mod != 3) {
14ce26e7
FB
2439 if (b == 0x83)
2440 s->rip_offset = 1;
2441 else
2442 s->rip_offset = insn_const_size(ot);
2c0262af
FB
2443 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2444 opreg = OR_TMP0;
2445 } else {
14ce26e7 2446 opreg = rm;
2c0262af
FB
2447 }
2448
2449 switch(b) {
2450 default:
2451 case 0x80:
2452 case 0x81:
d64477af 2453 case 0x82:
2c0262af
FB
2454 val = insn_get(s, ot);
2455 break;
2456 case 0x83:
2457 val = (int8_t)insn_get(s, OT_BYTE);
2458 break;
2459 }
2460 gen_op_movl_T1_im(val);
2461 gen_op(s, op, ot, opreg);
2462 }
2463 break;
2464
2465 /**************************/
2466 /* inc, dec, and other misc arith */
2467 case 0x40 ... 0x47: /* inc Gv */
2468 ot = dflag ? OT_LONG : OT_WORD;
2469 gen_inc(s, ot, OR_EAX + (b & 7), 1);
2470 break;
2471 case 0x48 ... 0x4f: /* dec Gv */
2472 ot = dflag ? OT_LONG : OT_WORD;
2473 gen_inc(s, ot, OR_EAX + (b & 7), -1);
2474 break;
2475 case 0xf6: /* GRP3 */
2476 case 0xf7:
2477 if ((b & 1) == 0)
2478 ot = OT_BYTE;
2479 else
14ce26e7 2480 ot = dflag + OT_WORD;
2c0262af 2481
61382a50 2482 modrm = ldub_code(s->pc++);
2c0262af 2483 mod = (modrm >> 6) & 3;
14ce26e7 2484 rm = (modrm & 7) | REX_B(s);
2c0262af
FB
2485 op = (modrm >> 3) & 7;
2486 if (mod != 3) {
14ce26e7
FB
2487 if (op == 0)
2488 s->rip_offset = insn_const_size(ot);
2c0262af
FB
2489 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2490 gen_op_ld_T0_A0[ot + s->mem_index]();
2491 } else {
2492 gen_op_mov_TN_reg[ot][0][rm]();
2493 }
2494
2495 switch(op) {
2496 case 0: /* test */
2497 val = insn_get(s, ot);
2498 gen_op_movl_T1_im(val);
2499 gen_op_testl_T0_T1_cc();
2500 s->cc_op = CC_OP_LOGICB + ot;
2501 break;
2502 case 2: /* not */
2503 gen_op_notl_T0();
2504 if (mod != 3) {
2505 gen_op_st_T0_A0[ot + s->mem_index]();
2506 } else {
2507 gen_op_mov_reg_T0[ot][rm]();
2508 }
2509 break;
2510 case 3: /* neg */
2511 gen_op_negl_T0();
2512 if (mod != 3) {
2513 gen_op_st_T0_A0[ot + s->mem_index]();
2514 } else {
2515 gen_op_mov_reg_T0[ot][rm]();
2516 }
2517 gen_op_update_neg_cc();
2518 s->cc_op = CC_OP_SUBB + ot;
2519 break;
2520 case 4: /* mul */
2521 switch(ot) {
2522 case OT_BYTE:
2523 gen_op_mulb_AL_T0();
d36cd60e 2524 s->cc_op = CC_OP_MULB;
2c0262af
FB
2525 break;
2526 case OT_WORD:
2527 gen_op_mulw_AX_T0();
d36cd60e 2528 s->cc_op = CC_OP_MULW;
2c0262af
FB
2529 break;
2530 default:
2531 case OT_LONG:
2532 gen_op_mull_EAX_T0();
d36cd60e 2533 s->cc_op = CC_OP_MULL;
2c0262af 2534 break;
14ce26e7
FB
2535#ifdef TARGET_X86_64
2536 case OT_QUAD:
2537 gen_op_mulq_EAX_T0();
2538 s->cc_op = CC_OP_MULQ;
2539 break;
2540#endif
2c0262af 2541 }
2c0262af
FB
2542 break;
2543 case 5: /* imul */
2544 switch(ot) {
2545 case OT_BYTE:
2546 gen_op_imulb_AL_T0();
d36cd60e 2547 s->cc_op = CC_OP_MULB;
2c0262af
FB
2548 break;
2549 case OT_WORD:
2550 gen_op_imulw_AX_T0();
d36cd60e 2551 s->cc_op = CC_OP_MULW;
2c0262af
FB
2552 break;
2553 default:
2554 case OT_LONG:
2555 gen_op_imull_EAX_T0();
d36cd60e 2556 s->cc_op = CC_OP_MULL;
2c0262af 2557 break;
14ce26e7
FB
2558#ifdef TARGET_X86_64
2559 case OT_QUAD:
2560 gen_op_imulq_EAX_T0();
2561 s->cc_op = CC_OP_MULQ;
2562 break;
2563#endif
2c0262af 2564 }
2c0262af
FB
2565 break;
2566 case 6: /* div */
2567 switch(ot) {
2568 case OT_BYTE:
14ce26e7
FB
2569 gen_jmp_im(pc_start - s->cs_base);
2570 gen_op_divb_AL_T0();
2c0262af
FB
2571 break;
2572 case OT_WORD:
14ce26e7
FB
2573 gen_jmp_im(pc_start - s->cs_base);
2574 gen_op_divw_AX_T0();
2c0262af
FB
2575 break;
2576 default:
2577 case OT_LONG:
14ce26e7
FB
2578 gen_jmp_im(pc_start - s->cs_base);
2579 gen_op_divl_EAX_T0();
2580 break;
2581#ifdef TARGET_X86_64
2582 case OT_QUAD:
2583 gen_jmp_im(pc_start - s->cs_base);
2584 gen_op_divq_EAX_T0();
2c0262af 2585 break;
14ce26e7 2586#endif
2c0262af
FB
2587 }
2588 break;
2589 case 7: /* idiv */
2590 switch(ot) {
2591 case OT_BYTE:
14ce26e7
FB
2592 gen_jmp_im(pc_start - s->cs_base);
2593 gen_op_idivb_AL_T0();
2c0262af
FB
2594 break;
2595 case OT_WORD:
14ce26e7
FB
2596 gen_jmp_im(pc_start - s->cs_base);
2597 gen_op_idivw_AX_T0();
2c0262af
FB
2598 break;
2599 default:
2600 case OT_LONG:
14ce26e7
FB
2601 gen_jmp_im(pc_start - s->cs_base);
2602 gen_op_idivl_EAX_T0();
2603 break;
2604#ifdef TARGET_X86_64
2605 case OT_QUAD:
2606 gen_jmp_im(pc_start - s->cs_base);
2607 gen_op_idivq_EAX_T0();
2c0262af 2608 break;
14ce26e7 2609#endif
2c0262af
FB
2610 }
2611 break;
2612 default:
2613 goto illegal_op;
2614 }
2615 break;
2616
2617 case 0xfe: /* GRP4 */
2618 case 0xff: /* GRP5 */
2619 if ((b & 1) == 0)
2620 ot = OT_BYTE;
2621 else
14ce26e7 2622 ot = dflag + OT_WORD;
2c0262af 2623
61382a50 2624 modrm = ldub_code(s->pc++);
2c0262af 2625 mod = (modrm >> 6) & 3;
14ce26e7 2626 rm = (modrm & 7) | REX_B(s);
2c0262af
FB
2627 op = (modrm >> 3) & 7;
2628 if (op >= 2 && b == 0xfe) {
2629 goto illegal_op;
2630 }
14ce26e7
FB
2631 if (CODE64(s)) {
2632 if (op >= 2 && op <= 5) {
2633 /* operand size for jumps is 64 bit */
2634 ot = OT_QUAD;
2635 } else if (op == 6) {
2636 /* default push size is 64 bit */
2637 ot = dflag ? OT_QUAD : OT_WORD;
2638 }
2639 }
2c0262af
FB
2640 if (mod != 3) {
2641 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2642 if (op >= 2 && op != 3 && op != 5)
2643 gen_op_ld_T0_A0[ot + s->mem_index]();
2644 } else {
2645 gen_op_mov_TN_reg[ot][0][rm]();
2646 }
2647
2648 switch(op) {
2649 case 0: /* inc Ev */
2650 if (mod != 3)
2651 opreg = OR_TMP0;
2652 else
2653 opreg = rm;
2654 gen_inc(s, ot, opreg, 1);
2655 break;
2656 case 1: /* dec Ev */
2657 if (mod != 3)
2658 opreg = OR_TMP0;
2659 else
2660 opreg = rm;
2661 gen_inc(s, ot, opreg, -1);
2662 break;
2663 case 2: /* call Ev */
4f31916f 2664 /* XXX: optimize if memory (no 'and' is necessary) */
2c0262af
FB
2665 if (s->dflag == 0)
2666 gen_op_andl_T0_ffff();
2c0262af 2667 next_eip = s->pc - s->cs_base;
4f31916f
FB
2668 gen_op_movl_T1_im(next_eip);
2669 gen_push_T1(s);
2670 gen_op_jmp_T0();
2c0262af
FB
2671 gen_eob(s);
2672 break;
61382a50 2673 case 3: /* lcall Ev */
2c0262af
FB
2674 gen_op_ld_T1_A0[ot + s->mem_index]();
2675 gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
61382a50 2676 gen_op_ldu_T0_A0[OT_WORD + s->mem_index]();
2c0262af
FB
2677 do_lcall:
2678 if (s->pe && !s->vm86) {
2679 if (s->cc_op != CC_OP_DYNAMIC)
2680 gen_op_set_cc_op(s->cc_op);
14ce26e7 2681 gen_jmp_im(pc_start - s->cs_base);
2c0262af
FB
2682 gen_op_lcall_protected_T0_T1(dflag, s->pc - s->cs_base);
2683 } else {
2684 gen_op_lcall_real_T0_T1(dflag, s->pc - s->cs_base);
2685 }
2686 gen_eob(s);
2687 break;
2688 case 4: /* jmp Ev */
2689 if (s->dflag == 0)
2690 gen_op_andl_T0_ffff();
2691 gen_op_jmp_T0();
2692 gen_eob(s);
2693 break;
2694 case 5: /* ljmp Ev */
2695 gen_op_ld_T1_A0[ot + s->mem_index]();
2696 gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
61382a50 2697 gen_op_ldu_T0_A0[OT_WORD + s->mem_index]();
2c0262af
FB
2698 do_ljmp:
2699 if (s->pe && !s->vm86) {
2700 if (s->cc_op != CC_OP_DYNAMIC)
2701 gen_op_set_cc_op(s->cc_op);
14ce26e7 2702 gen_jmp_im(pc_start - s->cs_base);
08cea4ee 2703 gen_op_ljmp_protected_T0_T1(s->pc - s->cs_base);
2c0262af
FB
2704 } else {
2705 gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[R_CS]));
2706 gen_op_movl_T0_T1();
2707 gen_op_jmp_T0();
2708 }
2709 gen_eob(s);
2710 break;
2711 case 6: /* push Ev */
2712 gen_push_T0(s);
2713 break;
2714 default:
2715 goto illegal_op;
2716 }
2717 break;
2718
2719 case 0x84: /* test Ev, Gv */
2720 case 0x85:
2721 if ((b & 1) == 0)
2722 ot = OT_BYTE;
2723 else
14ce26e7 2724 ot = dflag + OT_WORD;
2c0262af 2725
61382a50 2726 modrm = ldub_code(s->pc++);
2c0262af 2727 mod = (modrm >> 6) & 3;
14ce26e7
FB
2728 rm = (modrm & 7) | REX_B(s);
2729 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af
FB
2730
2731 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
14ce26e7 2732 gen_op_mov_TN_reg[ot][1][reg]();
2c0262af
FB
2733 gen_op_testl_T0_T1_cc();
2734 s->cc_op = CC_OP_LOGICB + ot;
2735 break;
2736
2737 case 0xa8: /* test eAX, Iv */
2738 case 0xa9:
2739 if ((b & 1) == 0)
2740 ot = OT_BYTE;
2741 else
14ce26e7 2742 ot = dflag + OT_WORD;
2c0262af
FB
2743 val = insn_get(s, ot);
2744
2745 gen_op_mov_TN_reg[ot][0][OR_EAX]();
2746 gen_op_movl_T1_im(val);
2747 gen_op_testl_T0_T1_cc();
2748 s->cc_op = CC_OP_LOGICB + ot;
2749 break;
2750
2751 case 0x98: /* CWDE/CBW */
14ce26e7
FB
2752#ifdef TARGET_X86_64
2753 if (dflag == 2) {
2754 gen_op_movslq_RAX_EAX();
2755 } else
2756#endif
2757 if (dflag == 1)
2c0262af
FB
2758 gen_op_movswl_EAX_AX();
2759 else
2760 gen_op_movsbw_AX_AL();
2761 break;
2762 case 0x99: /* CDQ/CWD */
14ce26e7
FB
2763#ifdef TARGET_X86_64
2764 if (dflag == 2) {
2765 gen_op_movsqo_RDX_RAX();
2766 } else
2767#endif
2768 if (dflag == 1)
2c0262af
FB
2769 gen_op_movslq_EDX_EAX();
2770 else
2771 gen_op_movswl_DX_AX();
2772 break;
2773 case 0x1af: /* imul Gv, Ev */
2774 case 0x69: /* imul Gv, Ev, I */
2775 case 0x6b:
14ce26e7 2776 ot = dflag + OT_WORD;
61382a50 2777 modrm = ldub_code(s->pc++);
14ce26e7
FB
2778 reg = ((modrm >> 3) & 7) | rex_r;
2779 if (b == 0x69)
2780 s->rip_offset = insn_const_size(ot);
2781 else if (b == 0x6b)
2782 s->rip_offset = 1;
2c0262af
FB
2783 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
2784 if (b == 0x69) {
2785 val = insn_get(s, ot);
2786 gen_op_movl_T1_im(val);
2787 } else if (b == 0x6b) {
d64477af 2788 val = (int8_t)insn_get(s, OT_BYTE);
2c0262af
FB
2789 gen_op_movl_T1_im(val);
2790 } else {
2791 gen_op_mov_TN_reg[ot][1][reg]();
2792 }
2793
14ce26e7
FB
2794#ifdef TARGET_X86_64
2795 if (ot == OT_QUAD) {
2796 gen_op_imulq_T0_T1();
2797 } else
2798#endif
2c0262af
FB
2799 if (ot == OT_LONG) {
2800 gen_op_imull_T0_T1();
2801 } else {
2802 gen_op_imulw_T0_T1();
2803 }
2804 gen_op_mov_reg_T0[ot][reg]();
d36cd60e 2805 s->cc_op = CC_OP_MULB + ot;
2c0262af
FB
2806 break;
2807 case 0x1c0:
2808 case 0x1c1: /* xadd Ev, Gv */
2809 if ((b & 1) == 0)
2810 ot = OT_BYTE;
2811 else
14ce26e7 2812 ot = dflag + OT_WORD;
61382a50 2813 modrm = ldub_code(s->pc++);
14ce26e7 2814 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af
FB
2815 mod = (modrm >> 6) & 3;
2816 if (mod == 3) {
14ce26e7 2817 rm = (modrm & 7) | REX_B(s);
2c0262af
FB
2818 gen_op_mov_TN_reg[ot][0][reg]();
2819 gen_op_mov_TN_reg[ot][1][rm]();
2820 gen_op_addl_T0_T1();
2c0262af 2821 gen_op_mov_reg_T1[ot][reg]();
5a1388b6 2822 gen_op_mov_reg_T0[ot][rm]();
2c0262af
FB
2823 } else {
2824 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2825 gen_op_mov_TN_reg[ot][0][reg]();
2826 gen_op_ld_T1_A0[ot + s->mem_index]();
2827 gen_op_addl_T0_T1();
2828 gen_op_st_T0_A0[ot + s->mem_index]();
2829 gen_op_mov_reg_T1[ot][reg]();
2830 }
2831 gen_op_update2_cc();
2832 s->cc_op = CC_OP_ADDB + ot;
2833 break;
2834 case 0x1b0:
2835 case 0x1b1: /* cmpxchg Ev, Gv */
2836 if ((b & 1) == 0)
2837 ot = OT_BYTE;
2838 else
14ce26e7 2839 ot = dflag + OT_WORD;
61382a50 2840 modrm = ldub_code(s->pc++);
14ce26e7 2841 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af
FB
2842 mod = (modrm >> 6) & 3;
2843 gen_op_mov_TN_reg[ot][1][reg]();
2844 if (mod == 3) {
14ce26e7 2845 rm = (modrm & 7) | REX_B(s);
2c0262af
FB
2846 gen_op_mov_TN_reg[ot][0][rm]();
2847 gen_op_cmpxchg_T0_T1_EAX_cc[ot]();
2848 gen_op_mov_reg_T0[ot][rm]();
2849 } else {
2850 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2851 gen_op_ld_T0_A0[ot + s->mem_index]();
4f31916f 2852 gen_op_cmpxchg_mem_T0_T1_EAX_cc[ot + s->mem_index]();
2c0262af
FB
2853 }
2854 s->cc_op = CC_OP_SUBB + ot;
2855 break;
2856 case 0x1c7: /* cmpxchg8b */
61382a50 2857 modrm = ldub_code(s->pc++);
2c0262af
FB
2858 mod = (modrm >> 6) & 3;
2859 if (mod == 3)
2860 goto illegal_op;
2861 if (s->cc_op != CC_OP_DYNAMIC)
2862 gen_op_set_cc_op(s->cc_op);
2863 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2864 gen_op_cmpxchg8b();
2865 s->cc_op = CC_OP_EFLAGS;
2866 break;
2867
2868 /**************************/
2869 /* push/pop */
2870 case 0x50 ... 0x57: /* push */
14ce26e7 2871 gen_op_mov_TN_reg[OT_LONG][0][(b & 7) | REX_B(s)]();
2c0262af
FB
2872 gen_push_T0(s);
2873 break;
2874 case 0x58 ... 0x5f: /* pop */
14ce26e7
FB
2875 if (CODE64(s)) {
2876 ot = dflag ? OT_QUAD : OT_WORD;
2877 } else {
2878 ot = dflag + OT_WORD;
2879 }
2c0262af 2880 gen_pop_T0(s);
77729c24 2881 /* NOTE: order is important for pop %sp */
2c0262af 2882 gen_pop_update(s);
14ce26e7 2883 gen_op_mov_reg_T0[ot][(b & 7) | REX_B(s)]();
2c0262af
FB
2884 break;
2885 case 0x60: /* pusha */
14ce26e7
FB
2886 if (CODE64(s))
2887 goto illegal_op;
2c0262af
FB
2888 gen_pusha(s);
2889 break;
2890 case 0x61: /* popa */
14ce26e7
FB
2891 if (CODE64(s))
2892 goto illegal_op;
2c0262af
FB
2893 gen_popa(s);
2894 break;
2895 case 0x68: /* push Iv */
2896 case 0x6a:
14ce26e7
FB
2897 if (CODE64(s)) {
2898 ot = dflag ? OT_QUAD : OT_WORD;
2899 } else {
2900 ot = dflag + OT_WORD;
2901 }
2c0262af
FB
2902 if (b == 0x68)
2903 val = insn_get(s, ot);
2904 else
2905 val = (int8_t)insn_get(s, OT_BYTE);
2906 gen_op_movl_T0_im(val);
2907 gen_push_T0(s);
2908 break;
2909 case 0x8f: /* pop Ev */
14ce26e7
FB
2910 if (CODE64(s)) {
2911 ot = dflag ? OT_QUAD : OT_WORD;
2912 } else {
2913 ot = dflag + OT_WORD;
2914 }
61382a50 2915 modrm = ldub_code(s->pc++);
77729c24 2916 mod = (modrm >> 6) & 3;
2c0262af 2917 gen_pop_T0(s);
77729c24
FB
2918 if (mod == 3) {
2919 /* NOTE: order is important for pop %sp */
2920 gen_pop_update(s);
14ce26e7 2921 rm = (modrm & 7) | REX_B(s);
77729c24
FB
2922 gen_op_mov_reg_T0[ot][rm]();
2923 } else {
2924 /* NOTE: order is important too for MMU exceptions */
14ce26e7 2925 s->popl_esp_hack = 1 << ot;
77729c24
FB
2926 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
2927 s->popl_esp_hack = 0;
2928 gen_pop_update(s);
2929 }
2c0262af
FB
2930 break;
2931 case 0xc8: /* enter */
2932 {
14ce26e7 2933 /* XXX: long mode support */
2c0262af 2934 int level;
61382a50 2935 val = lduw_code(s->pc);
2c0262af 2936 s->pc += 2;
61382a50 2937 level = ldub_code(s->pc++);
2c0262af
FB
2938 gen_enter(s, val, level);
2939 }
2940 break;
2941 case 0xc9: /* leave */
2942 /* XXX: exception not precise (ESP is updated before potential exception) */
14ce26e7
FB
2943 /* XXX: may be invalid for 16 bit in long mode */
2944 if (CODE64(s)) {
2945 gen_op_mov_TN_reg[OT_QUAD][0][R_EBP]();
2946 gen_op_mov_reg_T0[OT_QUAD][R_ESP]();
2947 } else if (s->ss32) {
2c0262af
FB
2948 gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
2949 gen_op_mov_reg_T0[OT_LONG][R_ESP]();
2950 } else {
2951 gen_op_mov_TN_reg[OT_WORD][0][R_EBP]();
2952 gen_op_mov_reg_T0[OT_WORD][R_ESP]();
2953 }
2954 gen_pop_T0(s);
14ce26e7
FB
2955 if (CODE64(s)) {
2956 ot = dflag ? OT_QUAD : OT_WORD;
2957 } else {
2958 ot = dflag + OT_WORD;
2959 }
2c0262af
FB
2960 gen_op_mov_reg_T0[ot][R_EBP]();
2961 gen_pop_update(s);
2962 break;
2963 case 0x06: /* push es */
2964 case 0x0e: /* push cs */
2965 case 0x16: /* push ss */
2966 case 0x1e: /* push ds */
14ce26e7
FB
2967 if (CODE64(s))
2968 goto illegal_op;
2c0262af
FB
2969 gen_op_movl_T0_seg(b >> 3);
2970 gen_push_T0(s);
2971 break;
2972 case 0x1a0: /* push fs */
2973 case 0x1a8: /* push gs */
2974 gen_op_movl_T0_seg((b >> 3) & 7);
2975 gen_push_T0(s);
2976 break;
2977 case 0x07: /* pop es */
2978 case 0x17: /* pop ss */
2979 case 0x1f: /* pop ds */
14ce26e7
FB
2980 if (CODE64(s))
2981 goto illegal_op;
2c0262af
FB
2982 reg = b >> 3;
2983 gen_pop_T0(s);
2984 gen_movl_seg_T0(s, reg, pc_start - s->cs_base);
2985 gen_pop_update(s);
2986 if (reg == R_SS) {
a2cc3b24
FB
2987 /* if reg == SS, inhibit interrupts/trace. */
2988 /* If several instructions disable interrupts, only the
2989 _first_ does it */
2990 if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
2991 gen_op_set_inhibit_irq();
2c0262af
FB
2992 s->tf = 0;
2993 }
2994 if (s->is_jmp) {
14ce26e7 2995 gen_jmp_im(s->pc - s->cs_base);
2c0262af
FB
2996 gen_eob(s);
2997 }
2998 break;
2999 case 0x1a1: /* pop fs */
3000 case 0x1a9: /* pop gs */
3001 gen_pop_T0(s);
3002 gen_movl_seg_T0(s, (b >> 3) & 7, pc_start - s->cs_base);
3003 gen_pop_update(s);
3004 if (s->is_jmp) {
14ce26e7 3005 gen_jmp_im(s->pc - s->cs_base);
2c0262af
FB
3006 gen_eob(s);
3007 }
3008 break;
3009
3010 /**************************/
3011 /* mov */
3012 case 0x88:
3013 case 0x89: /* mov Gv, Ev */
3014 if ((b & 1) == 0)
3015 ot = OT_BYTE;
3016 else
14ce26e7 3017 ot = dflag + OT_WORD;
61382a50 3018 modrm = ldub_code(s->pc++);
14ce26e7 3019 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af
FB
3020
3021 /* generate a generic store */
14ce26e7 3022 gen_ldst_modrm(s, modrm, ot, reg, 1);
2c0262af
FB
3023 break;
3024 case 0xc6:
3025 case 0xc7: /* mov Ev, Iv */
3026 if ((b & 1) == 0)
3027 ot = OT_BYTE;
3028 else
14ce26e7 3029 ot = dflag + OT_WORD;
61382a50 3030 modrm = ldub_code(s->pc++);
2c0262af 3031 mod = (modrm >> 6) & 3;
14ce26e7
FB
3032 if (mod != 3) {
3033 s->rip_offset = insn_const_size(ot);
2c0262af 3034 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
14ce26e7 3035 }
2c0262af
FB
3036 val = insn_get(s, ot);
3037 gen_op_movl_T0_im(val);
3038 if (mod != 3)
3039 gen_op_st_T0_A0[ot + s->mem_index]();
3040 else
14ce26e7 3041 gen_op_mov_reg_T0[ot][(modrm & 7) | REX_B(s)]();
2c0262af
FB
3042 break;
3043 case 0x8a:
3044 case 0x8b: /* mov Ev, Gv */
3045 if ((b & 1) == 0)
3046 ot = OT_BYTE;
3047 else
14ce26e7 3048 ot = OT_WORD + dflag;
61382a50 3049 modrm = ldub_code(s->pc++);
14ce26e7 3050 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af
FB
3051
3052 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
3053 gen_op_mov_reg_T0[ot][reg]();
3054 break;
3055 case 0x8e: /* mov seg, Gv */
61382a50 3056 modrm = ldub_code(s->pc++);
2c0262af
FB
3057 reg = (modrm >> 3) & 7;
3058 if (reg >= 6 || reg == R_CS)
3059 goto illegal_op;
3060 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
3061 gen_movl_seg_T0(s, reg, pc_start - s->cs_base);
3062 if (reg == R_SS) {
3063 /* if reg == SS, inhibit interrupts/trace */
a2cc3b24
FB
3064 /* If several instructions disable interrupts, only the
3065 _first_ does it */
3066 if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
3067 gen_op_set_inhibit_irq();
2c0262af
FB
3068 s->tf = 0;
3069 }
3070 if (s->is_jmp) {
14ce26e7 3071 gen_jmp_im(s->pc - s->cs_base);
2c0262af
FB
3072 gen_eob(s);
3073 }
3074 break;
3075 case 0x8c: /* mov Gv, seg */
61382a50 3076 modrm = ldub_code(s->pc++);
2c0262af
FB
3077 reg = (modrm >> 3) & 7;
3078 mod = (modrm >> 6) & 3;
3079 if (reg >= 6)
3080 goto illegal_op;
3081 gen_op_movl_T0_seg(reg);
14ce26e7
FB
3082 if (mod == 3)
3083 ot = OT_WORD + dflag;
3084 else
3085 ot = OT_WORD;
2c0262af
FB
3086 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
3087 break;
3088
3089 case 0x1b6: /* movzbS Gv, Eb */
3090 case 0x1b7: /* movzwS Gv, Eb */
3091 case 0x1be: /* movsbS Gv, Eb */
3092 case 0x1bf: /* movswS Gv, Eb */
3093 {
3094 int d_ot;
3095 /* d_ot is the size of destination */
3096 d_ot = dflag + OT_WORD;
3097 /* ot is the size of source */
3098 ot = (b & 1) + OT_BYTE;
61382a50 3099 modrm = ldub_code(s->pc++);
14ce26e7 3100 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af 3101 mod = (modrm >> 6) & 3;
14ce26e7 3102 rm = (modrm & 7) | REX_B(s);
2c0262af
FB
3103
3104 if (mod == 3) {
3105 gen_op_mov_TN_reg[ot][0][rm]();
3106 switch(ot | (b & 8)) {
3107 case OT_BYTE:
3108 gen_op_movzbl_T0_T0();
3109 break;
3110 case OT_BYTE | 8:
3111 gen_op_movsbl_T0_T0();
3112 break;
3113 case OT_WORD:
3114 gen_op_movzwl_T0_T0();
3115 break;
3116 default:
3117 case OT_WORD | 8:
3118 gen_op_movswl_T0_T0();
3119 break;
3120 }
3121 gen_op_mov_reg_T0[d_ot][reg]();
3122 } else {
3123 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3124 if (b & 8) {
3125 gen_op_lds_T0_A0[ot + s->mem_index]();
3126 } else {
3127 gen_op_ldu_T0_A0[ot + s->mem_index]();
3128 }
3129 gen_op_mov_reg_T0[d_ot][reg]();
3130 }
3131 }
3132 break;
3133
3134 case 0x8d: /* lea */
14ce26e7 3135 ot = dflag + OT_WORD;
61382a50 3136 modrm = ldub_code(s->pc++);
3a1d9b8b
FB
3137 mod = (modrm >> 6) & 3;
3138 if (mod == 3)
3139 goto illegal_op;
14ce26e7 3140 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af
FB
3141 /* we must ensure that no segment is added */
3142 s->override = -1;
3143 val = s->addseg;
3144 s->addseg = 0;
3145 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3146 s->addseg = val;
3147 gen_op_mov_reg_A0[ot - OT_WORD][reg]();
3148 break;
3149
3150 case 0xa0: /* mov EAX, Ov */
3151 case 0xa1:
3152 case 0xa2: /* mov Ov, EAX */
3153 case 0xa3:
2c0262af 3154 {
14ce26e7
FB
3155 target_ulong offset_addr;
3156
3157 if ((b & 1) == 0)
3158 ot = OT_BYTE;
3159 else
3160 ot = dflag + OT_WORD;
3161#ifdef TARGET_X86_64
3162 if (CODE64(s)) {
3163 offset_addr = ldq_code(s->pc);
3164 s->pc += 8;
3165 if (offset_addr == (int32_t)offset_addr)
3166 gen_op_movq_A0_im(offset_addr);
3167 else
3168 gen_op_movq_A0_im64(offset_addr >> 32, offset_addr);
3169 } else
3170#endif
3171 {
3172 if (s->aflag) {
3173 offset_addr = insn_get(s, OT_LONG);
3174 } else {
3175 offset_addr = insn_get(s, OT_WORD);
3176 }
3177 gen_op_movl_A0_im(offset_addr);
3178 }
3179 /* handle override */
3180 {
3181 int override, must_add_seg;
3182 must_add_seg = s->addseg;
3183 if (s->override >= 0) {
3184 override = s->override;
3185 must_add_seg = 1;
3186 } else {
3187 override = R_DS;
3188 }
3189 if (must_add_seg) {
3190 gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base));
3191 }
2c0262af 3192 }
14ce26e7
FB
3193 if ((b & 2) == 0) {
3194 gen_op_ld_T0_A0[ot + s->mem_index]();
3195 gen_op_mov_reg_T0[ot][R_EAX]();
3196 } else {
3197 gen_op_mov_TN_reg[ot][0][R_EAX]();
3198 gen_op_st_T0_A0[ot + s->mem_index]();
2c0262af
FB
3199 }
3200 }
2c0262af
FB
3201 break;
3202 case 0xd7: /* xlat */
14ce26e7
FB
3203#ifdef TARGET_X86_64
3204 if (CODE64(s)) {
3205 gen_op_movq_A0_reg[R_EBX]();
3206 gen_op_addq_A0_AL();
3207 } else
3208#endif
3209 {
3210 gen_op_movl_A0_reg[R_EBX]();
3211 gen_op_addl_A0_AL();
3212 if (s->aflag == 0)
3213 gen_op_andl_A0_ffff();
3214 }
2c0262af
FB
3215 /* handle override */
3216 {
3217 int override, must_add_seg;
3218 must_add_seg = s->addseg;
3219 override = R_DS;
3220 if (s->override >= 0) {
3221 override = s->override;
3222 must_add_seg = 1;
3223 } else {
3224 override = R_DS;
3225 }
3226 if (must_add_seg) {
3227 gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base));
3228 }
3229 }
3230 gen_op_ldu_T0_A0[OT_BYTE + s->mem_index]();
3231 gen_op_mov_reg_T0[OT_BYTE][R_EAX]();
3232 break;
3233 case 0xb0 ... 0xb7: /* mov R, Ib */
3234 val = insn_get(s, OT_BYTE);
3235 gen_op_movl_T0_im(val);
14ce26e7 3236 gen_op_mov_reg_T0[OT_BYTE][(b & 7) | REX_B(s)]();
2c0262af
FB
3237 break;
3238 case 0xb8 ... 0xbf: /* mov R, Iv */
14ce26e7
FB
3239#ifdef TARGET_X86_64
3240 if (dflag == 2) {
3241 uint64_t tmp;
3242 /* 64 bit case */
3243 tmp = ldq_code(s->pc);
3244 s->pc += 8;
3245 reg = (b & 7) | REX_B(s);
3246 gen_movtl_T0_im(tmp);
3247 gen_op_mov_reg_T0[OT_QUAD][reg]();
3248 } else
3249#endif
3250 {
3251 ot = dflag ? OT_LONG : OT_WORD;
3252 val = insn_get(s, ot);
3253 reg = (b & 7) | REX_B(s);
3254 gen_op_movl_T0_im(val);
3255 gen_op_mov_reg_T0[ot][reg]();
3256 }
2c0262af
FB
3257 break;
3258
3259 case 0x91 ... 0x97: /* xchg R, EAX */
14ce26e7
FB
3260 ot = dflag + OT_WORD;
3261 reg = (b & 7) | REX_B(s);
2c0262af
FB
3262 rm = R_EAX;
3263 goto do_xchg_reg;
3264 case 0x86:
3265 case 0x87: /* xchg Ev, Gv */
3266 if ((b & 1) == 0)
3267 ot = OT_BYTE;
3268 else
14ce26e7 3269 ot = dflag + OT_WORD;
61382a50 3270 modrm = ldub_code(s->pc++);
14ce26e7 3271 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af
FB
3272 mod = (modrm >> 6) & 3;
3273 if (mod == 3) {
14ce26e7 3274 rm = (modrm & 7) | REX_B(s);
2c0262af
FB
3275 do_xchg_reg:
3276 gen_op_mov_TN_reg[ot][0][reg]();
3277 gen_op_mov_TN_reg[ot][1][rm]();
3278 gen_op_mov_reg_T0[ot][rm]();
3279 gen_op_mov_reg_T1[ot][reg]();
3280 } else {
3281 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3282 gen_op_mov_TN_reg[ot][0][reg]();
3283 /* for xchg, lock is implicit */
3284 if (!(prefixes & PREFIX_LOCK))
3285 gen_op_lock();
3286 gen_op_ld_T1_A0[ot + s->mem_index]();
3287 gen_op_st_T0_A0[ot + s->mem_index]();
3288 if (!(prefixes & PREFIX_LOCK))
3289 gen_op_unlock();
3290 gen_op_mov_reg_T1[ot][reg]();
3291 }
3292 break;
3293 case 0xc4: /* les Gv */
14ce26e7
FB
3294 if (CODE64(s))
3295 goto illegal_op;
2c0262af
FB
3296 op = R_ES;
3297 goto do_lxx;
3298 case 0xc5: /* lds Gv */
14ce26e7
FB
3299 if (CODE64(s))
3300 goto illegal_op;
2c0262af
FB
3301 op = R_DS;
3302 goto do_lxx;
3303 case 0x1b2: /* lss Gv */
3304 op = R_SS;
3305 goto do_lxx;
3306 case 0x1b4: /* lfs Gv */
3307 op = R_FS;
3308 goto do_lxx;
3309 case 0x1b5: /* lgs Gv */
3310 op = R_GS;
3311 do_lxx:
3312 ot = dflag ? OT_LONG : OT_WORD;
61382a50 3313 modrm = ldub_code(s->pc++);
14ce26e7 3314 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af
FB
3315 mod = (modrm >> 6) & 3;
3316 if (mod == 3)
3317 goto illegal_op;
3318 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3319 gen_op_ld_T1_A0[ot + s->mem_index]();
3320 gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
3321 /* load the segment first to handle exceptions properly */
61382a50 3322 gen_op_ldu_T0_A0[OT_WORD + s->mem_index]();
2c0262af
FB
3323 gen_movl_seg_T0(s, op, pc_start - s->cs_base);
3324 /* then put the data */
3325 gen_op_mov_reg_T1[ot][reg]();
3326 if (s->is_jmp) {
14ce26e7 3327 gen_jmp_im(s->pc - s->cs_base);
2c0262af
FB
3328 gen_eob(s);
3329 }
3330 break;
3331
3332 /************************/
3333 /* shifts */
3334 case 0xc0:
3335 case 0xc1:
3336 /* shift Ev,Ib */
3337 shift = 2;
3338 grp2:
3339 {
3340 if ((b & 1) == 0)
3341 ot = OT_BYTE;
3342 else
14ce26e7 3343 ot = dflag + OT_WORD;
2c0262af 3344
61382a50 3345 modrm = ldub_code(s->pc++);
2c0262af 3346 mod = (modrm >> 6) & 3;
2c0262af
FB
3347 op = (modrm >> 3) & 7;
3348
3349 if (mod != 3) {
14ce26e7
FB
3350 if (shift == 2) {
3351 s->rip_offset = 1;
3352 }
2c0262af
FB
3353 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3354 opreg = OR_TMP0;
3355 } else {
14ce26e7 3356 opreg = (modrm & 7) | REX_B(s);
2c0262af
FB
3357 }
3358
3359 /* simpler op */
3360 if (shift == 0) {
3361 gen_shift(s, op, ot, opreg, OR_ECX);
3362 } else {
3363 if (shift == 2) {
61382a50 3364 shift = ldub_code(s->pc++);
2c0262af
FB
3365 }
3366 gen_shifti(s, op, ot, opreg, shift);
3367 }
3368 }
3369 break;
3370 case 0xd0:
3371 case 0xd1:
3372 /* shift Ev,1 */
3373 shift = 1;
3374 goto grp2;
3375 case 0xd2:
3376 case 0xd3:
3377 /* shift Ev,cl */
3378 shift = 0;
3379 goto grp2;
3380
3381 case 0x1a4: /* shld imm */
3382 op = 0;
3383 shift = 1;
3384 goto do_shiftd;
3385 case 0x1a5: /* shld cl */
3386 op = 0;
3387 shift = 0;
3388 goto do_shiftd;
3389 case 0x1ac: /* shrd imm */
3390 op = 1;
3391 shift = 1;
3392 goto do_shiftd;
3393 case 0x1ad: /* shrd cl */
3394 op = 1;
3395 shift = 0;
3396 do_shiftd:
14ce26e7 3397 ot = dflag + OT_WORD;
61382a50 3398 modrm = ldub_code(s->pc++);
2c0262af 3399 mod = (modrm >> 6) & 3;
14ce26e7
FB
3400 rm = (modrm & 7) | REX_B(s);
3401 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af
FB
3402
3403 if (mod != 3) {
3404 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3405 gen_op_ld_T0_A0[ot + s->mem_index]();
3406 } else {
3407 gen_op_mov_TN_reg[ot][0][rm]();
3408 }
3409 gen_op_mov_TN_reg[ot][1][reg]();
3410
3411 if (shift) {
61382a50 3412 val = ldub_code(s->pc++);
14ce26e7
FB
3413 if (ot == OT_QUAD)
3414 val &= 0x3f;
3415 else
3416 val &= 0x1f;
2c0262af
FB
3417 if (val) {
3418 if (mod == 3)
4f31916f 3419 gen_op_shiftd_T0_T1_im_cc[ot][op](val);
2c0262af 3420 else
4f31916f 3421 gen_op_shiftd_mem_T0_T1_im_cc[ot + s->mem_index][op](val);
2c0262af
FB
3422 if (op == 0 && ot != OT_WORD)
3423 s->cc_op = CC_OP_SHLB + ot;
3424 else
3425 s->cc_op = CC_OP_SARB + ot;
3426 }
3427 } else {
3428 if (s->cc_op != CC_OP_DYNAMIC)
3429 gen_op_set_cc_op(s->cc_op);
3430 if (mod == 3)
4f31916f 3431 gen_op_shiftd_T0_T1_ECX_cc[ot][op]();
2c0262af 3432 else
4f31916f 3433 gen_op_shiftd_mem_T0_T1_ECX_cc[ot + s->mem_index][op]();
2c0262af
FB
3434 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
3435 }
3436 if (mod == 3) {
3437 gen_op_mov_reg_T0[ot][rm]();
3438 }
3439 break;
3440
3441 /************************/
3442 /* floats */
3443 case 0xd8 ... 0xdf:
7eee2a50
FB
3444 if (s->flags & (HF_EM_MASK | HF_TS_MASK)) {
3445 /* if CR0.EM or CR0.TS are set, generate an FPU exception */
3446 /* XXX: what to do if illegal op ? */
3447 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
3448 break;
3449 }
61382a50 3450 modrm = ldub_code(s->pc++);
2c0262af
FB
3451 mod = (modrm >> 6) & 3;
3452 rm = modrm & 7;
3453 op = ((b & 7) << 3) | ((modrm >> 3) & 7);
2c0262af
FB
3454 if (mod != 3) {
3455 /* memory op */
3456 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3457 switch(op) {
3458 case 0x00 ... 0x07: /* fxxxs */
3459 case 0x10 ... 0x17: /* fixxxl */
3460 case 0x20 ... 0x27: /* fxxxl */
3461 case 0x30 ... 0x37: /* fixxx */
3462 {
3463 int op1;
3464 op1 = op & 7;
3465
3466 switch(op >> 4) {
3467 case 0:
3468 gen_op_flds_FT0_A0();
3469 break;
3470 case 1:
3471 gen_op_fildl_FT0_A0();
3472 break;
3473 case 2:
3474 gen_op_fldl_FT0_A0();
3475 break;
3476 case 3:
3477 default:
3478 gen_op_fild_FT0_A0();
3479 break;
3480 }
3481
3482 gen_op_fp_arith_ST0_FT0[op1]();
3483 if (op1 == 3) {
3484 /* fcomp needs pop */
3485 gen_op_fpop();
3486 }
3487 }
3488 break;
3489 case 0x08: /* flds */
3490 case 0x0a: /* fsts */
3491 case 0x0b: /* fstps */
3492 case 0x18: /* fildl */
3493 case 0x1a: /* fistl */
3494 case 0x1b: /* fistpl */
3495 case 0x28: /* fldl */
3496 case 0x2a: /* fstl */
3497 case 0x2b: /* fstpl */
3498 case 0x38: /* filds */
3499 case 0x3a: /* fists */
3500 case 0x3b: /* fistps */
3501
3502 switch(op & 7) {
3503 case 0:
3504 switch(op >> 4) {
3505 case 0:
3506 gen_op_flds_ST0_A0();
3507 break;
3508 case 1:
3509 gen_op_fildl_ST0_A0();
3510 break;
3511 case 2:
3512 gen_op_fldl_ST0_A0();
3513 break;
3514 case 3:
3515 default:
3516 gen_op_fild_ST0_A0();
3517 break;
3518 }
3519 break;
3520 default:
3521 switch(op >> 4) {
3522 case 0:
3523 gen_op_fsts_ST0_A0();
3524 break;
3525 case 1:
3526 gen_op_fistl_ST0_A0();
3527 break;
3528 case 2:
3529 gen_op_fstl_ST0_A0();
3530 break;
3531 case 3:
3532 default:
3533 gen_op_fist_ST0_A0();
3534 break;
3535 }
3536 if ((op & 7) == 3)
3537 gen_op_fpop();
3538 break;
3539 }
3540 break;
3541 case 0x0c: /* fldenv mem */
3542 gen_op_fldenv_A0(s->dflag);
3543 break;
3544 case 0x0d: /* fldcw mem */
3545 gen_op_fldcw_A0();
3546 break;
3547 case 0x0e: /* fnstenv mem */
3548 gen_op_fnstenv_A0(s->dflag);
3549 break;
3550 case 0x0f: /* fnstcw mem */
3551 gen_op_fnstcw_A0();
3552 break;
3553 case 0x1d: /* fldt mem */
3554 gen_op_fldt_ST0_A0();
3555 break;
3556 case 0x1f: /* fstpt mem */
3557 gen_op_fstt_ST0_A0();
3558 gen_op_fpop();
3559 break;
3560 case 0x2c: /* frstor mem */
3561 gen_op_frstor_A0(s->dflag);
3562 break;
3563 case 0x2e: /* fnsave mem */
3564 gen_op_fnsave_A0(s->dflag);
3565 break;
3566 case 0x2f: /* fnstsw mem */
3567 gen_op_fnstsw_A0();
3568 break;
3569 case 0x3c: /* fbld */
3570 gen_op_fbld_ST0_A0();
3571 break;
3572 case 0x3e: /* fbstp */
3573 gen_op_fbst_ST0_A0();
3574 gen_op_fpop();
3575 break;
3576 case 0x3d: /* fildll */
3577 gen_op_fildll_ST0_A0();
3578 break;
3579 case 0x3f: /* fistpll */
3580 gen_op_fistll_ST0_A0();
3581 gen_op_fpop();
3582 break;
3583 default:
3584 goto illegal_op;
3585 }
3586 } else {
3587 /* register float ops */
3588 opreg = rm;
3589
3590 switch(op) {
3591 case 0x08: /* fld sti */
3592 gen_op_fpush();
3593 gen_op_fmov_ST0_STN((opreg + 1) & 7);
3594 break;
3595 case 0x09: /* fxchg sti */
c169c906
FB
3596 case 0x29: /* fxchg4 sti, undocumented op */
3597 case 0x39: /* fxchg7 sti, undocumented op */
2c0262af
FB
3598 gen_op_fxchg_ST0_STN(opreg);
3599 break;
3600 case 0x0a: /* grp d9/2 */
3601 switch(rm) {
3602 case 0: /* fnop */
023fe10d
FB
3603 /* check exceptions (FreeBSD FPU probe) */
3604 if (s->cc_op != CC_OP_DYNAMIC)
3605 gen_op_set_cc_op(s->cc_op);
14ce26e7 3606 gen_jmp_im(pc_start - s->cs_base);
023fe10d 3607 gen_op_fwait();
2c0262af
FB
3608 break;
3609 default:
3610 goto illegal_op;
3611 }
3612 break;
3613 case 0x0c: /* grp d9/4 */
3614 switch(rm) {
3615 case 0: /* fchs */
3616 gen_op_fchs_ST0();
3617 break;
3618 case 1: /* fabs */
3619 gen_op_fabs_ST0();
3620 break;
3621 case 4: /* ftst */
3622 gen_op_fldz_FT0();
3623 gen_op_fcom_ST0_FT0();
3624 break;
3625 case 5: /* fxam */
3626 gen_op_fxam_ST0();
3627 break;
3628 default:
3629 goto illegal_op;
3630 }
3631 break;
3632 case 0x0d: /* grp d9/5 */
3633 {
3634 switch(rm) {
3635 case 0:
3636 gen_op_fpush();
3637 gen_op_fld1_ST0();
3638 break;
3639 case 1:
3640 gen_op_fpush();
3641 gen_op_fldl2t_ST0();
3642 break;
3643 case 2:
3644 gen_op_fpush();
3645 gen_op_fldl2e_ST0();
3646 break;
3647 case 3:
3648 gen_op_fpush();
3649 gen_op_fldpi_ST0();
3650 break;
3651 case 4:
3652 gen_op_fpush();
3653 gen_op_fldlg2_ST0();
3654 break;
3655 case 5:
3656 gen_op_fpush();
3657 gen_op_fldln2_ST0();
3658 break;
3659 case 6:
3660 gen_op_fpush();
3661 gen_op_fldz_ST0();
3662 break;
3663 default:
3664 goto illegal_op;
3665 }
3666 }
3667 break;
3668 case 0x0e: /* grp d9/6 */
3669 switch(rm) {
3670 case 0: /* f2xm1 */
3671 gen_op_f2xm1();
3672 break;
3673 case 1: /* fyl2x */
3674 gen_op_fyl2x();
3675 break;
3676 case 2: /* fptan */
3677 gen_op_fptan();
3678 break;
3679 case 3: /* fpatan */
3680 gen_op_fpatan();
3681 break;
3682 case 4: /* fxtract */
3683 gen_op_fxtract();
3684 break;
3685 case 5: /* fprem1 */
3686 gen_op_fprem1();
3687 break;
3688 case 6: /* fdecstp */
3689 gen_op_fdecstp();
3690 break;
3691 default:
3692 case 7: /* fincstp */
3693 gen_op_fincstp();
3694 break;
3695 }
3696 break;
3697 case 0x0f: /* grp d9/7 */
3698 switch(rm) {
3699 case 0: /* fprem */
3700 gen_op_fprem();
3701 break;
3702 case 1: /* fyl2xp1 */
3703 gen_op_fyl2xp1();
3704 break;
3705 case 2: /* fsqrt */
3706 gen_op_fsqrt();
3707 break;
3708 case 3: /* fsincos */
3709 gen_op_fsincos();
3710 break;
3711 case 5: /* fscale */
3712 gen_op_fscale();
3713 break;
3714 case 4: /* frndint */
3715 gen_op_frndint();
3716 break;
3717 case 6: /* fsin */
3718 gen_op_fsin();
3719 break;
3720 default:
3721 case 7: /* fcos */
3722 gen_op_fcos();
3723 break;
3724 }
3725 break;
3726 case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
3727 case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
3728 case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
3729 {
3730 int op1;
3731
3732 op1 = op & 7;
3733 if (op >= 0x20) {
3734 gen_op_fp_arith_STN_ST0[op1](opreg);
3735 if (op >= 0x30)
3736 gen_op_fpop();
3737 } else {
3738 gen_op_fmov_FT0_STN(opreg);
3739 gen_op_fp_arith_ST0_FT0[op1]();
3740 }
3741 }
3742 break;
3743 case 0x02: /* fcom */
c169c906 3744 case 0x22: /* fcom2, undocumented op */
2c0262af
FB
3745 gen_op_fmov_FT0_STN(opreg);
3746 gen_op_fcom_ST0_FT0();
3747 break;
3748 case 0x03: /* fcomp */
c169c906
FB
3749 case 0x23: /* fcomp3, undocumented op */
3750 case 0x32: /* fcomp5, undocumented op */
2c0262af
FB
3751 gen_op_fmov_FT0_STN(opreg);
3752 gen_op_fcom_ST0_FT0();
3753 gen_op_fpop();
3754 break;
3755 case 0x15: /* da/5 */
3756 switch(rm) {
3757 case 1: /* fucompp */
3758 gen_op_fmov_FT0_STN(1);
3759 gen_op_fucom_ST0_FT0();
3760 gen_op_fpop();
3761 gen_op_fpop();
3762 break;
3763 default:
3764 goto illegal_op;
3765 }
3766 break;
3767 case 0x1c:
3768 switch(rm) {
3769 case 0: /* feni (287 only, just do nop here) */
3770 break;
3771 case 1: /* fdisi (287 only, just do nop here) */
3772 break;
3773 case 2: /* fclex */
3774 gen_op_fclex();
3775 break;
3776 case 3: /* fninit */
3777 gen_op_fninit();
3778 break;
3779 case 4: /* fsetpm (287 only, just do nop here) */
3780 break;
3781 default:
3782 goto illegal_op;
3783 }
3784 break;
3785 case 0x1d: /* fucomi */
3786 if (s->cc_op != CC_OP_DYNAMIC)
3787 gen_op_set_cc_op(s->cc_op);
3788 gen_op_fmov_FT0_STN(opreg);
3789 gen_op_fucomi_ST0_FT0();
3790 s->cc_op = CC_OP_EFLAGS;
3791 break;
3792 case 0x1e: /* fcomi */
3793 if (s->cc_op != CC_OP_DYNAMIC)
3794 gen_op_set_cc_op(s->cc_op);
3795 gen_op_fmov_FT0_STN(opreg);
3796 gen_op_fcomi_ST0_FT0();
3797 s->cc_op = CC_OP_EFLAGS;
3798 break;
658c8bda
FB
3799 case 0x28: /* ffree sti */
3800 gen_op_ffree_STN(opreg);
3801 break;
2c0262af
FB
3802 case 0x2a: /* fst sti */
3803 gen_op_fmov_STN_ST0(opreg);
3804 break;
3805 case 0x2b: /* fstp sti */
c169c906
FB
3806 case 0x0b: /* fstp1 sti, undocumented op */
3807 case 0x3a: /* fstp8 sti, undocumented op */
3808 case 0x3b: /* fstp9 sti, undocumented op */
2c0262af
FB
3809 gen_op_fmov_STN_ST0(opreg);
3810 gen_op_fpop();
3811 break;
3812 case 0x2c: /* fucom st(i) */
3813 gen_op_fmov_FT0_STN(opreg);
3814 gen_op_fucom_ST0_FT0();
3815 break;
3816 case 0x2d: /* fucomp st(i) */
3817 gen_op_fmov_FT0_STN(opreg);
3818 gen_op_fucom_ST0_FT0();
3819 gen_op_fpop();
3820 break;
3821 case 0x33: /* de/3 */
3822 switch(rm) {
3823 case 1: /* fcompp */
3824 gen_op_fmov_FT0_STN(1);
3825 gen_op_fcom_ST0_FT0();
3826 gen_op_fpop();
3827 gen_op_fpop();
3828 break;
3829 default:
3830 goto illegal_op;
3831 }
3832 break;
c169c906
FB
3833 case 0x38: /* ffreep sti, undocumented op */
3834 gen_op_ffree_STN(opreg);
3835 gen_op_fpop();
3836 break;
2c0262af
FB
3837 case 0x3c: /* df/4 */
3838 switch(rm) {
3839 case 0:
3840 gen_op_fnstsw_EAX();
3841 break;
3842 default:
3843 goto illegal_op;
3844 }
3845 break;
3846 case 0x3d: /* fucomip */
3847 if (s->cc_op != CC_OP_DYNAMIC)
3848 gen_op_set_cc_op(s->cc_op);
3849 gen_op_fmov_FT0_STN(opreg);
3850 gen_op_fucomi_ST0_FT0();
3851 gen_op_fpop();
3852 s->cc_op = CC_OP_EFLAGS;
3853 break;
3854 case 0x3e: /* fcomip */
3855 if (s->cc_op != CC_OP_DYNAMIC)
3856 gen_op_set_cc_op(s->cc_op);
3857 gen_op_fmov_FT0_STN(opreg);
3858 gen_op_fcomi_ST0_FT0();
3859 gen_op_fpop();
3860 s->cc_op = CC_OP_EFLAGS;
3861 break;
a2cc3b24
FB
3862 case 0x10 ... 0x13: /* fcmovxx */
3863 case 0x18 ... 0x1b:
3864 {
3865 int op1;
3866 const static uint8_t fcmov_cc[8] = {
3867 (JCC_B << 1),
3868 (JCC_Z << 1),
3869 (JCC_BE << 1),
3870 (JCC_P << 1),
3871 };
3872 op1 = fcmov_cc[op & 3] | ((op >> 3) & 1);
3873 gen_setcc(s, op1);
3874 gen_op_fcmov_ST0_STN_T0(opreg);
3875 }
3876 break;
2c0262af
FB
3877 default:
3878 goto illegal_op;
3879 }
3880 }
7eee2a50
FB
3881#ifdef USE_CODE_COPY
3882 s->tb->cflags |= CF_TB_FP_USED;
3883#endif
2c0262af
FB
3884 break;
3885 /************************/
3886 /* string ops */
3887
3888 case 0xa4: /* movsS */
3889 case 0xa5:
3890 if ((b & 1) == 0)
3891 ot = OT_BYTE;
3892 else
14ce26e7 3893 ot = dflag + OT_WORD;
2c0262af
FB
3894
3895 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
3896 gen_repz_movs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
3897 } else {
3898 gen_movs(s, ot);
3899 }
3900 break;
3901
3902 case 0xaa: /* stosS */
3903 case 0xab:
3904 if ((b & 1) == 0)
3905 ot = OT_BYTE;
3906 else
14ce26e7 3907 ot = dflag + OT_WORD;
2c0262af
FB
3908
3909 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
3910 gen_repz_stos(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
3911 } else {
3912 gen_stos(s, ot);
3913 }
3914 break;
3915 case 0xac: /* lodsS */
3916 case 0xad:
3917 if ((b & 1) == 0)
3918 ot = OT_BYTE;
3919 else
14ce26e7 3920 ot = dflag + OT_WORD;
2c0262af
FB
3921 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
3922 gen_repz_lods(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
3923 } else {
3924 gen_lods(s, ot);
3925 }
3926 break;
3927 case 0xae: /* scasS */
3928 case 0xaf:
3929 if ((b & 1) == 0)
3930 ot = OT_BYTE;
3931 else
14ce26e7 3932 ot = dflag + OT_WORD;
2c0262af
FB
3933 if (prefixes & PREFIX_REPNZ) {
3934 gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
3935 } else if (prefixes & PREFIX_REPZ) {
3936 gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
3937 } else {
3938 gen_scas(s, ot);
3939 s->cc_op = CC_OP_SUBB + ot;
3940 }
3941 break;
3942
3943 case 0xa6: /* cmpsS */
3944 case 0xa7:
3945 if ((b & 1) == 0)
3946 ot = OT_BYTE;
3947 else
14ce26e7 3948 ot = dflag + OT_WORD;
2c0262af
FB
3949 if (prefixes & PREFIX_REPNZ) {
3950 gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
3951 } else if (prefixes & PREFIX_REPZ) {
3952 gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
3953 } else {
3954 gen_cmps(s, ot);
3955 s->cc_op = CC_OP_SUBB + ot;
3956 }
3957 break;
3958 case 0x6c: /* insS */
3959 case 0x6d:
f115e911
FB
3960 if ((b & 1) == 0)
3961 ot = OT_BYTE;
3962 else
3963 ot = dflag ? OT_LONG : OT_WORD;
3964 gen_check_io(s, ot, 1, pc_start - s->cs_base);
3965 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
3966 gen_repz_ins(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
2c0262af 3967 } else {
f115e911 3968 gen_ins(s, ot);
2c0262af
FB
3969 }
3970 break;
3971 case 0x6e: /* outsS */
3972 case 0x6f:
f115e911
FB
3973 if ((b & 1) == 0)
3974 ot = OT_BYTE;
3975 else
3976 ot = dflag ? OT_LONG : OT_WORD;
3977 gen_check_io(s, ot, 1, pc_start - s->cs_base);
3978 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
3979 gen_repz_outs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
2c0262af 3980 } else {
f115e911 3981 gen_outs(s, ot);
2c0262af
FB
3982 }
3983 break;
3984
3985 /************************/
3986 /* port I/O */
3987 case 0xe4:
3988 case 0xe5:
f115e911
FB
3989 if ((b & 1) == 0)
3990 ot = OT_BYTE;
3991 else
3992 ot = dflag ? OT_LONG : OT_WORD;
3993 val = ldub_code(s->pc++);
3994 gen_op_movl_T0_im(val);
3995 gen_check_io(s, ot, 0, pc_start - s->cs_base);
3996 gen_op_in[ot]();
3997 gen_op_mov_reg_T1[ot][R_EAX]();
2c0262af
FB
3998 break;
3999 case 0xe6:
4000 case 0xe7:
f115e911
FB
4001 if ((b & 1) == 0)
4002 ot = OT_BYTE;
4003 else
4004 ot = dflag ? OT_LONG : OT_WORD;
4005 val = ldub_code(s->pc++);
4006 gen_op_movl_T0_im(val);
4007 gen_check_io(s, ot, 0, pc_start - s->cs_base);
4008 gen_op_mov_TN_reg[ot][1][R_EAX]();
4009 gen_op_out[ot]();
2c0262af
FB
4010 break;
4011 case 0xec:
4012 case 0xed:
f115e911
FB
4013 if ((b & 1) == 0)
4014 ot = OT_BYTE;
4015 else
4016 ot = dflag ? OT_LONG : OT_WORD;
4017 gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
4f31916f 4018 gen_op_andl_T0_ffff();
f115e911
FB
4019 gen_check_io(s, ot, 0, pc_start - s->cs_base);
4020 gen_op_in[ot]();
4021 gen_op_mov_reg_T1[ot][R_EAX]();
2c0262af
FB
4022 break;
4023 case 0xee:
4024 case 0xef:
f115e911
FB
4025 if ((b & 1) == 0)
4026 ot = OT_BYTE;
4027 else
4028 ot = dflag ? OT_LONG : OT_WORD;
4029 gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
4f31916f 4030 gen_op_andl_T0_ffff();
f115e911
FB
4031 gen_check_io(s, ot, 0, pc_start - s->cs_base);
4032 gen_op_mov_TN_reg[ot][1][R_EAX]();
4033 gen_op_out[ot]();
2c0262af
FB
4034 break;
4035
4036 /************************/
4037 /* control */
4038 case 0xc2: /* ret im */
61382a50 4039 val = ldsw_code(s->pc);
2c0262af
FB
4040 s->pc += 2;
4041 gen_pop_T0(s);
4042 gen_stack_update(s, val + (2 << s->dflag));
4043 if (s->dflag == 0)
4044 gen_op_andl_T0_ffff();
4045 gen_op_jmp_T0();
4046 gen_eob(s);
4047 break;
4048 case 0xc3: /* ret */
4049 gen_pop_T0(s);
4050 gen_pop_update(s);
4051 if (s->dflag == 0)
4052 gen_op_andl_T0_ffff();
4053 gen_op_jmp_T0();
4054 gen_eob(s);
4055 break;
4056 case 0xca: /* lret im */
61382a50 4057 val = ldsw_code(s->pc);
2c0262af
FB
4058 s->pc += 2;
4059 do_lret:
4060 if (s->pe && !s->vm86) {
4061 if (s->cc_op != CC_OP_DYNAMIC)
4062 gen_op_set_cc_op(s->cc_op);
14ce26e7 4063 gen_jmp_im(pc_start - s->cs_base);
2c0262af
FB
4064 gen_op_lret_protected(s->dflag, val);
4065 } else {
4066 gen_stack_A0(s);
4067 /* pop offset */
4068 gen_op_ld_T0_A0[1 + s->dflag + s->mem_index]();
4069 if (s->dflag == 0)
4070 gen_op_andl_T0_ffff();
4071 /* NOTE: keeping EIP updated is not a problem in case of
4072 exception */
4073 gen_op_jmp_T0();
4074 /* pop selector */
4075 gen_op_addl_A0_im(2 << s->dflag);
4076 gen_op_ld_T0_A0[1 + s->dflag + s->mem_index]();
4077 gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[R_CS]));
4078 /* add stack offset */
4079 gen_stack_update(s, val + (4 << s->dflag));
4080 }
4081 gen_eob(s);
4082 break;
4083 case 0xcb: /* lret */
4084 val = 0;
4085 goto do_lret;
4086 case 0xcf: /* iret */
4087 if (!s->pe) {
4088 /* real mode */
4089 gen_op_iret_real(s->dflag);
4090 s->cc_op = CC_OP_EFLAGS;
f115e911
FB
4091 } else if (s->vm86) {
4092 if (s->iopl != 3) {
4093 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
4094 } else {
4095 gen_op_iret_real(s->dflag);
4096 s->cc_op = CC_OP_EFLAGS;
4097 }
2c0262af
FB
4098 } else {
4099 if (s->cc_op != CC_OP_DYNAMIC)
4100 gen_op_set_cc_op(s->cc_op);
14ce26e7 4101 gen_jmp_im(pc_start - s->cs_base);
08cea4ee 4102 gen_op_iret_protected(s->dflag, s->pc - s->cs_base);
2c0262af
FB
4103 s->cc_op = CC_OP_EFLAGS;
4104 }
4105 gen_eob(s);
4106 break;
4107 case 0xe8: /* call im */
4108 {
14ce26e7
FB
4109 if (dflag)
4110 tval = (int32_t)insn_get(s, OT_LONG);
4111 else
4112 tval = (int16_t)insn_get(s, OT_WORD);
2c0262af 4113 next_eip = s->pc - s->cs_base;
14ce26e7 4114 tval += next_eip;
2c0262af 4115 if (s->dflag == 0)
14ce26e7
FB
4116 tval &= 0xffff;
4117 gen_movtl_T0_im(next_eip);
2c0262af 4118 gen_push_T0(s);
14ce26e7 4119 gen_jmp(s, tval);
2c0262af
FB
4120 }
4121 break;
4122 case 0x9a: /* lcall im */
4123 {
4124 unsigned int selector, offset;
14ce26e7
FB
4125
4126 if (CODE64(s))
4127 goto illegal_op;
2c0262af
FB
4128 ot = dflag ? OT_LONG : OT_WORD;
4129 offset = insn_get(s, ot);
4130 selector = insn_get(s, OT_WORD);
4131
4132 gen_op_movl_T0_im(selector);
14ce26e7 4133 gen_op_movl_T1_imu(offset);
2c0262af
FB
4134 }
4135 goto do_lcall;
4136 case 0xe9: /* jmp */
14ce26e7
FB
4137 if (dflag)
4138 tval = (int32_t)insn_get(s, OT_LONG);
4139 else
4140 tval = (int16_t)insn_get(s, OT_WORD);
4141 tval += s->pc - s->cs_base;
2c0262af 4142 if (s->dflag == 0)
14ce26e7
FB
4143 tval &= 0xffff;
4144 gen_jmp(s, tval);
2c0262af
FB
4145 break;
4146 case 0xea: /* ljmp im */
4147 {
4148 unsigned int selector, offset;
4149
14ce26e7
FB
4150 if (CODE64(s))
4151 goto illegal_op;
2c0262af
FB
4152 ot = dflag ? OT_LONG : OT_WORD;
4153 offset = insn_get(s, ot);
4154 selector = insn_get(s, OT_WORD);
4155
4156 gen_op_movl_T0_im(selector);
14ce26e7 4157 gen_op_movl_T1_imu(offset);
2c0262af
FB
4158 }
4159 goto do_ljmp;
4160 case 0xeb: /* jmp Jb */
14ce26e7
FB
4161 tval = (int8_t)insn_get(s, OT_BYTE);
4162 tval += s->pc - s->cs_base;
2c0262af 4163 if (s->dflag == 0)
14ce26e7
FB
4164 tval &= 0xffff;
4165 gen_jmp(s, tval);
2c0262af
FB
4166 break;
4167 case 0x70 ... 0x7f: /* jcc Jb */
14ce26e7 4168 tval = (int8_t)insn_get(s, OT_BYTE);
2c0262af
FB
4169 goto do_jcc;
4170 case 0x180 ... 0x18f: /* jcc Jv */
4171 if (dflag) {
14ce26e7 4172 tval = (int32_t)insn_get(s, OT_LONG);
2c0262af 4173 } else {
14ce26e7 4174 tval = (int16_t)insn_get(s, OT_WORD);
2c0262af
FB
4175 }
4176 do_jcc:
4177 next_eip = s->pc - s->cs_base;
14ce26e7 4178 tval += next_eip;
2c0262af 4179 if (s->dflag == 0)
14ce26e7
FB
4180 tval &= 0xffff;
4181 gen_jcc(s, b, tval, next_eip);
2c0262af
FB
4182 break;
4183
4184 case 0x190 ... 0x19f: /* setcc Gv */
61382a50 4185 modrm = ldub_code(s->pc++);
2c0262af
FB
4186 gen_setcc(s, b);
4187 gen_ldst_modrm(s, modrm, OT_BYTE, OR_TMP0, 1);
4188 break;
4189 case 0x140 ... 0x14f: /* cmov Gv, Ev */
14ce26e7 4190 ot = dflag + OT_WORD;
61382a50 4191 modrm = ldub_code(s->pc++);
14ce26e7 4192 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af
FB
4193 mod = (modrm >> 6) & 3;
4194 gen_setcc(s, b);
4195 if (mod != 3) {
4196 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4197 gen_op_ld_T1_A0[ot + s->mem_index]();
4198 } else {
14ce26e7 4199 rm = (modrm & 7) | REX_B(s);
2c0262af
FB
4200 gen_op_mov_TN_reg[ot][1][rm]();
4201 }
4202 gen_op_cmov_reg_T1_T0[ot - OT_WORD][reg]();
4203 break;
4204
4205 /************************/
4206 /* flags */
4207 case 0x9c: /* pushf */
4208 if (s->vm86 && s->iopl != 3) {
4209 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
4210 } else {
4211 if (s->cc_op != CC_OP_DYNAMIC)
4212 gen_op_set_cc_op(s->cc_op);
4213 gen_op_movl_T0_eflags();
4214 gen_push_T0(s);
4215 }
4216 break;
4217 case 0x9d: /* popf */
4218 if (s->vm86 && s->iopl != 3) {
4219 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
4220 } else {
4221 gen_pop_T0(s);
4222 if (s->cpl == 0) {
4223 if (s->dflag) {
4224 gen_op_movl_eflags_T0_cpl0();
4225 } else {
4226 gen_op_movw_eflags_T0_cpl0();
4227 }
4228 } else {
4136f33c
FB
4229 if (s->cpl <= s->iopl) {
4230 if (s->dflag) {
4231 gen_op_movl_eflags_T0_io();
4232 } else {
4233 gen_op_movw_eflags_T0_io();
4234 }
2c0262af 4235 } else {
4136f33c
FB
4236 if (s->dflag) {
4237 gen_op_movl_eflags_T0();
4238 } else {
4239 gen_op_movw_eflags_T0();
4240 }
2c0262af
FB
4241 }
4242 }
4243 gen_pop_update(s);
4244 s->cc_op = CC_OP_EFLAGS;
4245 /* abort translation because TF flag may change */
14ce26e7 4246 gen_jmp_im(s->pc - s->cs_base);
2c0262af
FB
4247 gen_eob(s);
4248 }
4249 break;
4250 case 0x9e: /* sahf */
14ce26e7
FB
4251 if (CODE64(s))
4252 goto illegal_op;
2c0262af
FB
4253 gen_op_mov_TN_reg[OT_BYTE][0][R_AH]();
4254 if (s->cc_op != CC_OP_DYNAMIC)
4255 gen_op_set_cc_op(s->cc_op);
4256 gen_op_movb_eflags_T0();
4257 s->cc_op = CC_OP_EFLAGS;
4258 break;
4259 case 0x9f: /* lahf */
14ce26e7
FB
4260 if (CODE64(s))
4261 goto illegal_op;
2c0262af
FB
4262 if (s->cc_op != CC_OP_DYNAMIC)
4263 gen_op_set_cc_op(s->cc_op);
4264 gen_op_movl_T0_eflags();
4265 gen_op_mov_reg_T0[OT_BYTE][R_AH]();
4266 break;
4267 case 0xf5: /* cmc */
4268 if (s->cc_op != CC_OP_DYNAMIC)
4269 gen_op_set_cc_op(s->cc_op);
4270 gen_op_cmc();
4271 s->cc_op = CC_OP_EFLAGS;
4272 break;
4273 case 0xf8: /* clc */
4274 if (s->cc_op != CC_OP_DYNAMIC)
4275 gen_op_set_cc_op(s->cc_op);
4276 gen_op_clc();
4277 s->cc_op = CC_OP_EFLAGS;
4278 break;
4279 case 0xf9: /* stc */
4280 if (s->cc_op != CC_OP_DYNAMIC)
4281 gen_op_set_cc_op(s->cc_op);
4282 gen_op_stc();
4283 s->cc_op = CC_OP_EFLAGS;
4284 break;
4285 case 0xfc: /* cld */
4286 gen_op_cld();
4287 break;
4288 case 0xfd: /* std */
4289 gen_op_std();
4290 break;
4291
4292 /************************/
4293 /* bit operations */
4294 case 0x1ba: /* bt/bts/btr/btc Gv, im */
14ce26e7 4295 ot = dflag + OT_WORD;
61382a50 4296 modrm = ldub_code(s->pc++);
14ce26e7 4297 op = ((modrm >> 3) & 7) | rex_r;
2c0262af 4298 mod = (modrm >> 6) & 3;
14ce26e7 4299 rm = (modrm & 7) | REX_B(s);
2c0262af 4300 if (mod != 3) {
14ce26e7 4301 s->rip_offset = 1;
2c0262af
FB
4302 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4303 gen_op_ld_T0_A0[ot + s->mem_index]();
4304 } else {
4305 gen_op_mov_TN_reg[ot][0][rm]();
4306 }
4307 /* load shift */
61382a50 4308 val = ldub_code(s->pc++);
2c0262af
FB
4309 gen_op_movl_T1_im(val);
4310 if (op < 4)
4311 goto illegal_op;
4312 op -= 4;
4313 gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
4314 s->cc_op = CC_OP_SARB + ot;
4315 if (op != 0) {
4316 if (mod != 3)
4317 gen_op_st_T0_A0[ot + s->mem_index]();
4318 else
4319 gen_op_mov_reg_T0[ot][rm]();
4320 gen_op_update_bt_cc();
4321 }
4322 break;
4323 case 0x1a3: /* bt Gv, Ev */
4324 op = 0;
4325 goto do_btx;
4326 case 0x1ab: /* bts */
4327 op = 1;
4328 goto do_btx;
4329 case 0x1b3: /* btr */
4330 op = 2;
4331 goto do_btx;
4332 case 0x1bb: /* btc */
4333 op = 3;
4334 do_btx:
14ce26e7 4335 ot = dflag + OT_WORD;
61382a50 4336 modrm = ldub_code(s->pc++);
14ce26e7 4337 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af 4338 mod = (modrm >> 6) & 3;
14ce26e7 4339 rm = (modrm & 7) | REX_B(s);
2c0262af
FB
4340 gen_op_mov_TN_reg[OT_LONG][1][reg]();
4341 if (mod != 3) {
4342 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4343 /* specific case: we need to add a displacement */
14ce26e7 4344 gen_op_add_bit_A0_T1[ot - OT_WORD]();
2c0262af
FB
4345 gen_op_ld_T0_A0[ot + s->mem_index]();
4346 } else {
4347 gen_op_mov_TN_reg[ot][0][rm]();
4348 }
4349 gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
4350 s->cc_op = CC_OP_SARB + ot;
4351 if (op != 0) {
4352 if (mod != 3)
4353 gen_op_st_T0_A0[ot + s->mem_index]();
4354 else
4355 gen_op_mov_reg_T0[ot][rm]();
4356 gen_op_update_bt_cc();
4357 }
4358 break;
4359 case 0x1bc: /* bsf */
4360 case 0x1bd: /* bsr */
14ce26e7 4361 ot = dflag + OT_WORD;
61382a50 4362 modrm = ldub_code(s->pc++);
14ce26e7 4363 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af 4364 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
686f3f26
FB
4365 /* NOTE: in order to handle the 0 case, we must load the
4366 result. It could be optimized with a generated jump */
4367 gen_op_mov_TN_reg[ot][1][reg]();
2c0262af 4368 gen_op_bsx_T0_cc[ot - OT_WORD][b & 1]();
686f3f26 4369 gen_op_mov_reg_T1[ot][reg]();
2c0262af
FB
4370 s->cc_op = CC_OP_LOGICB + ot;
4371 break;
4372 /************************/
4373 /* bcd */
4374 case 0x27: /* daa */
14ce26e7
FB
4375 if (CODE64(s))
4376 goto illegal_op;
2c0262af
FB
4377 if (s->cc_op != CC_OP_DYNAMIC)
4378 gen_op_set_cc_op(s->cc_op);
4379 gen_op_daa();
4380 s->cc_op = CC_OP_EFLAGS;
4381 break;
4382 case 0x2f: /* das */
14ce26e7
FB
4383 if (CODE64(s))
4384 goto illegal_op;
2c0262af
FB
4385 if (s->cc_op != CC_OP_DYNAMIC)
4386 gen_op_set_cc_op(s->cc_op);
4387 gen_op_das();
4388 s->cc_op = CC_OP_EFLAGS;
4389 break;
4390 case 0x37: /* aaa */
14ce26e7
FB
4391 if (CODE64(s))
4392 goto illegal_op;
2c0262af
FB
4393 if (s->cc_op != CC_OP_DYNAMIC)
4394 gen_op_set_cc_op(s->cc_op);
4395 gen_op_aaa();
4396 s->cc_op = CC_OP_EFLAGS;
4397 break;
4398 case 0x3f: /* aas */
14ce26e7
FB
4399 if (CODE64(s))
4400 goto illegal_op;
2c0262af
FB
4401 if (s->cc_op != CC_OP_DYNAMIC)
4402 gen_op_set_cc_op(s->cc_op);
4403 gen_op_aas();
4404 s->cc_op = CC_OP_EFLAGS;
4405 break;
4406 case 0xd4: /* aam */
14ce26e7
FB
4407 if (CODE64(s))
4408 goto illegal_op;
61382a50 4409 val = ldub_code(s->pc++);
2c0262af
FB
4410 gen_op_aam(val);
4411 s->cc_op = CC_OP_LOGICB;
4412 break;
4413 case 0xd5: /* aad */
14ce26e7
FB
4414 if (CODE64(s))
4415 goto illegal_op;
61382a50 4416 val = ldub_code(s->pc++);
2c0262af
FB
4417 gen_op_aad(val);
4418 s->cc_op = CC_OP_LOGICB;
4419 break;
4420 /************************/
4421 /* misc */
4422 case 0x90: /* nop */
14ce26e7 4423 /* XXX: xchg + rex handling */
ab1f142b
FB
4424 /* XXX: correct lock test for all insn */
4425 if (prefixes & PREFIX_LOCK)
4426 goto illegal_op;
2c0262af
FB
4427 break;
4428 case 0x9b: /* fwait */
7eee2a50
FB
4429 if ((s->flags & (HF_MP_MASK | HF_TS_MASK)) ==
4430 (HF_MP_MASK | HF_TS_MASK)) {
4431 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
2ee73ac3
FB
4432 } else {
4433 if (s->cc_op != CC_OP_DYNAMIC)
4434 gen_op_set_cc_op(s->cc_op);
14ce26e7 4435 gen_jmp_im(pc_start - s->cs_base);
2ee73ac3 4436 gen_op_fwait();
7eee2a50 4437 }
2c0262af
FB
4438 break;
4439 case 0xcc: /* int3 */
4440 gen_interrupt(s, EXCP03_INT3, pc_start - s->cs_base, s->pc - s->cs_base);
4441 break;
4442 case 0xcd: /* int N */
61382a50 4443 val = ldub_code(s->pc++);
f115e911 4444 if (s->vm86 && s->iopl != 3) {
2c0262af 4445 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
f115e911
FB
4446 } else {
4447 gen_interrupt(s, val, pc_start - s->cs_base, s->pc - s->cs_base);
4448 }
2c0262af
FB
4449 break;
4450 case 0xce: /* into */
14ce26e7
FB
4451 if (CODE64(s))
4452 goto illegal_op;
2c0262af
FB
4453 if (s->cc_op != CC_OP_DYNAMIC)
4454 gen_op_set_cc_op(s->cc_op);
4455 gen_op_into(s->pc - s->cs_base);
4456 break;
4457 case 0xf1: /* icebp (undocumented, exits to external debugger) */
14ce26e7 4458#if 0
2c0262af 4459 gen_debug(s, pc_start - s->cs_base);
14ce26e7
FB
4460#else
4461 /* test ! */
4462 cpu_set_log(CPU_LOG_TB_IN_ASM | CPU_LOG_PCALL);
4463#endif
2c0262af
FB
4464 break;
4465 case 0xfa: /* cli */
4466 if (!s->vm86) {
4467 if (s->cpl <= s->iopl) {
4468 gen_op_cli();
4469 } else {
4470 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
4471 }
4472 } else {
4473 if (s->iopl == 3) {
4474 gen_op_cli();
4475 } else {
4476 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
4477 }
4478 }
4479 break;
4480 case 0xfb: /* sti */
4481 if (!s->vm86) {
4482 if (s->cpl <= s->iopl) {
4483 gen_sti:
4484 gen_op_sti();
4485 /* interruptions are enabled only the first insn after sti */
a2cc3b24
FB
4486 /* If several instructions disable interrupts, only the
4487 _first_ does it */
4488 if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
4489 gen_op_set_inhibit_irq();
2c0262af 4490 /* give a chance to handle pending irqs */
14ce26e7 4491 gen_jmp_im(s->pc - s->cs_base);
2c0262af
FB
4492 gen_eob(s);
4493 } else {
4494 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
4495 }
4496 } else {
4497 if (s->iopl == 3) {
4498 goto gen_sti;
4499 } else {
4500 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
4501 }
4502 }
4503 break;
4504 case 0x62: /* bound */
14ce26e7
FB
4505 if (CODE64(s))
4506 goto illegal_op;
2c0262af 4507 ot = dflag ? OT_LONG : OT_WORD;
61382a50 4508 modrm = ldub_code(s->pc++);
2c0262af
FB
4509 reg = (modrm >> 3) & 7;
4510 mod = (modrm >> 6) & 3;
4511 if (mod == 3)
4512 goto illegal_op;
cabf23c3 4513 gen_op_mov_TN_reg[ot][0][reg]();
2c0262af 4514 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
14ce26e7 4515 gen_jmp_im(pc_start - s->cs_base);
2c0262af 4516 if (ot == OT_WORD)
14ce26e7 4517 gen_op_boundw();
2c0262af 4518 else
14ce26e7 4519 gen_op_boundl();
2c0262af
FB
4520 break;
4521 case 0x1c8 ... 0x1cf: /* bswap reg */
14ce26e7
FB
4522 reg = (b & 7) | REX_B(s);
4523#ifdef TARGET_X86_64
4524 if (dflag == 2) {
4525 gen_op_mov_TN_reg[OT_QUAD][0][reg]();
4526 gen_op_bswapq_T0();
4527 gen_op_mov_reg_T0[OT_QUAD][reg]();
4528 } else
4529#endif
4530 {
4531 gen_op_mov_TN_reg[OT_LONG][0][reg]();
4532 gen_op_bswapl_T0();
4533 gen_op_mov_reg_T0[OT_LONG][reg]();
4534 }
2c0262af
FB
4535 break;
4536 case 0xd6: /* salc */
14ce26e7
FB
4537 if (CODE64(s))
4538 goto illegal_op;
2c0262af
FB
4539 if (s->cc_op != CC_OP_DYNAMIC)
4540 gen_op_set_cc_op(s->cc_op);
4541 gen_op_salc();
4542 break;
4543 case 0xe0: /* loopnz */
4544 case 0xe1: /* loopz */
4545 if (s->cc_op != CC_OP_DYNAMIC)
4546 gen_op_set_cc_op(s->cc_op);
4547 /* FALL THRU */
4548 case 0xe2: /* loop */
4549 case 0xe3: /* jecxz */
14ce26e7
FB
4550 {
4551 int l1, l2;
4552
4553 tval = (int8_t)insn_get(s, OT_BYTE);
4554 next_eip = s->pc - s->cs_base;
4555 tval += next_eip;
4556 if (s->dflag == 0)
4557 tval &= 0xffff;
4558
4559 l1 = gen_new_label();
4560 l2 = gen_new_label();
4561 b &= 3;
4562 if (b == 3) {
4563 gen_op_jz_ecx[s->aflag](l1);
4564 } else {
4565 gen_op_dec_ECX[s->aflag]();
4566 gen_op_loop[s->aflag][b](l1);
4567 }
4568
4569 gen_jmp_im(next_eip);
4570 gen_op_jmp_label(l2);
4571 gen_set_label(l1);
4572 gen_jmp_im(tval);
4573 gen_set_label(l2);
4574 gen_eob(s);
4575 }
2c0262af
FB
4576 break;
4577 case 0x130: /* wrmsr */
4578 case 0x132: /* rdmsr */
4579 if (s->cpl != 0) {
4580 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
4581 } else {
4582 if (b & 2)
4583 gen_op_rdmsr();
4584 else
4585 gen_op_wrmsr();
4586 }
4587 break;
4588 case 0x131: /* rdtsc */
4589 gen_op_rdtsc();
4590 break;
023fe10d 4591 case 0x134: /* sysenter */
14ce26e7
FB
4592 if (CODE64(s))
4593 goto illegal_op;
023fe10d
FB
4594 if (!s->pe) {
4595 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
4596 } else {
4597 if (s->cc_op != CC_OP_DYNAMIC) {
4598 gen_op_set_cc_op(s->cc_op);
4599 s->cc_op = CC_OP_DYNAMIC;
4600 }
14ce26e7 4601 gen_jmp_im(pc_start - s->cs_base);
023fe10d
FB
4602 gen_op_sysenter();
4603 gen_eob(s);
4604 }
4605 break;
4606 case 0x135: /* sysexit */
14ce26e7
FB
4607 if (CODE64(s))
4608 goto illegal_op;
023fe10d
FB
4609 if (!s->pe) {
4610 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
4611 } else {
4612 if (s->cc_op != CC_OP_DYNAMIC) {
4613 gen_op_set_cc_op(s->cc_op);
4614 s->cc_op = CC_OP_DYNAMIC;
4615 }
14ce26e7 4616 gen_jmp_im(pc_start - s->cs_base);
023fe10d
FB
4617 gen_op_sysexit();
4618 gen_eob(s);
4619 }
4620 break;
14ce26e7
FB
4621#ifdef TARGET_X86_64
4622 case 0x105: /* syscall */
4623 /* XXX: is it usable in real mode ? */
4624 if (s->cc_op != CC_OP_DYNAMIC) {
4625 gen_op_set_cc_op(s->cc_op);
4626 s->cc_op = CC_OP_DYNAMIC;
4627 }
4628 gen_jmp_im(pc_start - s->cs_base);
06c2f506 4629 gen_op_syscall(s->pc - pc_start);
14ce26e7
FB
4630 gen_eob(s);
4631 break;
4632 case 0x107: /* sysret */
4633 if (!s->pe) {
4634 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
4635 } else {
4636 if (s->cc_op != CC_OP_DYNAMIC) {
4637 gen_op_set_cc_op(s->cc_op);
4638 s->cc_op = CC_OP_DYNAMIC;
4639 }
4640 gen_jmp_im(pc_start - s->cs_base);
4641 gen_op_sysret(s->dflag);
4642 gen_eob(s);
4643 }
4644 break;
4645#endif
2c0262af
FB
4646 case 0x1a2: /* cpuid */
4647 gen_op_cpuid();
4648 break;
4649 case 0xf4: /* hlt */
4650 if (s->cpl != 0) {
4651 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
4652 } else {
4653 if (s->cc_op != CC_OP_DYNAMIC)
4654 gen_op_set_cc_op(s->cc_op);
14ce26e7 4655 gen_jmp_im(s->pc - s->cs_base);
2c0262af
FB
4656 gen_op_hlt();
4657 s->is_jmp = 3;
4658 }
4659 break;
4660 case 0x100:
61382a50 4661 modrm = ldub_code(s->pc++);
2c0262af
FB
4662 mod = (modrm >> 6) & 3;
4663 op = (modrm >> 3) & 7;
4664 switch(op) {
4665 case 0: /* sldt */
f115e911
FB
4666 if (!s->pe || s->vm86)
4667 goto illegal_op;
2c0262af
FB
4668 gen_op_movl_T0_env(offsetof(CPUX86State,ldt.selector));
4669 ot = OT_WORD;
4670 if (mod == 3)
4671 ot += s->dflag;
4672 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
4673 break;
4674 case 2: /* lldt */
f115e911
FB
4675 if (!s->pe || s->vm86)
4676 goto illegal_op;
2c0262af
FB
4677 if (s->cpl != 0) {
4678 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
4679 } else {
4680 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
14ce26e7 4681 gen_jmp_im(pc_start - s->cs_base);
2c0262af
FB
4682 gen_op_lldt_T0();
4683 }
4684 break;
4685 case 1: /* str */
f115e911
FB
4686 if (!s->pe || s->vm86)
4687 goto illegal_op;
2c0262af
FB
4688 gen_op_movl_T0_env(offsetof(CPUX86State,tr.selector));
4689 ot = OT_WORD;
4690 if (mod == 3)
4691 ot += s->dflag;
4692 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
4693 break;
4694 case 3: /* ltr */
f115e911
FB
4695 if (!s->pe || s->vm86)
4696 goto illegal_op;
2c0262af
FB
4697 if (s->cpl != 0) {
4698 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
4699 } else {
4700 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
14ce26e7 4701 gen_jmp_im(pc_start - s->cs_base);
2c0262af
FB
4702 gen_op_ltr_T0();
4703 }
4704 break;
4705 case 4: /* verr */
4706 case 5: /* verw */
f115e911
FB
4707 if (!s->pe || s->vm86)
4708 goto illegal_op;
4709 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
4710 if (s->cc_op != CC_OP_DYNAMIC)
4711 gen_op_set_cc_op(s->cc_op);
4712 if (op == 4)
4713 gen_op_verr();
4714 else
4715 gen_op_verw();
4716 s->cc_op = CC_OP_EFLAGS;
4717 break;
2c0262af
FB
4718 default:
4719 goto illegal_op;
4720 }
4721 break;
4722 case 0x101:
61382a50 4723 modrm = ldub_code(s->pc++);
2c0262af
FB
4724 mod = (modrm >> 6) & 3;
4725 op = (modrm >> 3) & 7;
4726 switch(op) {
4727 case 0: /* sgdt */
4728 case 1: /* sidt */
4729 if (mod == 3)
4730 goto illegal_op;
4731 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4732 if (op == 0)
4733 gen_op_movl_T0_env(offsetof(CPUX86State,gdt.limit));
4734 else
4735 gen_op_movl_T0_env(offsetof(CPUX86State,idt.limit));
4736 gen_op_st_T0_A0[OT_WORD + s->mem_index]();
14ce26e7
FB
4737#ifdef TARGET_X86_64
4738 if (CODE64(s))
4739 gen_op_addq_A0_im(2);
4740 else
4741#endif
4742 gen_op_addl_A0_im(2);
2c0262af 4743 if (op == 0)
14ce26e7 4744 gen_op_movtl_T0_env(offsetof(CPUX86State,gdt.base));
2c0262af 4745 else
14ce26e7 4746 gen_op_movtl_T0_env(offsetof(CPUX86State,idt.base));
2c0262af
FB
4747 if (!s->dflag)
4748 gen_op_andl_T0_im(0xffffff);
14ce26e7 4749 gen_op_st_T0_A0[CODE64(s) + OT_LONG + s->mem_index]();
2c0262af
FB
4750 break;
4751 case 2: /* lgdt */
4752 case 3: /* lidt */
4753 if (mod == 3)
4754 goto illegal_op;
4755 if (s->cpl != 0) {
4756 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
4757 } else {
4758 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4759 gen_op_ld_T1_A0[OT_WORD + s->mem_index]();
14ce26e7
FB
4760#ifdef TARGET_X86_64
4761 if (CODE64(s))
4762 gen_op_addq_A0_im(2);
4763 else
4764#endif
4765 gen_op_addl_A0_im(2);
4766 gen_op_ld_T0_A0[CODE64(s) + OT_LONG + s->mem_index]();
2c0262af
FB
4767 if (!s->dflag)
4768 gen_op_andl_T0_im(0xffffff);
4769 if (op == 2) {
14ce26e7 4770 gen_op_movtl_env_T0(offsetof(CPUX86State,gdt.base));
2c0262af
FB
4771 gen_op_movl_env_T1(offsetof(CPUX86State,gdt.limit));
4772 } else {
14ce26e7 4773 gen_op_movtl_env_T0(offsetof(CPUX86State,idt.base));
2c0262af
FB
4774 gen_op_movl_env_T1(offsetof(CPUX86State,idt.limit));
4775 }
4776 }
4777 break;
4778 case 4: /* smsw */
4779 gen_op_movl_T0_env(offsetof(CPUX86State,cr[0]));
4780 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 1);
4781 break;
4782 case 6: /* lmsw */
4783 if (s->cpl != 0) {
4784 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
4785 } else {
4786 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
4787 gen_op_lmsw_T0();
14ce26e7 4788 gen_jmp_im(s->pc - s->cs_base);
d71b9a8b 4789 gen_eob(s);
2c0262af
FB
4790 }
4791 break;
4792 case 7: /* invlpg */
4793 if (s->cpl != 0) {
4794 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
4795 } else {
14ce26e7
FB
4796 if (mod == 3) {
4797#ifdef TARGET_X86_64
4798 if (CODE64(s) && (modrm & 7) == 0) {
4799 /* swapgs */
4800 gen_op_movtl_T0_env(offsetof(CPUX86State,segs[R_GS].base));
4801 gen_op_movtl_T1_env(offsetof(CPUX86State,kernelgsbase));
4802 gen_op_movtl_env_T1(offsetof(CPUX86State,segs[R_GS].base));
4803 gen_op_movtl_env_T0(offsetof(CPUX86State,kernelgsbase));
4804 } else
4805#endif
4806 {
4807 goto illegal_op;
4808 }
4809 } else {
4810 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4811 gen_op_invlpg_A0();
4812 gen_jmp_im(s->pc - s->cs_base);
4813 gen_eob(s);
4814 }
2c0262af
FB
4815 }
4816 break;
4817 default:
4818 goto illegal_op;
4819 }
4820 break;
3415a4dd
FB
4821 case 0x108: /* invd */
4822 case 0x109: /* wbinvd */
4823 if (s->cpl != 0) {
4824 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
4825 } else {
4826 /* nothing to do */
4827 }
4828 break;
14ce26e7 4829 case 0x1ae: /* sfence */
f115e911 4830 modrm = ldub_code(s->pc++);
f115e911 4831 mod = (modrm >> 6) & 3;
14ce26e7
FB
4832 op = (modrm >> 3) & 7;
4833 switch(op) {
4834 case 0: /* fxsave */
4835 if (mod == 3 || !(s->cpuid_features & CPUID_FXSR))
4836 goto illegal_op;
f115e911 4837 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
14ce26e7
FB
4838 gen_op_fxsave_A0((s->dflag == 2));
4839 break;
4840 case 1: /* fxrstor */
4841 if (mod == 3 || !(s->cpuid_features & CPUID_FXSR))
4842 goto illegal_op;
4843 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4844 gen_op_fxrstor_A0((s->dflag == 2));
4845 break;
4846 case 5: /* lfence */
4847 case 6: /* mfence */
4848 case 7: /* sfence */
4849 if ((modrm & 0xc7) != 0xc0 || !(s->cpuid_features & CPUID_SSE))
4850 goto illegal_op;
4851 break;
4852 default:
4853 goto illegal_op;
f115e911 4854 }
14ce26e7
FB
4855 break;
4856 case 0x63: /* arpl or movslS (x86_64) */
4857#ifdef TARGET_X86_64
4858 if (CODE64(s)) {
4859 int d_ot;
4860 /* d_ot is the size of destination */
4861 d_ot = dflag + OT_WORD;
4862
4863 modrm = ldub_code(s->pc++);
4864 reg = ((modrm >> 3) & 7) | rex_r;
4865 mod = (modrm >> 6) & 3;
4866 rm = (modrm & 7) | REX_B(s);
4867
4868 if (mod == 3) {
4869 gen_op_mov_TN_reg[OT_LONG][0][rm]();
4870 /* sign extend */
4871 if (d_ot == OT_QUAD)
4872 gen_op_movslq_T0_T0();
4873 gen_op_mov_reg_T0[d_ot][reg]();
4874 } else {
4875 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4876 if (d_ot == OT_QUAD) {
4877 gen_op_lds_T0_A0[OT_LONG + s->mem_index]();
4878 } else {
4879 gen_op_ld_T0_A0[OT_LONG + s->mem_index]();
4880 }
4881 gen_op_mov_reg_T0[d_ot][reg]();
4882 }
4883 } else
4884#endif
4885 {
4886 if (!s->pe || s->vm86)
4887 goto illegal_op;
4888 ot = dflag ? OT_LONG : OT_WORD;
4889 modrm = ldub_code(s->pc++);
4890 reg = (modrm >> 3) & 7;
4891 mod = (modrm >> 6) & 3;
4892 rm = modrm & 7;
4893 if (mod != 3) {
4894 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4895 gen_op_ld_T0_A0[ot + s->mem_index]();
4896 } else {
4897 gen_op_mov_TN_reg[ot][0][rm]();
4898 }
4899 if (s->cc_op != CC_OP_DYNAMIC)
4900 gen_op_set_cc_op(s->cc_op);
4901 gen_op_arpl();
4902 s->cc_op = CC_OP_EFLAGS;
4903 if (mod != 3) {
4904 gen_op_st_T0_A0[ot + s->mem_index]();
4905 } else {
4906 gen_op_mov_reg_T0[ot][rm]();
4907 }
4908 gen_op_arpl_update();
f115e911 4909 }
f115e911 4910 break;
2c0262af
FB
4911 case 0x102: /* lar */
4912 case 0x103: /* lsl */
4913 if (!s->pe || s->vm86)
4914 goto illegal_op;
4915 ot = dflag ? OT_LONG : OT_WORD;
61382a50 4916 modrm = ldub_code(s->pc++);
14ce26e7 4917 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af
FB
4918 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
4919 gen_op_mov_TN_reg[ot][1][reg]();
4920 if (s->cc_op != CC_OP_DYNAMIC)
4921 gen_op_set_cc_op(s->cc_op);
4922 if (b == 0x102)
4923 gen_op_lar();
4924 else
4925 gen_op_lsl();
4926 s->cc_op = CC_OP_EFLAGS;
4927 gen_op_mov_reg_T1[ot][reg]();
4928 break;
4929 case 0x118:
61382a50 4930 modrm = ldub_code(s->pc++);
2c0262af
FB
4931 mod = (modrm >> 6) & 3;
4932 op = (modrm >> 3) & 7;
4933 switch(op) {
4934 case 0: /* prefetchnta */
4935 case 1: /* prefetchnt0 */
4936 case 2: /* prefetchnt0 */
4937 case 3: /* prefetchnt0 */
4938 if (mod == 3)
4939 goto illegal_op;
4940 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4941 /* nothing more to do */
4942 break;
4943 default:
4944 goto illegal_op;
4945 }
4946 break;
4947 case 0x120: /* mov reg, crN */
4948 case 0x122: /* mov crN, reg */
4949 if (s->cpl != 0) {
4950 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
4951 } else {
61382a50 4952 modrm = ldub_code(s->pc++);
2c0262af
FB
4953 if ((modrm & 0xc0) != 0xc0)
4954 goto illegal_op;
14ce26e7
FB
4955 rm = (modrm & 7) | REX_B(s);
4956 reg = ((modrm >> 3) & 7) | rex_r;
4957 if (CODE64(s))
4958 ot = OT_QUAD;
4959 else
4960 ot = OT_LONG;
2c0262af
FB
4961 switch(reg) {
4962 case 0:
4963 case 2:
4964 case 3:
4965 case 4:
4966 if (b & 2) {
14ce26e7 4967 gen_op_mov_TN_reg[ot][0][rm]();
2c0262af 4968 gen_op_movl_crN_T0(reg);
14ce26e7 4969 gen_jmp_im(s->pc - s->cs_base);
2c0262af
FB
4970 gen_eob(s);
4971 } else {
14ce26e7
FB
4972 gen_op_movtl_T0_env(offsetof(CPUX86State,cr[reg]));
4973 gen_op_mov_reg_T0[ot][rm]();
2c0262af
FB
4974 }
4975 break;
14ce26e7 4976 /* XXX: add CR8 for x86_64 */
2c0262af
FB
4977 default:
4978 goto illegal_op;
4979 }
4980 }
4981 break;
4982 case 0x121: /* mov reg, drN */
4983 case 0x123: /* mov drN, reg */
4984 if (s->cpl != 0) {
4985 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
4986 } else {
61382a50 4987 modrm = ldub_code(s->pc++);
2c0262af
FB
4988 if ((modrm & 0xc0) != 0xc0)
4989 goto illegal_op;
14ce26e7
FB
4990 rm = (modrm & 7) | REX_B(s);
4991 reg = ((modrm >> 3) & 7) | rex_r;
4992 if (CODE64(s))
4993 ot = OT_QUAD;
4994 else
4995 ot = OT_LONG;
2c0262af 4996 /* XXX: do it dynamically with CR4.DE bit */
14ce26e7 4997 if (reg == 4 || reg == 5 || reg >= 8)
2c0262af
FB
4998 goto illegal_op;
4999 if (b & 2) {
14ce26e7 5000 gen_op_mov_TN_reg[ot][0][rm]();
2c0262af 5001 gen_op_movl_drN_T0(reg);
14ce26e7 5002 gen_jmp_im(s->pc - s->cs_base);
2c0262af
FB
5003 gen_eob(s);
5004 } else {
14ce26e7
FB
5005 gen_op_movtl_T0_env(offsetof(CPUX86State,dr[reg]));
5006 gen_op_mov_reg_T0[ot][rm]();
2c0262af
FB
5007 }
5008 }
5009 break;
5010 case 0x106: /* clts */
5011 if (s->cpl != 0) {
5012 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5013 } else {
5014 gen_op_clts();
7eee2a50 5015 /* abort block because static cpu state changed */
14ce26e7 5016 gen_jmp_im(s->pc - s->cs_base);
7eee2a50 5017 gen_eob(s);
2c0262af
FB
5018 }
5019 break;
14ce26e7
FB
5020 /* SSE support */
5021 case 0x16f:
5022 if (prefixes & PREFIX_DATA) {
5023 /* movdqa xmm1, xmm2/mem128 */
5024 if (!(s->cpuid_features & CPUID_SSE))
5025 goto illegal_op;
5026 modrm = ldub_code(s->pc++);
5027 reg = ((modrm >> 3) & 7) | rex_r;
5028 mod = (modrm >> 6) & 3;
5029 if (mod != 3) {
5030 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
5031 gen_ldo_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg]));
5032 } else {
5033 rm = (modrm & 7) | REX_B(s);
5034 gen_op_movo(offsetof(CPUX86State,xmm_regs[reg]),
5035 offsetof(CPUX86State,xmm_regs[rm]));
5036 }
5037 } else {
5038 goto illegal_op;
5039 }
5040 break;
5041 case 0x1e7:
5042 if (prefixes & PREFIX_DATA) {
5043 /* movntdq mem128, xmm1 */
5044 if (!(s->cpuid_features & CPUID_SSE))
5045 goto illegal_op;
5046 modrm = ldub_code(s->pc++);
5047 reg = ((modrm >> 3) & 7) | rex_r;
5048 mod = (modrm >> 6) & 3;
5049 if (mod != 3) {
5050 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
5051 gen_sto_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg]));
5052 } else {
5053 goto illegal_op;
5054 }
5055 } else {
5056 goto illegal_op;
5057 }
5058 break;
5059 case 0x17f:
5060 if (prefixes & PREFIX_DATA) {
5061 /* movdqa xmm2/mem128, xmm1 */
5062 if (!(s->cpuid_features & CPUID_SSE))
5063 goto illegal_op;
5064 modrm = ldub_code(s->pc++);
5065 reg = ((modrm >> 3) & 7) | rex_r;
5066 mod = (modrm >> 6) & 3;
5067 if (mod != 3) {
5068 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
5069 gen_sto_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg]));
5070 } else {
5071 rm = (modrm & 7) | REX_B(s);
5072 gen_op_movo(offsetof(CPUX86State,xmm_regs[rm]),
5073 offsetof(CPUX86State,xmm_regs[reg]));
5074 }
5075 } else {
5076 goto illegal_op;
5077 }
5078 break;
2c0262af
FB
5079 default:
5080 goto illegal_op;
5081 }
5082 /* lock generation */
5083 if (s->prefix & PREFIX_LOCK)
5084 gen_op_unlock();
5085 return s->pc;
5086 illegal_op:
ab1f142b
FB
5087 if (s->prefix & PREFIX_LOCK)
5088 gen_op_unlock();
2c0262af
FB
5089 /* XXX: ensure that no lock was generated */
5090 gen_exception(s, EXCP06_ILLOP, pc_start - s->cs_base);
5091 return s->pc;
5092}
5093
5094#define CC_OSZAPC (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C)
5095#define CC_OSZAP (CC_O | CC_S | CC_Z | CC_A | CC_P)
5096
5097/* flags read by an operation */
5098static uint16_t opc_read_flags[NB_OPS] = {
5099 [INDEX_op_aas] = CC_A,
5100 [INDEX_op_aaa] = CC_A,
5101 [INDEX_op_das] = CC_A | CC_C,
5102 [INDEX_op_daa] = CC_A | CC_C,
5103
2c0262af
FB
5104 /* subtle: due to the incl/decl implementation, C is used */
5105 [INDEX_op_update_inc_cc] = CC_C,
5106
5107 [INDEX_op_into] = CC_O,
5108
5109 [INDEX_op_jb_subb] = CC_C,
5110 [INDEX_op_jb_subw] = CC_C,
5111 [INDEX_op_jb_subl] = CC_C,
5112
5113 [INDEX_op_jz_subb] = CC_Z,
5114 [INDEX_op_jz_subw] = CC_Z,
5115 [INDEX_op_jz_subl] = CC_Z,
5116
5117 [INDEX_op_jbe_subb] = CC_Z | CC_C,
5118 [INDEX_op_jbe_subw] = CC_Z | CC_C,
5119 [INDEX_op_jbe_subl] = CC_Z | CC_C,
5120
5121 [INDEX_op_js_subb] = CC_S,
5122 [INDEX_op_js_subw] = CC_S,
5123 [INDEX_op_js_subl] = CC_S,
5124
5125 [INDEX_op_jl_subb] = CC_O | CC_S,
5126 [INDEX_op_jl_subw] = CC_O | CC_S,
5127 [INDEX_op_jl_subl] = CC_O | CC_S,
5128
5129 [INDEX_op_jle_subb] = CC_O | CC_S | CC_Z,
5130 [INDEX_op_jle_subw] = CC_O | CC_S | CC_Z,
5131 [INDEX_op_jle_subl] = CC_O | CC_S | CC_Z,
5132
5133 [INDEX_op_loopnzw] = CC_Z,
5134 [INDEX_op_loopnzl] = CC_Z,
5135 [INDEX_op_loopzw] = CC_Z,
5136 [INDEX_op_loopzl] = CC_Z,
5137
5138 [INDEX_op_seto_T0_cc] = CC_O,
5139 [INDEX_op_setb_T0_cc] = CC_C,
5140 [INDEX_op_setz_T0_cc] = CC_Z,
5141 [INDEX_op_setbe_T0_cc] = CC_Z | CC_C,
5142 [INDEX_op_sets_T0_cc] = CC_S,
5143 [INDEX_op_setp_T0_cc] = CC_P,
5144 [INDEX_op_setl_T0_cc] = CC_O | CC_S,
5145 [INDEX_op_setle_T0_cc] = CC_O | CC_S | CC_Z,
5146
5147 [INDEX_op_setb_T0_subb] = CC_C,
5148 [INDEX_op_setb_T0_subw] = CC_C,
5149 [INDEX_op_setb_T0_subl] = CC_C,
5150
5151 [INDEX_op_setz_T0_subb] = CC_Z,
5152 [INDEX_op_setz_T0_subw] = CC_Z,
5153 [INDEX_op_setz_T0_subl] = CC_Z,
5154
5155 [INDEX_op_setbe_T0_subb] = CC_Z | CC_C,
5156 [INDEX_op_setbe_T0_subw] = CC_Z | CC_C,
5157 [INDEX_op_setbe_T0_subl] = CC_Z | CC_C,
5158
5159 [INDEX_op_sets_T0_subb] = CC_S,
5160 [INDEX_op_sets_T0_subw] = CC_S,
5161 [INDEX_op_sets_T0_subl] = CC_S,
5162
5163 [INDEX_op_setl_T0_subb] = CC_O | CC_S,
5164 [INDEX_op_setl_T0_subw] = CC_O | CC_S,
5165 [INDEX_op_setl_T0_subl] = CC_O | CC_S,
5166
5167 [INDEX_op_setle_T0_subb] = CC_O | CC_S | CC_Z,
5168 [INDEX_op_setle_T0_subw] = CC_O | CC_S | CC_Z,
5169 [INDEX_op_setle_T0_subl] = CC_O | CC_S | CC_Z,
5170
5171 [INDEX_op_movl_T0_eflags] = CC_OSZAPC,
5172 [INDEX_op_cmc] = CC_C,
5173 [INDEX_op_salc] = CC_C,
5174
7399c5a9 5175 /* needed for correct flag optimisation before string ops */
14ce26e7
FB
5176 [INDEX_op_jnz_ecxw] = CC_OSZAPC,
5177 [INDEX_op_jnz_ecxl] = CC_OSZAPC,
7399c5a9
FB
5178 [INDEX_op_jz_ecxw] = CC_OSZAPC,
5179 [INDEX_op_jz_ecxl] = CC_OSZAPC,
14ce26e7
FB
5180
5181#ifdef TARGET_X86_64
5182 [INDEX_op_jb_subq] = CC_C,
5183 [INDEX_op_jz_subq] = CC_Z,
5184 [INDEX_op_jbe_subq] = CC_Z | CC_C,
5185 [INDEX_op_js_subq] = CC_S,
5186 [INDEX_op_jl_subq] = CC_O | CC_S,
5187 [INDEX_op_jle_subq] = CC_O | CC_S | CC_Z,
5188
5189 [INDEX_op_loopnzq] = CC_Z,
5190 [INDEX_op_loopzq] = CC_Z,
5191
5192 [INDEX_op_setb_T0_subq] = CC_C,
5193 [INDEX_op_setz_T0_subq] = CC_Z,
5194 [INDEX_op_setbe_T0_subq] = CC_Z | CC_C,
5195 [INDEX_op_sets_T0_subq] = CC_S,
5196 [INDEX_op_setl_T0_subq] = CC_O | CC_S,
5197 [INDEX_op_setle_T0_subq] = CC_O | CC_S | CC_Z,
5198
5199 [INDEX_op_jnz_ecxq] = CC_OSZAPC,
5200 [INDEX_op_jz_ecxq] = CC_OSZAPC,
5201#endif
7399c5a9 5202
4f31916f
FB
5203#define DEF_READF(SUFFIX)\
5204 [INDEX_op_adcb ## SUFFIX ## _T0_T1_cc] = CC_C,\
5205 [INDEX_op_adcw ## SUFFIX ## _T0_T1_cc] = CC_C,\
5206 [INDEX_op_adcl ## SUFFIX ## _T0_T1_cc] = CC_C,\
14ce26e7 5207 X86_64_DEF([INDEX_op_adcq ## SUFFIX ## _T0_T1_cc] = CC_C,)\
4f31916f
FB
5208 [INDEX_op_sbbb ## SUFFIX ## _T0_T1_cc] = CC_C,\
5209 [INDEX_op_sbbw ## SUFFIX ## _T0_T1_cc] = CC_C,\
5210 [INDEX_op_sbbl ## SUFFIX ## _T0_T1_cc] = CC_C,\
14ce26e7 5211 X86_64_DEF([INDEX_op_sbbq ## SUFFIX ## _T0_T1_cc] = CC_C,)\
4f31916f
FB
5212\
5213 [INDEX_op_rclb ## SUFFIX ## _T0_T1_cc] = CC_C,\
5214 [INDEX_op_rclw ## SUFFIX ## _T0_T1_cc] = CC_C,\
5215 [INDEX_op_rcll ## SUFFIX ## _T0_T1_cc] = CC_C,\
14ce26e7 5216 X86_64_DEF([INDEX_op_rclq ## SUFFIX ## _T0_T1_cc] = CC_C,)\
4f31916f
FB
5217 [INDEX_op_rcrb ## SUFFIX ## _T0_T1_cc] = CC_C,\
5218 [INDEX_op_rcrw ## SUFFIX ## _T0_T1_cc] = CC_C,\
14ce26e7
FB
5219 [INDEX_op_rcrl ## SUFFIX ## _T0_T1_cc] = CC_C,\
5220 X86_64_DEF([INDEX_op_rcrq ## SUFFIX ## _T0_T1_cc] = CC_C,)
4f31916f 5221
4bb2fcc7 5222 DEF_READF( )
4f31916f
FB
5223 DEF_READF(_raw)
5224#ifndef CONFIG_USER_ONLY
5225 DEF_READF(_kernel)
5226 DEF_READF(_user)
5227#endif
2c0262af
FB
5228};
5229
5230/* flags written by an operation */
5231static uint16_t opc_write_flags[NB_OPS] = {
5232 [INDEX_op_update2_cc] = CC_OSZAPC,
5233 [INDEX_op_update1_cc] = CC_OSZAPC,
5234 [INDEX_op_cmpl_T0_T1_cc] = CC_OSZAPC,
5235 [INDEX_op_update_neg_cc] = CC_OSZAPC,
5236 /* subtle: due to the incl/decl implementation, C is used */
5237 [INDEX_op_update_inc_cc] = CC_OSZAPC,
5238 [INDEX_op_testl_T0_T1_cc] = CC_OSZAPC,
5239
2c0262af 5240 [INDEX_op_mulb_AL_T0] = CC_OSZAPC,
2c0262af 5241 [INDEX_op_mulw_AX_T0] = CC_OSZAPC,
2c0262af 5242 [INDEX_op_mull_EAX_T0] = CC_OSZAPC,
14ce26e7
FB
5243 X86_64_DEF([INDEX_op_mulq_EAX_T0] = CC_OSZAPC,)
5244 [INDEX_op_imulb_AL_T0] = CC_OSZAPC,
5245 [INDEX_op_imulw_AX_T0] = CC_OSZAPC,
2c0262af 5246 [INDEX_op_imull_EAX_T0] = CC_OSZAPC,
14ce26e7 5247 X86_64_DEF([INDEX_op_imulq_EAX_T0] = CC_OSZAPC,)
2c0262af
FB
5248 [INDEX_op_imulw_T0_T1] = CC_OSZAPC,
5249 [INDEX_op_imull_T0_T1] = CC_OSZAPC,
14ce26e7
FB
5250 X86_64_DEF([INDEX_op_imulq_T0_T1] = CC_OSZAPC,)
5251
2c0262af
FB
5252 /* bcd */
5253 [INDEX_op_aam] = CC_OSZAPC,
5254 [INDEX_op_aad] = CC_OSZAPC,
5255 [INDEX_op_aas] = CC_OSZAPC,
5256 [INDEX_op_aaa] = CC_OSZAPC,
5257 [INDEX_op_das] = CC_OSZAPC,
5258 [INDEX_op_daa] = CC_OSZAPC,
5259
5260 [INDEX_op_movb_eflags_T0] = CC_S | CC_Z | CC_A | CC_P | CC_C,
5261 [INDEX_op_movw_eflags_T0] = CC_OSZAPC,
5262 [INDEX_op_movl_eflags_T0] = CC_OSZAPC,
4136f33c
FB
5263 [INDEX_op_movw_eflags_T0_io] = CC_OSZAPC,
5264 [INDEX_op_movl_eflags_T0_io] = CC_OSZAPC,
5265 [INDEX_op_movw_eflags_T0_cpl0] = CC_OSZAPC,
5266 [INDEX_op_movl_eflags_T0_cpl0] = CC_OSZAPC,
2c0262af
FB
5267 [INDEX_op_clc] = CC_C,
5268 [INDEX_op_stc] = CC_C,
5269 [INDEX_op_cmc] = CC_C,
5270
2c0262af
FB
5271 [INDEX_op_btw_T0_T1_cc] = CC_OSZAPC,
5272 [INDEX_op_btl_T0_T1_cc] = CC_OSZAPC,
14ce26e7 5273 X86_64_DEF([INDEX_op_btq_T0_T1_cc] = CC_OSZAPC,)
2c0262af
FB
5274 [INDEX_op_btsw_T0_T1_cc] = CC_OSZAPC,
5275 [INDEX_op_btsl_T0_T1_cc] = CC_OSZAPC,
14ce26e7 5276 X86_64_DEF([INDEX_op_btsq_T0_T1_cc] = CC_OSZAPC,)
2c0262af
FB
5277 [INDEX_op_btrw_T0_T1_cc] = CC_OSZAPC,
5278 [INDEX_op_btrl_T0_T1_cc] = CC_OSZAPC,
14ce26e7 5279 X86_64_DEF([INDEX_op_btrq_T0_T1_cc] = CC_OSZAPC,)
2c0262af
FB
5280 [INDEX_op_btcw_T0_T1_cc] = CC_OSZAPC,
5281 [INDEX_op_btcl_T0_T1_cc] = CC_OSZAPC,
14ce26e7 5282 X86_64_DEF([INDEX_op_btcq_T0_T1_cc] = CC_OSZAPC,)
2c0262af
FB
5283
5284 [INDEX_op_bsfw_T0_cc] = CC_OSZAPC,
5285 [INDEX_op_bsfl_T0_cc] = CC_OSZAPC,
14ce26e7 5286 X86_64_DEF([INDEX_op_bsfq_T0_cc] = CC_OSZAPC,)
2c0262af
FB
5287 [INDEX_op_bsrw_T0_cc] = CC_OSZAPC,
5288 [INDEX_op_bsrl_T0_cc] = CC_OSZAPC,
14ce26e7 5289 X86_64_DEF([INDEX_op_bsrq_T0_cc] = CC_OSZAPC,)
2c0262af
FB
5290
5291 [INDEX_op_cmpxchgb_T0_T1_EAX_cc] = CC_OSZAPC,
5292 [INDEX_op_cmpxchgw_T0_T1_EAX_cc] = CC_OSZAPC,
5293 [INDEX_op_cmpxchgl_T0_T1_EAX_cc] = CC_OSZAPC,
14ce26e7 5294 X86_64_DEF([INDEX_op_cmpxchgq_T0_T1_EAX_cc] = CC_OSZAPC,)
2c0262af 5295
2c0262af
FB
5296 [INDEX_op_cmpxchg8b] = CC_Z,
5297 [INDEX_op_lar] = CC_Z,
5298 [INDEX_op_lsl] = CC_Z,
5299 [INDEX_op_fcomi_ST0_FT0] = CC_Z | CC_P | CC_C,
5300 [INDEX_op_fucomi_ST0_FT0] = CC_Z | CC_P | CC_C,
4f31916f
FB
5301
5302#define DEF_WRITEF(SUFFIX)\
5303 [INDEX_op_adcb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
5304 [INDEX_op_adcw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
5305 [INDEX_op_adcl ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
14ce26e7 5306 X86_64_DEF([INDEX_op_adcq ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,)\
4f31916f
FB
5307 [INDEX_op_sbbb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
5308 [INDEX_op_sbbw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
5309 [INDEX_op_sbbl ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
14ce26e7 5310 X86_64_DEF([INDEX_op_sbbq ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,)\
4f31916f
FB
5311\
5312 [INDEX_op_rolb ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
5313 [INDEX_op_rolw ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
5314 [INDEX_op_roll ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
14ce26e7 5315 X86_64_DEF([INDEX_op_rolq ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,)\
4f31916f
FB
5316 [INDEX_op_rorb ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
5317 [INDEX_op_rorw ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
5318 [INDEX_op_rorl ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
14ce26e7 5319 X86_64_DEF([INDEX_op_rorq ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,)\
4f31916f
FB
5320\
5321 [INDEX_op_rclb ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
5322 [INDEX_op_rclw ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
5323 [INDEX_op_rcll ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
14ce26e7 5324 X86_64_DEF([INDEX_op_rclq ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,)\
4f31916f
FB
5325 [INDEX_op_rcrb ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
5326 [INDEX_op_rcrw ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
5327 [INDEX_op_rcrl ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
14ce26e7 5328 X86_64_DEF([INDEX_op_rcrq ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,)\
4f31916f
FB
5329\
5330 [INDEX_op_shlb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
5331 [INDEX_op_shlw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
5332 [INDEX_op_shll ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
14ce26e7 5333 X86_64_DEF([INDEX_op_shlq ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,)\
4f31916f
FB
5334\
5335 [INDEX_op_shrb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
5336 [INDEX_op_shrw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
5337 [INDEX_op_shrl ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
14ce26e7 5338 X86_64_DEF([INDEX_op_shrq ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,)\
4f31916f
FB
5339\
5340 [INDEX_op_sarb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
5341 [INDEX_op_sarw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
5342 [INDEX_op_sarl ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
14ce26e7 5343 X86_64_DEF([INDEX_op_sarq ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,)\
4f31916f
FB
5344\
5345 [INDEX_op_shldw ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,\
5346 [INDEX_op_shldl ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,\
14ce26e7 5347 X86_64_DEF([INDEX_op_shldq ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,)\
4f31916f
FB
5348 [INDEX_op_shldw ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,\
5349 [INDEX_op_shldl ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,\
14ce26e7 5350 X86_64_DEF([INDEX_op_shldq ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,)\
4f31916f
FB
5351\
5352 [INDEX_op_shrdw ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,\
5353 [INDEX_op_shrdl ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,\
14ce26e7 5354 X86_64_DEF([INDEX_op_shrdq ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,)\
4f31916f
FB
5355 [INDEX_op_shrdw ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,\
5356 [INDEX_op_shrdl ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,\
14ce26e7 5357 X86_64_DEF([INDEX_op_shrdq ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,)\
4f31916f
FB
5358\
5359 [INDEX_op_cmpxchgb ## SUFFIX ## _T0_T1_EAX_cc] = CC_OSZAPC,\
5360 [INDEX_op_cmpxchgw ## SUFFIX ## _T0_T1_EAX_cc] = CC_OSZAPC,\
14ce26e7
FB
5361 [INDEX_op_cmpxchgl ## SUFFIX ## _T0_T1_EAX_cc] = CC_OSZAPC,\
5362 X86_64_DEF([INDEX_op_cmpxchgq ## SUFFIX ## _T0_T1_EAX_cc] = CC_OSZAPC,)
4f31916f
FB
5363
5364
4bb2fcc7 5365 DEF_WRITEF( )
4f31916f
FB
5366 DEF_WRITEF(_raw)
5367#ifndef CONFIG_USER_ONLY
5368 DEF_WRITEF(_kernel)
5369 DEF_WRITEF(_user)
5370#endif
2c0262af
FB
5371};
5372
5373/* simpler form of an operation if no flags need to be generated */
5374static uint16_t opc_simpler[NB_OPS] = {
5375 [INDEX_op_update2_cc] = INDEX_op_nop,
5376 [INDEX_op_update1_cc] = INDEX_op_nop,
5377 [INDEX_op_update_neg_cc] = INDEX_op_nop,
5378#if 0
5379 /* broken: CC_OP logic must be rewritten */
5380 [INDEX_op_update_inc_cc] = INDEX_op_nop,
5381#endif
2c0262af
FB
5382
5383 [INDEX_op_shlb_T0_T1_cc] = INDEX_op_shlb_T0_T1,
5384 [INDEX_op_shlw_T0_T1_cc] = INDEX_op_shlw_T0_T1,
5385 [INDEX_op_shll_T0_T1_cc] = INDEX_op_shll_T0_T1,
14ce26e7 5386 X86_64_DEF([INDEX_op_shlq_T0_T1_cc] = INDEX_op_shlq_T0_T1,)
2c0262af
FB
5387
5388 [INDEX_op_shrb_T0_T1_cc] = INDEX_op_shrb_T0_T1,
5389 [INDEX_op_shrw_T0_T1_cc] = INDEX_op_shrw_T0_T1,
5390 [INDEX_op_shrl_T0_T1_cc] = INDEX_op_shrl_T0_T1,
14ce26e7 5391 X86_64_DEF([INDEX_op_shrq_T0_T1_cc] = INDEX_op_shrq_T0_T1,)
2c0262af
FB
5392
5393 [INDEX_op_sarb_T0_T1_cc] = INDEX_op_sarb_T0_T1,
5394 [INDEX_op_sarw_T0_T1_cc] = INDEX_op_sarw_T0_T1,
5395 [INDEX_op_sarl_T0_T1_cc] = INDEX_op_sarl_T0_T1,
14ce26e7 5396 X86_64_DEF([INDEX_op_sarq_T0_T1_cc] = INDEX_op_sarq_T0_T1,)
4f31916f
FB
5397
5398#define DEF_SIMPLER(SUFFIX)\
5399 [INDEX_op_rolb ## SUFFIX ## _T0_T1_cc] = INDEX_op_rolb ## SUFFIX ## _T0_T1,\
5400 [INDEX_op_rolw ## SUFFIX ## _T0_T1_cc] = INDEX_op_rolw ## SUFFIX ## _T0_T1,\
5401 [INDEX_op_roll ## SUFFIX ## _T0_T1_cc] = INDEX_op_roll ## SUFFIX ## _T0_T1,\
14ce26e7 5402 X86_64_DEF([INDEX_op_rolq ## SUFFIX ## _T0_T1_cc] = INDEX_op_rolq ## SUFFIX ## _T0_T1,)\
4f31916f
FB
5403\
5404 [INDEX_op_rorb ## SUFFIX ## _T0_T1_cc] = INDEX_op_rorb ## SUFFIX ## _T0_T1,\
5405 [INDEX_op_rorw ## SUFFIX ## _T0_T1_cc] = INDEX_op_rorw ## SUFFIX ## _T0_T1,\
14ce26e7
FB
5406 [INDEX_op_rorl ## SUFFIX ## _T0_T1_cc] = INDEX_op_rorl ## SUFFIX ## _T0_T1,\
5407 X86_64_DEF([INDEX_op_rorq ## SUFFIX ## _T0_T1_cc] = INDEX_op_rorq ## SUFFIX ## _T0_T1,)
4f31916f 5408
4bb2fcc7 5409 DEF_SIMPLER( )
4f31916f
FB
5410 DEF_SIMPLER(_raw)
5411#ifndef CONFIG_USER_ONLY
5412 DEF_SIMPLER(_kernel)
5413 DEF_SIMPLER(_user)
5414#endif
2c0262af
FB
5415};
5416
5417void optimize_flags_init(void)
5418{
5419 int i;
5420 /* put default values in arrays */
5421 for(i = 0; i < NB_OPS; i++) {
5422 if (opc_simpler[i] == 0)
5423 opc_simpler[i] = i;
5424 }
5425}
5426
5427/* CPU flags computation optimization: we move backward thru the
5428 generated code to see which flags are needed. The operation is
5429 modified if suitable */
5430static void optimize_flags(uint16_t *opc_buf, int opc_buf_len)
5431{
5432 uint16_t *opc_ptr;
5433 int live_flags, write_flags, op;
5434
5435 opc_ptr = opc_buf + opc_buf_len;
5436 /* live_flags contains the flags needed by the next instructions
5437 in the code. At the end of the bloc, we consider that all the
5438 flags are live. */
5439 live_flags = CC_OSZAPC;
5440 while (opc_ptr > opc_buf) {
5441 op = *--opc_ptr;
5442 /* if none of the flags written by the instruction is used,
5443 then we can try to find a simpler instruction */
5444 write_flags = opc_write_flags[op];
5445 if ((live_flags & write_flags) == 0) {
5446 *opc_ptr = opc_simpler[op];
5447 }
5448 /* compute the live flags before the instruction */
5449 live_flags &= ~write_flags;
5450 live_flags |= opc_read_flags[op];
5451 }
5452}
5453
5454/* generate intermediate code in gen_opc_buf and gen_opparam_buf for
5455 basic block 'tb'. If search_pc is TRUE, also generate PC
5456 information for each intermediate instruction. */
5457static inline int gen_intermediate_code_internal(CPUState *env,
5458 TranslationBlock *tb,
5459 int search_pc)
5460{
5461 DisasContext dc1, *dc = &dc1;
14ce26e7 5462 target_ulong pc_ptr;
2c0262af 5463 uint16_t *gen_opc_end;
d720b93d 5464 int flags, j, lj, cflags;
14ce26e7
FB
5465 target_ulong pc_start;
5466 target_ulong cs_base;
2c0262af
FB
5467
5468 /* generate intermediate code */
14ce26e7
FB
5469 pc_start = tb->pc;
5470 cs_base = tb->cs_base;
2c0262af 5471 flags = tb->flags;
d720b93d 5472 cflags = tb->cflags;
3a1d9b8b 5473
4f31916f 5474 dc->pe = (flags >> HF_PE_SHIFT) & 1;
2c0262af
FB
5475 dc->code32 = (flags >> HF_CS32_SHIFT) & 1;
5476 dc->ss32 = (flags >> HF_SS32_SHIFT) & 1;
5477 dc->addseg = (flags >> HF_ADDSEG_SHIFT) & 1;
5478 dc->f_st = 0;
5479 dc->vm86 = (flags >> VM_SHIFT) & 1;
5480 dc->cpl = (flags >> HF_CPL_SHIFT) & 3;
5481 dc->iopl = (flags >> IOPL_SHIFT) & 3;
5482 dc->tf = (flags >> TF_SHIFT) & 1;
34865134 5483 dc->singlestep_enabled = env->singlestep_enabled;
2c0262af
FB
5484 dc->cc_op = CC_OP_DYNAMIC;
5485 dc->cs_base = cs_base;
5486 dc->tb = tb;
5487 dc->popl_esp_hack = 0;
5488 /* select memory access functions */
5489 dc->mem_index = 0;
5490 if (flags & HF_SOFTMMU_MASK) {
5491 if (dc->cpl == 3)
14ce26e7 5492 dc->mem_index = 2 * 4;
2c0262af 5493 else
14ce26e7 5494 dc->mem_index = 1 * 4;
2c0262af 5495 }
14ce26e7
FB
5496 dc->cpuid_features = env->cpuid_features;
5497#ifdef TARGET_X86_64
5498 dc->lma = (flags >> HF_LMA_SHIFT) & 1;
5499 dc->code64 = (flags >> HF_CS64_SHIFT) & 1;
5500#endif
7eee2a50 5501 dc->flags = flags;
a2cc3b24
FB
5502 dc->jmp_opt = !(dc->tf || env->singlestep_enabled ||
5503 (flags & HF_INHIBIT_IRQ_MASK)
415fa2ea 5504#ifndef CONFIG_SOFTMMU
2c0262af
FB
5505 || (flags & HF_SOFTMMU_MASK)
5506#endif
5507 );
4f31916f
FB
5508#if 0
5509 /* check addseg logic */
dc196a57 5510 if (!dc->addseg && (dc->vm86 || !dc->pe || !dc->code32))
4f31916f
FB
5511 printf("ERROR addseg\n");
5512#endif
5513
2c0262af
FB
5514 gen_opc_ptr = gen_opc_buf;
5515 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
5516 gen_opparam_ptr = gen_opparam_buf;
14ce26e7 5517 nb_gen_labels = 0;
2c0262af
FB
5518
5519 dc->is_jmp = DISAS_NEXT;
5520 pc_ptr = pc_start;
5521 lj = -1;
5522
2c0262af
FB
5523 for(;;) {
5524 if (env->nb_breakpoints > 0) {
5525 for(j = 0; j < env->nb_breakpoints; j++) {
14ce26e7 5526 if (env->breakpoints[j] == pc_ptr) {
2c0262af
FB
5527 gen_debug(dc, pc_ptr - dc->cs_base);
5528 break;
5529 }
5530 }
5531 }
5532 if (search_pc) {
5533 j = gen_opc_ptr - gen_opc_buf;
5534 if (lj < j) {
5535 lj++;
5536 while (lj < j)
5537 gen_opc_instr_start[lj++] = 0;
5538 }
14ce26e7 5539 gen_opc_pc[lj] = pc_ptr;
2c0262af
FB
5540 gen_opc_cc_op[lj] = dc->cc_op;
5541 gen_opc_instr_start[lj] = 1;
5542 }
5543 pc_ptr = disas_insn(dc, pc_ptr);
5544 /* stop translation if indicated */
5545 if (dc->is_jmp)
5546 break;
5547 /* if single step mode, we generate only one instruction and
5548 generate an exception */
a2cc3b24
FB
5549 /* if irq were inhibited with HF_INHIBIT_IRQ_MASK, we clear
5550 the flag and abort the translation to give the irqs a
5551 change to be happen */
5552 if (dc->tf || dc->singlestep_enabled ||
d720b93d
FB
5553 (flags & HF_INHIBIT_IRQ_MASK) ||
5554 (cflags & CF_SINGLE_INSN)) {
14ce26e7 5555 gen_jmp_im(pc_ptr - dc->cs_base);
2c0262af
FB
5556 gen_eob(dc);
5557 break;
5558 }
5559 /* if too long translation, stop generation too */
5560 if (gen_opc_ptr >= gen_opc_end ||
5561 (pc_ptr - pc_start) >= (TARGET_PAGE_SIZE - 32)) {
14ce26e7 5562 gen_jmp_im(pc_ptr - dc->cs_base);
2c0262af
FB
5563 gen_eob(dc);
5564 break;
5565 }
5566 }
5567 *gen_opc_ptr = INDEX_op_end;
5568 /* we don't forget to fill the last values */
5569 if (search_pc) {
5570 j = gen_opc_ptr - gen_opc_buf;
5571 lj++;
5572 while (lj <= j)
5573 gen_opc_instr_start[lj++] = 0;
5574 }
5575
5576#ifdef DEBUG_DISAS
658c8bda 5577 if (loglevel & CPU_LOG_TB_CPU) {
7fe48483 5578 cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
658c8bda 5579 }
e19e89a5 5580 if (loglevel & CPU_LOG_TB_IN_ASM) {
14ce26e7 5581 int disas_flags;
2c0262af
FB
5582 fprintf(logfile, "----------------\n");
5583 fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
14ce26e7
FB
5584#ifdef TARGET_X86_64
5585 if (dc->code64)
5586 disas_flags = 2;
5587 else
5588#endif
5589 disas_flags = !dc->code32;
5590 target_disas(logfile, pc_start, pc_ptr - pc_start, disas_flags);
2c0262af 5591 fprintf(logfile, "\n");
e19e89a5
FB
5592 if (loglevel & CPU_LOG_TB_OP) {
5593 fprintf(logfile, "OP:\n");
5594 dump_ops(gen_opc_buf, gen_opparam_buf);
5595 fprintf(logfile, "\n");
5596 }
2c0262af
FB
5597 }
5598#endif
5599
5600 /* optimize flag computations */
5601 optimize_flags(gen_opc_buf, gen_opc_ptr - gen_opc_buf);
5602
5603#ifdef DEBUG_DISAS
e19e89a5 5604 if (loglevel & CPU_LOG_TB_OP_OPT) {
2c0262af
FB
5605 fprintf(logfile, "AFTER FLAGS OPT:\n");
5606 dump_ops(gen_opc_buf, gen_opparam_buf);
5607 fprintf(logfile, "\n");
5608 }
5609#endif
5610 if (!search_pc)
5611 tb->size = pc_ptr - pc_start;
5612 return 0;
5613}
5614
5615int gen_intermediate_code(CPUState *env, TranslationBlock *tb)
5616{
5617 return gen_intermediate_code_internal(env, tb, 0);
5618}
5619
5620int gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
5621{
5622 return gen_intermediate_code_internal(env, tb, 1);
5623}
5624