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