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