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