]> git.proxmox.com Git - mirror_qemu.git/blame - target-i386/translate.c
test at least one invalid lock op code
[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>
27#include <sys/mman.h>
28
29#include "cpu.h"
30#include "exec-all.h"
31#include "disas.h"
32
33/* XXX: move that elsewhere */
34static uint16_t *gen_opc_ptr;
35static uint32_t *gen_opparam_ptr;
36
37#define PREFIX_REPZ 0x01
38#define PREFIX_REPNZ 0x02
39#define PREFIX_LOCK 0x04
40#define PREFIX_DATA 0x08
41#define PREFIX_ADR 0x10
42
43typedef struct DisasContext {
44 /* current insn context */
45 int override; /* -1 if no override */
46 int prefix;
47 int aflag, dflag;
48 uint8_t *pc; /* pc = eip + cs_base */
49 int is_jmp; /* 1 = means jump (stop translation), 2 means CPU
50 static state change (stop translation) */
51 /* current block context */
52 uint8_t *cs_base; /* base of CS segment */
53 int pe; /* protected mode */
54 int code32; /* 32 bit code segment */
55 int ss32; /* 32 bit stack segment */
56 int cc_op; /* current CC operation */
57 int addseg; /* non zero if either DS/ES/SS have a non zero base */
58 int f_st; /* currently unused */
59 int vm86; /* vm86 mode */
60 int cpl;
61 int iopl;
62 int tf; /* TF cpu flag */
34865134 63 int singlestep_enabled; /* "hardware" single step enabled */
2c0262af
FB
64 int jmp_opt; /* use direct block chaining for direct jumps */
65 int mem_index; /* select memory access functions */
66 struct TranslationBlock *tb;
67 int popl_esp_hack; /* for correct popl with esp base handling */
68} DisasContext;
69
70static void gen_eob(DisasContext *s);
71static void gen_jmp(DisasContext *s, unsigned int eip);
72
73/* i386 arith/logic operations */
74enum {
75 OP_ADDL,
76 OP_ORL,
77 OP_ADCL,
78 OP_SBBL,
79 OP_ANDL,
80 OP_SUBL,
81 OP_XORL,
82 OP_CMPL,
83};
84
85/* i386 shift ops */
86enum {
87 OP_ROL,
88 OP_ROR,
89 OP_RCL,
90 OP_RCR,
91 OP_SHL,
92 OP_SHR,
93 OP_SHL1, /* undocumented */
94 OP_SAR = 7,
95};
96
97enum {
98#define DEF(s, n, copy_size) INDEX_op_ ## s,
99#include "opc.h"
100#undef DEF
101 NB_OPS,
102};
103
104#include "gen-op.h"
105
106/* operand size */
107enum {
108 OT_BYTE = 0,
109 OT_WORD,
110 OT_LONG,
111 OT_QUAD,
112};
113
114enum {
115 /* I386 int registers */
116 OR_EAX, /* MUST be even numbered */
117 OR_ECX,
118 OR_EDX,
119 OR_EBX,
120 OR_ESP,
121 OR_EBP,
122 OR_ESI,
123 OR_EDI,
124 OR_TMP0, /* temporary operand register */
125 OR_TMP1,
126 OR_A0, /* temporary register used when doing address evaluation */
127 OR_ZERO, /* fixed zero register */
128 NB_OREGS,
129};
130
2c0262af
FB
131static GenOpFunc *gen_op_mov_reg_T0[3][8] = {
132 [OT_BYTE] = {
133 gen_op_movb_EAX_T0,
134 gen_op_movb_ECX_T0,
135 gen_op_movb_EDX_T0,
136 gen_op_movb_EBX_T0,
137 gen_op_movh_EAX_T0,
138 gen_op_movh_ECX_T0,
139 gen_op_movh_EDX_T0,
140 gen_op_movh_EBX_T0,
141 },
142 [OT_WORD] = {
143 gen_op_movw_EAX_T0,
144 gen_op_movw_ECX_T0,
145 gen_op_movw_EDX_T0,
146 gen_op_movw_EBX_T0,
147 gen_op_movw_ESP_T0,
148 gen_op_movw_EBP_T0,
149 gen_op_movw_ESI_T0,
150 gen_op_movw_EDI_T0,
151 },
152 [OT_LONG] = {
153 gen_op_movl_EAX_T0,
154 gen_op_movl_ECX_T0,
155 gen_op_movl_EDX_T0,
156 gen_op_movl_EBX_T0,
157 gen_op_movl_ESP_T0,
158 gen_op_movl_EBP_T0,
159 gen_op_movl_ESI_T0,
160 gen_op_movl_EDI_T0,
161 },
162};
163
164static GenOpFunc *gen_op_mov_reg_T1[3][8] = {
165 [OT_BYTE] = {
166 gen_op_movb_EAX_T1,
167 gen_op_movb_ECX_T1,
168 gen_op_movb_EDX_T1,
169 gen_op_movb_EBX_T1,
170 gen_op_movh_EAX_T1,
171 gen_op_movh_ECX_T1,
172 gen_op_movh_EDX_T1,
173 gen_op_movh_EBX_T1,
174 },
175 [OT_WORD] = {
176 gen_op_movw_EAX_T1,
177 gen_op_movw_ECX_T1,
178 gen_op_movw_EDX_T1,
179 gen_op_movw_EBX_T1,
180 gen_op_movw_ESP_T1,
181 gen_op_movw_EBP_T1,
182 gen_op_movw_ESI_T1,
183 gen_op_movw_EDI_T1,
184 },
185 [OT_LONG] = {
186 gen_op_movl_EAX_T1,
187 gen_op_movl_ECX_T1,
188 gen_op_movl_EDX_T1,
189 gen_op_movl_EBX_T1,
190 gen_op_movl_ESP_T1,
191 gen_op_movl_EBP_T1,
192 gen_op_movl_ESI_T1,
193 gen_op_movl_EDI_T1,
194 },
195};
196
197static GenOpFunc *gen_op_mov_reg_A0[2][8] = {
198 [0] = {
199 gen_op_movw_EAX_A0,
200 gen_op_movw_ECX_A0,
201 gen_op_movw_EDX_A0,
202 gen_op_movw_EBX_A0,
203 gen_op_movw_ESP_A0,
204 gen_op_movw_EBP_A0,
205 gen_op_movw_ESI_A0,
206 gen_op_movw_EDI_A0,
207 },
208 [1] = {
209 gen_op_movl_EAX_A0,
210 gen_op_movl_ECX_A0,
211 gen_op_movl_EDX_A0,
212 gen_op_movl_EBX_A0,
213 gen_op_movl_ESP_A0,
214 gen_op_movl_EBP_A0,
215 gen_op_movl_ESI_A0,
216 gen_op_movl_EDI_A0,
217 },
218};
219
220static GenOpFunc *gen_op_mov_TN_reg[3][2][8] =
221{
222 [OT_BYTE] = {
223 {
224 gen_op_movl_T0_EAX,
225 gen_op_movl_T0_ECX,
226 gen_op_movl_T0_EDX,
227 gen_op_movl_T0_EBX,
228 gen_op_movh_T0_EAX,
229 gen_op_movh_T0_ECX,
230 gen_op_movh_T0_EDX,
231 gen_op_movh_T0_EBX,
232 },
233 {
234 gen_op_movl_T1_EAX,
235 gen_op_movl_T1_ECX,
236 gen_op_movl_T1_EDX,
237 gen_op_movl_T1_EBX,
238 gen_op_movh_T1_EAX,
239 gen_op_movh_T1_ECX,
240 gen_op_movh_T1_EDX,
241 gen_op_movh_T1_EBX,
242 },
243 },
244 [OT_WORD] = {
245 {
246 gen_op_movl_T0_EAX,
247 gen_op_movl_T0_ECX,
248 gen_op_movl_T0_EDX,
249 gen_op_movl_T0_EBX,
250 gen_op_movl_T0_ESP,
251 gen_op_movl_T0_EBP,
252 gen_op_movl_T0_ESI,
253 gen_op_movl_T0_EDI,
254 },
255 {
256 gen_op_movl_T1_EAX,
257 gen_op_movl_T1_ECX,
258 gen_op_movl_T1_EDX,
259 gen_op_movl_T1_EBX,
260 gen_op_movl_T1_ESP,
261 gen_op_movl_T1_EBP,
262 gen_op_movl_T1_ESI,
263 gen_op_movl_T1_EDI,
264 },
265 },
266 [OT_LONG] = {
267 {
268 gen_op_movl_T0_EAX,
269 gen_op_movl_T0_ECX,
270 gen_op_movl_T0_EDX,
271 gen_op_movl_T0_EBX,
272 gen_op_movl_T0_ESP,
273 gen_op_movl_T0_EBP,
274 gen_op_movl_T0_ESI,
275 gen_op_movl_T0_EDI,
276 },
277 {
278 gen_op_movl_T1_EAX,
279 gen_op_movl_T1_ECX,
280 gen_op_movl_T1_EDX,
281 gen_op_movl_T1_EBX,
282 gen_op_movl_T1_ESP,
283 gen_op_movl_T1_EBP,
284 gen_op_movl_T1_ESI,
285 gen_op_movl_T1_EDI,
286 },
287 },
288};
289
290static GenOpFunc *gen_op_movl_A0_reg[8] = {
291 gen_op_movl_A0_EAX,
292 gen_op_movl_A0_ECX,
293 gen_op_movl_A0_EDX,
294 gen_op_movl_A0_EBX,
295 gen_op_movl_A0_ESP,
296 gen_op_movl_A0_EBP,
297 gen_op_movl_A0_ESI,
298 gen_op_movl_A0_EDI,
299};
300
301static GenOpFunc *gen_op_addl_A0_reg_sN[4][8] = {
302 [0] = {
303 gen_op_addl_A0_EAX,
304 gen_op_addl_A0_ECX,
305 gen_op_addl_A0_EDX,
306 gen_op_addl_A0_EBX,
307 gen_op_addl_A0_ESP,
308 gen_op_addl_A0_EBP,
309 gen_op_addl_A0_ESI,
310 gen_op_addl_A0_EDI,
311 },
312 [1] = {
313 gen_op_addl_A0_EAX_s1,
314 gen_op_addl_A0_ECX_s1,
315 gen_op_addl_A0_EDX_s1,
316 gen_op_addl_A0_EBX_s1,
317 gen_op_addl_A0_ESP_s1,
318 gen_op_addl_A0_EBP_s1,
319 gen_op_addl_A0_ESI_s1,
320 gen_op_addl_A0_EDI_s1,
321 },
322 [2] = {
323 gen_op_addl_A0_EAX_s2,
324 gen_op_addl_A0_ECX_s2,
325 gen_op_addl_A0_EDX_s2,
326 gen_op_addl_A0_EBX_s2,
327 gen_op_addl_A0_ESP_s2,
328 gen_op_addl_A0_EBP_s2,
329 gen_op_addl_A0_ESI_s2,
330 gen_op_addl_A0_EDI_s2,
331 },
332 [3] = {
333 gen_op_addl_A0_EAX_s3,
334 gen_op_addl_A0_ECX_s3,
335 gen_op_addl_A0_EDX_s3,
336 gen_op_addl_A0_EBX_s3,
337 gen_op_addl_A0_ESP_s3,
338 gen_op_addl_A0_EBP_s3,
339 gen_op_addl_A0_ESI_s3,
340 gen_op_addl_A0_EDI_s3,
341 },
342};
343
344static GenOpFunc *gen_op_cmov_reg_T1_T0[2][8] = {
345 [0] = {
346 gen_op_cmovw_EAX_T1_T0,
347 gen_op_cmovw_ECX_T1_T0,
348 gen_op_cmovw_EDX_T1_T0,
349 gen_op_cmovw_EBX_T1_T0,
350 gen_op_cmovw_ESP_T1_T0,
351 gen_op_cmovw_EBP_T1_T0,
352 gen_op_cmovw_ESI_T1_T0,
353 gen_op_cmovw_EDI_T1_T0,
354 },
355 [1] = {
356 gen_op_cmovl_EAX_T1_T0,
357 gen_op_cmovl_ECX_T1_T0,
358 gen_op_cmovl_EDX_T1_T0,
359 gen_op_cmovl_EBX_T1_T0,
360 gen_op_cmovl_ESP_T1_T0,
361 gen_op_cmovl_EBP_T1_T0,
362 gen_op_cmovl_ESI_T1_T0,
363 gen_op_cmovl_EDI_T1_T0,
364 },
365};
366
367static GenOpFunc *gen_op_arith_T0_T1_cc[8] = {
368 NULL,
369 gen_op_orl_T0_T1,
370 NULL,
371 NULL,
372 gen_op_andl_T0_T1,
373 NULL,
374 gen_op_xorl_T0_T1,
375 NULL,
376};
377
4f31916f
FB
378#define DEF_ARITHC(SUFFIX)\
379 {\
380 gen_op_adcb ## SUFFIX ## _T0_T1_cc,\
381 gen_op_sbbb ## SUFFIX ## _T0_T1_cc,\
382 },\
383 {\
384 gen_op_adcw ## SUFFIX ## _T0_T1_cc,\
385 gen_op_sbbw ## SUFFIX ## _T0_T1_cc,\
386 },\
387 {\
388 gen_op_adcl ## SUFFIX ## _T0_T1_cc,\
389 gen_op_sbbl ## SUFFIX ## _T0_T1_cc,\
2c0262af 390 },
4f31916f
FB
391
392static GenOpFunc *gen_op_arithc_T0_T1_cc[3][2] = {
393 DEF_ARITHC()
2c0262af
FB
394};
395
4f31916f
FB
396static GenOpFunc *gen_op_arithc_mem_T0_T1_cc[9][2] = {
397 DEF_ARITHC(_raw)
398#ifndef CONFIG_USER_ONLY
399 DEF_ARITHC(_kernel)
400 DEF_ARITHC(_user)
401#endif
2c0262af
FB
402};
403
404static const int cc_op_arithb[8] = {
405 CC_OP_ADDB,
406 CC_OP_LOGICB,
407 CC_OP_ADDB,
408 CC_OP_SUBB,
409 CC_OP_LOGICB,
410 CC_OP_SUBB,
411 CC_OP_LOGICB,
412 CC_OP_SUBB,
413};
414
4f31916f
FB
415#define DEF_CMPXCHG(SUFFIX)\
416 gen_op_cmpxchgb ## SUFFIX ## _T0_T1_EAX_cc,\
417 gen_op_cmpxchgw ## SUFFIX ## _T0_T1_EAX_cc,\
418 gen_op_cmpxchgl ## SUFFIX ## _T0_T1_EAX_cc,
419
420
2c0262af 421static GenOpFunc *gen_op_cmpxchg_T0_T1_EAX_cc[3] = {
4f31916f 422 DEF_CMPXCHG()
2c0262af
FB
423};
424
4f31916f
FB
425static GenOpFunc *gen_op_cmpxchg_mem_T0_T1_EAX_cc[9] = {
426 DEF_CMPXCHG(_raw)
427#ifndef CONFIG_USER_ONLY
428 DEF_CMPXCHG(_kernel)
429 DEF_CMPXCHG(_user)
430#endif
2c0262af
FB
431};
432
4f31916f
FB
433#define DEF_SHIFT(SUFFIX)\
434 {\
435 gen_op_rolb ## SUFFIX ## _T0_T1_cc,\
436 gen_op_rorb ## SUFFIX ## _T0_T1_cc,\
437 gen_op_rclb ## SUFFIX ## _T0_T1_cc,\
438 gen_op_rcrb ## SUFFIX ## _T0_T1_cc,\
439 gen_op_shlb ## SUFFIX ## _T0_T1_cc,\
440 gen_op_shrb ## SUFFIX ## _T0_T1_cc,\
441 gen_op_shlb ## SUFFIX ## _T0_T1_cc,\
442 gen_op_sarb ## SUFFIX ## _T0_T1_cc,\
443 },\
444 {\
445 gen_op_rolw ## SUFFIX ## _T0_T1_cc,\
446 gen_op_rorw ## SUFFIX ## _T0_T1_cc,\
447 gen_op_rclw ## SUFFIX ## _T0_T1_cc,\
448 gen_op_rcrw ## SUFFIX ## _T0_T1_cc,\
449 gen_op_shlw ## SUFFIX ## _T0_T1_cc,\
450 gen_op_shrw ## SUFFIX ## _T0_T1_cc,\
451 gen_op_shlw ## SUFFIX ## _T0_T1_cc,\
452 gen_op_sarw ## SUFFIX ## _T0_T1_cc,\
453 },\
454 {\
455 gen_op_roll ## SUFFIX ## _T0_T1_cc,\
456 gen_op_rorl ## SUFFIX ## _T0_T1_cc,\
457 gen_op_rcll ## SUFFIX ## _T0_T1_cc,\
458 gen_op_rcrl ## SUFFIX ## _T0_T1_cc,\
459 gen_op_shll ## SUFFIX ## _T0_T1_cc,\
460 gen_op_shrl ## SUFFIX ## _T0_T1_cc,\
461 gen_op_shll ## SUFFIX ## _T0_T1_cc,\
462 gen_op_sarl ## SUFFIX ## _T0_T1_cc,\
2c0262af 463 },
4f31916f
FB
464
465static GenOpFunc *gen_op_shift_T0_T1_cc[3][8] = {
466 DEF_SHIFT()
2c0262af
FB
467};
468
4f31916f
FB
469static GenOpFunc *gen_op_shift_mem_T0_T1_cc[9][8] = {
470 DEF_SHIFT(_raw)
471#ifndef CONFIG_USER_ONLY
472 DEF_SHIFT(_kernel)
473 DEF_SHIFT(_user)
474#endif
2c0262af
FB
475};
476
4f31916f
FB
477#define DEF_SHIFTD(SUFFIX, op)\
478 {\
479 NULL,\
480 NULL,\
481 },\
482 {\
483 gen_op_shldw ## SUFFIX ## _T0_T1_ ## op ## _cc,\
484 gen_op_shrdw ## SUFFIX ## _T0_T1_ ## op ## _cc,\
485 },\
486 {\
487 gen_op_shldl ## SUFFIX ## _T0_T1_ ## op ## _cc,\
488 gen_op_shrdl ## SUFFIX ## _T0_T1_ ## op ## _cc,\
2c0262af 489 },
4f31916f
FB
490
491
492static GenOpFunc1 *gen_op_shiftd_T0_T1_im_cc[3][2] = {
493 DEF_SHIFTD(, im)
2c0262af
FB
494};
495
4f31916f
FB
496static GenOpFunc *gen_op_shiftd_T0_T1_ECX_cc[3][2] = {
497 DEF_SHIFTD(, ECX)
2c0262af
FB
498};
499
4f31916f
FB
500static GenOpFunc1 *gen_op_shiftd_mem_T0_T1_im_cc[9][2] = {
501 DEF_SHIFTD(_raw, im)
502#ifndef CONFIG_USER_ONLY
503 DEF_SHIFTD(_kernel, im)
504 DEF_SHIFTD(_user, im)
505#endif
2c0262af
FB
506};
507
4f31916f
FB
508static GenOpFunc *gen_op_shiftd_mem_T0_T1_ECX_cc[9][2] = {
509 DEF_SHIFTD(_raw, ECX)
510#ifndef CONFIG_USER_ONLY
511 DEF_SHIFTD(_kernel, ECX)
512 DEF_SHIFTD(_user, ECX)
513#endif
2c0262af
FB
514};
515
516static GenOpFunc *gen_op_btx_T0_T1_cc[2][4] = {
517 [0] = {
518 gen_op_btw_T0_T1_cc,
519 gen_op_btsw_T0_T1_cc,
520 gen_op_btrw_T0_T1_cc,
521 gen_op_btcw_T0_T1_cc,
522 },
523 [1] = {
524 gen_op_btl_T0_T1_cc,
525 gen_op_btsl_T0_T1_cc,
526 gen_op_btrl_T0_T1_cc,
527 gen_op_btcl_T0_T1_cc,
528 },
529};
530
531static GenOpFunc *gen_op_bsx_T0_cc[2][2] = {
532 [0] = {
533 gen_op_bsfw_T0_cc,
534 gen_op_bsrw_T0_cc,
535 },
536 [1] = {
537 gen_op_bsfl_T0_cc,
538 gen_op_bsrl_T0_cc,
539 },
540};
541
542static GenOpFunc *gen_op_lds_T0_A0[3 * 3] = {
61382a50
FB
543 gen_op_ldsb_raw_T0_A0,
544 gen_op_ldsw_raw_T0_A0,
2c0262af 545 NULL,
61382a50 546#ifndef CONFIG_USER_ONLY
2c0262af
FB
547 gen_op_ldsb_kernel_T0_A0,
548 gen_op_ldsw_kernel_T0_A0,
549 NULL,
550
551 gen_op_ldsb_user_T0_A0,
552 gen_op_ldsw_user_T0_A0,
553 NULL,
61382a50 554#endif
2c0262af
FB
555};
556
557static GenOpFunc *gen_op_ldu_T0_A0[3 * 3] = {
61382a50
FB
558 gen_op_ldub_raw_T0_A0,
559 gen_op_lduw_raw_T0_A0,
2c0262af
FB
560 NULL,
561
61382a50 562#ifndef CONFIG_USER_ONLY
2c0262af
FB
563 gen_op_ldub_kernel_T0_A0,
564 gen_op_lduw_kernel_T0_A0,
565 NULL,
566
567 gen_op_ldub_user_T0_A0,
568 gen_op_lduw_user_T0_A0,
569 NULL,
61382a50 570#endif
2c0262af
FB
571};
572
573/* sign does not matter, except for lidt/lgdt call (TODO: fix it) */
574static GenOpFunc *gen_op_ld_T0_A0[3 * 3] = {
61382a50
FB
575 gen_op_ldub_raw_T0_A0,
576 gen_op_lduw_raw_T0_A0,
577 gen_op_ldl_raw_T0_A0,
2c0262af 578
61382a50 579#ifndef CONFIG_USER_ONLY
2c0262af
FB
580 gen_op_ldub_kernel_T0_A0,
581 gen_op_lduw_kernel_T0_A0,
582 gen_op_ldl_kernel_T0_A0,
583
584 gen_op_ldub_user_T0_A0,
585 gen_op_lduw_user_T0_A0,
586 gen_op_ldl_user_T0_A0,
61382a50 587#endif
2c0262af
FB
588};
589
590static GenOpFunc *gen_op_ld_T1_A0[3 * 3] = {
61382a50
FB
591 gen_op_ldub_raw_T1_A0,
592 gen_op_lduw_raw_T1_A0,
593 gen_op_ldl_raw_T1_A0,
2c0262af 594
61382a50 595#ifndef CONFIG_USER_ONLY
2c0262af
FB
596 gen_op_ldub_kernel_T1_A0,
597 gen_op_lduw_kernel_T1_A0,
598 gen_op_ldl_kernel_T1_A0,
599
600 gen_op_ldub_user_T1_A0,
601 gen_op_lduw_user_T1_A0,
602 gen_op_ldl_user_T1_A0,
61382a50 603#endif
2c0262af
FB
604};
605
606static GenOpFunc *gen_op_st_T0_A0[3 * 3] = {
61382a50
FB
607 gen_op_stb_raw_T0_A0,
608 gen_op_stw_raw_T0_A0,
609 gen_op_stl_raw_T0_A0,
2c0262af 610
61382a50 611#ifndef CONFIG_USER_ONLY
2c0262af
FB
612 gen_op_stb_kernel_T0_A0,
613 gen_op_stw_kernel_T0_A0,
614 gen_op_stl_kernel_T0_A0,
615
616 gen_op_stb_user_T0_A0,
617 gen_op_stw_user_T0_A0,
618 gen_op_stl_user_T0_A0,
61382a50 619#endif
2c0262af
FB
620};
621
4f31916f
FB
622static GenOpFunc *gen_op_st_T1_A0[3 * 3] = {
623 NULL,
624 gen_op_stw_raw_T1_A0,
625 gen_op_stl_raw_T1_A0,
626
627#ifndef CONFIG_USER_ONLY
628 NULL,
629 gen_op_stw_kernel_T1_A0,
630 gen_op_stl_kernel_T1_A0,
631
632 NULL,
633 gen_op_stw_user_T1_A0,
634 gen_op_stl_user_T1_A0,
635#endif
636};
637
2c0262af
FB
638static inline void gen_string_movl_A0_ESI(DisasContext *s)
639{
640 int override;
641
642 override = s->override;
643 if (s->aflag) {
644 /* 32 bit address */
645 if (s->addseg && override < 0)
646 override = R_DS;
647 if (override >= 0) {
648 gen_op_movl_A0_seg(offsetof(CPUX86State,segs[override].base));
649 gen_op_addl_A0_reg_sN[0][R_ESI]();
650 } else {
651 gen_op_movl_A0_reg[R_ESI]();
652 }
653 } else {
654 /* 16 address, always override */
655 if (override < 0)
656 override = R_DS;
657 gen_op_movl_A0_reg[R_ESI]();
658 gen_op_andl_A0_ffff();
659 gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base));
660 }
661}
662
663static inline void gen_string_movl_A0_EDI(DisasContext *s)
664{
665 if (s->aflag) {
666 if (s->addseg) {
667 gen_op_movl_A0_seg(offsetof(CPUX86State,segs[R_ES].base));
668 gen_op_addl_A0_reg_sN[0][R_EDI]();
669 } else {
670 gen_op_movl_A0_reg[R_EDI]();
671 }
672 } else {
673 gen_op_movl_A0_reg[R_EDI]();
674 gen_op_andl_A0_ffff();
675 gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_ES].base));
676 }
677}
678
679static GenOpFunc *gen_op_movl_T0_Dshift[3] = {
680 gen_op_movl_T0_Dshiftb,
681 gen_op_movl_T0_Dshiftw,
682 gen_op_movl_T0_Dshiftl,
683};
684
685static GenOpFunc2 *gen_op_jz_ecx[2] = {
686 gen_op_jz_ecxw,
687 gen_op_jz_ecxl,
688};
689
690static GenOpFunc1 *gen_op_jz_ecx_im[2] = {
691 gen_op_jz_ecxw_im,
692 gen_op_jz_ecxl_im,
693};
694
695static GenOpFunc *gen_op_dec_ECX[2] = {
696 gen_op_decw_ECX,
697 gen_op_decl_ECX,
698};
699
700static GenOpFunc1 *gen_op_string_jnz_sub[2][3] = {
701 {
702 gen_op_string_jnz_subb,
703 gen_op_string_jnz_subw,
704 gen_op_string_jnz_subl,
705 },
706 {
707 gen_op_string_jz_subb,
708 gen_op_string_jz_subw,
709 gen_op_string_jz_subl,
710 },
711};
712
713static GenOpFunc1 *gen_op_string_jnz_sub_im[2][3] = {
714 {
715 gen_op_string_jnz_subb_im,
716 gen_op_string_jnz_subw_im,
717 gen_op_string_jnz_subl_im,
718 },
719 {
720 gen_op_string_jz_subb_im,
721 gen_op_string_jz_subw_im,
722 gen_op_string_jz_subl_im,
723 },
724};
725
726static GenOpFunc *gen_op_in_DX_T0[3] = {
727 gen_op_inb_DX_T0,
728 gen_op_inw_DX_T0,
729 gen_op_inl_DX_T0,
730};
731
732static GenOpFunc *gen_op_out_DX_T0[3] = {
733 gen_op_outb_DX_T0,
734 gen_op_outw_DX_T0,
735 gen_op_outl_DX_T0,
736};
737
f115e911
FB
738static GenOpFunc *gen_op_in[3] = {
739 gen_op_inb_T0_T1,
740 gen_op_inw_T0_T1,
741 gen_op_inl_T0_T1,
742};
743
744static GenOpFunc *gen_op_out[3] = {
745 gen_op_outb_T0_T1,
746 gen_op_outw_T0_T1,
747 gen_op_outl_T0_T1,
748};
749
750static GenOpFunc *gen_check_io_T0[3] = {
751 gen_op_check_iob_T0,
752 gen_op_check_iow_T0,
753 gen_op_check_iol_T0,
754};
755
756static GenOpFunc *gen_check_io_DX[3] = {
757 gen_op_check_iob_DX,
758 gen_op_check_iow_DX,
759 gen_op_check_iol_DX,
760};
761
762static void gen_check_io(DisasContext *s, int ot, int use_dx, int cur_eip)
763{
764 if (s->pe && (s->cpl > s->iopl || s->vm86)) {
765 if (s->cc_op != CC_OP_DYNAMIC)
766 gen_op_set_cc_op(s->cc_op);
767 gen_op_jmp_im(cur_eip);
768 if (use_dx)
769 gen_check_io_DX[ot]();
770 else
771 gen_check_io_T0[ot]();
772 }
773}
774
2c0262af
FB
775static inline void gen_movs(DisasContext *s, int ot)
776{
777 gen_string_movl_A0_ESI(s);
778 gen_op_ld_T0_A0[ot + s->mem_index]();
779 gen_string_movl_A0_EDI(s);
780 gen_op_st_T0_A0[ot + s->mem_index]();
781 gen_op_movl_T0_Dshift[ot]();
782 if (s->aflag) {
783 gen_op_addl_ESI_T0();
784 gen_op_addl_EDI_T0();
785 } else {
786 gen_op_addw_ESI_T0();
787 gen_op_addw_EDI_T0();
788 }
789}
790
791static inline void gen_update_cc_op(DisasContext *s)
792{
793 if (s->cc_op != CC_OP_DYNAMIC) {
794 gen_op_set_cc_op(s->cc_op);
795 s->cc_op = CC_OP_DYNAMIC;
796 }
797}
798
799static inline void gen_jz_ecx_string(DisasContext *s, unsigned int next_eip)
800{
801 if (s->jmp_opt) {
802 gen_op_jz_ecx[s->aflag]((long)s->tb, next_eip);
803 } else {
804 /* XXX: does not work with gdbstub "ice" single step - not a
805 serious problem */
806 gen_op_jz_ecx_im[s->aflag](next_eip);
807 }
808}
809
810static inline void gen_stos(DisasContext *s, int ot)
811{
812 gen_op_mov_TN_reg[OT_LONG][0][R_EAX]();
813 gen_string_movl_A0_EDI(s);
814 gen_op_st_T0_A0[ot + s->mem_index]();
815 gen_op_movl_T0_Dshift[ot]();
816 if (s->aflag) {
817 gen_op_addl_EDI_T0();
818 } else {
819 gen_op_addw_EDI_T0();
820 }
821}
822
823static inline void gen_lods(DisasContext *s, int ot)
824{
825 gen_string_movl_A0_ESI(s);
826 gen_op_ld_T0_A0[ot + s->mem_index]();
827 gen_op_mov_reg_T0[ot][R_EAX]();
828 gen_op_movl_T0_Dshift[ot]();
829 if (s->aflag) {
830 gen_op_addl_ESI_T0();
831 } else {
832 gen_op_addw_ESI_T0();
833 }
834}
835
836static inline void gen_scas(DisasContext *s, int ot)
837{
838 gen_op_mov_TN_reg[OT_LONG][0][R_EAX]();
839 gen_string_movl_A0_EDI(s);
840 gen_op_ld_T1_A0[ot + s->mem_index]();
841 gen_op_cmpl_T0_T1_cc();
842 gen_op_movl_T0_Dshift[ot]();
843 if (s->aflag) {
844 gen_op_addl_EDI_T0();
845 } else {
846 gen_op_addw_EDI_T0();
847 }
848}
849
850static inline void gen_cmps(DisasContext *s, int ot)
851{
852 gen_string_movl_A0_ESI(s);
853 gen_op_ld_T0_A0[ot + s->mem_index]();
854 gen_string_movl_A0_EDI(s);
855 gen_op_ld_T1_A0[ot + s->mem_index]();
856 gen_op_cmpl_T0_T1_cc();
857 gen_op_movl_T0_Dshift[ot]();
858 if (s->aflag) {
859 gen_op_addl_ESI_T0();
860 gen_op_addl_EDI_T0();
861 } else {
862 gen_op_addw_ESI_T0();
863 gen_op_addw_EDI_T0();
864 }
865}
866
867static inline void gen_ins(DisasContext *s, int ot)
868{
869 gen_op_in_DX_T0[ot]();
870 gen_string_movl_A0_EDI(s);
871 gen_op_st_T0_A0[ot + s->mem_index]();
872 gen_op_movl_T0_Dshift[ot]();
873 if (s->aflag) {
874 gen_op_addl_EDI_T0();
875 } else {
876 gen_op_addw_EDI_T0();
877 }
878}
879
880static inline void gen_outs(DisasContext *s, int ot)
881{
882 gen_string_movl_A0_ESI(s);
883 gen_op_ld_T0_A0[ot + s->mem_index]();
884 gen_op_out_DX_T0[ot]();
885 gen_op_movl_T0_Dshift[ot]();
886 if (s->aflag) {
887 gen_op_addl_ESI_T0();
888 } else {
889 gen_op_addw_ESI_T0();
890 }
891}
892
893/* same method as Valgrind : we generate jumps to current or next
894 instruction */
895#define GEN_REPZ(op) \
896static inline void gen_repz_ ## op(DisasContext *s, int ot, \
897 unsigned int cur_eip, unsigned int next_eip) \
898{ \
899 gen_update_cc_op(s); \
900 gen_jz_ecx_string(s, next_eip); \
901 gen_ ## op(s, ot); \
902 gen_op_dec_ECX[s->aflag](); \
903 /* a loop would cause two single step exceptions if ECX = 1 \
904 before rep string_insn */ \
905 if (!s->jmp_opt) \
906 gen_op_jz_ecx_im[s->aflag](next_eip); \
907 gen_jmp(s, cur_eip); \
908}
909
910#define GEN_REPZ2(op) \
911static inline void gen_repz_ ## op(DisasContext *s, int ot, \
912 unsigned int cur_eip, \
913 unsigned int next_eip, \
914 int nz) \
915{ \
916 gen_update_cc_op(s); \
917 gen_jz_ecx_string(s, next_eip); \
918 gen_ ## op(s, ot); \
919 gen_op_dec_ECX[s->aflag](); \
920 gen_op_set_cc_op(CC_OP_SUBB + ot); \
921 if (!s->jmp_opt) \
922 gen_op_string_jnz_sub_im[nz][ot](next_eip); \
923 else \
924 gen_op_string_jnz_sub[nz][ot]((long)s->tb); \
925 if (!s->jmp_opt) \
926 gen_op_jz_ecx_im[s->aflag](next_eip); \
927 gen_jmp(s, cur_eip); \
928}
929
930GEN_REPZ(movs)
931GEN_REPZ(stos)
932GEN_REPZ(lods)
933GEN_REPZ(ins)
934GEN_REPZ(outs)
935GEN_REPZ2(scas)
936GEN_REPZ2(cmps)
937
2c0262af
FB
938enum {
939 JCC_O,
940 JCC_B,
941 JCC_Z,
942 JCC_BE,
943 JCC_S,
944 JCC_P,
945 JCC_L,
946 JCC_LE,
947};
948
949static GenOpFunc3 *gen_jcc_sub[3][8] = {
950 [OT_BYTE] = {
951 NULL,
952 gen_op_jb_subb,
953 gen_op_jz_subb,
954 gen_op_jbe_subb,
955 gen_op_js_subb,
956 NULL,
957 gen_op_jl_subb,
958 gen_op_jle_subb,
959 },
960 [OT_WORD] = {
961 NULL,
962 gen_op_jb_subw,
963 gen_op_jz_subw,
964 gen_op_jbe_subw,
965 gen_op_js_subw,
966 NULL,
967 gen_op_jl_subw,
968 gen_op_jle_subw,
969 },
970 [OT_LONG] = {
971 NULL,
972 gen_op_jb_subl,
973 gen_op_jz_subl,
974 gen_op_jbe_subl,
975 gen_op_js_subl,
976 NULL,
977 gen_op_jl_subl,
978 gen_op_jle_subl,
979 },
980};
981static GenOpFunc2 *gen_op_loop[2][4] = {
982 [0] = {
983 gen_op_loopnzw,
984 gen_op_loopzw,
985 gen_op_loopw,
986 gen_op_jecxzw,
987 },
988 [1] = {
989 gen_op_loopnzl,
990 gen_op_loopzl,
991 gen_op_loopl,
992 gen_op_jecxzl,
993 },
994};
995
996static GenOpFunc *gen_setcc_slow[8] = {
997 gen_op_seto_T0_cc,
998 gen_op_setb_T0_cc,
999 gen_op_setz_T0_cc,
1000 gen_op_setbe_T0_cc,
1001 gen_op_sets_T0_cc,
1002 gen_op_setp_T0_cc,
1003 gen_op_setl_T0_cc,
1004 gen_op_setle_T0_cc,
1005};
1006
1007static GenOpFunc *gen_setcc_sub[3][8] = {
1008 [OT_BYTE] = {
1009 NULL,
1010 gen_op_setb_T0_subb,
1011 gen_op_setz_T0_subb,
1012 gen_op_setbe_T0_subb,
1013 gen_op_sets_T0_subb,
1014 NULL,
1015 gen_op_setl_T0_subb,
1016 gen_op_setle_T0_subb,
1017 },
1018 [OT_WORD] = {
1019 NULL,
1020 gen_op_setb_T0_subw,
1021 gen_op_setz_T0_subw,
1022 gen_op_setbe_T0_subw,
1023 gen_op_sets_T0_subw,
1024 NULL,
1025 gen_op_setl_T0_subw,
1026 gen_op_setle_T0_subw,
1027 },
1028 [OT_LONG] = {
1029 NULL,
1030 gen_op_setb_T0_subl,
1031 gen_op_setz_T0_subl,
1032 gen_op_setbe_T0_subl,
1033 gen_op_sets_T0_subl,
1034 NULL,
1035 gen_op_setl_T0_subl,
1036 gen_op_setle_T0_subl,
1037 },
1038};
1039
1040static GenOpFunc *gen_op_fp_arith_ST0_FT0[8] = {
1041 gen_op_fadd_ST0_FT0,
1042 gen_op_fmul_ST0_FT0,
1043 gen_op_fcom_ST0_FT0,
1044 gen_op_fcom_ST0_FT0,
1045 gen_op_fsub_ST0_FT0,
1046 gen_op_fsubr_ST0_FT0,
1047 gen_op_fdiv_ST0_FT0,
1048 gen_op_fdivr_ST0_FT0,
1049};
1050
1051/* NOTE the exception in "r" op ordering */
1052static GenOpFunc1 *gen_op_fp_arith_STN_ST0[8] = {
1053 gen_op_fadd_STN_ST0,
1054 gen_op_fmul_STN_ST0,
1055 NULL,
1056 NULL,
1057 gen_op_fsubr_STN_ST0,
1058 gen_op_fsub_STN_ST0,
1059 gen_op_fdivr_STN_ST0,
1060 gen_op_fdiv_STN_ST0,
1061};
1062
1063/* if d == OR_TMP0, it means memory operand (address in A0) */
1064static void gen_op(DisasContext *s1, int op, int ot, int d)
1065{
1066 GenOpFunc *gen_update_cc;
1067
1068 if (d != OR_TMP0) {
1069 gen_op_mov_TN_reg[ot][0][d]();
1070 } else {
1071 gen_op_ld_T0_A0[ot + s1->mem_index]();
1072 }
1073 switch(op) {
1074 case OP_ADCL:
1075 case OP_SBBL:
1076 if (s1->cc_op != CC_OP_DYNAMIC)
1077 gen_op_set_cc_op(s1->cc_op);
1078 if (d != OR_TMP0) {
1079 gen_op_arithc_T0_T1_cc[ot][op - OP_ADCL]();
1080 gen_op_mov_reg_T0[ot][d]();
1081 } else {
4f31916f 1082 gen_op_arithc_mem_T0_T1_cc[ot + s1->mem_index][op - OP_ADCL]();
2c0262af
FB
1083 }
1084 s1->cc_op = CC_OP_DYNAMIC;
1085 goto the_end;
1086 case OP_ADDL:
1087 gen_op_addl_T0_T1();
1088 s1->cc_op = CC_OP_ADDB + ot;
1089 gen_update_cc = gen_op_update2_cc;
1090 break;
1091 case OP_SUBL:
1092 gen_op_subl_T0_T1();
1093 s1->cc_op = CC_OP_SUBB + ot;
1094 gen_update_cc = gen_op_update2_cc;
1095 break;
1096 default:
1097 case OP_ANDL:
1098 case OP_ORL:
1099 case OP_XORL:
1100 gen_op_arith_T0_T1_cc[op]();
1101 s1->cc_op = CC_OP_LOGICB + ot;
1102 gen_update_cc = gen_op_update1_cc;
1103 break;
1104 case OP_CMPL:
1105 gen_op_cmpl_T0_T1_cc();
1106 s1->cc_op = CC_OP_SUBB + ot;
1107 gen_update_cc = NULL;
1108 break;
1109 }
1110 if (op != OP_CMPL) {
1111 if (d != OR_TMP0)
1112 gen_op_mov_reg_T0[ot][d]();
1113 else
1114 gen_op_st_T0_A0[ot + s1->mem_index]();
1115 }
1116 /* the flags update must happen after the memory write (precise
1117 exception support) */
1118 if (gen_update_cc)
1119 gen_update_cc();
1120 the_end: ;
1121}
1122
1123/* if d == OR_TMP0, it means memory operand (address in A0) */
1124static void gen_inc(DisasContext *s1, int ot, int d, int c)
1125{
1126 if (d != OR_TMP0)
1127 gen_op_mov_TN_reg[ot][0][d]();
1128 else
1129 gen_op_ld_T0_A0[ot + s1->mem_index]();
1130 if (s1->cc_op != CC_OP_DYNAMIC)
1131 gen_op_set_cc_op(s1->cc_op);
1132 if (c > 0) {
1133 gen_op_incl_T0();
1134 s1->cc_op = CC_OP_INCB + ot;
1135 } else {
1136 gen_op_decl_T0();
1137 s1->cc_op = CC_OP_DECB + ot;
1138 }
1139 if (d != OR_TMP0)
1140 gen_op_mov_reg_T0[ot][d]();
1141 else
1142 gen_op_st_T0_A0[ot + s1->mem_index]();
1143 gen_op_update_inc_cc();
1144}
1145
1146static void gen_shift(DisasContext *s1, int op, int ot, int d, int s)
1147{
1148 if (d != OR_TMP0)
1149 gen_op_mov_TN_reg[ot][0][d]();
1150 else
1151 gen_op_ld_T0_A0[ot + s1->mem_index]();
1152 if (s != OR_TMP1)
1153 gen_op_mov_TN_reg[ot][1][s]();
1154 /* for zero counts, flags are not updated, so must do it dynamically */
1155 if (s1->cc_op != CC_OP_DYNAMIC)
1156 gen_op_set_cc_op(s1->cc_op);
1157
1158 if (d != OR_TMP0)
1159 gen_op_shift_T0_T1_cc[ot][op]();
1160 else
4f31916f 1161 gen_op_shift_mem_T0_T1_cc[ot + s1->mem_index][op]();
2c0262af
FB
1162 if (d != OR_TMP0)
1163 gen_op_mov_reg_T0[ot][d]();
1164 s1->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
1165}
1166
1167static void gen_shifti(DisasContext *s1, int op, int ot, int d, int c)
1168{
1169 /* currently not optimized */
1170 gen_op_movl_T1_im(c);
1171 gen_shift(s1, op, ot, d, OR_TMP1);
1172}
1173
1174static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ptr)
1175{
1176 int havesib;
1177 int base, disp;
1178 int index;
1179 int scale;
1180 int opreg;
1181 int mod, rm, code, override, must_add_seg;
1182
1183 override = s->override;
1184 must_add_seg = s->addseg;
1185 if (override >= 0)
1186 must_add_seg = 1;
1187 mod = (modrm >> 6) & 3;
1188 rm = modrm & 7;
1189
1190 if (s->aflag) {
1191
1192 havesib = 0;
1193 base = rm;
1194 index = 0;
1195 scale = 0;
1196
1197 if (base == 4) {
1198 havesib = 1;
61382a50 1199 code = ldub_code(s->pc++);
2c0262af
FB
1200 scale = (code >> 6) & 3;
1201 index = (code >> 3) & 7;
1202 base = code & 7;
1203 }
1204
1205 switch (mod) {
1206 case 0:
1207 if (base == 5) {
1208 base = -1;
61382a50 1209 disp = ldl_code(s->pc);
2c0262af
FB
1210 s->pc += 4;
1211 } else {
1212 disp = 0;
1213 }
1214 break;
1215 case 1:
61382a50 1216 disp = (int8_t)ldub_code(s->pc++);
2c0262af
FB
1217 break;
1218 default:
1219 case 2:
61382a50 1220 disp = ldl_code(s->pc);
2c0262af
FB
1221 s->pc += 4;
1222 break;
1223 }
1224
1225 if (base >= 0) {
1226 /* for correct popl handling with esp */
1227 if (base == 4 && s->popl_esp_hack)
1228 disp += s->popl_esp_hack;
1229 gen_op_movl_A0_reg[base]();
1230 if (disp != 0)
1231 gen_op_addl_A0_im(disp);
1232 } else {
1233 gen_op_movl_A0_im(disp);
1234 }
1235 /* XXX: index == 4 is always invalid */
1236 if (havesib && (index != 4 || scale != 0)) {
1237 gen_op_addl_A0_reg_sN[scale][index]();
1238 }
1239 if (must_add_seg) {
1240 if (override < 0) {
1241 if (base == R_EBP || base == R_ESP)
1242 override = R_SS;
1243 else
1244 override = R_DS;
1245 }
1246 gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base));
1247 }
1248 } else {
1249 switch (mod) {
1250 case 0:
1251 if (rm == 6) {
61382a50 1252 disp = lduw_code(s->pc);
2c0262af
FB
1253 s->pc += 2;
1254 gen_op_movl_A0_im(disp);
1255 rm = 0; /* avoid SS override */
1256 goto no_rm;
1257 } else {
1258 disp = 0;
1259 }
1260 break;
1261 case 1:
61382a50 1262 disp = (int8_t)ldub_code(s->pc++);
2c0262af
FB
1263 break;
1264 default:
1265 case 2:
61382a50 1266 disp = lduw_code(s->pc);
2c0262af
FB
1267 s->pc += 2;
1268 break;
1269 }
1270 switch(rm) {
1271 case 0:
1272 gen_op_movl_A0_reg[R_EBX]();
1273 gen_op_addl_A0_reg_sN[0][R_ESI]();
1274 break;
1275 case 1:
1276 gen_op_movl_A0_reg[R_EBX]();
1277 gen_op_addl_A0_reg_sN[0][R_EDI]();
1278 break;
1279 case 2:
1280 gen_op_movl_A0_reg[R_EBP]();
1281 gen_op_addl_A0_reg_sN[0][R_ESI]();
1282 break;
1283 case 3:
1284 gen_op_movl_A0_reg[R_EBP]();
1285 gen_op_addl_A0_reg_sN[0][R_EDI]();
1286 break;
1287 case 4:
1288 gen_op_movl_A0_reg[R_ESI]();
1289 break;
1290 case 5:
1291 gen_op_movl_A0_reg[R_EDI]();
1292 break;
1293 case 6:
1294 gen_op_movl_A0_reg[R_EBP]();
1295 break;
1296 default:
1297 case 7:
1298 gen_op_movl_A0_reg[R_EBX]();
1299 break;
1300 }
1301 if (disp != 0)
1302 gen_op_addl_A0_im(disp);
1303 gen_op_andl_A0_ffff();
1304 no_rm:
1305 if (must_add_seg) {
1306 if (override < 0) {
1307 if (rm == 2 || rm == 3 || rm == 6)
1308 override = R_SS;
1309 else
1310 override = R_DS;
1311 }
1312 gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base));
1313 }
1314 }
1315
1316 opreg = OR_A0;
1317 disp = 0;
1318 *reg_ptr = opreg;
1319 *offset_ptr = disp;
1320}
1321
1322/* generate modrm memory load or store of 'reg'. TMP0 is used if reg !=
1323 OR_TMP0 */
1324static void gen_ldst_modrm(DisasContext *s, int modrm, int ot, int reg, int is_store)
1325{
1326 int mod, rm, opreg, disp;
1327
1328 mod = (modrm >> 6) & 3;
1329 rm = modrm & 7;
1330 if (mod == 3) {
1331 if (is_store) {
1332 if (reg != OR_TMP0)
1333 gen_op_mov_TN_reg[ot][0][reg]();
1334 gen_op_mov_reg_T0[ot][rm]();
1335 } else {
1336 gen_op_mov_TN_reg[ot][0][rm]();
1337 if (reg != OR_TMP0)
1338 gen_op_mov_reg_T0[ot][reg]();
1339 }
1340 } else {
1341 gen_lea_modrm(s, modrm, &opreg, &disp);
1342 if (is_store) {
1343 if (reg != OR_TMP0)
1344 gen_op_mov_TN_reg[ot][0][reg]();
1345 gen_op_st_T0_A0[ot + s->mem_index]();
1346 } else {
1347 gen_op_ld_T0_A0[ot + s->mem_index]();
1348 if (reg != OR_TMP0)
1349 gen_op_mov_reg_T0[ot][reg]();
1350 }
1351 }
1352}
1353
1354static inline uint32_t insn_get(DisasContext *s, int ot)
1355{
1356 uint32_t ret;
1357
1358 switch(ot) {
1359 case OT_BYTE:
61382a50 1360 ret = ldub_code(s->pc);
2c0262af
FB
1361 s->pc++;
1362 break;
1363 case OT_WORD:
61382a50 1364 ret = lduw_code(s->pc);
2c0262af
FB
1365 s->pc += 2;
1366 break;
1367 default:
1368 case OT_LONG:
61382a50 1369 ret = ldl_code(s->pc);
2c0262af
FB
1370 s->pc += 4;
1371 break;
1372 }
1373 return ret;
1374}
1375
1376static inline void gen_jcc(DisasContext *s, int b, int val, int next_eip)
1377{
1378 TranslationBlock *tb;
1379 int inv, jcc_op;
1380 GenOpFunc3 *func;
1381
1382 inv = b & 1;
1383 jcc_op = (b >> 1) & 7;
1384
1385 if (s->jmp_opt) {
1386 switch(s->cc_op) {
1387 /* we optimize the cmp/jcc case */
1388 case CC_OP_SUBB:
1389 case CC_OP_SUBW:
1390 case CC_OP_SUBL:
1391 func = gen_jcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
1392 break;
1393
1394 /* some jumps are easy to compute */
1395 case CC_OP_ADDB:
1396 case CC_OP_ADDW:
1397 case CC_OP_ADDL:
1398 case CC_OP_ADCB:
1399 case CC_OP_ADCW:
1400 case CC_OP_ADCL:
1401 case CC_OP_SBBB:
1402 case CC_OP_SBBW:
1403 case CC_OP_SBBL:
1404 case CC_OP_LOGICB:
1405 case CC_OP_LOGICW:
1406 case CC_OP_LOGICL:
1407 case CC_OP_INCB:
1408 case CC_OP_INCW:
1409 case CC_OP_INCL:
1410 case CC_OP_DECB:
1411 case CC_OP_DECW:
1412 case CC_OP_DECL:
1413 case CC_OP_SHLB:
1414 case CC_OP_SHLW:
1415 case CC_OP_SHLL:
1416 case CC_OP_SARB:
1417 case CC_OP_SARW:
1418 case CC_OP_SARL:
1419 switch(jcc_op) {
1420 case JCC_Z:
1421 func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1422 break;
1423 case JCC_S:
1424 func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1425 break;
1426 default:
1427 func = NULL;
1428 break;
1429 }
1430 break;
1431 default:
1432 func = NULL;
1433 break;
1434 }
1435
1436 if (s->cc_op != CC_OP_DYNAMIC)
1437 gen_op_set_cc_op(s->cc_op);
1438
1439 if (!func) {
1440 gen_setcc_slow[jcc_op]();
1441 func = gen_op_jcc;
1442 }
1443
1444 tb = s->tb;
1445 if (!inv) {
1446 func((long)tb, val, next_eip);
1447 } else {
1448 func((long)tb, next_eip, val);
1449 }
1450 s->is_jmp = 3;
1451 } else {
1452 if (s->cc_op != CC_OP_DYNAMIC) {
1453 gen_op_set_cc_op(s->cc_op);
1454 s->cc_op = CC_OP_DYNAMIC;
1455 }
1456 gen_setcc_slow[jcc_op]();
1457 if (!inv) {
1458 gen_op_jcc_im(val, next_eip);
1459 } else {
1460 gen_op_jcc_im(next_eip, val);
1461 }
1462 gen_eob(s);
1463 }
1464}
1465
1466static void gen_setcc(DisasContext *s, int b)
1467{
1468 int inv, jcc_op;
1469 GenOpFunc *func;
1470
1471 inv = b & 1;
1472 jcc_op = (b >> 1) & 7;
1473 switch(s->cc_op) {
1474 /* we optimize the cmp/jcc case */
1475 case CC_OP_SUBB:
1476 case CC_OP_SUBW:
1477 case CC_OP_SUBL:
1478 func = gen_setcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
1479 if (!func)
1480 goto slow_jcc;
1481 break;
1482
1483 /* some jumps are easy to compute */
1484 case CC_OP_ADDB:
1485 case CC_OP_ADDW:
1486 case CC_OP_ADDL:
1487 case CC_OP_LOGICB:
1488 case CC_OP_LOGICW:
1489 case CC_OP_LOGICL:
1490 case CC_OP_INCB:
1491 case CC_OP_INCW:
1492 case CC_OP_INCL:
1493 case CC_OP_DECB:
1494 case CC_OP_DECW:
1495 case CC_OP_DECL:
1496 case CC_OP_SHLB:
1497 case CC_OP_SHLW:
1498 case CC_OP_SHLL:
1499 switch(jcc_op) {
1500 case JCC_Z:
1501 func = gen_setcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1502 break;
1503 case JCC_S:
1504 func = gen_setcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1505 break;
1506 default:
1507 goto slow_jcc;
1508 }
1509 break;
1510 default:
1511 slow_jcc:
1512 if (s->cc_op != CC_OP_DYNAMIC)
1513 gen_op_set_cc_op(s->cc_op);
1514 func = gen_setcc_slow[jcc_op];
1515 break;
1516 }
1517 func();
1518 if (inv) {
1519 gen_op_xor_T0_1();
1520 }
1521}
1522
1523/* move T0 to seg_reg and compute if the CPU state may change. Never
1524 call this function with seg_reg == R_CS */
1525static void gen_movl_seg_T0(DisasContext *s, int seg_reg, unsigned int cur_eip)
1526{
3415a4dd
FB
1527 if (s->pe && !s->vm86) {
1528 /* XXX: optimize by finding processor state dynamically */
1529 if (s->cc_op != CC_OP_DYNAMIC)
1530 gen_op_set_cc_op(s->cc_op);
1531 gen_op_jmp_im(cur_eip);
1532 gen_op_movl_seg_T0(seg_reg);
1533 } else {
2c0262af 1534 gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[seg_reg]));
3415a4dd 1535 }
2c0262af
FB
1536 /* abort translation because the register may have a non zero base
1537 or because ss32 may change. For R_SS, translation must always
1538 stop as a special handling must be done to disable hardware
1539 interrupts for the next instruction */
1540 if (seg_reg == R_SS || (!s->addseg && seg_reg < R_FS))
1541 s->is_jmp = 3;
1542}
1543
4f31916f
FB
1544static inline void gen_stack_update(DisasContext *s, int addend)
1545{
1546 if (s->ss32) {
1547 if (addend == 2)
1548 gen_op_addl_ESP_2();
1549 else if (addend == 4)
1550 gen_op_addl_ESP_4();
1551 else
1552 gen_op_addl_ESP_im(addend);
1553 } else {
1554 if (addend == 2)
1555 gen_op_addw_ESP_2();
1556 else if (addend == 4)
1557 gen_op_addw_ESP_4();
1558 else
1559 gen_op_addw_ESP_im(addend);
1560 }
1561}
1562
2c0262af
FB
1563/* generate a push. It depends on ss32, addseg and dflag */
1564static void gen_push_T0(DisasContext *s)
1565{
4f31916f
FB
1566 gen_op_movl_A0_reg[R_ESP]();
1567 if (!s->dflag)
1568 gen_op_subl_A0_2();
1569 else
1570 gen_op_subl_A0_4();
2c0262af 1571 if (s->ss32) {
4f31916f
FB
1572 if (s->addseg) {
1573 gen_op_movl_T1_A0();
1574 gen_op_addl_A0_SS();
2c0262af
FB
1575 }
1576 } else {
4f31916f
FB
1577 gen_op_andl_A0_ffff();
1578 gen_op_movl_T1_A0();
1579 gen_op_addl_A0_SS();
2c0262af 1580 }
4f31916f
FB
1581 gen_op_st_T0_A0[s->dflag + 1 + s->mem_index]();
1582 if (s->ss32 && !s->addseg)
1583 gen_op_movl_ESP_A0();
1584 else
1585 gen_op_mov_reg_T1[s->ss32 + 1][R_ESP]();
2c0262af
FB
1586}
1587
4f31916f
FB
1588/* generate a push. It depends on ss32, addseg and dflag */
1589/* slower version for T1, only used for call Ev */
1590static void gen_push_T1(DisasContext *s)
2c0262af 1591{
4f31916f
FB
1592 gen_op_movl_A0_reg[R_ESP]();
1593 if (!s->dflag)
1594 gen_op_subl_A0_2();
1595 else
1596 gen_op_subl_A0_4();
2c0262af 1597 if (s->ss32) {
4f31916f
FB
1598 if (s->addseg) {
1599 gen_op_addl_A0_SS();
2c0262af
FB
1600 }
1601 } else {
4f31916f
FB
1602 gen_op_andl_A0_ffff();
1603 gen_op_addl_A0_SS();
2c0262af 1604 }
4f31916f
FB
1605 gen_op_st_T1_A0[s->dflag + 1 + s->mem_index]();
1606
1607 if (s->ss32 && !s->addseg)
1608 gen_op_movl_ESP_A0();
1609 else
1610 gen_stack_update(s, (-2) << s->dflag);
2c0262af
FB
1611}
1612
4f31916f
FB
1613/* two step pop is necessary for precise exceptions */
1614static void gen_pop_T0(DisasContext *s)
2c0262af 1615{
4f31916f 1616 gen_op_movl_A0_reg[R_ESP]();
2c0262af 1617 if (s->ss32) {
4f31916f
FB
1618 if (s->addseg)
1619 gen_op_addl_A0_SS();
2c0262af 1620 } else {
4f31916f
FB
1621 gen_op_andl_A0_ffff();
1622 gen_op_addl_A0_SS();
2c0262af 1623 }
4f31916f 1624 gen_op_ld_T0_A0[s->dflag + 1 + s->mem_index]();
2c0262af
FB
1625}
1626
1627static void gen_pop_update(DisasContext *s)
1628{
1629 gen_stack_update(s, 2 << s->dflag);
1630}
1631
1632static void gen_stack_A0(DisasContext *s)
1633{
1634 gen_op_movl_A0_ESP();
1635 if (!s->ss32)
1636 gen_op_andl_A0_ffff();
1637 gen_op_movl_T1_A0();
1638 if (s->addseg)
1639 gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
1640}
1641
1642/* NOTE: wrap around in 16 bit not fully handled */
1643static void gen_pusha(DisasContext *s)
1644{
1645 int i;
1646 gen_op_movl_A0_ESP();
1647 gen_op_addl_A0_im(-16 << s->dflag);
1648 if (!s->ss32)
1649 gen_op_andl_A0_ffff();
1650 gen_op_movl_T1_A0();
1651 if (s->addseg)
1652 gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
1653 for(i = 0;i < 8; i++) {
1654 gen_op_mov_TN_reg[OT_LONG][0][7 - i]();
1655 gen_op_st_T0_A0[OT_WORD + s->dflag + s->mem_index]();
1656 gen_op_addl_A0_im(2 << s->dflag);
1657 }
1658 gen_op_mov_reg_T1[OT_WORD + s->dflag][R_ESP]();
1659}
1660
1661/* NOTE: wrap around in 16 bit not fully handled */
1662static void gen_popa(DisasContext *s)
1663{
1664 int i;
1665 gen_op_movl_A0_ESP();
1666 if (!s->ss32)
1667 gen_op_andl_A0_ffff();
1668 gen_op_movl_T1_A0();
1669 gen_op_addl_T1_im(16 << s->dflag);
1670 if (s->addseg)
1671 gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
1672 for(i = 0;i < 8; i++) {
1673 /* ESP is not reloaded */
1674 if (i != 3) {
1675 gen_op_ld_T0_A0[OT_WORD + s->dflag + s->mem_index]();
1676 gen_op_mov_reg_T0[OT_WORD + s->dflag][7 - i]();
1677 }
1678 gen_op_addl_A0_im(2 << s->dflag);
1679 }
1680 gen_op_mov_reg_T1[OT_WORD + s->dflag][R_ESP]();
1681}
1682
1683/* NOTE: wrap around in 16 bit not fully handled */
1684/* XXX: check this */
1685static void gen_enter(DisasContext *s, int esp_addend, int level)
1686{
1687 int ot, level1, addend, opsize;
1688
1689 ot = s->dflag + OT_WORD;
1690 level &= 0x1f;
1691 level1 = level;
1692 opsize = 2 << s->dflag;
1693
1694 gen_op_movl_A0_ESP();
1695 gen_op_addl_A0_im(-opsize);
1696 if (!s->ss32)
1697 gen_op_andl_A0_ffff();
1698 gen_op_movl_T1_A0();
1699 if (s->addseg)
1700 gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
1701 /* push bp */
1702 gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
1703 gen_op_st_T0_A0[ot + s->mem_index]();
1704 if (level) {
1705 while (level--) {
1706 gen_op_addl_A0_im(-opsize);
1707 gen_op_addl_T0_im(-opsize);
1708 gen_op_st_T0_A0[ot + s->mem_index]();
1709 }
1710 gen_op_addl_A0_im(-opsize);
4f31916f 1711 gen_op_st_T1_A0[ot + s->mem_index]();
2c0262af
FB
1712 }
1713 gen_op_mov_reg_T1[ot][R_EBP]();
1714 addend = -esp_addend;
1715 if (level1)
1716 addend -= opsize * (level1 + 1);
1717 gen_op_addl_T1_im(addend);
1718 gen_op_mov_reg_T1[ot][R_ESP]();
1719}
1720
1721static void gen_exception(DisasContext *s, int trapno, unsigned int cur_eip)
1722{
1723 if (s->cc_op != CC_OP_DYNAMIC)
1724 gen_op_set_cc_op(s->cc_op);
1725 gen_op_jmp_im(cur_eip);
1726 gen_op_raise_exception(trapno);
1727 s->is_jmp = 3;
1728}
1729
1730/* an interrupt is different from an exception because of the
1731 priviledge checks */
1732static void gen_interrupt(DisasContext *s, int intno,
1733 unsigned int cur_eip, unsigned int next_eip)
1734{
1735 if (s->cc_op != CC_OP_DYNAMIC)
1736 gen_op_set_cc_op(s->cc_op);
1737 gen_op_jmp_im(cur_eip);
1738 gen_op_raise_interrupt(intno, next_eip);
1739 s->is_jmp = 3;
1740}
1741
1742static void gen_debug(DisasContext *s, unsigned int cur_eip)
1743{
1744 if (s->cc_op != CC_OP_DYNAMIC)
1745 gen_op_set_cc_op(s->cc_op);
1746 gen_op_jmp_im(cur_eip);
1747 gen_op_debug();
1748 s->is_jmp = 3;
1749}
1750
1751/* generate a generic end of block. Trace exception is also generated
1752 if needed */
1753static void gen_eob(DisasContext *s)
1754{
1755 if (s->cc_op != CC_OP_DYNAMIC)
1756 gen_op_set_cc_op(s->cc_op);
a2cc3b24
FB
1757 if (s->tb->flags & HF_INHIBIT_IRQ_MASK) {
1758 gen_op_reset_inhibit_irq();
1759 }
34865134
FB
1760 if (s->singlestep_enabled) {
1761 gen_op_debug();
1762 } else if (s->tf) {
2c0262af
FB
1763 gen_op_raise_exception(EXCP01_SSTP);
1764 } else {
1765 gen_op_movl_T0_0();
1766 gen_op_exit_tb();
1767 }
1768 s->is_jmp = 3;
1769}
1770
1771/* generate a jump to eip. No segment change must happen before as a
1772 direct call to the next block may occur */
1773static void gen_jmp(DisasContext *s, unsigned int eip)
1774{
1775 TranslationBlock *tb = s->tb;
1776
1777 if (s->jmp_opt) {
1778 if (s->cc_op != CC_OP_DYNAMIC)
1779 gen_op_set_cc_op(s->cc_op);
1780 gen_op_jmp((long)tb, eip);
1781 s->is_jmp = 3;
1782 } else {
1783 gen_op_jmp_im(eip);
1784 gen_eob(s);
1785 }
1786}
1787
1788/* convert one instruction. s->is_jmp is set if the translation must
1789 be stopped. Return the next pc value */
1790static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
1791{
1792 int b, prefixes, aflag, dflag;
1793 int shift, ot;
1794 int modrm, reg, rm, mod, reg_addr, op, opreg, offset_addr, val;
1795 unsigned int next_eip;
1796
1797 s->pc = pc_start;
1798 prefixes = 0;
1799 aflag = s->code32;
1800 dflag = s->code32;
1801 s->override = -1;
1802 next_byte:
61382a50 1803 b = ldub_code(s->pc);
2c0262af
FB
1804 s->pc++;
1805 /* check prefixes */
1806 switch (b) {
1807 case 0xf3:
1808 prefixes |= PREFIX_REPZ;
1809 goto next_byte;
1810 case 0xf2:
1811 prefixes |= PREFIX_REPNZ;
1812 goto next_byte;
1813 case 0xf0:
1814 prefixes |= PREFIX_LOCK;
1815 goto next_byte;
1816 case 0x2e:
1817 s->override = R_CS;
1818 goto next_byte;
1819 case 0x36:
1820 s->override = R_SS;
1821 goto next_byte;
1822 case 0x3e:
1823 s->override = R_DS;
1824 goto next_byte;
1825 case 0x26:
1826 s->override = R_ES;
1827 goto next_byte;
1828 case 0x64:
1829 s->override = R_FS;
1830 goto next_byte;
1831 case 0x65:
1832 s->override = R_GS;
1833 goto next_byte;
1834 case 0x66:
1835 prefixes |= PREFIX_DATA;
1836 goto next_byte;
1837 case 0x67:
1838 prefixes |= PREFIX_ADR;
1839 goto next_byte;
1840 }
1841
1842 if (prefixes & PREFIX_DATA)
1843 dflag ^= 1;
1844 if (prefixes & PREFIX_ADR)
1845 aflag ^= 1;
1846
1847 s->prefix = prefixes;
1848 s->aflag = aflag;
1849 s->dflag = dflag;
1850
1851 /* lock generation */
1852 if (prefixes & PREFIX_LOCK)
1853 gen_op_lock();
1854
1855 /* now check op code */
1856 reswitch:
1857 switch(b) {
1858 case 0x0f:
1859 /**************************/
1860 /* extended op code */
61382a50 1861 b = ldub_code(s->pc++) | 0x100;
2c0262af
FB
1862 goto reswitch;
1863
1864 /**************************/
1865 /* arith & logic */
1866 case 0x00 ... 0x05:
1867 case 0x08 ... 0x0d:
1868 case 0x10 ... 0x15:
1869 case 0x18 ... 0x1d:
1870 case 0x20 ... 0x25:
1871 case 0x28 ... 0x2d:
1872 case 0x30 ... 0x35:
1873 case 0x38 ... 0x3d:
1874 {
1875 int op, f, val;
1876 op = (b >> 3) & 7;
1877 f = (b >> 1) & 3;
1878
1879 if ((b & 1) == 0)
1880 ot = OT_BYTE;
1881 else
1882 ot = dflag ? OT_LONG : OT_WORD;
1883
1884 switch(f) {
1885 case 0: /* OP Ev, Gv */
61382a50 1886 modrm = ldub_code(s->pc++);
2c0262af
FB
1887 reg = ((modrm >> 3) & 7);
1888 mod = (modrm >> 6) & 3;
1889 rm = modrm & 7;
1890 if (mod != 3) {
1891 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1892 opreg = OR_TMP0;
1893 } else if (op == OP_XORL && rm == reg) {
1894 xor_zero:
1895 /* xor reg, reg optimisation */
1896 gen_op_movl_T0_0();
1897 s->cc_op = CC_OP_LOGICB + ot;
1898 gen_op_mov_reg_T0[ot][reg]();
1899 gen_op_update1_cc();
1900 break;
1901 } else {
1902 opreg = rm;
1903 }
1904 gen_op_mov_TN_reg[ot][1][reg]();
1905 gen_op(s, op, ot, opreg);
1906 break;
1907 case 1: /* OP Gv, Ev */
61382a50 1908 modrm = ldub_code(s->pc++);
2c0262af
FB
1909 mod = (modrm >> 6) & 3;
1910 reg = ((modrm >> 3) & 7);
1911 rm = modrm & 7;
1912 if (mod != 3) {
1913 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1914 gen_op_ld_T1_A0[ot + s->mem_index]();
1915 } else if (op == OP_XORL && rm == reg) {
1916 goto xor_zero;
1917 } else {
1918 gen_op_mov_TN_reg[ot][1][rm]();
1919 }
1920 gen_op(s, op, ot, reg);
1921 break;
1922 case 2: /* OP A, Iv */
1923 val = insn_get(s, ot);
1924 gen_op_movl_T1_im(val);
1925 gen_op(s, op, ot, OR_EAX);
1926 break;
1927 }
1928 }
1929 break;
1930
1931 case 0x80: /* GRP1 */
1932 case 0x81:
1933 case 0x83:
1934 {
1935 int val;
1936
1937 if ((b & 1) == 0)
1938 ot = OT_BYTE;
1939 else
1940 ot = dflag ? OT_LONG : OT_WORD;
1941
61382a50 1942 modrm = ldub_code(s->pc++);
2c0262af
FB
1943 mod = (modrm >> 6) & 3;
1944 rm = modrm & 7;
1945 op = (modrm >> 3) & 7;
1946
1947 if (mod != 3) {
1948 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1949 opreg = OR_TMP0;
1950 } else {
1951 opreg = rm + OR_EAX;
1952 }
1953
1954 switch(b) {
1955 default:
1956 case 0x80:
1957 case 0x81:
1958 val = insn_get(s, ot);
1959 break;
1960 case 0x83:
1961 val = (int8_t)insn_get(s, OT_BYTE);
1962 break;
1963 }
1964 gen_op_movl_T1_im(val);
1965 gen_op(s, op, ot, opreg);
1966 }
1967 break;
1968
1969 /**************************/
1970 /* inc, dec, and other misc arith */
1971 case 0x40 ... 0x47: /* inc Gv */
1972 ot = dflag ? OT_LONG : OT_WORD;
1973 gen_inc(s, ot, OR_EAX + (b & 7), 1);
1974 break;
1975 case 0x48 ... 0x4f: /* dec Gv */
1976 ot = dflag ? OT_LONG : OT_WORD;
1977 gen_inc(s, ot, OR_EAX + (b & 7), -1);
1978 break;
1979 case 0xf6: /* GRP3 */
1980 case 0xf7:
1981 if ((b & 1) == 0)
1982 ot = OT_BYTE;
1983 else
1984 ot = dflag ? OT_LONG : OT_WORD;
1985
61382a50 1986 modrm = ldub_code(s->pc++);
2c0262af
FB
1987 mod = (modrm >> 6) & 3;
1988 rm = modrm & 7;
1989 op = (modrm >> 3) & 7;
1990 if (mod != 3) {
1991 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1992 gen_op_ld_T0_A0[ot + s->mem_index]();
1993 } else {
1994 gen_op_mov_TN_reg[ot][0][rm]();
1995 }
1996
1997 switch(op) {
1998 case 0: /* test */
1999 val = insn_get(s, ot);
2000 gen_op_movl_T1_im(val);
2001 gen_op_testl_T0_T1_cc();
2002 s->cc_op = CC_OP_LOGICB + ot;
2003 break;
2004 case 2: /* not */
2005 gen_op_notl_T0();
2006 if (mod != 3) {
2007 gen_op_st_T0_A0[ot + s->mem_index]();
2008 } else {
2009 gen_op_mov_reg_T0[ot][rm]();
2010 }
2011 break;
2012 case 3: /* neg */
2013 gen_op_negl_T0();
2014 if (mod != 3) {
2015 gen_op_st_T0_A0[ot + s->mem_index]();
2016 } else {
2017 gen_op_mov_reg_T0[ot][rm]();
2018 }
2019 gen_op_update_neg_cc();
2020 s->cc_op = CC_OP_SUBB + ot;
2021 break;
2022 case 4: /* mul */
2023 switch(ot) {
2024 case OT_BYTE:
2025 gen_op_mulb_AL_T0();
d36cd60e 2026 s->cc_op = CC_OP_MULB;
2c0262af
FB
2027 break;
2028 case OT_WORD:
2029 gen_op_mulw_AX_T0();
d36cd60e 2030 s->cc_op = CC_OP_MULW;
2c0262af
FB
2031 break;
2032 default:
2033 case OT_LONG:
2034 gen_op_mull_EAX_T0();
d36cd60e 2035 s->cc_op = CC_OP_MULL;
2c0262af
FB
2036 break;
2037 }
2c0262af
FB
2038 break;
2039 case 5: /* imul */
2040 switch(ot) {
2041 case OT_BYTE:
2042 gen_op_imulb_AL_T0();
d36cd60e 2043 s->cc_op = CC_OP_MULB;
2c0262af
FB
2044 break;
2045 case OT_WORD:
2046 gen_op_imulw_AX_T0();
d36cd60e 2047 s->cc_op = CC_OP_MULW;
2c0262af
FB
2048 break;
2049 default:
2050 case OT_LONG:
2051 gen_op_imull_EAX_T0();
d36cd60e 2052 s->cc_op = CC_OP_MULL;
2c0262af
FB
2053 break;
2054 }
2c0262af
FB
2055 break;
2056 case 6: /* div */
2057 switch(ot) {
2058 case OT_BYTE:
2059 gen_op_divb_AL_T0(pc_start - s->cs_base);
2060 break;
2061 case OT_WORD:
2062 gen_op_divw_AX_T0(pc_start - s->cs_base);
2063 break;
2064 default:
2065 case OT_LONG:
2066 gen_op_divl_EAX_T0(pc_start - s->cs_base);
2067 break;
2068 }
2069 break;
2070 case 7: /* idiv */
2071 switch(ot) {
2072 case OT_BYTE:
2073 gen_op_idivb_AL_T0(pc_start - s->cs_base);
2074 break;
2075 case OT_WORD:
2076 gen_op_idivw_AX_T0(pc_start - s->cs_base);
2077 break;
2078 default:
2079 case OT_LONG:
2080 gen_op_idivl_EAX_T0(pc_start - s->cs_base);
2081 break;
2082 }
2083 break;
2084 default:
2085 goto illegal_op;
2086 }
2087 break;
2088
2089 case 0xfe: /* GRP4 */
2090 case 0xff: /* GRP5 */
2091 if ((b & 1) == 0)
2092 ot = OT_BYTE;
2093 else
2094 ot = dflag ? OT_LONG : OT_WORD;
2095
61382a50 2096 modrm = ldub_code(s->pc++);
2c0262af
FB
2097 mod = (modrm >> 6) & 3;
2098 rm = modrm & 7;
2099 op = (modrm >> 3) & 7;
2100 if (op >= 2 && b == 0xfe) {
2101 goto illegal_op;
2102 }
2103 if (mod != 3) {
2104 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2105 if (op >= 2 && op != 3 && op != 5)
2106 gen_op_ld_T0_A0[ot + s->mem_index]();
2107 } else {
2108 gen_op_mov_TN_reg[ot][0][rm]();
2109 }
2110
2111 switch(op) {
2112 case 0: /* inc Ev */
2113 if (mod != 3)
2114 opreg = OR_TMP0;
2115 else
2116 opreg = rm;
2117 gen_inc(s, ot, opreg, 1);
2118 break;
2119 case 1: /* dec Ev */
2120 if (mod != 3)
2121 opreg = OR_TMP0;
2122 else
2123 opreg = rm;
2124 gen_inc(s, ot, opreg, -1);
2125 break;
2126 case 2: /* call Ev */
4f31916f 2127 /* XXX: optimize if memory (no 'and' is necessary) */
2c0262af
FB
2128 if (s->dflag == 0)
2129 gen_op_andl_T0_ffff();
2c0262af 2130 next_eip = s->pc - s->cs_base;
4f31916f
FB
2131 gen_op_movl_T1_im(next_eip);
2132 gen_push_T1(s);
2133 gen_op_jmp_T0();
2c0262af
FB
2134 gen_eob(s);
2135 break;
61382a50 2136 case 3: /* lcall Ev */
2c0262af
FB
2137 gen_op_ld_T1_A0[ot + s->mem_index]();
2138 gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
61382a50 2139 gen_op_ldu_T0_A0[OT_WORD + s->mem_index]();
2c0262af
FB
2140 do_lcall:
2141 if (s->pe && !s->vm86) {
2142 if (s->cc_op != CC_OP_DYNAMIC)
2143 gen_op_set_cc_op(s->cc_op);
2144 gen_op_jmp_im(pc_start - s->cs_base);
2145 gen_op_lcall_protected_T0_T1(dflag, s->pc - s->cs_base);
2146 } else {
2147 gen_op_lcall_real_T0_T1(dflag, s->pc - s->cs_base);
2148 }
2149 gen_eob(s);
2150 break;
2151 case 4: /* jmp Ev */
2152 if (s->dflag == 0)
2153 gen_op_andl_T0_ffff();
2154 gen_op_jmp_T0();
2155 gen_eob(s);
2156 break;
2157 case 5: /* ljmp Ev */
2158 gen_op_ld_T1_A0[ot + s->mem_index]();
2159 gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
61382a50 2160 gen_op_ldu_T0_A0[OT_WORD + s->mem_index]();
2c0262af
FB
2161 do_ljmp:
2162 if (s->pe && !s->vm86) {
2163 if (s->cc_op != CC_OP_DYNAMIC)
2164 gen_op_set_cc_op(s->cc_op);
2165 gen_op_jmp_im(pc_start - s->cs_base);
2166 gen_op_ljmp_protected_T0_T1();
2167 } else {
2168 gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[R_CS]));
2169 gen_op_movl_T0_T1();
2170 gen_op_jmp_T0();
2171 }
2172 gen_eob(s);
2173 break;
2174 case 6: /* push Ev */
2175 gen_push_T0(s);
2176 break;
2177 default:
2178 goto illegal_op;
2179 }
2180 break;
2181
2182 case 0x84: /* test Ev, Gv */
2183 case 0x85:
2184 if ((b & 1) == 0)
2185 ot = OT_BYTE;
2186 else
2187 ot = dflag ? OT_LONG : OT_WORD;
2188
61382a50 2189 modrm = ldub_code(s->pc++);
2c0262af
FB
2190 mod = (modrm >> 6) & 3;
2191 rm = modrm & 7;
2192 reg = (modrm >> 3) & 7;
2193
2194 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
2195 gen_op_mov_TN_reg[ot][1][reg + OR_EAX]();
2196 gen_op_testl_T0_T1_cc();
2197 s->cc_op = CC_OP_LOGICB + ot;
2198 break;
2199
2200 case 0xa8: /* test eAX, Iv */
2201 case 0xa9:
2202 if ((b & 1) == 0)
2203 ot = OT_BYTE;
2204 else
2205 ot = dflag ? OT_LONG : OT_WORD;
2206 val = insn_get(s, ot);
2207
2208 gen_op_mov_TN_reg[ot][0][OR_EAX]();
2209 gen_op_movl_T1_im(val);
2210 gen_op_testl_T0_T1_cc();
2211 s->cc_op = CC_OP_LOGICB + ot;
2212 break;
2213
2214 case 0x98: /* CWDE/CBW */
2215 if (dflag)
2216 gen_op_movswl_EAX_AX();
2217 else
2218 gen_op_movsbw_AX_AL();
2219 break;
2220 case 0x99: /* CDQ/CWD */
2221 if (dflag)
2222 gen_op_movslq_EDX_EAX();
2223 else
2224 gen_op_movswl_DX_AX();
2225 break;
2226 case 0x1af: /* imul Gv, Ev */
2227 case 0x69: /* imul Gv, Ev, I */
2228 case 0x6b:
2229 ot = dflag ? OT_LONG : OT_WORD;
61382a50 2230 modrm = ldub_code(s->pc++);
2c0262af
FB
2231 reg = ((modrm >> 3) & 7) + OR_EAX;
2232 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
2233 if (b == 0x69) {
2234 val = insn_get(s, ot);
2235 gen_op_movl_T1_im(val);
2236 } else if (b == 0x6b) {
2237 val = insn_get(s, OT_BYTE);
2238 gen_op_movl_T1_im(val);
2239 } else {
2240 gen_op_mov_TN_reg[ot][1][reg]();
2241 }
2242
2243 if (ot == OT_LONG) {
2244 gen_op_imull_T0_T1();
2245 } else {
2246 gen_op_imulw_T0_T1();
2247 }
2248 gen_op_mov_reg_T0[ot][reg]();
d36cd60e 2249 s->cc_op = CC_OP_MULB + ot;
2c0262af
FB
2250 break;
2251 case 0x1c0:
2252 case 0x1c1: /* xadd Ev, Gv */
2253 if ((b & 1) == 0)
2254 ot = OT_BYTE;
2255 else
2256 ot = dflag ? OT_LONG : OT_WORD;
61382a50 2257 modrm = ldub_code(s->pc++);
2c0262af
FB
2258 reg = (modrm >> 3) & 7;
2259 mod = (modrm >> 6) & 3;
2260 if (mod == 3) {
2261 rm = modrm & 7;
2262 gen_op_mov_TN_reg[ot][0][reg]();
2263 gen_op_mov_TN_reg[ot][1][rm]();
2264 gen_op_addl_T0_T1();
2c0262af 2265 gen_op_mov_reg_T1[ot][reg]();
5a1388b6 2266 gen_op_mov_reg_T0[ot][rm]();
2c0262af
FB
2267 } else {
2268 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2269 gen_op_mov_TN_reg[ot][0][reg]();
2270 gen_op_ld_T1_A0[ot + s->mem_index]();
2271 gen_op_addl_T0_T1();
2272 gen_op_st_T0_A0[ot + s->mem_index]();
2273 gen_op_mov_reg_T1[ot][reg]();
2274 }
2275 gen_op_update2_cc();
2276 s->cc_op = CC_OP_ADDB + ot;
2277 break;
2278 case 0x1b0:
2279 case 0x1b1: /* cmpxchg Ev, Gv */
2280 if ((b & 1) == 0)
2281 ot = OT_BYTE;
2282 else
2283 ot = dflag ? OT_LONG : OT_WORD;
61382a50 2284 modrm = ldub_code(s->pc++);
2c0262af
FB
2285 reg = (modrm >> 3) & 7;
2286 mod = (modrm >> 6) & 3;
2287 gen_op_mov_TN_reg[ot][1][reg]();
2288 if (mod == 3) {
2289 rm = modrm & 7;
2290 gen_op_mov_TN_reg[ot][0][rm]();
2291 gen_op_cmpxchg_T0_T1_EAX_cc[ot]();
2292 gen_op_mov_reg_T0[ot][rm]();
2293 } else {
2294 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2295 gen_op_ld_T0_A0[ot + s->mem_index]();
4f31916f 2296 gen_op_cmpxchg_mem_T0_T1_EAX_cc[ot + s->mem_index]();
2c0262af
FB
2297 }
2298 s->cc_op = CC_OP_SUBB + ot;
2299 break;
2300 case 0x1c7: /* cmpxchg8b */
61382a50 2301 modrm = ldub_code(s->pc++);
2c0262af
FB
2302 mod = (modrm >> 6) & 3;
2303 if (mod == 3)
2304 goto illegal_op;
2305 if (s->cc_op != CC_OP_DYNAMIC)
2306 gen_op_set_cc_op(s->cc_op);
2307 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2308 gen_op_cmpxchg8b();
2309 s->cc_op = CC_OP_EFLAGS;
2310 break;
2311
2312 /**************************/
2313 /* push/pop */
2314 case 0x50 ... 0x57: /* push */
2315 gen_op_mov_TN_reg[OT_LONG][0][b & 7]();
2316 gen_push_T0(s);
2317 break;
2318 case 0x58 ... 0x5f: /* pop */
2319 ot = dflag ? OT_LONG : OT_WORD;
2320 gen_pop_T0(s);
77729c24 2321 /* NOTE: order is important for pop %sp */
2c0262af 2322 gen_pop_update(s);
77729c24 2323 gen_op_mov_reg_T0[ot][b & 7]();
2c0262af
FB
2324 break;
2325 case 0x60: /* pusha */
2326 gen_pusha(s);
2327 break;
2328 case 0x61: /* popa */
2329 gen_popa(s);
2330 break;
2331 case 0x68: /* push Iv */
2332 case 0x6a:
2333 ot = dflag ? OT_LONG : OT_WORD;
2334 if (b == 0x68)
2335 val = insn_get(s, ot);
2336 else
2337 val = (int8_t)insn_get(s, OT_BYTE);
2338 gen_op_movl_T0_im(val);
2339 gen_push_T0(s);
2340 break;
2341 case 0x8f: /* pop Ev */
2342 ot = dflag ? OT_LONG : OT_WORD;
61382a50 2343 modrm = ldub_code(s->pc++);
77729c24 2344 mod = (modrm >> 6) & 3;
2c0262af 2345 gen_pop_T0(s);
77729c24
FB
2346 if (mod == 3) {
2347 /* NOTE: order is important for pop %sp */
2348 gen_pop_update(s);
2349 rm = modrm & 7;
2350 gen_op_mov_reg_T0[ot][rm]();
2351 } else {
2352 /* NOTE: order is important too for MMU exceptions */
2353 s->popl_esp_hack = 2 << dflag;
2354 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
2355 s->popl_esp_hack = 0;
2356 gen_pop_update(s);
2357 }
2c0262af
FB
2358 break;
2359 case 0xc8: /* enter */
2360 {
2361 int level;
61382a50 2362 val = lduw_code(s->pc);
2c0262af 2363 s->pc += 2;
61382a50 2364 level = ldub_code(s->pc++);
2c0262af
FB
2365 gen_enter(s, val, level);
2366 }
2367 break;
2368 case 0xc9: /* leave */
2369 /* XXX: exception not precise (ESP is updated before potential exception) */
2370 if (s->ss32) {
2371 gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
2372 gen_op_mov_reg_T0[OT_LONG][R_ESP]();
2373 } else {
2374 gen_op_mov_TN_reg[OT_WORD][0][R_EBP]();
2375 gen_op_mov_reg_T0[OT_WORD][R_ESP]();
2376 }
2377 gen_pop_T0(s);
2378 ot = dflag ? OT_LONG : OT_WORD;
2379 gen_op_mov_reg_T0[ot][R_EBP]();
2380 gen_pop_update(s);
2381 break;
2382 case 0x06: /* push es */
2383 case 0x0e: /* push cs */
2384 case 0x16: /* push ss */
2385 case 0x1e: /* push ds */
2386 gen_op_movl_T0_seg(b >> 3);
2387 gen_push_T0(s);
2388 break;
2389 case 0x1a0: /* push fs */
2390 case 0x1a8: /* push gs */
2391 gen_op_movl_T0_seg((b >> 3) & 7);
2392 gen_push_T0(s);
2393 break;
2394 case 0x07: /* pop es */
2395 case 0x17: /* pop ss */
2396 case 0x1f: /* pop ds */
2397 reg = b >> 3;
2398 gen_pop_T0(s);
2399 gen_movl_seg_T0(s, reg, pc_start - s->cs_base);
2400 gen_pop_update(s);
2401 if (reg == R_SS) {
a2cc3b24
FB
2402 /* if reg == SS, inhibit interrupts/trace. */
2403 /* If several instructions disable interrupts, only the
2404 _first_ does it */
2405 if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
2406 gen_op_set_inhibit_irq();
2c0262af
FB
2407 s->tf = 0;
2408 }
2409 if (s->is_jmp) {
2410 gen_op_jmp_im(s->pc - s->cs_base);
2411 gen_eob(s);
2412 }
2413 break;
2414 case 0x1a1: /* pop fs */
2415 case 0x1a9: /* pop gs */
2416 gen_pop_T0(s);
2417 gen_movl_seg_T0(s, (b >> 3) & 7, pc_start - s->cs_base);
2418 gen_pop_update(s);
2419 if (s->is_jmp) {
2420 gen_op_jmp_im(s->pc - s->cs_base);
2421 gen_eob(s);
2422 }
2423 break;
2424
2425 /**************************/
2426 /* mov */
2427 case 0x88:
2428 case 0x89: /* mov Gv, Ev */
2429 if ((b & 1) == 0)
2430 ot = OT_BYTE;
2431 else
2432 ot = dflag ? OT_LONG : OT_WORD;
61382a50 2433 modrm = ldub_code(s->pc++);
2c0262af
FB
2434 reg = (modrm >> 3) & 7;
2435
2436 /* generate a generic store */
2437 gen_ldst_modrm(s, modrm, ot, OR_EAX + reg, 1);
2438 break;
2439 case 0xc6:
2440 case 0xc7: /* mov Ev, Iv */
2441 if ((b & 1) == 0)
2442 ot = OT_BYTE;
2443 else
2444 ot = dflag ? OT_LONG : OT_WORD;
61382a50 2445 modrm = ldub_code(s->pc++);
2c0262af
FB
2446 mod = (modrm >> 6) & 3;
2447 if (mod != 3)
2448 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2449 val = insn_get(s, ot);
2450 gen_op_movl_T0_im(val);
2451 if (mod != 3)
2452 gen_op_st_T0_A0[ot + s->mem_index]();
2453 else
2454 gen_op_mov_reg_T0[ot][modrm & 7]();
2455 break;
2456 case 0x8a:
2457 case 0x8b: /* mov Ev, Gv */
2458 if ((b & 1) == 0)
2459 ot = OT_BYTE;
2460 else
2461 ot = dflag ? OT_LONG : OT_WORD;
61382a50 2462 modrm = ldub_code(s->pc++);
2c0262af
FB
2463 reg = (modrm >> 3) & 7;
2464
2465 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
2466 gen_op_mov_reg_T0[ot][reg]();
2467 break;
2468 case 0x8e: /* mov seg, Gv */
61382a50 2469 modrm = ldub_code(s->pc++);
2c0262af
FB
2470 reg = (modrm >> 3) & 7;
2471 if (reg >= 6 || reg == R_CS)
2472 goto illegal_op;
2473 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
2474 gen_movl_seg_T0(s, reg, pc_start - s->cs_base);
2475 if (reg == R_SS) {
2476 /* if reg == SS, inhibit interrupts/trace */
a2cc3b24
FB
2477 /* If several instructions disable interrupts, only the
2478 _first_ does it */
2479 if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
2480 gen_op_set_inhibit_irq();
2c0262af
FB
2481 s->tf = 0;
2482 }
2483 if (s->is_jmp) {
2484 gen_op_jmp_im(s->pc - s->cs_base);
2485 gen_eob(s);
2486 }
2487 break;
2488 case 0x8c: /* mov Gv, seg */
61382a50 2489 modrm = ldub_code(s->pc++);
2c0262af
FB
2490 reg = (modrm >> 3) & 7;
2491 mod = (modrm >> 6) & 3;
2492 if (reg >= 6)
2493 goto illegal_op;
2494 gen_op_movl_T0_seg(reg);
2495 ot = OT_WORD;
2496 if (mod == 3 && dflag)
2497 ot = OT_LONG;
2498 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
2499 break;
2500
2501 case 0x1b6: /* movzbS Gv, Eb */
2502 case 0x1b7: /* movzwS Gv, Eb */
2503 case 0x1be: /* movsbS Gv, Eb */
2504 case 0x1bf: /* movswS Gv, Eb */
2505 {
2506 int d_ot;
2507 /* d_ot is the size of destination */
2508 d_ot = dflag + OT_WORD;
2509 /* ot is the size of source */
2510 ot = (b & 1) + OT_BYTE;
61382a50 2511 modrm = ldub_code(s->pc++);
2c0262af
FB
2512 reg = ((modrm >> 3) & 7) + OR_EAX;
2513 mod = (modrm >> 6) & 3;
2514 rm = modrm & 7;
2515
2516 if (mod == 3) {
2517 gen_op_mov_TN_reg[ot][0][rm]();
2518 switch(ot | (b & 8)) {
2519 case OT_BYTE:
2520 gen_op_movzbl_T0_T0();
2521 break;
2522 case OT_BYTE | 8:
2523 gen_op_movsbl_T0_T0();
2524 break;
2525 case OT_WORD:
2526 gen_op_movzwl_T0_T0();
2527 break;
2528 default:
2529 case OT_WORD | 8:
2530 gen_op_movswl_T0_T0();
2531 break;
2532 }
2533 gen_op_mov_reg_T0[d_ot][reg]();
2534 } else {
2535 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2536 if (b & 8) {
2537 gen_op_lds_T0_A0[ot + s->mem_index]();
2538 } else {
2539 gen_op_ldu_T0_A0[ot + s->mem_index]();
2540 }
2541 gen_op_mov_reg_T0[d_ot][reg]();
2542 }
2543 }
2544 break;
2545
2546 case 0x8d: /* lea */
2547 ot = dflag ? OT_LONG : OT_WORD;
61382a50 2548 modrm = ldub_code(s->pc++);
2c0262af
FB
2549 reg = (modrm >> 3) & 7;
2550 /* we must ensure that no segment is added */
2551 s->override = -1;
2552 val = s->addseg;
2553 s->addseg = 0;
2554 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2555 s->addseg = val;
2556 gen_op_mov_reg_A0[ot - OT_WORD][reg]();
2557 break;
2558
2559 case 0xa0: /* mov EAX, Ov */
2560 case 0xa1:
2561 case 0xa2: /* mov Ov, EAX */
2562 case 0xa3:
2563 if ((b & 1) == 0)
2564 ot = OT_BYTE;
2565 else
2566 ot = dflag ? OT_LONG : OT_WORD;
2567 if (s->aflag)
2568 offset_addr = insn_get(s, OT_LONG);
2569 else
2570 offset_addr = insn_get(s, OT_WORD);
2571 gen_op_movl_A0_im(offset_addr);
2572 /* handle override */
2573 {
2574 int override, must_add_seg;
2575 must_add_seg = s->addseg;
2576 if (s->override >= 0) {
2577 override = s->override;
2578 must_add_seg = 1;
2579 } else {
2580 override = R_DS;
2581 }
2582 if (must_add_seg) {
2583 gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base));
2584 }
2585 }
2586 if ((b & 2) == 0) {
2587 gen_op_ld_T0_A0[ot + s->mem_index]();
2588 gen_op_mov_reg_T0[ot][R_EAX]();
2589 } else {
2590 gen_op_mov_TN_reg[ot][0][R_EAX]();
2591 gen_op_st_T0_A0[ot + s->mem_index]();
2592 }
2593 break;
2594 case 0xd7: /* xlat */
2595 gen_op_movl_A0_reg[R_EBX]();
2596 gen_op_addl_A0_AL();
2597 if (s->aflag == 0)
2598 gen_op_andl_A0_ffff();
2599 /* handle override */
2600 {
2601 int override, must_add_seg;
2602 must_add_seg = s->addseg;
2603 override = R_DS;
2604 if (s->override >= 0) {
2605 override = s->override;
2606 must_add_seg = 1;
2607 } else {
2608 override = R_DS;
2609 }
2610 if (must_add_seg) {
2611 gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base));
2612 }
2613 }
2614 gen_op_ldu_T0_A0[OT_BYTE + s->mem_index]();
2615 gen_op_mov_reg_T0[OT_BYTE][R_EAX]();
2616 break;
2617 case 0xb0 ... 0xb7: /* mov R, Ib */
2618 val = insn_get(s, OT_BYTE);
2619 gen_op_movl_T0_im(val);
2620 gen_op_mov_reg_T0[OT_BYTE][b & 7]();
2621 break;
2622 case 0xb8 ... 0xbf: /* mov R, Iv */
2623 ot = dflag ? OT_LONG : OT_WORD;
2624 val = insn_get(s, ot);
2625 reg = OR_EAX + (b & 7);
2626 gen_op_movl_T0_im(val);
2627 gen_op_mov_reg_T0[ot][reg]();
2628 break;
2629
2630 case 0x91 ... 0x97: /* xchg R, EAX */
2631 ot = dflag ? OT_LONG : OT_WORD;
2632 reg = b & 7;
2633 rm = R_EAX;
2634 goto do_xchg_reg;
2635 case 0x86:
2636 case 0x87: /* xchg Ev, Gv */
2637 if ((b & 1) == 0)
2638 ot = OT_BYTE;
2639 else
2640 ot = dflag ? OT_LONG : OT_WORD;
61382a50 2641 modrm = ldub_code(s->pc++);
2c0262af
FB
2642 reg = (modrm >> 3) & 7;
2643 mod = (modrm >> 6) & 3;
2644 if (mod == 3) {
2645 rm = modrm & 7;
2646 do_xchg_reg:
2647 gen_op_mov_TN_reg[ot][0][reg]();
2648 gen_op_mov_TN_reg[ot][1][rm]();
2649 gen_op_mov_reg_T0[ot][rm]();
2650 gen_op_mov_reg_T1[ot][reg]();
2651 } else {
2652 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2653 gen_op_mov_TN_reg[ot][0][reg]();
2654 /* for xchg, lock is implicit */
2655 if (!(prefixes & PREFIX_LOCK))
2656 gen_op_lock();
2657 gen_op_ld_T1_A0[ot + s->mem_index]();
2658 gen_op_st_T0_A0[ot + s->mem_index]();
2659 if (!(prefixes & PREFIX_LOCK))
2660 gen_op_unlock();
2661 gen_op_mov_reg_T1[ot][reg]();
2662 }
2663 break;
2664 case 0xc4: /* les Gv */
2665 op = R_ES;
2666 goto do_lxx;
2667 case 0xc5: /* lds Gv */
2668 op = R_DS;
2669 goto do_lxx;
2670 case 0x1b2: /* lss Gv */
2671 op = R_SS;
2672 goto do_lxx;
2673 case 0x1b4: /* lfs Gv */
2674 op = R_FS;
2675 goto do_lxx;
2676 case 0x1b5: /* lgs Gv */
2677 op = R_GS;
2678 do_lxx:
2679 ot = dflag ? OT_LONG : OT_WORD;
61382a50 2680 modrm = ldub_code(s->pc++);
2c0262af
FB
2681 reg = (modrm >> 3) & 7;
2682 mod = (modrm >> 6) & 3;
2683 if (mod == 3)
2684 goto illegal_op;
2685 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2686 gen_op_ld_T1_A0[ot + s->mem_index]();
2687 gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
2688 /* load the segment first to handle exceptions properly */
61382a50 2689 gen_op_ldu_T0_A0[OT_WORD + s->mem_index]();
2c0262af
FB
2690 gen_movl_seg_T0(s, op, pc_start - s->cs_base);
2691 /* then put the data */
2692 gen_op_mov_reg_T1[ot][reg]();
2693 if (s->is_jmp) {
2694 gen_op_jmp_im(s->pc - s->cs_base);
2695 gen_eob(s);
2696 }
2697 break;
2698
2699 /************************/
2700 /* shifts */
2701 case 0xc0:
2702 case 0xc1:
2703 /* shift Ev,Ib */
2704 shift = 2;
2705 grp2:
2706 {
2707 if ((b & 1) == 0)
2708 ot = OT_BYTE;
2709 else
2710 ot = dflag ? OT_LONG : OT_WORD;
2711
61382a50 2712 modrm = ldub_code(s->pc++);
2c0262af
FB
2713 mod = (modrm >> 6) & 3;
2714 rm = modrm & 7;
2715 op = (modrm >> 3) & 7;
2716
2717 if (mod != 3) {
2718 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2719 opreg = OR_TMP0;
2720 } else {
2721 opreg = rm + OR_EAX;
2722 }
2723
2724 /* simpler op */
2725 if (shift == 0) {
2726 gen_shift(s, op, ot, opreg, OR_ECX);
2727 } else {
2728 if (shift == 2) {
61382a50 2729 shift = ldub_code(s->pc++);
2c0262af
FB
2730 }
2731 gen_shifti(s, op, ot, opreg, shift);
2732 }
2733 }
2734 break;
2735 case 0xd0:
2736 case 0xd1:
2737 /* shift Ev,1 */
2738 shift = 1;
2739 goto grp2;
2740 case 0xd2:
2741 case 0xd3:
2742 /* shift Ev,cl */
2743 shift = 0;
2744 goto grp2;
2745
2746 case 0x1a4: /* shld imm */
2747 op = 0;
2748 shift = 1;
2749 goto do_shiftd;
2750 case 0x1a5: /* shld cl */
2751 op = 0;
2752 shift = 0;
2753 goto do_shiftd;
2754 case 0x1ac: /* shrd imm */
2755 op = 1;
2756 shift = 1;
2757 goto do_shiftd;
2758 case 0x1ad: /* shrd cl */
2759 op = 1;
2760 shift = 0;
2761 do_shiftd:
2762 ot = dflag ? OT_LONG : OT_WORD;
61382a50 2763 modrm = ldub_code(s->pc++);
2c0262af
FB
2764 mod = (modrm >> 6) & 3;
2765 rm = modrm & 7;
2766 reg = (modrm >> 3) & 7;
2767
2768 if (mod != 3) {
2769 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2770 gen_op_ld_T0_A0[ot + s->mem_index]();
2771 } else {
2772 gen_op_mov_TN_reg[ot][0][rm]();
2773 }
2774 gen_op_mov_TN_reg[ot][1][reg]();
2775
2776 if (shift) {
61382a50 2777 val = ldub_code(s->pc++);
2c0262af
FB
2778 val &= 0x1f;
2779 if (val) {
2780 if (mod == 3)
4f31916f 2781 gen_op_shiftd_T0_T1_im_cc[ot][op](val);
2c0262af 2782 else
4f31916f 2783 gen_op_shiftd_mem_T0_T1_im_cc[ot + s->mem_index][op](val);
2c0262af
FB
2784 if (op == 0 && ot != OT_WORD)
2785 s->cc_op = CC_OP_SHLB + ot;
2786 else
2787 s->cc_op = CC_OP_SARB + ot;
2788 }
2789 } else {
2790 if (s->cc_op != CC_OP_DYNAMIC)
2791 gen_op_set_cc_op(s->cc_op);
2792 if (mod == 3)
4f31916f 2793 gen_op_shiftd_T0_T1_ECX_cc[ot][op]();
2c0262af 2794 else
4f31916f 2795 gen_op_shiftd_mem_T0_T1_ECX_cc[ot + s->mem_index][op]();
2c0262af
FB
2796 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2797 }
2798 if (mod == 3) {
2799 gen_op_mov_reg_T0[ot][rm]();
2800 }
2801 break;
2802
2803 /************************/
2804 /* floats */
2805 case 0xd8 ... 0xdf:
61382a50 2806 modrm = ldub_code(s->pc++);
2c0262af
FB
2807 mod = (modrm >> 6) & 3;
2808 rm = modrm & 7;
2809 op = ((b & 7) << 3) | ((modrm >> 3) & 7);
2810
2811 if (mod != 3) {
2812 /* memory op */
2813 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2814 switch(op) {
2815 case 0x00 ... 0x07: /* fxxxs */
2816 case 0x10 ... 0x17: /* fixxxl */
2817 case 0x20 ... 0x27: /* fxxxl */
2818 case 0x30 ... 0x37: /* fixxx */
2819 {
2820 int op1;
2821 op1 = op & 7;
2822
2823 switch(op >> 4) {
2824 case 0:
2825 gen_op_flds_FT0_A0();
2826 break;
2827 case 1:
2828 gen_op_fildl_FT0_A0();
2829 break;
2830 case 2:
2831 gen_op_fldl_FT0_A0();
2832 break;
2833 case 3:
2834 default:
2835 gen_op_fild_FT0_A0();
2836 break;
2837 }
2838
2839 gen_op_fp_arith_ST0_FT0[op1]();
2840 if (op1 == 3) {
2841 /* fcomp needs pop */
2842 gen_op_fpop();
2843 }
2844 }
2845 break;
2846 case 0x08: /* flds */
2847 case 0x0a: /* fsts */
2848 case 0x0b: /* fstps */
2849 case 0x18: /* fildl */
2850 case 0x1a: /* fistl */
2851 case 0x1b: /* fistpl */
2852 case 0x28: /* fldl */
2853 case 0x2a: /* fstl */
2854 case 0x2b: /* fstpl */
2855 case 0x38: /* filds */
2856 case 0x3a: /* fists */
2857 case 0x3b: /* fistps */
2858
2859 switch(op & 7) {
2860 case 0:
2861 switch(op >> 4) {
2862 case 0:
2863 gen_op_flds_ST0_A0();
2864 break;
2865 case 1:
2866 gen_op_fildl_ST0_A0();
2867 break;
2868 case 2:
2869 gen_op_fldl_ST0_A0();
2870 break;
2871 case 3:
2872 default:
2873 gen_op_fild_ST0_A0();
2874 break;
2875 }
2876 break;
2877 default:
2878 switch(op >> 4) {
2879 case 0:
2880 gen_op_fsts_ST0_A0();
2881 break;
2882 case 1:
2883 gen_op_fistl_ST0_A0();
2884 break;
2885 case 2:
2886 gen_op_fstl_ST0_A0();
2887 break;
2888 case 3:
2889 default:
2890 gen_op_fist_ST0_A0();
2891 break;
2892 }
2893 if ((op & 7) == 3)
2894 gen_op_fpop();
2895 break;
2896 }
2897 break;
2898 case 0x0c: /* fldenv mem */
2899 gen_op_fldenv_A0(s->dflag);
2900 break;
2901 case 0x0d: /* fldcw mem */
2902 gen_op_fldcw_A0();
2903 break;
2904 case 0x0e: /* fnstenv mem */
2905 gen_op_fnstenv_A0(s->dflag);
2906 break;
2907 case 0x0f: /* fnstcw mem */
2908 gen_op_fnstcw_A0();
2909 break;
2910 case 0x1d: /* fldt mem */
2911 gen_op_fldt_ST0_A0();
2912 break;
2913 case 0x1f: /* fstpt mem */
2914 gen_op_fstt_ST0_A0();
2915 gen_op_fpop();
2916 break;
2917 case 0x2c: /* frstor mem */
2918 gen_op_frstor_A0(s->dflag);
2919 break;
2920 case 0x2e: /* fnsave mem */
2921 gen_op_fnsave_A0(s->dflag);
2922 break;
2923 case 0x2f: /* fnstsw mem */
2924 gen_op_fnstsw_A0();
2925 break;
2926 case 0x3c: /* fbld */
2927 gen_op_fbld_ST0_A0();
2928 break;
2929 case 0x3e: /* fbstp */
2930 gen_op_fbst_ST0_A0();
2931 gen_op_fpop();
2932 break;
2933 case 0x3d: /* fildll */
2934 gen_op_fildll_ST0_A0();
2935 break;
2936 case 0x3f: /* fistpll */
2937 gen_op_fistll_ST0_A0();
2938 gen_op_fpop();
2939 break;
2940 default:
2941 goto illegal_op;
2942 }
2943 } else {
2944 /* register float ops */
2945 opreg = rm;
2946
2947 switch(op) {
2948 case 0x08: /* fld sti */
2949 gen_op_fpush();
2950 gen_op_fmov_ST0_STN((opreg + 1) & 7);
2951 break;
2952 case 0x09: /* fxchg sti */
2953 gen_op_fxchg_ST0_STN(opreg);
2954 break;
2955 case 0x0a: /* grp d9/2 */
2956 switch(rm) {
2957 case 0: /* fnop */
2958 break;
2959 default:
2960 goto illegal_op;
2961 }
2962 break;
2963 case 0x0c: /* grp d9/4 */
2964 switch(rm) {
2965 case 0: /* fchs */
2966 gen_op_fchs_ST0();
2967 break;
2968 case 1: /* fabs */
2969 gen_op_fabs_ST0();
2970 break;
2971 case 4: /* ftst */
2972 gen_op_fldz_FT0();
2973 gen_op_fcom_ST0_FT0();
2974 break;
2975 case 5: /* fxam */
2976 gen_op_fxam_ST0();
2977 break;
2978 default:
2979 goto illegal_op;
2980 }
2981 break;
2982 case 0x0d: /* grp d9/5 */
2983 {
2984 switch(rm) {
2985 case 0:
2986 gen_op_fpush();
2987 gen_op_fld1_ST0();
2988 break;
2989 case 1:
2990 gen_op_fpush();
2991 gen_op_fldl2t_ST0();
2992 break;
2993 case 2:
2994 gen_op_fpush();
2995 gen_op_fldl2e_ST0();
2996 break;
2997 case 3:
2998 gen_op_fpush();
2999 gen_op_fldpi_ST0();
3000 break;
3001 case 4:
3002 gen_op_fpush();
3003 gen_op_fldlg2_ST0();
3004 break;
3005 case 5:
3006 gen_op_fpush();
3007 gen_op_fldln2_ST0();
3008 break;
3009 case 6:
3010 gen_op_fpush();
3011 gen_op_fldz_ST0();
3012 break;
3013 default:
3014 goto illegal_op;
3015 }
3016 }
3017 break;
3018 case 0x0e: /* grp d9/6 */
3019 switch(rm) {
3020 case 0: /* f2xm1 */
3021 gen_op_f2xm1();
3022 break;
3023 case 1: /* fyl2x */
3024 gen_op_fyl2x();
3025 break;
3026 case 2: /* fptan */
3027 gen_op_fptan();
3028 break;
3029 case 3: /* fpatan */
3030 gen_op_fpatan();
3031 break;
3032 case 4: /* fxtract */
3033 gen_op_fxtract();
3034 break;
3035 case 5: /* fprem1 */
3036 gen_op_fprem1();
3037 break;
3038 case 6: /* fdecstp */
3039 gen_op_fdecstp();
3040 break;
3041 default:
3042 case 7: /* fincstp */
3043 gen_op_fincstp();
3044 break;
3045 }
3046 break;
3047 case 0x0f: /* grp d9/7 */
3048 switch(rm) {
3049 case 0: /* fprem */
3050 gen_op_fprem();
3051 break;
3052 case 1: /* fyl2xp1 */
3053 gen_op_fyl2xp1();
3054 break;
3055 case 2: /* fsqrt */
3056 gen_op_fsqrt();
3057 break;
3058 case 3: /* fsincos */
3059 gen_op_fsincos();
3060 break;
3061 case 5: /* fscale */
3062 gen_op_fscale();
3063 break;
3064 case 4: /* frndint */
3065 gen_op_frndint();
3066 break;
3067 case 6: /* fsin */
3068 gen_op_fsin();
3069 break;
3070 default:
3071 case 7: /* fcos */
3072 gen_op_fcos();
3073 break;
3074 }
3075 break;
3076 case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
3077 case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
3078 case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
3079 {
3080 int op1;
3081
3082 op1 = op & 7;
3083 if (op >= 0x20) {
3084 gen_op_fp_arith_STN_ST0[op1](opreg);
3085 if (op >= 0x30)
3086 gen_op_fpop();
3087 } else {
3088 gen_op_fmov_FT0_STN(opreg);
3089 gen_op_fp_arith_ST0_FT0[op1]();
3090 }
3091 }
3092 break;
3093 case 0x02: /* fcom */
3094 gen_op_fmov_FT0_STN(opreg);
3095 gen_op_fcom_ST0_FT0();
3096 break;
3097 case 0x03: /* fcomp */
3098 gen_op_fmov_FT0_STN(opreg);
3099 gen_op_fcom_ST0_FT0();
3100 gen_op_fpop();
3101 break;
3102 case 0x15: /* da/5 */
3103 switch(rm) {
3104 case 1: /* fucompp */
3105 gen_op_fmov_FT0_STN(1);
3106 gen_op_fucom_ST0_FT0();
3107 gen_op_fpop();
3108 gen_op_fpop();
3109 break;
3110 default:
3111 goto illegal_op;
3112 }
3113 break;
3114 case 0x1c:
3115 switch(rm) {
3116 case 0: /* feni (287 only, just do nop here) */
3117 break;
3118 case 1: /* fdisi (287 only, just do nop here) */
3119 break;
3120 case 2: /* fclex */
3121 gen_op_fclex();
3122 break;
3123 case 3: /* fninit */
3124 gen_op_fninit();
3125 break;
3126 case 4: /* fsetpm (287 only, just do nop here) */
3127 break;
3128 default:
3129 goto illegal_op;
3130 }
3131 break;
3132 case 0x1d: /* fucomi */
3133 if (s->cc_op != CC_OP_DYNAMIC)
3134 gen_op_set_cc_op(s->cc_op);
3135 gen_op_fmov_FT0_STN(opreg);
3136 gen_op_fucomi_ST0_FT0();
3137 s->cc_op = CC_OP_EFLAGS;
3138 break;
3139 case 0x1e: /* fcomi */
3140 if (s->cc_op != CC_OP_DYNAMIC)
3141 gen_op_set_cc_op(s->cc_op);
3142 gen_op_fmov_FT0_STN(opreg);
3143 gen_op_fcomi_ST0_FT0();
3144 s->cc_op = CC_OP_EFLAGS;
3145 break;
3146 case 0x2a: /* fst sti */
3147 gen_op_fmov_STN_ST0(opreg);
3148 break;
3149 case 0x2b: /* fstp sti */
3150 gen_op_fmov_STN_ST0(opreg);
3151 gen_op_fpop();
3152 break;
3153 case 0x2c: /* fucom st(i) */
3154 gen_op_fmov_FT0_STN(opreg);
3155 gen_op_fucom_ST0_FT0();
3156 break;
3157 case 0x2d: /* fucomp st(i) */
3158 gen_op_fmov_FT0_STN(opreg);
3159 gen_op_fucom_ST0_FT0();
3160 gen_op_fpop();
3161 break;
3162 case 0x33: /* de/3 */
3163 switch(rm) {
3164 case 1: /* fcompp */
3165 gen_op_fmov_FT0_STN(1);
3166 gen_op_fcom_ST0_FT0();
3167 gen_op_fpop();
3168 gen_op_fpop();
3169 break;
3170 default:
3171 goto illegal_op;
3172 }
3173 break;
3174 case 0x3c: /* df/4 */
3175 switch(rm) {
3176 case 0:
3177 gen_op_fnstsw_EAX();
3178 break;
3179 default:
3180 goto illegal_op;
3181 }
3182 break;
3183 case 0x3d: /* fucomip */
3184 if (s->cc_op != CC_OP_DYNAMIC)
3185 gen_op_set_cc_op(s->cc_op);
3186 gen_op_fmov_FT0_STN(opreg);
3187 gen_op_fucomi_ST0_FT0();
3188 gen_op_fpop();
3189 s->cc_op = CC_OP_EFLAGS;
3190 break;
3191 case 0x3e: /* fcomip */
3192 if (s->cc_op != CC_OP_DYNAMIC)
3193 gen_op_set_cc_op(s->cc_op);
3194 gen_op_fmov_FT0_STN(opreg);
3195 gen_op_fcomi_ST0_FT0();
3196 gen_op_fpop();
3197 s->cc_op = CC_OP_EFLAGS;
3198 break;
a2cc3b24
FB
3199 case 0x10 ... 0x13: /* fcmovxx */
3200 case 0x18 ... 0x1b:
3201 {
3202 int op1;
3203 const static uint8_t fcmov_cc[8] = {
3204 (JCC_B << 1),
3205 (JCC_Z << 1),
3206 (JCC_BE << 1),
3207 (JCC_P << 1),
3208 };
3209 op1 = fcmov_cc[op & 3] | ((op >> 3) & 1);
3210 gen_setcc(s, op1);
3211 gen_op_fcmov_ST0_STN_T0(opreg);
3212 }
3213 break;
2c0262af
FB
3214 default:
3215 goto illegal_op;
3216 }
3217 }
3218 break;
3219 /************************/
3220 /* string ops */
3221
3222 case 0xa4: /* movsS */
3223 case 0xa5:
3224 if ((b & 1) == 0)
3225 ot = OT_BYTE;
3226 else
3227 ot = dflag ? OT_LONG : OT_WORD;
3228
3229 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
3230 gen_repz_movs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
3231 } else {
3232 gen_movs(s, ot);
3233 }
3234 break;
3235
3236 case 0xaa: /* stosS */
3237 case 0xab:
3238 if ((b & 1) == 0)
3239 ot = OT_BYTE;
3240 else
3241 ot = dflag ? OT_LONG : OT_WORD;
3242
3243 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
3244 gen_repz_stos(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
3245 } else {
3246 gen_stos(s, ot);
3247 }
3248 break;
3249 case 0xac: /* lodsS */
3250 case 0xad:
3251 if ((b & 1) == 0)
3252 ot = OT_BYTE;
3253 else
3254 ot = dflag ? OT_LONG : OT_WORD;
3255 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
3256 gen_repz_lods(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
3257 } else {
3258 gen_lods(s, ot);
3259 }
3260 break;
3261 case 0xae: /* scasS */
3262 case 0xaf:
3263 if ((b & 1) == 0)
3264 ot = OT_BYTE;
3265 else
3266 ot = dflag ? OT_LONG : OT_WORD;
3267 if (prefixes & PREFIX_REPNZ) {
3268 gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
3269 } else if (prefixes & PREFIX_REPZ) {
3270 gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
3271 } else {
3272 gen_scas(s, ot);
3273 s->cc_op = CC_OP_SUBB + ot;
3274 }
3275 break;
3276
3277 case 0xa6: /* cmpsS */
3278 case 0xa7:
3279 if ((b & 1) == 0)
3280 ot = OT_BYTE;
3281 else
3282 ot = dflag ? OT_LONG : OT_WORD;
3283 if (prefixes & PREFIX_REPNZ) {
3284 gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
3285 } else if (prefixes & PREFIX_REPZ) {
3286 gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
3287 } else {
3288 gen_cmps(s, ot);
3289 s->cc_op = CC_OP_SUBB + ot;
3290 }
3291 break;
3292 case 0x6c: /* insS */
3293 case 0x6d:
f115e911
FB
3294 if ((b & 1) == 0)
3295 ot = OT_BYTE;
3296 else
3297 ot = dflag ? OT_LONG : OT_WORD;
3298 gen_check_io(s, ot, 1, pc_start - s->cs_base);
3299 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
3300 gen_repz_ins(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
2c0262af 3301 } else {
f115e911 3302 gen_ins(s, ot);
2c0262af
FB
3303 }
3304 break;
3305 case 0x6e: /* outsS */
3306 case 0x6f:
f115e911
FB
3307 if ((b & 1) == 0)
3308 ot = OT_BYTE;
3309 else
3310 ot = dflag ? OT_LONG : OT_WORD;
3311 gen_check_io(s, ot, 1, pc_start - s->cs_base);
3312 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
3313 gen_repz_outs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
2c0262af 3314 } else {
f115e911 3315 gen_outs(s, ot);
2c0262af
FB
3316 }
3317 break;
3318
3319 /************************/
3320 /* port I/O */
3321 case 0xe4:
3322 case 0xe5:
f115e911
FB
3323 if ((b & 1) == 0)
3324 ot = OT_BYTE;
3325 else
3326 ot = dflag ? OT_LONG : OT_WORD;
3327 val = ldub_code(s->pc++);
3328 gen_op_movl_T0_im(val);
3329 gen_check_io(s, ot, 0, pc_start - s->cs_base);
3330 gen_op_in[ot]();
3331 gen_op_mov_reg_T1[ot][R_EAX]();
2c0262af
FB
3332 break;
3333 case 0xe6:
3334 case 0xe7:
f115e911
FB
3335 if ((b & 1) == 0)
3336 ot = OT_BYTE;
3337 else
3338 ot = dflag ? OT_LONG : OT_WORD;
3339 val = ldub_code(s->pc++);
3340 gen_op_movl_T0_im(val);
3341 gen_check_io(s, ot, 0, pc_start - s->cs_base);
3342 gen_op_mov_TN_reg[ot][1][R_EAX]();
3343 gen_op_out[ot]();
2c0262af
FB
3344 break;
3345 case 0xec:
3346 case 0xed:
f115e911
FB
3347 if ((b & 1) == 0)
3348 ot = OT_BYTE;
3349 else
3350 ot = dflag ? OT_LONG : OT_WORD;
3351 gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
4f31916f 3352 gen_op_andl_T0_ffff();
f115e911
FB
3353 gen_check_io(s, ot, 0, pc_start - s->cs_base);
3354 gen_op_in[ot]();
3355 gen_op_mov_reg_T1[ot][R_EAX]();
2c0262af
FB
3356 break;
3357 case 0xee:
3358 case 0xef:
f115e911
FB
3359 if ((b & 1) == 0)
3360 ot = OT_BYTE;
3361 else
3362 ot = dflag ? OT_LONG : OT_WORD;
3363 gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
4f31916f 3364 gen_op_andl_T0_ffff();
f115e911
FB
3365 gen_check_io(s, ot, 0, pc_start - s->cs_base);
3366 gen_op_mov_TN_reg[ot][1][R_EAX]();
3367 gen_op_out[ot]();
2c0262af
FB
3368 break;
3369
3370 /************************/
3371 /* control */
3372 case 0xc2: /* ret im */
61382a50 3373 val = ldsw_code(s->pc);
2c0262af
FB
3374 s->pc += 2;
3375 gen_pop_T0(s);
3376 gen_stack_update(s, val + (2 << s->dflag));
3377 if (s->dflag == 0)
3378 gen_op_andl_T0_ffff();
3379 gen_op_jmp_T0();
3380 gen_eob(s);
3381 break;
3382 case 0xc3: /* ret */
3383 gen_pop_T0(s);
3384 gen_pop_update(s);
3385 if (s->dflag == 0)
3386 gen_op_andl_T0_ffff();
3387 gen_op_jmp_T0();
3388 gen_eob(s);
3389 break;
3390 case 0xca: /* lret im */
61382a50 3391 val = ldsw_code(s->pc);
2c0262af
FB
3392 s->pc += 2;
3393 do_lret:
3394 if (s->pe && !s->vm86) {
3395 if (s->cc_op != CC_OP_DYNAMIC)
3396 gen_op_set_cc_op(s->cc_op);
3397 gen_op_jmp_im(pc_start - s->cs_base);
3398 gen_op_lret_protected(s->dflag, val);
3399 } else {
3400 gen_stack_A0(s);
3401 /* pop offset */
3402 gen_op_ld_T0_A0[1 + s->dflag + s->mem_index]();
3403 if (s->dflag == 0)
3404 gen_op_andl_T0_ffff();
3405 /* NOTE: keeping EIP updated is not a problem in case of
3406 exception */
3407 gen_op_jmp_T0();
3408 /* pop selector */
3409 gen_op_addl_A0_im(2 << s->dflag);
3410 gen_op_ld_T0_A0[1 + s->dflag + s->mem_index]();
3411 gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[R_CS]));
3412 /* add stack offset */
3413 gen_stack_update(s, val + (4 << s->dflag));
3414 }
3415 gen_eob(s);
3416 break;
3417 case 0xcb: /* lret */
3418 val = 0;
3419 goto do_lret;
3420 case 0xcf: /* iret */
3421 if (!s->pe) {
3422 /* real mode */
3423 gen_op_iret_real(s->dflag);
3424 s->cc_op = CC_OP_EFLAGS;
f115e911
FB
3425 } else if (s->vm86) {
3426 if (s->iopl != 3) {
3427 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3428 } else {
3429 gen_op_iret_real(s->dflag);
3430 s->cc_op = CC_OP_EFLAGS;
3431 }
2c0262af
FB
3432 } else {
3433 if (s->cc_op != CC_OP_DYNAMIC)
3434 gen_op_set_cc_op(s->cc_op);
3435 gen_op_jmp_im(pc_start - s->cs_base);
3436 gen_op_iret_protected(s->dflag);
3437 s->cc_op = CC_OP_EFLAGS;
3438 }
3439 gen_eob(s);
3440 break;
3441 case 0xe8: /* call im */
3442 {
3443 unsigned int next_eip;
3444 ot = dflag ? OT_LONG : OT_WORD;
3445 val = insn_get(s, ot);
3446 next_eip = s->pc - s->cs_base;
3447 val += next_eip;
3448 if (s->dflag == 0)
3449 val &= 0xffff;
3450 gen_op_movl_T0_im(next_eip);
3451 gen_push_T0(s);
3452 gen_jmp(s, val);
3453 }
3454 break;
3455 case 0x9a: /* lcall im */
3456 {
3457 unsigned int selector, offset;
3458
3459 ot = dflag ? OT_LONG : OT_WORD;
3460 offset = insn_get(s, ot);
3461 selector = insn_get(s, OT_WORD);
3462
3463 gen_op_movl_T0_im(selector);
3464 gen_op_movl_T1_im(offset);
3465 }
3466 goto do_lcall;
3467 case 0xe9: /* jmp */
3468 ot = dflag ? OT_LONG : OT_WORD;
3469 val = insn_get(s, ot);
3470 val += s->pc - s->cs_base;
3471 if (s->dflag == 0)
3472 val = val & 0xffff;
3473 gen_jmp(s, val);
3474 break;
3475 case 0xea: /* ljmp im */
3476 {
3477 unsigned int selector, offset;
3478
3479 ot = dflag ? OT_LONG : OT_WORD;
3480 offset = insn_get(s, ot);
3481 selector = insn_get(s, OT_WORD);
3482
3483 gen_op_movl_T0_im(selector);
3484 gen_op_movl_T1_im(offset);
3485 }
3486 goto do_ljmp;
3487 case 0xeb: /* jmp Jb */
3488 val = (int8_t)insn_get(s, OT_BYTE);
3489 val += s->pc - s->cs_base;
3490 if (s->dflag == 0)
3491 val = val & 0xffff;
3492 gen_jmp(s, val);
3493 break;
3494 case 0x70 ... 0x7f: /* jcc Jb */
3495 val = (int8_t)insn_get(s, OT_BYTE);
3496 goto do_jcc;
3497 case 0x180 ... 0x18f: /* jcc Jv */
3498 if (dflag) {
3499 val = insn_get(s, OT_LONG);
3500 } else {
3501 val = (int16_t)insn_get(s, OT_WORD);
3502 }
3503 do_jcc:
3504 next_eip = s->pc - s->cs_base;
3505 val += next_eip;
3506 if (s->dflag == 0)
3507 val &= 0xffff;
3508 gen_jcc(s, b, val, next_eip);
3509 break;
3510
3511 case 0x190 ... 0x19f: /* setcc Gv */
61382a50 3512 modrm = ldub_code(s->pc++);
2c0262af
FB
3513 gen_setcc(s, b);
3514 gen_ldst_modrm(s, modrm, OT_BYTE, OR_TMP0, 1);
3515 break;
3516 case 0x140 ... 0x14f: /* cmov Gv, Ev */
3517 ot = dflag ? OT_LONG : OT_WORD;
61382a50 3518 modrm = ldub_code(s->pc++);
2c0262af
FB
3519 reg = (modrm >> 3) & 7;
3520 mod = (modrm >> 6) & 3;
3521 gen_setcc(s, b);
3522 if (mod != 3) {
3523 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3524 gen_op_ld_T1_A0[ot + s->mem_index]();
3525 } else {
3526 rm = modrm & 7;
3527 gen_op_mov_TN_reg[ot][1][rm]();
3528 }
3529 gen_op_cmov_reg_T1_T0[ot - OT_WORD][reg]();
3530 break;
3531
3532 /************************/
3533 /* flags */
3534 case 0x9c: /* pushf */
3535 if (s->vm86 && s->iopl != 3) {
3536 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3537 } else {
3538 if (s->cc_op != CC_OP_DYNAMIC)
3539 gen_op_set_cc_op(s->cc_op);
3540 gen_op_movl_T0_eflags();
3541 gen_push_T0(s);
3542 }
3543 break;
3544 case 0x9d: /* popf */
3545 if (s->vm86 && s->iopl != 3) {
3546 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3547 } else {
3548 gen_pop_T0(s);
3549 if (s->cpl == 0) {
3550 if (s->dflag) {
3551 gen_op_movl_eflags_T0_cpl0();
3552 } else {
3553 gen_op_movw_eflags_T0_cpl0();
3554 }
3555 } else {
4136f33c
FB
3556 if (s->cpl <= s->iopl) {
3557 if (s->dflag) {
3558 gen_op_movl_eflags_T0_io();
3559 } else {
3560 gen_op_movw_eflags_T0_io();
3561 }
2c0262af 3562 } else {
4136f33c
FB
3563 if (s->dflag) {
3564 gen_op_movl_eflags_T0();
3565 } else {
3566 gen_op_movw_eflags_T0();
3567 }
2c0262af
FB
3568 }
3569 }
3570 gen_pop_update(s);
3571 s->cc_op = CC_OP_EFLAGS;
3572 /* abort translation because TF flag may change */
3573 gen_op_jmp_im(s->pc - s->cs_base);
3574 gen_eob(s);
3575 }
3576 break;
3577 case 0x9e: /* sahf */
3578 gen_op_mov_TN_reg[OT_BYTE][0][R_AH]();
3579 if (s->cc_op != CC_OP_DYNAMIC)
3580 gen_op_set_cc_op(s->cc_op);
3581 gen_op_movb_eflags_T0();
3582 s->cc_op = CC_OP_EFLAGS;
3583 break;
3584 case 0x9f: /* lahf */
3585 if (s->cc_op != CC_OP_DYNAMIC)
3586 gen_op_set_cc_op(s->cc_op);
3587 gen_op_movl_T0_eflags();
3588 gen_op_mov_reg_T0[OT_BYTE][R_AH]();
3589 break;
3590 case 0xf5: /* cmc */
3591 if (s->cc_op != CC_OP_DYNAMIC)
3592 gen_op_set_cc_op(s->cc_op);
3593 gen_op_cmc();
3594 s->cc_op = CC_OP_EFLAGS;
3595 break;
3596 case 0xf8: /* clc */
3597 if (s->cc_op != CC_OP_DYNAMIC)
3598 gen_op_set_cc_op(s->cc_op);
3599 gen_op_clc();
3600 s->cc_op = CC_OP_EFLAGS;
3601 break;
3602 case 0xf9: /* stc */
3603 if (s->cc_op != CC_OP_DYNAMIC)
3604 gen_op_set_cc_op(s->cc_op);
3605 gen_op_stc();
3606 s->cc_op = CC_OP_EFLAGS;
3607 break;
3608 case 0xfc: /* cld */
3609 gen_op_cld();
3610 break;
3611 case 0xfd: /* std */
3612 gen_op_std();
3613 break;
3614
3615 /************************/
3616 /* bit operations */
3617 case 0x1ba: /* bt/bts/btr/btc Gv, im */
3618 ot = dflag ? OT_LONG : OT_WORD;
61382a50 3619 modrm = ldub_code(s->pc++);
2c0262af
FB
3620 op = (modrm >> 3) & 7;
3621 mod = (modrm >> 6) & 3;
3622 rm = modrm & 7;
3623 if (mod != 3) {
3624 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3625 gen_op_ld_T0_A0[ot + s->mem_index]();
3626 } else {
3627 gen_op_mov_TN_reg[ot][0][rm]();
3628 }
3629 /* load shift */
61382a50 3630 val = ldub_code(s->pc++);
2c0262af
FB
3631 gen_op_movl_T1_im(val);
3632 if (op < 4)
3633 goto illegal_op;
3634 op -= 4;
3635 gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
3636 s->cc_op = CC_OP_SARB + ot;
3637 if (op != 0) {
3638 if (mod != 3)
3639 gen_op_st_T0_A0[ot + s->mem_index]();
3640 else
3641 gen_op_mov_reg_T0[ot][rm]();
3642 gen_op_update_bt_cc();
3643 }
3644 break;
3645 case 0x1a3: /* bt Gv, Ev */
3646 op = 0;
3647 goto do_btx;
3648 case 0x1ab: /* bts */
3649 op = 1;
3650 goto do_btx;
3651 case 0x1b3: /* btr */
3652 op = 2;
3653 goto do_btx;
3654 case 0x1bb: /* btc */
3655 op = 3;
3656 do_btx:
3657 ot = dflag ? OT_LONG : OT_WORD;
61382a50 3658 modrm = ldub_code(s->pc++);
2c0262af
FB
3659 reg = (modrm >> 3) & 7;
3660 mod = (modrm >> 6) & 3;
3661 rm = modrm & 7;
3662 gen_op_mov_TN_reg[OT_LONG][1][reg]();
3663 if (mod != 3) {
3664 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3665 /* specific case: we need to add a displacement */
3666 if (ot == OT_WORD)
3667 gen_op_add_bitw_A0_T1();
3668 else
3669 gen_op_add_bitl_A0_T1();
3670 gen_op_ld_T0_A0[ot + s->mem_index]();
3671 } else {
3672 gen_op_mov_TN_reg[ot][0][rm]();
3673 }
3674 gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
3675 s->cc_op = CC_OP_SARB + ot;
3676 if (op != 0) {
3677 if (mod != 3)
3678 gen_op_st_T0_A0[ot + s->mem_index]();
3679 else
3680 gen_op_mov_reg_T0[ot][rm]();
3681 gen_op_update_bt_cc();
3682 }
3683 break;
3684 case 0x1bc: /* bsf */
3685 case 0x1bd: /* bsr */
3686 ot = dflag ? OT_LONG : OT_WORD;
61382a50 3687 modrm = ldub_code(s->pc++);
2c0262af
FB
3688 reg = (modrm >> 3) & 7;
3689 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
3690 gen_op_bsx_T0_cc[ot - OT_WORD][b & 1]();
3691 /* NOTE: we always write back the result. Intel doc says it is
3692 undefined if T0 == 0 */
3693 gen_op_mov_reg_T0[ot][reg]();
3694 s->cc_op = CC_OP_LOGICB + ot;
3695 break;
3696 /************************/
3697 /* bcd */
3698 case 0x27: /* daa */
3699 if (s->cc_op != CC_OP_DYNAMIC)
3700 gen_op_set_cc_op(s->cc_op);
3701 gen_op_daa();
3702 s->cc_op = CC_OP_EFLAGS;
3703 break;
3704 case 0x2f: /* das */
3705 if (s->cc_op != CC_OP_DYNAMIC)
3706 gen_op_set_cc_op(s->cc_op);
3707 gen_op_das();
3708 s->cc_op = CC_OP_EFLAGS;
3709 break;
3710 case 0x37: /* aaa */
3711 if (s->cc_op != CC_OP_DYNAMIC)
3712 gen_op_set_cc_op(s->cc_op);
3713 gen_op_aaa();
3714 s->cc_op = CC_OP_EFLAGS;
3715 break;
3716 case 0x3f: /* aas */
3717 if (s->cc_op != CC_OP_DYNAMIC)
3718 gen_op_set_cc_op(s->cc_op);
3719 gen_op_aas();
3720 s->cc_op = CC_OP_EFLAGS;
3721 break;
3722 case 0xd4: /* aam */
61382a50 3723 val = ldub_code(s->pc++);
2c0262af
FB
3724 gen_op_aam(val);
3725 s->cc_op = CC_OP_LOGICB;
3726 break;
3727 case 0xd5: /* aad */
61382a50 3728 val = ldub_code(s->pc++);
2c0262af
FB
3729 gen_op_aad(val);
3730 s->cc_op = CC_OP_LOGICB;
3731 break;
3732 /************************/
3733 /* misc */
3734 case 0x90: /* nop */
3735 break;
3736 case 0x9b: /* fwait */
3737 break;
3738 case 0xcc: /* int3 */
3739 gen_interrupt(s, EXCP03_INT3, pc_start - s->cs_base, s->pc - s->cs_base);
3740 break;
3741 case 0xcd: /* int N */
61382a50 3742 val = ldub_code(s->pc++);
f115e911 3743 if (s->vm86 && s->iopl != 3) {
2c0262af 3744 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
f115e911
FB
3745 } else {
3746 gen_interrupt(s, val, pc_start - s->cs_base, s->pc - s->cs_base);
3747 }
2c0262af
FB
3748 break;
3749 case 0xce: /* into */
3750 if (s->cc_op != CC_OP_DYNAMIC)
3751 gen_op_set_cc_op(s->cc_op);
3752 gen_op_into(s->pc - s->cs_base);
3753 break;
3754 case 0xf1: /* icebp (undocumented, exits to external debugger) */
3755 gen_debug(s, pc_start - s->cs_base);
3756 break;
3757 case 0xfa: /* cli */
3758 if (!s->vm86) {
3759 if (s->cpl <= s->iopl) {
3760 gen_op_cli();
3761 } else {
3762 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3763 }
3764 } else {
3765 if (s->iopl == 3) {
3766 gen_op_cli();
3767 } else {
3768 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3769 }
3770 }
3771 break;
3772 case 0xfb: /* sti */
3773 if (!s->vm86) {
3774 if (s->cpl <= s->iopl) {
3775 gen_sti:
3776 gen_op_sti();
3777 /* interruptions are enabled only the first insn after sti */
a2cc3b24
FB
3778 /* If several instructions disable interrupts, only the
3779 _first_ does it */
3780 if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
3781 gen_op_set_inhibit_irq();
2c0262af
FB
3782 /* give a chance to handle pending irqs */
3783 gen_op_jmp_im(s->pc - s->cs_base);
3784 gen_eob(s);
3785 } else {
3786 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3787 }
3788 } else {
3789 if (s->iopl == 3) {
3790 goto gen_sti;
3791 } else {
3792 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3793 }
3794 }
3795 break;
3796 case 0x62: /* bound */
3797 ot = dflag ? OT_LONG : OT_WORD;
61382a50 3798 modrm = ldub_code(s->pc++);
2c0262af
FB
3799 reg = (modrm >> 3) & 7;
3800 mod = (modrm >> 6) & 3;
3801 if (mod == 3)
3802 goto illegal_op;
3803 gen_op_mov_reg_T0[ot][reg]();
3804 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3805 if (ot == OT_WORD)
3806 gen_op_boundw(pc_start - s->cs_base);
3807 else
3808 gen_op_boundl(pc_start - s->cs_base);
3809 break;
3810 case 0x1c8 ... 0x1cf: /* bswap reg */
3811 reg = b & 7;
3812 gen_op_mov_TN_reg[OT_LONG][0][reg]();
3813 gen_op_bswapl_T0();
3814 gen_op_mov_reg_T0[OT_LONG][reg]();
3815 break;
3816 case 0xd6: /* salc */
3817 if (s->cc_op != CC_OP_DYNAMIC)
3818 gen_op_set_cc_op(s->cc_op);
3819 gen_op_salc();
3820 break;
3821 case 0xe0: /* loopnz */
3822 case 0xe1: /* loopz */
3823 if (s->cc_op != CC_OP_DYNAMIC)
3824 gen_op_set_cc_op(s->cc_op);
3825 /* FALL THRU */
3826 case 0xe2: /* loop */
3827 case 0xe3: /* jecxz */
3828 val = (int8_t)insn_get(s, OT_BYTE);
3829 next_eip = s->pc - s->cs_base;
3830 val += next_eip;
3831 if (s->dflag == 0)
3832 val &= 0xffff;
3833 gen_op_loop[s->aflag][b & 3](val, next_eip);
3834 gen_eob(s);
3835 break;
3836 case 0x130: /* wrmsr */
3837 case 0x132: /* rdmsr */
3838 if (s->cpl != 0) {
3839 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3840 } else {
3841 if (b & 2)
3842 gen_op_rdmsr();
3843 else
3844 gen_op_wrmsr();
3845 }
3846 break;
3847 case 0x131: /* rdtsc */
3848 gen_op_rdtsc();
3849 break;
3850 case 0x1a2: /* cpuid */
3851 gen_op_cpuid();
3852 break;
3853 case 0xf4: /* hlt */
3854 if (s->cpl != 0) {
3855 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3856 } else {
3857 if (s->cc_op != CC_OP_DYNAMIC)
3858 gen_op_set_cc_op(s->cc_op);
3859 gen_op_jmp_im(s->pc - s->cs_base);
3860 gen_op_hlt();
3861 s->is_jmp = 3;
3862 }
3863 break;
3864 case 0x100:
61382a50 3865 modrm = ldub_code(s->pc++);
2c0262af
FB
3866 mod = (modrm >> 6) & 3;
3867 op = (modrm >> 3) & 7;
3868 switch(op) {
3869 case 0: /* sldt */
f115e911
FB
3870 if (!s->pe || s->vm86)
3871 goto illegal_op;
2c0262af
FB
3872 gen_op_movl_T0_env(offsetof(CPUX86State,ldt.selector));
3873 ot = OT_WORD;
3874 if (mod == 3)
3875 ot += s->dflag;
3876 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
3877 break;
3878 case 2: /* lldt */
f115e911
FB
3879 if (!s->pe || s->vm86)
3880 goto illegal_op;
2c0262af
FB
3881 if (s->cpl != 0) {
3882 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3883 } else {
3884 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
3885 gen_op_jmp_im(pc_start - s->cs_base);
3886 gen_op_lldt_T0();
3887 }
3888 break;
3889 case 1: /* str */
f115e911
FB
3890 if (!s->pe || s->vm86)
3891 goto illegal_op;
2c0262af
FB
3892 gen_op_movl_T0_env(offsetof(CPUX86State,tr.selector));
3893 ot = OT_WORD;
3894 if (mod == 3)
3895 ot += s->dflag;
3896 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
3897 break;
3898 case 3: /* ltr */
f115e911
FB
3899 if (!s->pe || s->vm86)
3900 goto illegal_op;
2c0262af
FB
3901 if (s->cpl != 0) {
3902 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3903 } else {
3904 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
3905 gen_op_jmp_im(pc_start - s->cs_base);
3906 gen_op_ltr_T0();
3907 }
3908 break;
3909 case 4: /* verr */
3910 case 5: /* verw */
f115e911
FB
3911 if (!s->pe || s->vm86)
3912 goto illegal_op;
3913 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
3914 if (s->cc_op != CC_OP_DYNAMIC)
3915 gen_op_set_cc_op(s->cc_op);
3916 if (op == 4)
3917 gen_op_verr();
3918 else
3919 gen_op_verw();
3920 s->cc_op = CC_OP_EFLAGS;
3921 break;
2c0262af
FB
3922 default:
3923 goto illegal_op;
3924 }
3925 break;
3926 case 0x101:
61382a50 3927 modrm = ldub_code(s->pc++);
2c0262af
FB
3928 mod = (modrm >> 6) & 3;
3929 op = (modrm >> 3) & 7;
3930 switch(op) {
3931 case 0: /* sgdt */
3932 case 1: /* sidt */
3933 if (mod == 3)
3934 goto illegal_op;
3935 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3936 if (op == 0)
3937 gen_op_movl_T0_env(offsetof(CPUX86State,gdt.limit));
3938 else
3939 gen_op_movl_T0_env(offsetof(CPUX86State,idt.limit));
3940 gen_op_st_T0_A0[OT_WORD + s->mem_index]();
3941 gen_op_addl_A0_im(2);
3942 if (op == 0)
3943 gen_op_movl_T0_env(offsetof(CPUX86State,gdt.base));
3944 else
3945 gen_op_movl_T0_env(offsetof(CPUX86State,idt.base));
3946 if (!s->dflag)
3947 gen_op_andl_T0_im(0xffffff);
3948 gen_op_st_T0_A0[OT_LONG + s->mem_index]();
3949 break;
3950 case 2: /* lgdt */
3951 case 3: /* lidt */
3952 if (mod == 3)
3953 goto illegal_op;
3954 if (s->cpl != 0) {
3955 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3956 } else {
3957 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3958 gen_op_ld_T1_A0[OT_WORD + s->mem_index]();
3959 gen_op_addl_A0_im(2);
3960 gen_op_ld_T0_A0[OT_LONG + s->mem_index]();
3961 if (!s->dflag)
3962 gen_op_andl_T0_im(0xffffff);
3963 if (op == 2) {
3964 gen_op_movl_env_T0(offsetof(CPUX86State,gdt.base));
3965 gen_op_movl_env_T1(offsetof(CPUX86State,gdt.limit));
3966 } else {
3967 gen_op_movl_env_T0(offsetof(CPUX86State,idt.base));
3968 gen_op_movl_env_T1(offsetof(CPUX86State,idt.limit));
3969 }
3970 }
3971 break;
3972 case 4: /* smsw */
3973 gen_op_movl_T0_env(offsetof(CPUX86State,cr[0]));
3974 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 1);
3975 break;
3976 case 6: /* lmsw */
3977 if (s->cpl != 0) {
3978 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3979 } else {
3980 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
3981 gen_op_lmsw_T0();
d71b9a8b
FB
3982 gen_op_jmp_im(s->pc - s->cs_base);
3983 gen_eob(s);
2c0262af
FB
3984 }
3985 break;
3986 case 7: /* invlpg */
3987 if (s->cpl != 0) {
3988 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3989 } else {
3990 if (mod == 3)
3991 goto illegal_op;
3992 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3993 gen_op_invlpg_A0();
3415a4dd
FB
3994 gen_op_jmp_im(s->pc - s->cs_base);
3995 gen_eob(s);
2c0262af
FB
3996 }
3997 break;
3998 default:
3999 goto illegal_op;
4000 }
4001 break;
3415a4dd
FB
4002 case 0x108: /* invd */
4003 case 0x109: /* wbinvd */
4004 if (s->cpl != 0) {
4005 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
4006 } else {
4007 /* nothing to do */
4008 }
4009 break;
f115e911
FB
4010 case 0x63: /* arpl */
4011 if (!s->pe || s->vm86)
4012 goto illegal_op;
4013 ot = dflag ? OT_LONG : OT_WORD;
4014 modrm = ldub_code(s->pc++);
4015 reg = (modrm >> 3) & 7;
4016 mod = (modrm >> 6) & 3;
4017 rm = modrm & 7;
4018 if (mod != 3) {
4019 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4020 gen_op_ld_T0_A0[ot + s->mem_index]();
4021 } else {
4022 gen_op_mov_TN_reg[ot][0][rm]();
4023 }
4024 if (s->cc_op != CC_OP_DYNAMIC)
4025 gen_op_set_cc_op(s->cc_op);
4026 gen_op_arpl();
4027 s->cc_op = CC_OP_EFLAGS;
4028 if (mod != 3) {
4029 gen_op_st_T0_A0[ot + s->mem_index]();
4030 } else {
4031 gen_op_mov_reg_T0[ot][rm]();
4032 }
4033 gen_op_arpl_update();
4034 break;
2c0262af
FB
4035 case 0x102: /* lar */
4036 case 0x103: /* lsl */
4037 if (!s->pe || s->vm86)
4038 goto illegal_op;
4039 ot = dflag ? OT_LONG : OT_WORD;
61382a50 4040 modrm = ldub_code(s->pc++);
2c0262af
FB
4041 reg = (modrm >> 3) & 7;
4042 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
4043 gen_op_mov_TN_reg[ot][1][reg]();
4044 if (s->cc_op != CC_OP_DYNAMIC)
4045 gen_op_set_cc_op(s->cc_op);
4046 if (b == 0x102)
4047 gen_op_lar();
4048 else
4049 gen_op_lsl();
4050 s->cc_op = CC_OP_EFLAGS;
4051 gen_op_mov_reg_T1[ot][reg]();
4052 break;
4053 case 0x118:
61382a50 4054 modrm = ldub_code(s->pc++);
2c0262af
FB
4055 mod = (modrm >> 6) & 3;
4056 op = (modrm >> 3) & 7;
4057 switch(op) {
4058 case 0: /* prefetchnta */
4059 case 1: /* prefetchnt0 */
4060 case 2: /* prefetchnt0 */
4061 case 3: /* prefetchnt0 */
4062 if (mod == 3)
4063 goto illegal_op;
4064 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4065 /* nothing more to do */
4066 break;
4067 default:
4068 goto illegal_op;
4069 }
4070 break;
4071 case 0x120: /* mov reg, crN */
4072 case 0x122: /* mov crN, reg */
4073 if (s->cpl != 0) {
4074 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
4075 } else {
61382a50 4076 modrm = ldub_code(s->pc++);
2c0262af
FB
4077 if ((modrm & 0xc0) != 0xc0)
4078 goto illegal_op;
4079 rm = modrm & 7;
4080 reg = (modrm >> 3) & 7;
4081 switch(reg) {
4082 case 0:
4083 case 2:
4084 case 3:
4085 case 4:
4086 if (b & 2) {
4087 gen_op_mov_TN_reg[OT_LONG][0][rm]();
4088 gen_op_movl_crN_T0(reg);
4089 gen_op_jmp_im(s->pc - s->cs_base);
4090 gen_eob(s);
4091 } else {
4092 gen_op_movl_T0_env(offsetof(CPUX86State,cr[reg]));
4093 gen_op_mov_reg_T0[OT_LONG][rm]();
4094 }
4095 break;
4096 default:
4097 goto illegal_op;
4098 }
4099 }
4100 break;
4101 case 0x121: /* mov reg, drN */
4102 case 0x123: /* mov drN, reg */
4103 if (s->cpl != 0) {
4104 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
4105 } else {
61382a50 4106 modrm = ldub_code(s->pc++);
2c0262af
FB
4107 if ((modrm & 0xc0) != 0xc0)
4108 goto illegal_op;
4109 rm = modrm & 7;
4110 reg = (modrm >> 3) & 7;
4111 /* XXX: do it dynamically with CR4.DE bit */
4112 if (reg == 4 || reg == 5)
4113 goto illegal_op;
4114 if (b & 2) {
4115 gen_op_mov_TN_reg[OT_LONG][0][rm]();
4116 gen_op_movl_drN_T0(reg);
4117 gen_op_jmp_im(s->pc - s->cs_base);
4118 gen_eob(s);
4119 } else {
4120 gen_op_movl_T0_env(offsetof(CPUX86State,dr[reg]));
4121 gen_op_mov_reg_T0[OT_LONG][rm]();
4122 }
4123 }
4124 break;
4125 case 0x106: /* clts */
4126 if (s->cpl != 0) {
4127 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
4128 } else {
4129 gen_op_clts();
4130 }
4131 break;
4132 default:
4133 goto illegal_op;
4134 }
4135 /* lock generation */
4136 if (s->prefix & PREFIX_LOCK)
4137 gen_op_unlock();
4138 return s->pc;
4139 illegal_op:
4140 /* XXX: ensure that no lock was generated */
4141 gen_exception(s, EXCP06_ILLOP, pc_start - s->cs_base);
4142 return s->pc;
4143}
4144
4145#define CC_OSZAPC (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C)
4146#define CC_OSZAP (CC_O | CC_S | CC_Z | CC_A | CC_P)
4147
4148/* flags read by an operation */
4149static uint16_t opc_read_flags[NB_OPS] = {
4150 [INDEX_op_aas] = CC_A,
4151 [INDEX_op_aaa] = CC_A,
4152 [INDEX_op_das] = CC_A | CC_C,
4153 [INDEX_op_daa] = CC_A | CC_C,
4154
2c0262af
FB
4155 /* subtle: due to the incl/decl implementation, C is used */
4156 [INDEX_op_update_inc_cc] = CC_C,
4157
4158 [INDEX_op_into] = CC_O,
4159
4160 [INDEX_op_jb_subb] = CC_C,
4161 [INDEX_op_jb_subw] = CC_C,
4162 [INDEX_op_jb_subl] = CC_C,
4163
4164 [INDEX_op_jz_subb] = CC_Z,
4165 [INDEX_op_jz_subw] = CC_Z,
4166 [INDEX_op_jz_subl] = CC_Z,
4167
4168 [INDEX_op_jbe_subb] = CC_Z | CC_C,
4169 [INDEX_op_jbe_subw] = CC_Z | CC_C,
4170 [INDEX_op_jbe_subl] = CC_Z | CC_C,
4171
4172 [INDEX_op_js_subb] = CC_S,
4173 [INDEX_op_js_subw] = CC_S,
4174 [INDEX_op_js_subl] = CC_S,
4175
4176 [INDEX_op_jl_subb] = CC_O | CC_S,
4177 [INDEX_op_jl_subw] = CC_O | CC_S,
4178 [INDEX_op_jl_subl] = CC_O | CC_S,
4179
4180 [INDEX_op_jle_subb] = CC_O | CC_S | CC_Z,
4181 [INDEX_op_jle_subw] = CC_O | CC_S | CC_Z,
4182 [INDEX_op_jle_subl] = CC_O | CC_S | CC_Z,
4183
4184 [INDEX_op_loopnzw] = CC_Z,
4185 [INDEX_op_loopnzl] = CC_Z,
4186 [INDEX_op_loopzw] = CC_Z,
4187 [INDEX_op_loopzl] = CC_Z,
4188
4189 [INDEX_op_seto_T0_cc] = CC_O,
4190 [INDEX_op_setb_T0_cc] = CC_C,
4191 [INDEX_op_setz_T0_cc] = CC_Z,
4192 [INDEX_op_setbe_T0_cc] = CC_Z | CC_C,
4193 [INDEX_op_sets_T0_cc] = CC_S,
4194 [INDEX_op_setp_T0_cc] = CC_P,
4195 [INDEX_op_setl_T0_cc] = CC_O | CC_S,
4196 [INDEX_op_setle_T0_cc] = CC_O | CC_S | CC_Z,
4197
4198 [INDEX_op_setb_T0_subb] = CC_C,
4199 [INDEX_op_setb_T0_subw] = CC_C,
4200 [INDEX_op_setb_T0_subl] = CC_C,
4201
4202 [INDEX_op_setz_T0_subb] = CC_Z,
4203 [INDEX_op_setz_T0_subw] = CC_Z,
4204 [INDEX_op_setz_T0_subl] = CC_Z,
4205
4206 [INDEX_op_setbe_T0_subb] = CC_Z | CC_C,
4207 [INDEX_op_setbe_T0_subw] = CC_Z | CC_C,
4208 [INDEX_op_setbe_T0_subl] = CC_Z | CC_C,
4209
4210 [INDEX_op_sets_T0_subb] = CC_S,
4211 [INDEX_op_sets_T0_subw] = CC_S,
4212 [INDEX_op_sets_T0_subl] = CC_S,
4213
4214 [INDEX_op_setl_T0_subb] = CC_O | CC_S,
4215 [INDEX_op_setl_T0_subw] = CC_O | CC_S,
4216 [INDEX_op_setl_T0_subl] = CC_O | CC_S,
4217
4218 [INDEX_op_setle_T0_subb] = CC_O | CC_S | CC_Z,
4219 [INDEX_op_setle_T0_subw] = CC_O | CC_S | CC_Z,
4220 [INDEX_op_setle_T0_subl] = CC_O | CC_S | CC_Z,
4221
4222 [INDEX_op_movl_T0_eflags] = CC_OSZAPC,
4223 [INDEX_op_cmc] = CC_C,
4224 [INDEX_op_salc] = CC_C,
4225
4f31916f
FB
4226#define DEF_READF(SUFFIX)\
4227 [INDEX_op_adcb ## SUFFIX ## _T0_T1_cc] = CC_C,\
4228 [INDEX_op_adcw ## SUFFIX ## _T0_T1_cc] = CC_C,\
4229 [INDEX_op_adcl ## SUFFIX ## _T0_T1_cc] = CC_C,\
4230 [INDEX_op_sbbb ## SUFFIX ## _T0_T1_cc] = CC_C,\
4231 [INDEX_op_sbbw ## SUFFIX ## _T0_T1_cc] = CC_C,\
4232 [INDEX_op_sbbl ## SUFFIX ## _T0_T1_cc] = CC_C,\
4233\
4234 [INDEX_op_rclb ## SUFFIX ## _T0_T1_cc] = CC_C,\
4235 [INDEX_op_rclw ## SUFFIX ## _T0_T1_cc] = CC_C,\
4236 [INDEX_op_rcll ## SUFFIX ## _T0_T1_cc] = CC_C,\
4237 [INDEX_op_rcrb ## SUFFIX ## _T0_T1_cc] = CC_C,\
4238 [INDEX_op_rcrw ## SUFFIX ## _T0_T1_cc] = CC_C,\
4239 [INDEX_op_rcrl ## SUFFIX ## _T0_T1_cc] = CC_C,
4240
4241
4242 DEF_READF()
4243 DEF_READF(_raw)
4244#ifndef CONFIG_USER_ONLY
4245 DEF_READF(_kernel)
4246 DEF_READF(_user)
4247#endif
2c0262af
FB
4248};
4249
4250/* flags written by an operation */
4251static uint16_t opc_write_flags[NB_OPS] = {
4252 [INDEX_op_update2_cc] = CC_OSZAPC,
4253 [INDEX_op_update1_cc] = CC_OSZAPC,
4254 [INDEX_op_cmpl_T0_T1_cc] = CC_OSZAPC,
4255 [INDEX_op_update_neg_cc] = CC_OSZAPC,
4256 /* subtle: due to the incl/decl implementation, C is used */
4257 [INDEX_op_update_inc_cc] = CC_OSZAPC,
4258 [INDEX_op_testl_T0_T1_cc] = CC_OSZAPC,
4259
2c0262af
FB
4260 [INDEX_op_mulb_AL_T0] = CC_OSZAPC,
4261 [INDEX_op_imulb_AL_T0] = CC_OSZAPC,
4262 [INDEX_op_mulw_AX_T0] = CC_OSZAPC,
4263 [INDEX_op_imulw_AX_T0] = CC_OSZAPC,
4264 [INDEX_op_mull_EAX_T0] = CC_OSZAPC,
4265 [INDEX_op_imull_EAX_T0] = CC_OSZAPC,
4266 [INDEX_op_imulw_T0_T1] = CC_OSZAPC,
4267 [INDEX_op_imull_T0_T1] = CC_OSZAPC,
4268
4269 /* bcd */
4270 [INDEX_op_aam] = CC_OSZAPC,
4271 [INDEX_op_aad] = CC_OSZAPC,
4272 [INDEX_op_aas] = CC_OSZAPC,
4273 [INDEX_op_aaa] = CC_OSZAPC,
4274 [INDEX_op_das] = CC_OSZAPC,
4275 [INDEX_op_daa] = CC_OSZAPC,
4276
4277 [INDEX_op_movb_eflags_T0] = CC_S | CC_Z | CC_A | CC_P | CC_C,
4278 [INDEX_op_movw_eflags_T0] = CC_OSZAPC,
4279 [INDEX_op_movl_eflags_T0] = CC_OSZAPC,
4136f33c
FB
4280 [INDEX_op_movw_eflags_T0_io] = CC_OSZAPC,
4281 [INDEX_op_movl_eflags_T0_io] = CC_OSZAPC,
4282 [INDEX_op_movw_eflags_T0_cpl0] = CC_OSZAPC,
4283 [INDEX_op_movl_eflags_T0_cpl0] = CC_OSZAPC,
2c0262af
FB
4284 [INDEX_op_clc] = CC_C,
4285 [INDEX_op_stc] = CC_C,
4286 [INDEX_op_cmc] = CC_C,
4287
2c0262af
FB
4288 [INDEX_op_btw_T0_T1_cc] = CC_OSZAPC,
4289 [INDEX_op_btl_T0_T1_cc] = CC_OSZAPC,
4290 [INDEX_op_btsw_T0_T1_cc] = CC_OSZAPC,
4291 [INDEX_op_btsl_T0_T1_cc] = CC_OSZAPC,
4292 [INDEX_op_btrw_T0_T1_cc] = CC_OSZAPC,
4293 [INDEX_op_btrl_T0_T1_cc] = CC_OSZAPC,
4294 [INDEX_op_btcw_T0_T1_cc] = CC_OSZAPC,
4295 [INDEX_op_btcl_T0_T1_cc] = CC_OSZAPC,
4296
4297 [INDEX_op_bsfw_T0_cc] = CC_OSZAPC,
4298 [INDEX_op_bsfl_T0_cc] = CC_OSZAPC,
4299 [INDEX_op_bsrw_T0_cc] = CC_OSZAPC,
4300 [INDEX_op_bsrl_T0_cc] = CC_OSZAPC,
4301
4302 [INDEX_op_cmpxchgb_T0_T1_EAX_cc] = CC_OSZAPC,
4303 [INDEX_op_cmpxchgw_T0_T1_EAX_cc] = CC_OSZAPC,
4304 [INDEX_op_cmpxchgl_T0_T1_EAX_cc] = CC_OSZAPC,
4305
2c0262af
FB
4306 [INDEX_op_cmpxchg8b] = CC_Z,
4307 [INDEX_op_lar] = CC_Z,
4308 [INDEX_op_lsl] = CC_Z,
4309 [INDEX_op_fcomi_ST0_FT0] = CC_Z | CC_P | CC_C,
4310 [INDEX_op_fucomi_ST0_FT0] = CC_Z | CC_P | CC_C,
4f31916f
FB
4311
4312#define DEF_WRITEF(SUFFIX)\
4313 [INDEX_op_adcb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
4314 [INDEX_op_adcw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
4315 [INDEX_op_adcl ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
4316 [INDEX_op_sbbb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
4317 [INDEX_op_sbbw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
4318 [INDEX_op_sbbl ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
4319\
4320 [INDEX_op_rolb ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
4321 [INDEX_op_rolw ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
4322 [INDEX_op_roll ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
4323 [INDEX_op_rorb ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
4324 [INDEX_op_rorw ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
4325 [INDEX_op_rorl ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
4326\
4327 [INDEX_op_rclb ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
4328 [INDEX_op_rclw ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
4329 [INDEX_op_rcll ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
4330 [INDEX_op_rcrb ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
4331 [INDEX_op_rcrw ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
4332 [INDEX_op_rcrl ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
4333\
4334 [INDEX_op_shlb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
4335 [INDEX_op_shlw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
4336 [INDEX_op_shll ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
4337\
4338 [INDEX_op_shrb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
4339 [INDEX_op_shrw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
4340 [INDEX_op_shrl ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
4341\
4342 [INDEX_op_sarb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
4343 [INDEX_op_sarw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
4344 [INDEX_op_sarl ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
4345\
4346 [INDEX_op_shldw ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,\
4347 [INDEX_op_shldl ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,\
4348 [INDEX_op_shldw ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,\
4349 [INDEX_op_shldl ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,\
4350\
4351 [INDEX_op_shrdw ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,\
4352 [INDEX_op_shrdl ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,\
4353 [INDEX_op_shrdw ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,\
4354 [INDEX_op_shrdl ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,\
4355\
4356 [INDEX_op_cmpxchgb ## SUFFIX ## _T0_T1_EAX_cc] = CC_OSZAPC,\
4357 [INDEX_op_cmpxchgw ## SUFFIX ## _T0_T1_EAX_cc] = CC_OSZAPC,\
4358 [INDEX_op_cmpxchgl ## SUFFIX ## _T0_T1_EAX_cc] = CC_OSZAPC,
4359
4360
4361 DEF_WRITEF()
4362 DEF_WRITEF(_raw)
4363#ifndef CONFIG_USER_ONLY
4364 DEF_WRITEF(_kernel)
4365 DEF_WRITEF(_user)
4366#endif
2c0262af
FB
4367};
4368
4369/* simpler form of an operation if no flags need to be generated */
4370static uint16_t opc_simpler[NB_OPS] = {
4371 [INDEX_op_update2_cc] = INDEX_op_nop,
4372 [INDEX_op_update1_cc] = INDEX_op_nop,
4373 [INDEX_op_update_neg_cc] = INDEX_op_nop,
4374#if 0
4375 /* broken: CC_OP logic must be rewritten */
4376 [INDEX_op_update_inc_cc] = INDEX_op_nop,
4377#endif
2c0262af
FB
4378
4379 [INDEX_op_shlb_T0_T1_cc] = INDEX_op_shlb_T0_T1,
4380 [INDEX_op_shlw_T0_T1_cc] = INDEX_op_shlw_T0_T1,
4381 [INDEX_op_shll_T0_T1_cc] = INDEX_op_shll_T0_T1,
4382
4383 [INDEX_op_shrb_T0_T1_cc] = INDEX_op_shrb_T0_T1,
4384 [INDEX_op_shrw_T0_T1_cc] = INDEX_op_shrw_T0_T1,
4385 [INDEX_op_shrl_T0_T1_cc] = INDEX_op_shrl_T0_T1,
4386
4387 [INDEX_op_sarb_T0_T1_cc] = INDEX_op_sarb_T0_T1,
4388 [INDEX_op_sarw_T0_T1_cc] = INDEX_op_sarw_T0_T1,
4389 [INDEX_op_sarl_T0_T1_cc] = INDEX_op_sarl_T0_T1,
4f31916f
FB
4390
4391#define DEF_SIMPLER(SUFFIX)\
4392 [INDEX_op_rolb ## SUFFIX ## _T0_T1_cc] = INDEX_op_rolb ## SUFFIX ## _T0_T1,\
4393 [INDEX_op_rolw ## SUFFIX ## _T0_T1_cc] = INDEX_op_rolw ## SUFFIX ## _T0_T1,\
4394 [INDEX_op_roll ## SUFFIX ## _T0_T1_cc] = INDEX_op_roll ## SUFFIX ## _T0_T1,\
4395\
4396 [INDEX_op_rorb ## SUFFIX ## _T0_T1_cc] = INDEX_op_rorb ## SUFFIX ## _T0_T1,\
4397 [INDEX_op_rorw ## SUFFIX ## _T0_T1_cc] = INDEX_op_rorw ## SUFFIX ## _T0_T1,\
4398 [INDEX_op_rorl ## SUFFIX ## _T0_T1_cc] = INDEX_op_rorl ## SUFFIX ## _T0_T1,
4399
4400 DEF_SIMPLER()
4401 DEF_SIMPLER(_raw)
4402#ifndef CONFIG_USER_ONLY
4403 DEF_SIMPLER(_kernel)
4404 DEF_SIMPLER(_user)
4405#endif
2c0262af
FB
4406};
4407
4408void optimize_flags_init(void)
4409{
4410 int i;
4411 /* put default values in arrays */
4412 for(i = 0; i < NB_OPS; i++) {
4413 if (opc_simpler[i] == 0)
4414 opc_simpler[i] = i;
4415 }
4416}
4417
4418/* CPU flags computation optimization: we move backward thru the
4419 generated code to see which flags are needed. The operation is
4420 modified if suitable */
4421static void optimize_flags(uint16_t *opc_buf, int opc_buf_len)
4422{
4423 uint16_t *opc_ptr;
4424 int live_flags, write_flags, op;
4425
4426 opc_ptr = opc_buf + opc_buf_len;
4427 /* live_flags contains the flags needed by the next instructions
4428 in the code. At the end of the bloc, we consider that all the
4429 flags are live. */
4430 live_flags = CC_OSZAPC;
4431 while (opc_ptr > opc_buf) {
4432 op = *--opc_ptr;
4433 /* if none of the flags written by the instruction is used,
4434 then we can try to find a simpler instruction */
4435 write_flags = opc_write_flags[op];
4436 if ((live_flags & write_flags) == 0) {
4437 *opc_ptr = opc_simpler[op];
4438 }
4439 /* compute the live flags before the instruction */
4440 live_flags &= ~write_flags;
4441 live_flags |= opc_read_flags[op];
4442 }
4443}
4444
4445/* generate intermediate code in gen_opc_buf and gen_opparam_buf for
4446 basic block 'tb'. If search_pc is TRUE, also generate PC
4447 information for each intermediate instruction. */
4448static inline int gen_intermediate_code_internal(CPUState *env,
4449 TranslationBlock *tb,
4450 int search_pc)
4451{
4452 DisasContext dc1, *dc = &dc1;
4453 uint8_t *pc_ptr;
4454 uint16_t *gen_opc_end;
4455 int flags, j, lj;
4456 uint8_t *pc_start;
4457 uint8_t *cs_base;
4458
4459 /* generate intermediate code */
4460 pc_start = (uint8_t *)tb->pc;
4461 cs_base = (uint8_t *)tb->cs_base;
4462 flags = tb->flags;
4463
4f31916f 4464 dc->pe = (flags >> HF_PE_SHIFT) & 1;
2c0262af
FB
4465 dc->code32 = (flags >> HF_CS32_SHIFT) & 1;
4466 dc->ss32 = (flags >> HF_SS32_SHIFT) & 1;
4467 dc->addseg = (flags >> HF_ADDSEG_SHIFT) & 1;
4468 dc->f_st = 0;
4469 dc->vm86 = (flags >> VM_SHIFT) & 1;
4470 dc->cpl = (flags >> HF_CPL_SHIFT) & 3;
4471 dc->iopl = (flags >> IOPL_SHIFT) & 3;
4472 dc->tf = (flags >> TF_SHIFT) & 1;
34865134 4473 dc->singlestep_enabled = env->singlestep_enabled;
2c0262af
FB
4474 dc->cc_op = CC_OP_DYNAMIC;
4475 dc->cs_base = cs_base;
4476 dc->tb = tb;
4477 dc->popl_esp_hack = 0;
4478 /* select memory access functions */
4479 dc->mem_index = 0;
4480 if (flags & HF_SOFTMMU_MASK) {
4481 if (dc->cpl == 3)
4482 dc->mem_index = 6;
4483 else
4484 dc->mem_index = 3;
4485 }
a2cc3b24
FB
4486 dc->jmp_opt = !(dc->tf || env->singlestep_enabled ||
4487 (flags & HF_INHIBIT_IRQ_MASK)
415fa2ea 4488#ifndef CONFIG_SOFTMMU
2c0262af
FB
4489 || (flags & HF_SOFTMMU_MASK)
4490#endif
4491 );
4f31916f
FB
4492#if 0
4493 /* check addseg logic */
4494 if (!dc->addseg && (dc->vm86 || !dc->pe))
4495 printf("ERROR addseg\n");
4496#endif
4497
2c0262af
FB
4498 gen_opc_ptr = gen_opc_buf;
4499 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
4500 gen_opparam_ptr = gen_opparam_buf;
4501
4502 dc->is_jmp = DISAS_NEXT;
4503 pc_ptr = pc_start;
4504 lj = -1;
4505
2c0262af
FB
4506 for(;;) {
4507 if (env->nb_breakpoints > 0) {
4508 for(j = 0; j < env->nb_breakpoints; j++) {
4509 if (env->breakpoints[j] == (unsigned long)pc_ptr) {
4510 gen_debug(dc, pc_ptr - dc->cs_base);
4511 break;
4512 }
4513 }
4514 }
4515 if (search_pc) {
4516 j = gen_opc_ptr - gen_opc_buf;
4517 if (lj < j) {
4518 lj++;
4519 while (lj < j)
4520 gen_opc_instr_start[lj++] = 0;
4521 }
4522 gen_opc_pc[lj] = (uint32_t)pc_ptr;
4523 gen_opc_cc_op[lj] = dc->cc_op;
4524 gen_opc_instr_start[lj] = 1;
4525 }
4526 pc_ptr = disas_insn(dc, pc_ptr);
4527 /* stop translation if indicated */
4528 if (dc->is_jmp)
4529 break;
4530 /* if single step mode, we generate only one instruction and
4531 generate an exception */
a2cc3b24
FB
4532 /* if irq were inhibited with HF_INHIBIT_IRQ_MASK, we clear
4533 the flag and abort the translation to give the irqs a
4534 change to be happen */
4535 if (dc->tf || dc->singlestep_enabled ||
4536 (flags & HF_INHIBIT_IRQ_MASK)) {
2c0262af
FB
4537 gen_op_jmp_im(pc_ptr - dc->cs_base);
4538 gen_eob(dc);
4539 break;
4540 }
4541 /* if too long translation, stop generation too */
4542 if (gen_opc_ptr >= gen_opc_end ||
4543 (pc_ptr - pc_start) >= (TARGET_PAGE_SIZE - 32)) {
4544 gen_op_jmp_im(pc_ptr - dc->cs_base);
4545 gen_eob(dc);
4546 break;
4547 }
4548 }
4549 *gen_opc_ptr = INDEX_op_end;
4550 /* we don't forget to fill the last values */
4551 if (search_pc) {
4552 j = gen_opc_ptr - gen_opc_buf;
4553 lj++;
4554 while (lj <= j)
4555 gen_opc_instr_start[lj++] = 0;
4556 }
4557
4558#ifdef DEBUG_DISAS
4559 if (loglevel) {
4560 fprintf(logfile, "----------------\n");
4561 fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
4562 disas(logfile, pc_start, pc_ptr - pc_start, 0, !dc->code32);
4563 fprintf(logfile, "\n");
5a1388b6 4564#if 0
2c0262af
FB
4565 fprintf(logfile, "OP:\n");
4566 dump_ops(gen_opc_buf, gen_opparam_buf);
4567 fprintf(logfile, "\n");
5a1388b6 4568#endif
2c0262af
FB
4569 }
4570#endif
4571
4572 /* optimize flag computations */
4573 optimize_flags(gen_opc_buf, gen_opc_ptr - gen_opc_buf);
4574
4575#ifdef DEBUG_DISAS
4576 if (loglevel) {
4577 fprintf(logfile, "AFTER FLAGS OPT:\n");
4578 dump_ops(gen_opc_buf, gen_opparam_buf);
4579 fprintf(logfile, "\n");
4580 }
4581#endif
4582 if (!search_pc)
4583 tb->size = pc_ptr - pc_start;
4584 return 0;
4585}
4586
4587int gen_intermediate_code(CPUState *env, TranslationBlock *tb)
4588{
4589 return gen_intermediate_code_internal(env, tb, 0);
4590}
4591
4592int gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
4593{
4594 return gen_intermediate_code_internal(env, tb, 1);
4595}
4596