Commit 4b74fe1f0013c622693b26141c0ed031a284a45a
1 parent
586314f2
many fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@19 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
8 changed files
with
684 additions
and
178 deletions
cpu-i386.h
| @@ -78,19 +78,27 @@ enum { | @@ -78,19 +78,27 @@ enum { | ||
| 78 | CC_OP_ADDW, | 78 | CC_OP_ADDW, |
| 79 | CC_OP_ADDL, | 79 | CC_OP_ADDL, |
| 80 | 80 | ||
| 81 | + CC_OP_ADCB, /* modify all flags, CC_DST = res, CC_SRC = src1 */ | ||
| 82 | + CC_OP_ADCW, | ||
| 83 | + CC_OP_ADCL, | ||
| 84 | + | ||
| 81 | CC_OP_SUBB, /* modify all flags, CC_DST = res, CC_SRC = src1 */ | 85 | CC_OP_SUBB, /* modify all flags, CC_DST = res, CC_SRC = src1 */ |
| 82 | CC_OP_SUBW, | 86 | CC_OP_SUBW, |
| 83 | CC_OP_SUBL, | 87 | CC_OP_SUBL, |
| 84 | 88 | ||
| 89 | + CC_OP_SBBB, /* modify all flags, CC_DST = res, CC_SRC = src1 */ | ||
| 90 | + CC_OP_SBBW, | ||
| 91 | + CC_OP_SBBL, | ||
| 92 | + | ||
| 85 | CC_OP_LOGICB, /* modify all flags, CC_DST = res */ | 93 | CC_OP_LOGICB, /* modify all flags, CC_DST = res */ |
| 86 | CC_OP_LOGICW, | 94 | CC_OP_LOGICW, |
| 87 | CC_OP_LOGICL, | 95 | CC_OP_LOGICL, |
| 88 | 96 | ||
| 89 | - CC_OP_INCB, /* modify all flags except, CC_DST = res */ | 97 | + CC_OP_INCB, /* modify all flags except, CC_DST = res, CC_SRC = C */ |
| 90 | CC_OP_INCW, | 98 | CC_OP_INCW, |
| 91 | CC_OP_INCL, | 99 | CC_OP_INCL, |
| 92 | 100 | ||
| 93 | - CC_OP_DECB, /* modify all flags except, CC_DST = res */ | 101 | + CC_OP_DECB, /* modify all flags except, CC_DST = res, CC_SRC = C */ |
| 94 | CC_OP_DECW, | 102 | CC_OP_DECW, |
| 95 | CC_OP_DECL, | 103 | CC_OP_DECL, |
| 96 | 104 | ||
| @@ -98,6 +106,10 @@ enum { | @@ -98,6 +106,10 @@ enum { | ||
| 98 | CC_OP_SHLW, | 106 | CC_OP_SHLW, |
| 99 | CC_OP_SHLL, | 107 | CC_OP_SHLL, |
| 100 | 108 | ||
| 109 | + CC_OP_SARB, /* modify all flags, CC_DST = res, CC_SRC.lsb = C */ | ||
| 110 | + CC_OP_SARW, | ||
| 111 | + CC_OP_SARL, | ||
| 112 | + | ||
| 101 | CC_OP_NB, | 113 | CC_OP_NB, |
| 102 | }; | 114 | }; |
| 103 | 115 |
dyngen.c
| @@ -198,14 +198,10 @@ void gen_code(const char *name, unsigned long offset, unsigned long size, | @@ -198,14 +198,10 @@ void gen_code(const char *name, unsigned long offset, unsigned long size, | ||
| 198 | { | 198 | { |
| 199 | uint8_t *p; | 199 | uint8_t *p; |
| 200 | p = p_end - 1; | 200 | p = p_end - 1; |
| 201 | - /* find ret */ | ||
| 202 | - while (p > p_start && *p != 0xc3) | ||
| 203 | - p--; | ||
| 204 | - /* skip double ret */ | ||
| 205 | - if (p > p_start && p[-1] == 0xc3) | ||
| 206 | - p--; | ||
| 207 | if (p == p_start) | 201 | if (p == p_start) |
| 208 | error("empty code for %s", name); | 202 | error("empty code for %s", name); |
| 203 | + if (p[0] != 0xc3) | ||
| 204 | + error("ret expected at the end of %s", name); | ||
| 209 | copy_size = p - p_start; | 205 | copy_size = p - p_start; |
| 210 | } | 206 | } |
| 211 | break; | 207 | break; |
linux-user/main.c
| @@ -128,21 +128,21 @@ int main(int argc, char **argv) | @@ -128,21 +128,21 @@ int main(int argc, char **argv) | ||
| 128 | /* Zero out image_info */ | 128 | /* Zero out image_info */ |
| 129 | memset(info, 0, sizeof(struct image_info)); | 129 | memset(info, 0, sizeof(struct image_info)); |
| 130 | 130 | ||
| 131 | - if(elf_exec(filename, argv+1, environ, regs, info) != 0) { | 131 | + if(elf_exec(filename, argv+optind, environ, regs, info) != 0) { |
| 132 | printf("Error loading %s\n", filename); | 132 | printf("Error loading %s\n", filename); |
| 133 | exit(1); | 133 | exit(1); |
| 134 | } | 134 | } |
| 135 | 135 | ||
| 136 | -#if 0 | ||
| 137 | - printf("start_brk 0x%08lx\n" , info->start_brk); | ||
| 138 | - printf("end_code 0x%08lx\n" , info->end_code); | ||
| 139 | - printf("start_code 0x%08lx\n" , info->start_code); | ||
| 140 | - printf("end_data 0x%08lx\n" , info->end_data); | ||
| 141 | - printf("start_stack 0x%08lx\n" , info->start_stack); | ||
| 142 | - printf("brk 0x%08lx\n" , info->brk); | ||
| 143 | - printf("esp 0x%08lx\n" , regs->esp); | ||
| 144 | - printf("eip 0x%08lx\n" , regs->eip); | ||
| 145 | -#endif | 136 | + if (loglevel) { |
| 137 | + fprintf(logfile, "start_brk 0x%08lx\n" , info->start_brk); | ||
| 138 | + fprintf(logfile, "end_code 0x%08lx\n" , info->end_code); | ||
| 139 | + fprintf(logfile, "start_code 0x%08lx\n" , info->start_code); | ||
| 140 | + fprintf(logfile, "end_data 0x%08lx\n" , info->end_data); | ||
| 141 | + fprintf(logfile, "start_stack 0x%08lx\n" , info->start_stack); | ||
| 142 | + fprintf(logfile, "brk 0x%08lx\n" , info->brk); | ||
| 143 | + fprintf(logfile, "esp 0x%08lx\n" , regs->esp); | ||
| 144 | + fprintf(logfile, "eip 0x%08lx\n" , regs->eip); | ||
| 145 | + } | ||
| 146 | 146 | ||
| 147 | target_set_brk((char *)info->brk); | 147 | target_set_brk((char *)info->brk); |
| 148 | syscall_init(); | 148 | syscall_init(); |
op-i386.c
| @@ -10,7 +10,18 @@ typedef signed short int16_t; | @@ -10,7 +10,18 @@ typedef signed short int16_t; | ||
| 10 | typedef signed int int32_t; | 10 | typedef signed int int32_t; |
| 11 | typedef signed long long int64_t; | 11 | typedef signed long long int64_t; |
| 12 | 12 | ||
| 13 | +#define bswap32(x) \ | ||
| 14 | +({ \ | ||
| 15 | + uint32_t __x = (x); \ | ||
| 16 | + ((uint32_t)( \ | ||
| 17 | + (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \ | ||
| 18 | + (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) << 8) | \ | ||
| 19 | + (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >> 8) | \ | ||
| 20 | + (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) )); \ | ||
| 21 | +}) | ||
| 22 | + | ||
| 13 | #define NULL 0 | 23 | #define NULL 0 |
| 24 | +#include <fenv.h> | ||
| 14 | 25 | ||
| 15 | typedef struct FILE FILE; | 26 | typedef struct FILE FILE; |
| 16 | extern FILE *logfile; | 27 | extern FILE *logfile; |
| @@ -18,41 +29,39 @@ extern int loglevel; | @@ -18,41 +29,39 @@ extern int loglevel; | ||
| 18 | extern int fprintf(FILE *, const char *, ...); | 29 | extern int fprintf(FILE *, const char *, ...); |
| 19 | 30 | ||
| 20 | #ifdef __i386__ | 31 | #ifdef __i386__ |
| 21 | -register int T0 asm("esi"); | ||
| 22 | -register int T1 asm("ebx"); | ||
| 23 | -register int A0 asm("edi"); | 32 | +register unsigned int T0 asm("ebx"); |
| 33 | +register unsigned int T1 asm("esi"); | ||
| 34 | +register unsigned int A0 asm("edi"); | ||
| 24 | register struct CPUX86State *env asm("ebp"); | 35 | register struct CPUX86State *env asm("ebp"); |
| 25 | -#define FORCE_RET() asm volatile ("ret"); | ||
| 26 | #endif | 36 | #endif |
| 27 | #ifdef __powerpc__ | 37 | #ifdef __powerpc__ |
| 28 | -register int T0 asm("r24"); | ||
| 29 | -register int T1 asm("r25"); | ||
| 30 | -register int A0 asm("r26"); | 38 | +register unsigned int T0 asm("r24"); |
| 39 | +register unsigned int T1 asm("r25"); | ||
| 40 | +register unsigned int A0 asm("r26"); | ||
| 31 | register struct CPUX86State *env asm("r27"); | 41 | register struct CPUX86State *env asm("r27"); |
| 32 | -#define FORCE_RET() asm volatile ("blr"); | ||
| 33 | #endif | 42 | #endif |
| 34 | #ifdef __arm__ | 43 | #ifdef __arm__ |
| 35 | -register int T0 asm("r4"); | ||
| 36 | -register int T1 asm("r5"); | ||
| 37 | -register int A0 asm("r6"); | 44 | +register unsigned int T0 asm("r4"); |
| 45 | +register unsigned int T1 asm("r5"); | ||
| 46 | +register unsigned int A0 asm("r6"); | ||
| 38 | register struct CPUX86State *env asm("r7"); | 47 | register struct CPUX86State *env asm("r7"); |
| 39 | -#define FORCE_RET() asm volatile ("mov pc, lr"); | ||
| 40 | #endif | 48 | #endif |
| 41 | #ifdef __mips__ | 49 | #ifdef __mips__ |
| 42 | -register int T0 asm("s0"); | ||
| 43 | -register int T1 asm("s1"); | ||
| 44 | -register int A0 asm("s2"); | 50 | +register unsigned int T0 asm("s0"); |
| 51 | +register unsigned int T1 asm("s1"); | ||
| 52 | +register unsigned int A0 asm("s2"); | ||
| 45 | register struct CPUX86State *env asm("s3"); | 53 | register struct CPUX86State *env asm("s3"); |
| 46 | -#define FORCE_RET() asm volatile ("jr $31"); | ||
| 47 | #endif | 54 | #endif |
| 48 | #ifdef __sparc__ | 55 | #ifdef __sparc__ |
| 49 | -register int T0 asm("l0"); | ||
| 50 | -register int T1 asm("l1"); | ||
| 51 | -register int A0 asm("l2"); | 56 | +register unsigned int T0 asm("l0"); |
| 57 | +register unsigned int T1 asm("l1"); | ||
| 58 | +register unsigned int A0 asm("l2"); | ||
| 52 | register struct CPUX86State *env asm("l3"); | 59 | register struct CPUX86State *env asm("l3"); |
| 53 | -#define FORCE_RET() asm volatile ("retl ; nop"); | ||
| 54 | #endif | 60 | #endif |
| 55 | 61 | ||
| 62 | +/* force GCC to generate only one epilog at the end of the function */ | ||
| 63 | +#define FORCE_RET() asm volatile (""); | ||
| 64 | + | ||
| 56 | #ifndef OPPROTO | 65 | #ifndef OPPROTO |
| 57 | #define OPPROTO | 66 | #define OPPROTO |
| 58 | #endif | 67 | #endif |
| @@ -267,20 +276,6 @@ void OPPROTO op_orl_T0_T1_cc(void) | @@ -267,20 +276,6 @@ void OPPROTO op_orl_T0_T1_cc(void) | ||
| 267 | CC_DST = T0; | 276 | CC_DST = T0; |
| 268 | } | 277 | } |
| 269 | 278 | ||
| 270 | -void OPPROTO op_adcl_T0_T1_cc(void) | ||
| 271 | -{ | ||
| 272 | - CC_SRC = T0; | ||
| 273 | - T0 = T0 + T1 + cc_table[CC_OP].compute_c(); | ||
| 274 | - CC_DST = T0; | ||
| 275 | -} | ||
| 276 | - | ||
| 277 | -void OPPROTO op_sbbl_T0_T1_cc(void) | ||
| 278 | -{ | ||
| 279 | - CC_SRC = T0; | ||
| 280 | - T0 = T0 - T1 - cc_table[CC_OP].compute_c(); | ||
| 281 | - CC_DST = T0; | ||
| 282 | -} | ||
| 283 | - | ||
| 284 | void OPPROTO op_andl_T0_T1_cc(void) | 279 | void OPPROTO op_andl_T0_T1_cc(void) |
| 285 | { | 280 | { |
| 286 | T0 &= T1; | 281 | T0 &= T1; |
| @@ -320,12 +315,14 @@ void OPPROTO op_negl_T0_cc(void) | @@ -320,12 +315,14 @@ void OPPROTO op_negl_T0_cc(void) | ||
| 320 | 315 | ||
| 321 | void OPPROTO op_incl_T0_cc(void) | 316 | void OPPROTO op_incl_T0_cc(void) |
| 322 | { | 317 | { |
| 318 | + CC_SRC = cc_table[CC_OP].compute_c(); | ||
| 323 | T0++; | 319 | T0++; |
| 324 | CC_DST = T0; | 320 | CC_DST = T0; |
| 325 | } | 321 | } |
| 326 | 322 | ||
| 327 | void OPPROTO op_decl_T0_cc(void) | 323 | void OPPROTO op_decl_T0_cc(void) |
| 328 | { | 324 | { |
| 325 | + CC_SRC = cc_table[CC_OP].compute_c(); | ||
| 329 | T0--; | 326 | T0--; |
| 330 | CC_DST = T0; | 327 | CC_DST = T0; |
| 331 | } | 328 | } |
| @@ -335,6 +332,11 @@ void OPPROTO op_testl_T0_T1_cc(void) | @@ -335,6 +332,11 @@ void OPPROTO op_testl_T0_T1_cc(void) | ||
| 335 | CC_DST = T0 & T1; | 332 | CC_DST = T0 & T1; |
| 336 | } | 333 | } |
| 337 | 334 | ||
| 335 | +void OPPROTO op_bswapl_T0(void) | ||
| 336 | +{ | ||
| 337 | + T0 = bswap32(T0); | ||
| 338 | +} | ||
| 339 | + | ||
| 338 | /* multiply/divide */ | 340 | /* multiply/divide */ |
| 339 | void OPPROTO op_mulb_AL_T0(void) | 341 | void OPPROTO op_mulb_AL_T0(void) |
| 340 | { | 342 | { |
| @@ -399,7 +401,7 @@ void OPPROTO op_imulw_T0_T1(void) | @@ -399,7 +401,7 @@ void OPPROTO op_imulw_T0_T1(void) | ||
| 399 | void OPPROTO op_imull_T0_T1(void) | 401 | void OPPROTO op_imull_T0_T1(void) |
| 400 | { | 402 | { |
| 401 | int64_t res; | 403 | int64_t res; |
| 402 | - res = (int64_t)((int32_t)EAX) * (int64_t)((int32_t)T1); | 404 | + res = (int64_t)((int32_t)T0) * (int64_t)((int32_t)T1); |
| 403 | T0 = res; | 405 | T0 = res; |
| 404 | CC_SRC = (res != (int32_t)res); | 406 | CC_SRC = (res != (int32_t)res); |
| 405 | } | 407 | } |
| @@ -468,10 +470,10 @@ void OPPROTO op_divl_EAX_T0(void) | @@ -468,10 +470,10 @@ void OPPROTO op_divl_EAX_T0(void) | ||
| 468 | void OPPROTO op_idivl_EAX_T0(void) | 470 | void OPPROTO op_idivl_EAX_T0(void) |
| 469 | { | 471 | { |
| 470 | int den, q, r; | 472 | int den, q, r; |
| 471 | - int16_t num; | 473 | + int64_t num; |
| 472 | 474 | ||
| 473 | num = EAX | ((uint64_t)EDX << 32); | 475 | num = EAX | ((uint64_t)EDX << 32); |
| 474 | - den = (int16_t)T0; | 476 | + den = T0; |
| 475 | q = (num / den); | 477 | q = (num / den); |
| 476 | r = (num % den); | 478 | r = (num % den); |
| 477 | EAX = q; | 479 | EAX = q; |
| @@ -495,6 +497,16 @@ void OPPROTO op_movl_A0_im(void) | @@ -495,6 +497,16 @@ void OPPROTO op_movl_A0_im(void) | ||
| 495 | A0 = PARAM1; | 497 | A0 = PARAM1; |
| 496 | } | 498 | } |
| 497 | 499 | ||
| 500 | +void OPPROTO op_addl_A0_im(void) | ||
| 501 | +{ | ||
| 502 | + A0 += PARAM1; | ||
| 503 | +} | ||
| 504 | + | ||
| 505 | +void OPPROTO op_andl_A0_ffff(void) | ||
| 506 | +{ | ||
| 507 | + A0 = A0 & 0xffff; | ||
| 508 | +} | ||
| 509 | + | ||
| 498 | /* memory access */ | 510 | /* memory access */ |
| 499 | 511 | ||
| 500 | void OPPROTO op_ldub_T0_A0(void) | 512 | void OPPROTO op_ldub_T0_A0(void) |
| @@ -562,7 +574,17 @@ void OPPROTO op_stl_T0_A0(void) | @@ -562,7 +574,17 @@ void OPPROTO op_stl_T0_A0(void) | ||
| 562 | stl((uint8_t *)A0, T0); | 574 | stl((uint8_t *)A0, T0); |
| 563 | } | 575 | } |
| 564 | 576 | ||
| 565 | -/* jumps */ | 577 | +/* used for bit operations */ |
| 578 | + | ||
| 579 | +void OPPROTO op_add_bitw_A0_T1(void) | ||
| 580 | +{ | ||
| 581 | + A0 += ((int32_t)T1 >> 4) << 1; | ||
| 582 | +} | ||
| 583 | + | ||
| 584 | +void OPPROTO op_add_bitl_A0_T1(void) | ||
| 585 | +{ | ||
| 586 | + A0 += ((int32_t)T1 >> 5) << 2; | ||
| 587 | +} | ||
| 566 | 588 | ||
| 567 | /* indirect jump */ | 589 | /* indirect jump */ |
| 568 | 590 | ||
| @@ -938,25 +960,37 @@ CCTable cc_table[CC_OP_NB] = { | @@ -938,25 +960,37 @@ CCTable cc_table[CC_OP_NB] = { | ||
| 938 | [CC_OP_ADDW] = { compute_all_addw, compute_c_addw }, | 960 | [CC_OP_ADDW] = { compute_all_addw, compute_c_addw }, |
| 939 | [CC_OP_ADDL] = { compute_all_addl, compute_c_addl }, | 961 | [CC_OP_ADDL] = { compute_all_addl, compute_c_addl }, |
| 940 | 962 | ||
| 963 | + [CC_OP_ADCB] = { compute_all_adcb, compute_c_adcb }, | ||
| 964 | + [CC_OP_ADCW] = { compute_all_adcw, compute_c_adcw }, | ||
| 965 | + [CC_OP_ADCL] = { compute_all_adcl, compute_c_adcl }, | ||
| 966 | + | ||
| 941 | [CC_OP_SUBB] = { compute_all_subb, compute_c_subb }, | 967 | [CC_OP_SUBB] = { compute_all_subb, compute_c_subb }, |
| 942 | [CC_OP_SUBW] = { compute_all_subw, compute_c_subw }, | 968 | [CC_OP_SUBW] = { compute_all_subw, compute_c_subw }, |
| 943 | [CC_OP_SUBL] = { compute_all_subl, compute_c_subl }, | 969 | [CC_OP_SUBL] = { compute_all_subl, compute_c_subl }, |
| 944 | 970 | ||
| 971 | + [CC_OP_SBBB] = { compute_all_sbbb, compute_c_sbbb }, | ||
| 972 | + [CC_OP_SBBW] = { compute_all_sbbw, compute_c_sbbw }, | ||
| 973 | + [CC_OP_SBBL] = { compute_all_sbbl, compute_c_sbbl }, | ||
| 974 | + | ||
| 945 | [CC_OP_LOGICB] = { compute_all_logicb, compute_c_logicb }, | 975 | [CC_OP_LOGICB] = { compute_all_logicb, compute_c_logicb }, |
| 946 | [CC_OP_LOGICW] = { compute_all_logicw, compute_c_logicw }, | 976 | [CC_OP_LOGICW] = { compute_all_logicw, compute_c_logicw }, |
| 947 | [CC_OP_LOGICL] = { compute_all_logicl, compute_c_logicl }, | 977 | [CC_OP_LOGICL] = { compute_all_logicl, compute_c_logicl }, |
| 948 | 978 | ||
| 949 | - [CC_OP_INCB] = { compute_all_incb, compute_c_incb }, | ||
| 950 | - [CC_OP_INCW] = { compute_all_incw, compute_c_incw }, | 979 | + [CC_OP_INCB] = { compute_all_incb, compute_c_incl }, |
| 980 | + [CC_OP_INCW] = { compute_all_incw, compute_c_incl }, | ||
| 951 | [CC_OP_INCL] = { compute_all_incl, compute_c_incl }, | 981 | [CC_OP_INCL] = { compute_all_incl, compute_c_incl }, |
| 952 | 982 | ||
| 953 | - [CC_OP_DECB] = { compute_all_decb, compute_c_incb }, | ||
| 954 | - [CC_OP_DECW] = { compute_all_decw, compute_c_incw }, | 983 | + [CC_OP_DECB] = { compute_all_decb, compute_c_incl }, |
| 984 | + [CC_OP_DECW] = { compute_all_decw, compute_c_incl }, | ||
| 955 | [CC_OP_DECL] = { compute_all_decl, compute_c_incl }, | 985 | [CC_OP_DECL] = { compute_all_decl, compute_c_incl }, |
| 956 | 986 | ||
| 957 | - [CC_OP_SHLB] = { compute_all_shlb, compute_c_shlb }, | ||
| 958 | - [CC_OP_SHLW] = { compute_all_shlw, compute_c_shlw }, | 987 | + [CC_OP_SHLB] = { compute_all_shlb, compute_c_shll }, |
| 988 | + [CC_OP_SHLW] = { compute_all_shlw, compute_c_shll }, | ||
| 959 | [CC_OP_SHLL] = { compute_all_shll, compute_c_shll }, | 989 | [CC_OP_SHLL] = { compute_all_shll, compute_c_shll }, |
| 990 | + | ||
| 991 | + [CC_OP_SARB] = { compute_all_sarb, compute_c_shll }, | ||
| 992 | + [CC_OP_SARW] = { compute_all_sarw, compute_c_shll }, | ||
| 993 | + [CC_OP_SARL] = { compute_all_sarl, compute_c_shll }, | ||
| 960 | }; | 994 | }; |
| 961 | 995 | ||
| 962 | /* floating point support */ | 996 | /* floating point support */ |
| @@ -1640,6 +1674,41 @@ void OPPROTO op_fcos(void) | @@ -1640,6 +1674,41 @@ void OPPROTO op_fcos(void) | ||
| 1640 | helper_fcos(); | 1674 | helper_fcos(); |
| 1641 | } | 1675 | } |
| 1642 | 1676 | ||
| 1677 | +void OPPROTO op_fnstsw_A0(void) | ||
| 1678 | +{ | ||
| 1679 | + int fpus; | ||
| 1680 | + fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11; | ||
| 1681 | + stw((void *)A0, fpus); | ||
| 1682 | +} | ||
| 1683 | + | ||
| 1684 | +void OPPROTO op_fnstcw_A0(void) | ||
| 1685 | +{ | ||
| 1686 | + stw((void *)A0, env->fpuc); | ||
| 1687 | +} | ||
| 1688 | + | ||
| 1689 | +void OPPROTO op_fldcw_A0(void) | ||
| 1690 | +{ | ||
| 1691 | + int rnd_type; | ||
| 1692 | + env->fpuc = lduw((void *)A0); | ||
| 1693 | + /* set rounding mode */ | ||
| 1694 | + switch(env->fpuc & RC_MASK) { | ||
| 1695 | + default: | ||
| 1696 | + case RC_NEAR: | ||
| 1697 | + rnd_type = FE_TONEAREST; | ||
| 1698 | + break; | ||
| 1699 | + case RC_DOWN: | ||
| 1700 | + rnd_type = FE_DOWNWARD; | ||
| 1701 | + break; | ||
| 1702 | + case RC_UP: | ||
| 1703 | + rnd_type = FE_UPWARD; | ||
| 1704 | + break; | ||
| 1705 | + case RC_CHOP: | ||
| 1706 | + rnd_type = FE_TOWARDZERO; | ||
| 1707 | + break; | ||
| 1708 | + } | ||
| 1709 | + fesetround(rnd_type); | ||
| 1710 | +} | ||
| 1711 | + | ||
| 1643 | /* main execution loop */ | 1712 | /* main execution loop */ |
| 1644 | uint8_t code_gen_buffer[65536]; | 1713 | uint8_t code_gen_buffer[65536]; |
| 1645 | 1714 | ||
| @@ -1651,9 +1720,15 @@ static const char *cc_op_str[] = { | @@ -1651,9 +1720,15 @@ static const char *cc_op_str[] = { | ||
| 1651 | "ADDB", | 1720 | "ADDB", |
| 1652 | "ADDW", | 1721 | "ADDW", |
| 1653 | "ADDL", | 1722 | "ADDL", |
| 1723 | + "ADCB", | ||
| 1724 | + "ADCW", | ||
| 1725 | + "ADCL", | ||
| 1654 | "SUBB", | 1726 | "SUBB", |
| 1655 | "SUBW", | 1727 | "SUBW", |
| 1656 | "SUBL", | 1728 | "SUBL", |
| 1729 | + "SBBB", | ||
| 1730 | + "SBBW", | ||
| 1731 | + "SBBL", | ||
| 1657 | "LOGICB", | 1732 | "LOGICB", |
| 1658 | "LOGICW", | 1733 | "LOGICW", |
| 1659 | "LOGICL", | 1734 | "LOGICL", |
| @@ -1666,6 +1741,9 @@ static const char *cc_op_str[] = { | @@ -1666,6 +1741,9 @@ static const char *cc_op_str[] = { | ||
| 1666 | "SHLB", | 1741 | "SHLB", |
| 1667 | "SHLW", | 1742 | "SHLW", |
| 1668 | "SHLL", | 1743 | "SHLL", |
| 1744 | + "SARB", | ||
| 1745 | + "SARW", | ||
| 1746 | + "SARL", | ||
| 1669 | }; | 1747 | }; |
| 1670 | #endif | 1748 | #endif |
| 1671 | 1749 | ||
| @@ -1688,13 +1766,24 @@ int cpu_x86_exec(CPUX86State *env1) | @@ -1688,13 +1766,24 @@ int cpu_x86_exec(CPUX86State *env1) | ||
| 1688 | for(;;) { | 1766 | for(;;) { |
| 1689 | #ifdef DEBUG_EXEC | 1767 | #ifdef DEBUG_EXEC |
| 1690 | if (loglevel) { | 1768 | if (loglevel) { |
| 1769 | + int eflags; | ||
| 1770 | + eflags = cc_table[CC_OP].compute_all(); | ||
| 1771 | + eflags |= (DF & DIRECTION_FLAG); | ||
| 1691 | fprintf(logfile, | 1772 | fprintf(logfile, |
| 1692 | "EAX=%08x EBX=%08X ECX=%08x EDX=%08x\n" | 1773 | "EAX=%08x EBX=%08X ECX=%08x EDX=%08x\n" |
| 1693 | - "ESI=%08x ESI=%08X EBP=%08x ESP=%08x\n" | ||
| 1694 | - "CCS=%08x CCD=%08x CCOP=%s\n", | 1774 | + "ESI=%08x EDI=%08X EBP=%08x ESP=%08x\n" |
| 1775 | + "CCS=%08x CCD=%08x CCO=%-8s EFL=%c%c%c%c%c%c%c\n", | ||
| 1695 | env->regs[R_EAX], env->regs[R_EBX], env->regs[R_ECX], env->regs[R_EDX], | 1776 | env->regs[R_EAX], env->regs[R_EBX], env->regs[R_ECX], env->regs[R_EDX], |
| 1696 | env->regs[R_ESI], env->regs[R_EDI], env->regs[R_EBP], env->regs[R_ESP], | 1777 | env->regs[R_ESI], env->regs[R_EDI], env->regs[R_EBP], env->regs[R_ESP], |
| 1697 | - env->cc_src, env->cc_dst, cc_op_str[env->cc_op]); | 1778 | + env->cc_src, env->cc_dst, cc_op_str[env->cc_op], |
| 1779 | + eflags & DIRECTION_FLAG ? 'D' : '-', | ||
| 1780 | + eflags & CC_O ? 'O' : '-', | ||
| 1781 | + eflags & CC_S ? 'S' : '-', | ||
| 1782 | + eflags & CC_Z ? 'Z' : '-', | ||
| 1783 | + eflags & CC_A ? 'A' : '-', | ||
| 1784 | + eflags & CC_P ? 'P' : '-', | ||
| 1785 | + eflags & CC_C ? 'C' : '-' | ||
| 1786 | + ); | ||
| 1698 | } | 1787 | } |
| 1699 | #endif | 1788 | #endif |
| 1700 | cpu_x86_gen_code(code_gen_buffer, &code_gen_size, (uint8_t *)env->pc); | 1789 | cpu_x86_gen_code(code_gen_buffer, &code_gen_size, (uint8_t *)env->pc); |
ops_template.h
| @@ -33,7 +33,7 @@ static int glue(compute_all_add, SUFFIX)(void) | @@ -33,7 +33,7 @@ static int glue(compute_all_add, SUFFIX)(void) | ||
| 33 | cf = (DATA_TYPE)CC_DST < (DATA_TYPE)src1; | 33 | cf = (DATA_TYPE)CC_DST < (DATA_TYPE)src1; |
| 34 | pf = parity_table[(uint8_t)CC_DST]; | 34 | pf = parity_table[(uint8_t)CC_DST]; |
| 35 | af = (CC_DST ^ src1 ^ src2) & 0x10; | 35 | af = (CC_DST ^ src1 ^ src2) & 0x10; |
| 36 | - zf = ((DATA_TYPE)CC_DST != 0) << 6; | 36 | + zf = ((DATA_TYPE)CC_DST == 0) << 6; |
| 37 | sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80; | 37 | sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80; |
| 38 | of = lshift((src1 ^ src2 ^ -1) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O; | 38 | of = lshift((src1 ^ src2 ^ -1) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O; |
| 39 | return cf | pf | af | zf | sf | of; | 39 | return cf | pf | af | zf | sf | of; |
| @@ -47,6 +47,29 @@ static int glue(compute_c_add, SUFFIX)(void) | @@ -47,6 +47,29 @@ static int glue(compute_c_add, SUFFIX)(void) | ||
| 47 | return cf; | 47 | return cf; |
| 48 | } | 48 | } |
| 49 | 49 | ||
| 50 | +static int glue(compute_all_adc, SUFFIX)(void) | ||
| 51 | +{ | ||
| 52 | + int cf, pf, af, zf, sf, of; | ||
| 53 | + int src1, src2; | ||
| 54 | + src1 = CC_SRC; | ||
| 55 | + src2 = CC_DST - CC_SRC - 1; | ||
| 56 | + cf = (DATA_TYPE)CC_DST <= (DATA_TYPE)src1; | ||
| 57 | + pf = parity_table[(uint8_t)CC_DST]; | ||
| 58 | + af = (CC_DST ^ src1 ^ src2) & 0x10; | ||
| 59 | + zf = ((DATA_TYPE)CC_DST == 0) << 6; | ||
| 60 | + sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80; | ||
| 61 | + of = lshift((src1 ^ src2 ^ -1) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O; | ||
| 62 | + return cf | pf | af | zf | sf | of; | ||
| 63 | +} | ||
| 64 | + | ||
| 65 | +static int glue(compute_c_adc, SUFFIX)(void) | ||
| 66 | +{ | ||
| 67 | + int src1, cf; | ||
| 68 | + src1 = CC_SRC; | ||
| 69 | + cf = (DATA_TYPE)CC_DST <= (DATA_TYPE)src1; | ||
| 70 | + return cf; | ||
| 71 | +} | ||
| 72 | + | ||
| 50 | static int glue(compute_all_sub, SUFFIX)(void) | 73 | static int glue(compute_all_sub, SUFFIX)(void) |
| 51 | { | 74 | { |
| 52 | int cf, pf, af, zf, sf, of; | 75 | int cf, pf, af, zf, sf, of; |
| @@ -56,9 +79,9 @@ static int glue(compute_all_sub, SUFFIX)(void) | @@ -56,9 +79,9 @@ static int glue(compute_all_sub, SUFFIX)(void) | ||
| 56 | cf = (DATA_TYPE)src1 < (DATA_TYPE)src2; | 79 | cf = (DATA_TYPE)src1 < (DATA_TYPE)src2; |
| 57 | pf = parity_table[(uint8_t)CC_DST]; | 80 | pf = parity_table[(uint8_t)CC_DST]; |
| 58 | af = (CC_DST ^ src1 ^ src2) & 0x10; | 81 | af = (CC_DST ^ src1 ^ src2) & 0x10; |
| 59 | - zf = ((DATA_TYPE)CC_DST != 0) << 6; | 82 | + zf = ((DATA_TYPE)CC_DST == 0) << 6; |
| 60 | sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80; | 83 | sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80; |
| 61 | - of = lshift((src1 ^ src2 ^ -1) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O; | 84 | + of = lshift((src1 ^ src2) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O; |
| 62 | return cf | pf | af | zf | sf | of; | 85 | return cf | pf | af | zf | sf | of; |
| 63 | } | 86 | } |
| 64 | 87 | ||
| @@ -67,7 +90,31 @@ static int glue(compute_c_sub, SUFFIX)(void) | @@ -67,7 +90,31 @@ static int glue(compute_c_sub, SUFFIX)(void) | ||
| 67 | int src1, src2, cf; | 90 | int src1, src2, cf; |
| 68 | src1 = CC_SRC; | 91 | src1 = CC_SRC; |
| 69 | src2 = CC_SRC - CC_DST; | 92 | src2 = CC_SRC - CC_DST; |
| 70 | - cf = (DATA_TYPE)src1 < (DATA_TYPE)src1; | 93 | + cf = (DATA_TYPE)src1 < (DATA_TYPE)src2; |
| 94 | + return cf; | ||
| 95 | +} | ||
| 96 | + | ||
| 97 | +static int glue(compute_all_sbb, SUFFIX)(void) | ||
| 98 | +{ | ||
| 99 | + int cf, pf, af, zf, sf, of; | ||
| 100 | + int src1, src2; | ||
| 101 | + src1 = CC_SRC; | ||
| 102 | + src2 = CC_SRC - CC_DST - 1; | ||
| 103 | + cf = (DATA_TYPE)src1 <= (DATA_TYPE)src2; | ||
| 104 | + pf = parity_table[(uint8_t)CC_DST]; | ||
| 105 | + af = (CC_DST ^ src1 ^ src2) & 0x10; | ||
| 106 | + zf = ((DATA_TYPE)CC_DST == 0) << 6; | ||
| 107 | + sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80; | ||
| 108 | + of = lshift((src1 ^ src2) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O; | ||
| 109 | + return cf | pf | af | zf | sf | of; | ||
| 110 | +} | ||
| 111 | + | ||
| 112 | +static int glue(compute_c_sbb, SUFFIX)(void) | ||
| 113 | +{ | ||
| 114 | + int src1, src2, cf; | ||
| 115 | + src1 = CC_SRC; | ||
| 116 | + src2 = CC_SRC - CC_DST - 1; | ||
| 117 | + cf = (DATA_TYPE)src1 <= (DATA_TYPE)src2; | ||
| 71 | return cf; | 118 | return cf; |
| 72 | } | 119 | } |
| 73 | 120 | ||
| @@ -77,7 +124,7 @@ static int glue(compute_all_logic, SUFFIX)(void) | @@ -77,7 +124,7 @@ static int glue(compute_all_logic, SUFFIX)(void) | ||
| 77 | cf = 0; | 124 | cf = 0; |
| 78 | pf = parity_table[(uint8_t)CC_DST]; | 125 | pf = parity_table[(uint8_t)CC_DST]; |
| 79 | af = 0; | 126 | af = 0; |
| 80 | - zf = ((DATA_TYPE)CC_DST != 0) << 6; | 127 | + zf = ((DATA_TYPE)CC_DST == 0) << 6; |
| 81 | sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80; | 128 | sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80; |
| 82 | of = 0; | 129 | of = 0; |
| 83 | return cf | pf | af | zf | sf | of; | 130 | return cf | pf | af | zf | sf | of; |
| @@ -97,16 +144,18 @@ static int glue(compute_all_inc, SUFFIX)(void) | @@ -97,16 +144,18 @@ static int glue(compute_all_inc, SUFFIX)(void) | ||
| 97 | cf = CC_SRC; | 144 | cf = CC_SRC; |
| 98 | pf = parity_table[(uint8_t)CC_DST]; | 145 | pf = parity_table[(uint8_t)CC_DST]; |
| 99 | af = (CC_DST ^ src1 ^ src2) & 0x10; | 146 | af = (CC_DST ^ src1 ^ src2) & 0x10; |
| 100 | - zf = ((DATA_TYPE)CC_DST != 0) << 6; | 147 | + zf = ((DATA_TYPE)CC_DST == 0) << 6; |
| 101 | sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80; | 148 | sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80; |
| 102 | - of = lshift((src1 ^ src2 ^ -1) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O; | 149 | + of = ((CC_DST & DATA_MASK) == SIGN_MASK) << 11; |
| 103 | return cf | pf | af | zf | sf | of; | 150 | return cf | pf | af | zf | sf | of; |
| 104 | } | 151 | } |
| 105 | 152 | ||
| 153 | +#if DATA_BITS == 32 | ||
| 106 | static int glue(compute_c_inc, SUFFIX)(void) | 154 | static int glue(compute_c_inc, SUFFIX)(void) |
| 107 | { | 155 | { |
| 108 | return CC_SRC; | 156 | return CC_SRC; |
| 109 | } | 157 | } |
| 158 | +#endif | ||
| 110 | 159 | ||
| 111 | static int glue(compute_all_dec, SUFFIX)(void) | 160 | static int glue(compute_all_dec, SUFFIX)(void) |
| 112 | { | 161 | { |
| @@ -117,9 +166,9 @@ static int glue(compute_all_dec, SUFFIX)(void) | @@ -117,9 +166,9 @@ static int glue(compute_all_dec, SUFFIX)(void) | ||
| 117 | cf = CC_SRC; | 166 | cf = CC_SRC; |
| 118 | pf = parity_table[(uint8_t)CC_DST]; | 167 | pf = parity_table[(uint8_t)CC_DST]; |
| 119 | af = (CC_DST ^ src1 ^ src2) & 0x10; | 168 | af = (CC_DST ^ src1 ^ src2) & 0x10; |
| 120 | - zf = ((DATA_TYPE)CC_DST != 0) << 6; | 169 | + zf = ((DATA_TYPE)CC_DST == 0) << 6; |
| 121 | sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80; | 170 | sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80; |
| 122 | - of = lshift((src1 ^ src2 ^ -1) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O; | 171 | + of = ((CC_DST & DATA_MASK) == ((uint32_t)SIGN_MASK - 1)) << 11; |
| 123 | return cf | pf | af | zf | sf | of; | 172 | return cf | pf | af | zf | sf | of; |
| 124 | } | 173 | } |
| 125 | 174 | ||
| @@ -129,16 +178,30 @@ static int glue(compute_all_shl, SUFFIX)(void) | @@ -129,16 +178,30 @@ static int glue(compute_all_shl, SUFFIX)(void) | ||
| 129 | cf = CC_SRC & 1; | 178 | cf = CC_SRC & 1; |
| 130 | pf = parity_table[(uint8_t)CC_DST]; | 179 | pf = parity_table[(uint8_t)CC_DST]; |
| 131 | af = 0; /* undefined */ | 180 | af = 0; /* undefined */ |
| 132 | - zf = ((DATA_TYPE)CC_DST != 0) << 6; | 181 | + zf = ((DATA_TYPE)CC_DST == 0) << 6; |
| 133 | sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80; | 182 | sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80; |
| 134 | - of = sf << 4; /* only meaniful for shr with count == 1 */ | 183 | + of = lshift(CC_SRC, 12 - DATA_BITS) & CC_O; /* only meaniful for shr with count == 1 */ |
| 135 | return cf | pf | af | zf | sf | of; | 184 | return cf | pf | af | zf | sf | of; |
| 136 | } | 185 | } |
| 137 | 186 | ||
| 187 | +#if DATA_BITS == 32 | ||
| 138 | static int glue(compute_c_shl, SUFFIX)(void) | 188 | static int glue(compute_c_shl, SUFFIX)(void) |
| 139 | { | 189 | { |
| 140 | return CC_SRC & 1; | 190 | return CC_SRC & 1; |
| 141 | } | 191 | } |
| 192 | +#endif | ||
| 193 | + | ||
| 194 | +static int glue(compute_all_sar, SUFFIX)(void) | ||
| 195 | +{ | ||
| 196 | + int cf, pf, af, zf, sf, of; | ||
| 197 | + cf = CC_SRC & 1; | ||
| 198 | + pf = parity_table[(uint8_t)CC_DST]; | ||
| 199 | + af = 0; /* undefined */ | ||
| 200 | + zf = ((DATA_TYPE)CC_DST == 0) << 6; | ||
| 201 | + sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80; | ||
| 202 | + of = 0; /* only meaniful for shr with count == 1 */ | ||
| 203 | + return cf | pf | af | zf | sf | of; | ||
| 204 | +} | ||
| 142 | 205 | ||
| 143 | /* various optimized jumps cases */ | 206 | /* various optimized jumps cases */ |
| 144 | 207 | ||
| @@ -157,7 +220,7 @@ void OPPROTO glue(op_jb_sub, SUFFIX)(void) | @@ -157,7 +220,7 @@ void OPPROTO glue(op_jb_sub, SUFFIX)(void) | ||
| 157 | 220 | ||
| 158 | void OPPROTO glue(op_jz_sub, SUFFIX)(void) | 221 | void OPPROTO glue(op_jz_sub, SUFFIX)(void) |
| 159 | { | 222 | { |
| 160 | - if ((DATA_TYPE)CC_DST != 0) | 223 | + if ((DATA_TYPE)CC_DST == 0) |
| 161 | PC = PARAM1; | 224 | PC = PARAM1; |
| 162 | else | 225 | else |
| 163 | PC = PARAM2; | 226 | PC = PARAM2; |
| @@ -225,7 +288,7 @@ void OPPROTO glue(op_setb_T0_sub, SUFFIX)(void) | @@ -225,7 +288,7 @@ void OPPROTO glue(op_setb_T0_sub, SUFFIX)(void) | ||
| 225 | 288 | ||
| 226 | void OPPROTO glue(op_setz_T0_sub, SUFFIX)(void) | 289 | void OPPROTO glue(op_setz_T0_sub, SUFFIX)(void) |
| 227 | { | 290 | { |
| 228 | - T0 = ((DATA_TYPE)CC_DST != 0); | 291 | + T0 = ((DATA_TYPE)CC_DST == 0); |
| 229 | } | 292 | } |
| 230 | 293 | ||
| 231 | void OPPROTO glue(op_setbe_T0_sub, SUFFIX)(void) | 294 | void OPPROTO glue(op_setbe_T0_sub, SUFFIX)(void) |
| @@ -275,6 +338,7 @@ void OPPROTO glue(glue(op_rol, SUFFIX), _T0_T1_cc)(void) | @@ -275,6 +338,7 @@ void OPPROTO glue(glue(op_rol, SUFFIX), _T0_T1_cc)(void) | ||
| 275 | (T0 & CC_C); | 338 | (T0 & CC_C); |
| 276 | CC_OP = CC_OP_EFLAGS; | 339 | CC_OP = CC_OP_EFLAGS; |
| 277 | } | 340 | } |
| 341 | + FORCE_RET(); | ||
| 278 | } | 342 | } |
| 279 | 343 | ||
| 280 | void OPPROTO glue(glue(op_ror, SUFFIX), _T0_T1_cc)(void) | 344 | void OPPROTO glue(glue(op_ror, SUFFIX), _T0_T1_cc)(void) |
| @@ -290,6 +354,7 @@ void OPPROTO glue(glue(op_ror, SUFFIX), _T0_T1_cc)(void) | @@ -290,6 +354,7 @@ void OPPROTO glue(glue(op_ror, SUFFIX), _T0_T1_cc)(void) | ||
| 290 | ((T0 >> (DATA_BITS - 1)) & CC_C); | 354 | ((T0 >> (DATA_BITS - 1)) & CC_C); |
| 291 | CC_OP = CC_OP_EFLAGS; | 355 | CC_OP = CC_OP_EFLAGS; |
| 292 | } | 356 | } |
| 357 | + FORCE_RET(); | ||
| 293 | } | 358 | } |
| 294 | 359 | ||
| 295 | void OPPROTO glue(glue(op_rcl, SUFFIX), _T0_T1_cc)(void) | 360 | void OPPROTO glue(glue(op_rcl, SUFFIX), _T0_T1_cc)(void) |
| @@ -305,6 +370,7 @@ void OPPROTO glue(glue(op_rcl, SUFFIX), _T0_T1_cc)(void) | @@ -305,6 +370,7 @@ void OPPROTO glue(glue(op_rcl, SUFFIX), _T0_T1_cc)(void) | ||
| 305 | #endif | 370 | #endif |
| 306 | if (count) { | 371 | if (count) { |
| 307 | eflags = cc_table[CC_OP].compute_all(); | 372 | eflags = cc_table[CC_OP].compute_all(); |
| 373 | + T0 &= DATA_MASK; | ||
| 308 | src = T0; | 374 | src = T0; |
| 309 | res = (T0 << count) | ((eflags & CC_C) << (count - 1)); | 375 | res = (T0 << count) | ((eflags & CC_C) << (count - 1)); |
| 310 | if (count > 1) | 376 | if (count > 1) |
| @@ -315,6 +381,7 @@ void OPPROTO glue(glue(op_rcl, SUFFIX), _T0_T1_cc)(void) | @@ -315,6 +381,7 @@ void OPPROTO glue(glue(op_rcl, SUFFIX), _T0_T1_cc)(void) | ||
| 315 | ((src >> (DATA_BITS - count)) & CC_C); | 381 | ((src >> (DATA_BITS - count)) & CC_C); |
| 316 | CC_OP = CC_OP_EFLAGS; | 382 | CC_OP = CC_OP_EFLAGS; |
| 317 | } | 383 | } |
| 384 | + FORCE_RET(); | ||
| 318 | } | 385 | } |
| 319 | 386 | ||
| 320 | void OPPROTO glue(glue(op_rcr, SUFFIX), _T0_T1_cc)(void) | 387 | void OPPROTO glue(glue(op_rcr, SUFFIX), _T0_T1_cc)(void) |
| @@ -330,6 +397,7 @@ void OPPROTO glue(glue(op_rcr, SUFFIX), _T0_T1_cc)(void) | @@ -330,6 +397,7 @@ void OPPROTO glue(glue(op_rcr, SUFFIX), _T0_T1_cc)(void) | ||
| 330 | #endif | 397 | #endif |
| 331 | if (count) { | 398 | if (count) { |
| 332 | eflags = cc_table[CC_OP].compute_all(); | 399 | eflags = cc_table[CC_OP].compute_all(); |
| 400 | + T0 &= DATA_MASK; | ||
| 333 | src = T0; | 401 | src = T0; |
| 334 | res = (T0 >> count) | ((eflags & CC_C) << (DATA_BITS - count)); | 402 | res = (T0 >> count) | ((eflags & CC_C) << (DATA_BITS - count)); |
| 335 | if (count > 1) | 403 | if (count > 1) |
| @@ -340,6 +408,7 @@ void OPPROTO glue(glue(op_rcr, SUFFIX), _T0_T1_cc)(void) | @@ -340,6 +408,7 @@ void OPPROTO glue(glue(op_rcr, SUFFIX), _T0_T1_cc)(void) | ||
| 340 | ((src >> (count - 1)) & CC_C); | 408 | ((src >> (count - 1)) & CC_C); |
| 341 | CC_OP = CC_OP_EFLAGS; | 409 | CC_OP = CC_OP_EFLAGS; |
| 342 | } | 410 | } |
| 411 | + FORCE_RET(); | ||
| 343 | } | 412 | } |
| 344 | 413 | ||
| 345 | void OPPROTO glue(glue(op_shl, SUFFIX), _T0_T1_cc)(void) | 414 | void OPPROTO glue(glue(op_shl, SUFFIX), _T0_T1_cc)(void) |
| @@ -352,11 +421,12 @@ void OPPROTO glue(glue(op_shl, SUFFIX), _T0_T1_cc)(void) | @@ -352,11 +421,12 @@ void OPPROTO glue(glue(op_shl, SUFFIX), _T0_T1_cc)(void) | ||
| 352 | CC_DST = T0; | 421 | CC_DST = T0; |
| 353 | CC_OP = CC_OP_ADDB + SHIFT; | 422 | CC_OP = CC_OP_ADDB + SHIFT; |
| 354 | } else if (count) { | 423 | } else if (count) { |
| 355 | - CC_SRC = T0 >> (DATA_BITS - count); | 424 | + CC_SRC = (DATA_TYPE)T0 >> (DATA_BITS - count); |
| 356 | T0 = T0 << count; | 425 | T0 = T0 << count; |
| 357 | CC_DST = T0; | 426 | CC_DST = T0; |
| 358 | CC_OP = CC_OP_SHLB + SHIFT; | 427 | CC_OP = CC_OP_SHLB + SHIFT; |
| 359 | } | 428 | } |
| 429 | + FORCE_RET(); | ||
| 360 | } | 430 | } |
| 361 | 431 | ||
| 362 | void OPPROTO glue(glue(op_shr, SUFFIX), _T0_T1_cc)(void) | 432 | void OPPROTO glue(glue(op_shr, SUFFIX), _T0_T1_cc)(void) |
| @@ -370,6 +440,7 @@ void OPPROTO glue(glue(op_shr, SUFFIX), _T0_T1_cc)(void) | @@ -370,6 +440,7 @@ void OPPROTO glue(glue(op_shr, SUFFIX), _T0_T1_cc)(void) | ||
| 370 | CC_DST = T0; | 440 | CC_DST = T0; |
| 371 | CC_OP = CC_OP_SHLB + SHIFT; | 441 | CC_OP = CC_OP_SHLB + SHIFT; |
| 372 | } | 442 | } |
| 443 | + FORCE_RET(); | ||
| 373 | } | 444 | } |
| 374 | 445 | ||
| 375 | void OPPROTO glue(glue(op_sar, SUFFIX), _T0_T1_cc)(void) | 446 | void OPPROTO glue(glue(op_sar, SUFFIX), _T0_T1_cc)(void) |
| @@ -381,10 +452,69 @@ void OPPROTO glue(glue(op_sar, SUFFIX), _T0_T1_cc)(void) | @@ -381,10 +452,69 @@ void OPPROTO glue(glue(op_sar, SUFFIX), _T0_T1_cc)(void) | ||
| 381 | CC_SRC = src >> (count - 1); | 452 | CC_SRC = src >> (count - 1); |
| 382 | T0 = src >> count; | 453 | T0 = src >> count; |
| 383 | CC_DST = T0; | 454 | CC_DST = T0; |
| 384 | - CC_OP = CC_OP_SHLB + SHIFT; | 455 | + CC_OP = CC_OP_SARB + SHIFT; |
| 385 | } | 456 | } |
| 457 | + FORCE_RET(); | ||
| 386 | } | 458 | } |
| 387 | 459 | ||
| 460 | +/* carry add/sub (we only need to set CC_OP differently) */ | ||
| 461 | + | ||
| 462 | +void OPPROTO glue(glue(op_adc, SUFFIX), _T0_T1_cc)(void) | ||
| 463 | +{ | ||
| 464 | + int cf; | ||
| 465 | + cf = cc_table[CC_OP].compute_c(); | ||
| 466 | + CC_SRC = T0; | ||
| 467 | + T0 = T0 + T1 + cf; | ||
| 468 | + CC_DST = T0; | ||
| 469 | + CC_OP = CC_OP_ADDB + SHIFT + cf * 3; | ||
| 470 | +} | ||
| 471 | + | ||
| 472 | +void OPPROTO glue(glue(op_sbb, SUFFIX), _T0_T1_cc)(void) | ||
| 473 | +{ | ||
| 474 | + int cf; | ||
| 475 | + cf = cc_table[CC_OP].compute_c(); | ||
| 476 | + CC_SRC = T0; | ||
| 477 | + T0 = T0 - T1 - cf; | ||
| 478 | + CC_DST = T0; | ||
| 479 | + CC_OP = CC_OP_SUBB + SHIFT + cf * 3; | ||
| 480 | +} | ||
| 481 | + | ||
| 482 | +/* bit operations */ | ||
| 483 | +#if DATA_BITS >= 16 | ||
| 484 | + | ||
| 485 | +void OPPROTO glue(glue(op_bt, SUFFIX), _T0_T1_cc)(void) | ||
| 486 | +{ | ||
| 487 | + int count; | ||
| 488 | + count = T1 & SHIFT_MASK; | ||
| 489 | + CC_SRC = T0 >> count; | ||
| 490 | +} | ||
| 491 | + | ||
| 492 | +void OPPROTO glue(glue(op_bts, SUFFIX), _T0_T1_cc)(void) | ||
| 493 | +{ | ||
| 494 | + int count; | ||
| 495 | + count = T1 & SHIFT_MASK; | ||
| 496 | + CC_SRC = T0 >> count; | ||
| 497 | + T0 |= (1 << count); | ||
| 498 | +} | ||
| 499 | + | ||
| 500 | +void OPPROTO glue(glue(op_btr, SUFFIX), _T0_T1_cc)(void) | ||
| 501 | +{ | ||
| 502 | + int count; | ||
| 503 | + count = T1 & SHIFT_MASK; | ||
| 504 | + CC_SRC = T0 >> count; | ||
| 505 | + T0 &= ~(1 << count); | ||
| 506 | +} | ||
| 507 | + | ||
| 508 | +void OPPROTO glue(glue(op_btc, SUFFIX), _T0_T1_cc)(void) | ||
| 509 | +{ | ||
| 510 | + int count; | ||
| 511 | + count = T1 & SHIFT_MASK; | ||
| 512 | + CC_SRC = T0 >> count; | ||
| 513 | + T0 ^= (1 << count); | ||
| 514 | +} | ||
| 515 | + | ||
| 516 | +#endif | ||
| 517 | + | ||
| 388 | /* string operations */ | 518 | /* string operations */ |
| 389 | /* XXX: maybe use lower level instructions to ease exception handling */ | 519 | /* XXX: maybe use lower level instructions to ease exception handling */ |
| 390 | 520 | ||
| @@ -464,8 +594,8 @@ void OPPROTO glue(op_scas, SUFFIX)(void) | @@ -464,8 +594,8 @@ void OPPROTO glue(op_scas, SUFFIX)(void) | ||
| 464 | { | 594 | { |
| 465 | int v; | 595 | int v; |
| 466 | 596 | ||
| 467 | - v = glue(ldu, SUFFIX)((void *)ESI); | ||
| 468 | - ESI += (DF << SHIFT); | 597 | + v = glue(ldu, SUFFIX)((void *)EDI); |
| 598 | + EDI += (DF << SHIFT); | ||
| 469 | CC_SRC = EAX; | 599 | CC_SRC = EAX; |
| 470 | CC_DST = EAX - v; | 600 | CC_DST = EAX - v; |
| 471 | } | 601 | } |
| @@ -476,20 +606,14 @@ void OPPROTO glue(op_repz_scas, SUFFIX)(void) | @@ -476,20 +606,14 @@ void OPPROTO glue(op_repz_scas, SUFFIX)(void) | ||
| 476 | 606 | ||
| 477 | if (ECX != 0) { | 607 | if (ECX != 0) { |
| 478 | /* NOTE: the flags are not modified if ECX == 0 */ | 608 | /* NOTE: the flags are not modified if ECX == 0 */ |
| 479 | -#if SHIFT == 0 | ||
| 480 | - v1 = EAX & 0xff; | ||
| 481 | -#elif SHIFT == 1 | ||
| 482 | - v1 = EAX & 0xffff; | ||
| 483 | -#else | ||
| 484 | - v1 = EAX; | ||
| 485 | -#endif | 609 | + v1 = EAX & DATA_MASK; |
| 486 | inc = (DF << SHIFT); | 610 | inc = (DF << SHIFT); |
| 487 | do { | 611 | do { |
| 488 | - v2 = glue(ldu, SUFFIX)((void *)ESI); | 612 | + v2 = glue(ldu, SUFFIX)((void *)EDI); |
| 613 | + EDI += inc; | ||
| 614 | + ECX--; | ||
| 489 | if (v1 != v2) | 615 | if (v1 != v2) |
| 490 | break; | 616 | break; |
| 491 | - ESI += inc; | ||
| 492 | - ECX--; | ||
| 493 | } while (ECX != 0); | 617 | } while (ECX != 0); |
| 494 | CC_SRC = v1; | 618 | CC_SRC = v1; |
| 495 | CC_DST = v1 - v2; | 619 | CC_DST = v1 - v2; |
| @@ -503,20 +627,14 @@ void OPPROTO glue(op_repnz_scas, SUFFIX)(void) | @@ -503,20 +627,14 @@ void OPPROTO glue(op_repnz_scas, SUFFIX)(void) | ||
| 503 | 627 | ||
| 504 | if (ECX != 0) { | 628 | if (ECX != 0) { |
| 505 | /* NOTE: the flags are not modified if ECX == 0 */ | 629 | /* NOTE: the flags are not modified if ECX == 0 */ |
| 506 | -#if SHIFT == 0 | ||
| 507 | - v1 = EAX & 0xff; | ||
| 508 | -#elif SHIFT == 1 | ||
| 509 | - v1 = EAX & 0xffff; | ||
| 510 | -#else | ||
| 511 | - v1 = EAX; | ||
| 512 | -#endif | 630 | + v1 = EAX & DATA_MASK; |
| 513 | inc = (DF << SHIFT); | 631 | inc = (DF << SHIFT); |
| 514 | do { | 632 | do { |
| 515 | - v2 = glue(ldu, SUFFIX)((void *)ESI); | 633 | + v2 = glue(ldu, SUFFIX)((void *)EDI); |
| 634 | + EDI += inc; | ||
| 635 | + ECX--; | ||
| 516 | if (v1 == v2) | 636 | if (v1 == v2) |
| 517 | break; | 637 | break; |
| 518 | - ESI += inc; | ||
| 519 | - ECX--; | ||
| 520 | } while (ECX != 0); | 638 | } while (ECX != 0); |
| 521 | CC_SRC = v1; | 639 | CC_SRC = v1; |
| 522 | CC_DST = v1 - v2; | 640 | CC_DST = v1 - v2; |
| @@ -543,11 +661,11 @@ void OPPROTO glue(op_repz_cmps, SUFFIX)(void) | @@ -543,11 +661,11 @@ void OPPROTO glue(op_repz_cmps, SUFFIX)(void) | ||
| 543 | do { | 661 | do { |
| 544 | v1 = glue(ldu, SUFFIX)((void *)ESI); | 662 | v1 = glue(ldu, SUFFIX)((void *)ESI); |
| 545 | v2 = glue(ldu, SUFFIX)((void *)EDI); | 663 | v2 = glue(ldu, SUFFIX)((void *)EDI); |
| 546 | - if (v1 != v2) | ||
| 547 | - break; | ||
| 548 | ESI += inc; | 664 | ESI += inc; |
| 549 | EDI += inc; | 665 | EDI += inc; |
| 550 | ECX--; | 666 | ECX--; |
| 667 | + if (v1 != v2) | ||
| 668 | + break; | ||
| 551 | } while (ECX != 0); | 669 | } while (ECX != 0); |
| 552 | CC_SRC = v1; | 670 | CC_SRC = v1; |
| 553 | CC_DST = v1 - v2; | 671 | CC_DST = v1 - v2; |
| @@ -563,11 +681,11 @@ void OPPROTO glue(op_repnz_cmps, SUFFIX)(void) | @@ -563,11 +681,11 @@ void OPPROTO glue(op_repnz_cmps, SUFFIX)(void) | ||
| 563 | do { | 681 | do { |
| 564 | v1 = glue(ldu, SUFFIX)((void *)ESI); | 682 | v1 = glue(ldu, SUFFIX)((void *)ESI); |
| 565 | v2 = glue(ldu, SUFFIX)((void *)EDI); | 683 | v2 = glue(ldu, SUFFIX)((void *)EDI); |
| 566 | - if (v1 == v2) | ||
| 567 | - break; | ||
| 568 | ESI += inc; | 684 | ESI += inc; |
| 569 | EDI += inc; | 685 | EDI += inc; |
| 570 | ECX--; | 686 | ECX--; |
| 687 | + if (v1 == v2) | ||
| 688 | + break; | ||
| 571 | } while (ECX != 0); | 689 | } while (ECX != 0); |
| 572 | CC_SRC = v1; | 690 | CC_SRC = v1; |
| 573 | CC_DST = v1 - v2; | 691 | CC_DST = v1 - v2; |
tests/Makefile
| @@ -20,7 +20,7 @@ test2: test2.c | @@ -20,7 +20,7 @@ test2: test2.c | ||
| 20 | 20 | ||
| 21 | # i386 emulation test (dump various opcodes) */ | 21 | # i386 emulation test (dump various opcodes) */ |
| 22 | test-i386: test-i386.c test-i386.h test-i386-shift.h | 22 | test-i386: test-i386.c test-i386.h test-i386-shift.h |
| 23 | - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< | 23 | + $(CC) $(CFLAGS) $(LDFLAGS) -static -o $@ $< |
| 24 | 24 | ||
| 25 | test: test-i386 | 25 | test: test-i386 |
| 26 | ./test-i386 > test-i386.ref | 26 | ./test-i386 > test-i386.ref |
tests/test-i386.c
| @@ -14,13 +14,12 @@ | @@ -14,13 +14,12 @@ | ||
| 14 | #define CC_S 0x0080 | 14 | #define CC_S 0x0080 |
| 15 | #define CC_O 0x0800 | 15 | #define CC_O 0x0800 |
| 16 | 16 | ||
| 17 | -/* XXX: currently no A flag */ | ||
| 18 | -#define CC_MASK (CC_C | CC_P | CC_Z | CC_S | CC_O) | ||
| 19 | - | ||
| 20 | #define __init_call __attribute__ ((unused,__section__ (".initcall.init"))) | 17 | #define __init_call __attribute__ ((unused,__section__ (".initcall.init"))) |
| 21 | 18 | ||
| 22 | static void *call_start __init_call = NULL; | 19 | static void *call_start __init_call = NULL; |
| 23 | 20 | ||
| 21 | +#define CC_MASK (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A) | ||
| 22 | + | ||
| 24 | #define OP add | 23 | #define OP add |
| 25 | #include "test-i386.h" | 24 | #include "test-i386.h" |
| 26 | 25 | ||
| @@ -67,6 +66,9 @@ static void *call_start __init_call = NULL; | @@ -67,6 +66,9 @@ static void *call_start __init_call = NULL; | ||
| 67 | #define OP1 | 66 | #define OP1 |
| 68 | #include "test-i386.h" | 67 | #include "test-i386.h" |
| 69 | 68 | ||
| 69 | +#undef CC_MASK | ||
| 70 | +#define CC_MASK (CC_C | CC_P | CC_Z | CC_S | CC_O) | ||
| 71 | + | ||
| 70 | #define OP shl | 72 | #define OP shl |
| 71 | #include "test-i386-shift.h" | 73 | #include "test-i386-shift.h" |
| 72 | 74 | ||
| @@ -268,18 +270,148 @@ void test_jcc(void) | @@ -268,18 +270,148 @@ void test_jcc(void) | ||
| 268 | TEST_JCC("jns", 0, 0); | 270 | TEST_JCC("jns", 0, 0); |
| 269 | } | 271 | } |
| 270 | 272 | ||
| 273 | +#undef CC_MASK | ||
| 274 | +#define CC_MASK (CC_O | CC_C) | ||
| 275 | + | ||
| 276 | +#define OP mul | ||
| 277 | +#include "test-i386-muldiv.h" | ||
| 278 | + | ||
| 279 | +#define OP imul | ||
| 280 | +#include "test-i386-muldiv.h" | ||
| 281 | + | ||
| 282 | +#undef CC_MASK | ||
| 283 | +#define CC_MASK (0) | ||
| 284 | + | ||
| 285 | +#define OP div | ||
| 286 | +#include "test-i386-muldiv.h" | ||
| 287 | + | ||
| 288 | +#define OP idiv | ||
| 289 | +#include "test-i386-muldiv.h" | ||
| 290 | + | ||
| 291 | +void test_imulw2(int op0, int op1) | ||
| 292 | +{ | ||
| 293 | + int res, s1, s0, flags; | ||
| 294 | + s0 = op0; | ||
| 295 | + s1 = op1; | ||
| 296 | + res = s0; | ||
| 297 | + flags = 0; | ||
| 298 | + asm ("push %4\n\t" | ||
| 299 | + "popf\n\t" | ||
| 300 | + "imulw %w2, %w0\n\t" | ||
| 301 | + "pushf\n\t" | ||
| 302 | + "popl %1\n\t" | ||
| 303 | + : "=q" (res), "=g" (flags) | ||
| 304 | + : "q" (s1), "0" (res), "1" (flags)); | ||
| 305 | + printf("%-10s A=%08x B=%08x R=%08x CC=%04x\n", | ||
| 306 | + "imulw", s0, s1, res, flags & CC_MASK); | ||
| 307 | +} | ||
| 308 | + | ||
| 309 | +void test_imull2(int op0, int op1) | ||
| 310 | +{ | ||
| 311 | + int res, s1, s0, flags; | ||
| 312 | + s0 = op0; | ||
| 313 | + s1 = op1; | ||
| 314 | + res = s0; | ||
| 315 | + flags = 0; | ||
| 316 | + asm ("push %4\n\t" | ||
| 317 | + "popf\n\t" | ||
| 318 | + "imull %2, %0\n\t" | ||
| 319 | + "pushf\n\t" | ||
| 320 | + "popl %1\n\t" | ||
| 321 | + : "=q" (res), "=g" (flags) | ||
| 322 | + : "q" (s1), "0" (res), "1" (flags)); | ||
| 323 | + printf("%-10s A=%08x B=%08x R=%08x CC=%04x\n", | ||
| 324 | + "imull", s0, s1, res, flags & CC_MASK); | ||
| 325 | +} | ||
| 326 | + | ||
| 327 | +void test_mul(void) | ||
| 328 | +{ | ||
| 329 | + test_imulb(0x1234561d, 4); | ||
| 330 | + test_imulb(3, -4); | ||
| 331 | + test_imulb(0x80, 0x80); | ||
| 332 | + test_imulb(0x10, 0x10); | ||
| 333 | + | ||
| 334 | + test_imulw(0, 0x1234001d, 45); | ||
| 335 | + test_imulw(0, 23, -45); | ||
| 336 | + test_imulw(0, 0x8000, 0x8000); | ||
| 337 | + test_imulw(0, 0x100, 0x100); | ||
| 338 | + | ||
| 339 | + test_imull(0, 0x1234001d, 45); | ||
| 340 | + test_imull(0, 23, -45); | ||
| 341 | + test_imull(0, 0x80000000, 0x80000000); | ||
| 342 | + test_imull(0, 0x10000, 0x10000); | ||
| 343 | + | ||
| 344 | + test_mulb(0x1234561d, 4); | ||
| 345 | + test_mulb(3, -4); | ||
| 346 | + test_mulb(0x80, 0x80); | ||
| 347 | + test_mulb(0x10, 0x10); | ||
| 348 | + | ||
| 349 | + test_mulw(0, 0x1234001d, 45); | ||
| 350 | + test_mulw(0, 23, -45); | ||
| 351 | + test_mulw(0, 0x8000, 0x8000); | ||
| 352 | + test_mulw(0, 0x100, 0x100); | ||
| 353 | + | ||
| 354 | + test_mull(0, 0x1234001d, 45); | ||
| 355 | + test_mull(0, 23, -45); | ||
| 356 | + test_mull(0, 0x80000000, 0x80000000); | ||
| 357 | + test_mull(0, 0x10000, 0x10000); | ||
| 358 | + | ||
| 359 | + test_imulw2(0x1234001d, 45); | ||
| 360 | + test_imulw2(23, -45); | ||
| 361 | + test_imulw2(0x8000, 0x8000); | ||
| 362 | + test_imulw2(0x100, 0x100); | ||
| 363 | + | ||
| 364 | + test_imull2(0x1234001d, 45); | ||
| 365 | + test_imull2(23, -45); | ||
| 366 | + test_imull2(0x80000000, 0x80000000); | ||
| 367 | + test_imull2(0x10000, 0x10000); | ||
| 368 | + | ||
| 369 | + test_idivb(0x12341678, 0x127e); | ||
| 370 | + test_idivb(0x43210123, -5); | ||
| 371 | + test_idivb(0x12340004, -1); | ||
| 372 | + | ||
| 373 | + test_idivw(0, 0x12345678, 12347); | ||
| 374 | + test_idivw(0, -23223, -45); | ||
| 375 | + test_idivw(0, 0x12348000, -1); | ||
| 376 | + test_idivw(0x12343, 0x12345678, 0x81238567); | ||
| 377 | + | ||
| 378 | + test_idivl(0, 0x12345678, 12347); | ||
| 379 | + test_idivl(0, -233223, -45); | ||
| 380 | + test_idivl(0, 0x80000000, -1); | ||
| 381 | + test_idivl(0x12343, 0x12345678, 0x81234567); | ||
| 382 | + | ||
| 383 | + test_divb(0x12341678, 0x127e); | ||
| 384 | + test_divb(0x43210123, -5); | ||
| 385 | + test_divb(0x12340004, -1); | ||
| 386 | + | ||
| 387 | + test_divw(0, 0x12345678, 12347); | ||
| 388 | + test_divw(0, -23223, -45); | ||
| 389 | + test_divw(0, 0x12348000, -1); | ||
| 390 | + test_divw(0x12343, 0x12345678, 0x81238567); | ||
| 391 | + | ||
| 392 | + test_divl(0, 0x12345678, 12347); | ||
| 393 | + test_divl(0, -233223, -45); | ||
| 394 | + test_divl(0, 0x80000000, -1); | ||
| 395 | + test_divl(0x12343, 0x12345678, 0x81234567); | ||
| 396 | +} | ||
| 397 | + | ||
| 398 | + | ||
| 271 | static void *call_end __init_call = NULL; | 399 | static void *call_end __init_call = NULL; |
| 272 | 400 | ||
| 273 | int main(int argc, char **argv) | 401 | int main(int argc, char **argv) |
| 274 | { | 402 | { |
| 275 | void **ptr; | 403 | void **ptr; |
| 276 | void (*func)(void); | 404 | void (*func)(void); |
| 405 | + | ||
| 406 | + test_mul(); | ||
| 407 | +#if 0 | ||
| 277 | ptr = &call_start + 1; | 408 | ptr = &call_start + 1; |
| 278 | while (*ptr != NULL) { | 409 | while (*ptr != NULL) { |
| 279 | func = *ptr++; | 410 | func = *ptr++; |
| 280 | func(); | 411 | func(); |
| 281 | } | 412 | } |
| 282 | - test_lea(); | ||
| 283 | test_jcc(); | 413 | test_jcc(); |
| 414 | + test_lea(); | ||
| 415 | +#endif | ||
| 284 | return 0; | 416 | return 0; |
| 285 | } | 417 | } |
translate-i386.c
| @@ -27,7 +27,9 @@ static void error(const char *fmt, ...) | @@ -27,7 +27,9 @@ static void error(const char *fmt, ...) | ||
| 27 | va_list ap; | 27 | va_list ap; |
| 28 | 28 | ||
| 29 | va_start(ap, fmt); | 29 | va_start(ap, fmt); |
| 30 | + fprintf(stderr, "\n"); | ||
| 30 | vfprintf(stderr, fmt, ap); | 31 | vfprintf(stderr, fmt, ap); |
| 32 | + fprintf(stderr, "\n"); | ||
| 31 | va_end(ap); | 33 | va_end(ap); |
| 32 | exit(1); | 34 | exit(1); |
| 33 | } | 35 | } |
| @@ -98,42 +100,13 @@ enum { | @@ -98,42 +100,13 @@ enum { | ||
| 98 | OR_EBP, | 100 | OR_EBP, |
| 99 | OR_ESI, | 101 | OR_ESI, |
| 100 | OR_EDI, | 102 | OR_EDI, |
| 101 | - | ||
| 102 | - /* I386 float registers */ | ||
| 103 | - OR_ST0, | ||
| 104 | - OR_ST1, | ||
| 105 | - OR_ST2, | ||
| 106 | - OR_ST3, | ||
| 107 | - OR_ST4, | ||
| 108 | - OR_ST5, | ||
| 109 | - OR_ST6, | ||
| 110 | - OR_ST7, | ||
| 111 | OR_TMP0, /* temporary operand register */ | 103 | OR_TMP0, /* temporary operand register */ |
| 112 | OR_TMP1, | 104 | OR_TMP1, |
| 113 | OR_A0, /* temporary register used when doing address evaluation */ | 105 | OR_A0, /* temporary register used when doing address evaluation */ |
| 114 | - OR_EFLAGS, /* cpu flags */ | ||
| 115 | - OR_ITMP0, /* used for byte/word insertion */ | ||
| 116 | - OR_ITMP1, /* used for byte/word insertion */ | ||
| 117 | - OR_ITMP2, /* used for byte/word insertion */ | ||
| 118 | - OR_FTMP0, /* float temporary */ | ||
| 119 | - OR_DF, /* D flag, for string ops */ | ||
| 120 | OR_ZERO, /* fixed zero register */ | 106 | OR_ZERO, /* fixed zero register */ |
| 121 | - OR_IM, /* dummy immediate value register */ | ||
| 122 | NB_OREGS, | 107 | NB_OREGS, |
| 123 | }; | 108 | }; |
| 124 | 109 | ||
| 125 | -#if 0 | ||
| 126 | -static const double tab_const[7] = { | ||
| 127 | - 1.0, | ||
| 128 | - 3.32192809488736234789, /* log2(10) */ | ||
| 129 | - M_LOG2E, | ||
| 130 | - M_PI, | ||
| 131 | - 0.30102999566398119521, /* log10(2) */ | ||
| 132 | - M_LN2, | ||
| 133 | - 0.0 | ||
| 134 | -}; | ||
| 135 | -#endif | ||
| 136 | - | ||
| 137 | typedef void (GenOpFunc)(void); | 110 | typedef void (GenOpFunc)(void); |
| 138 | typedef void (GenOpFunc1)(long); | 111 | typedef void (GenOpFunc1)(long); |
| 139 | typedef void (GenOpFunc2)(long, long); | 112 | typedef void (GenOpFunc2)(long, long); |
| @@ -354,14 +327,29 @@ static GenOpFunc *gen_op_addl_A0_reg_sN[4][8] = { | @@ -354,14 +327,29 @@ static GenOpFunc *gen_op_addl_A0_reg_sN[4][8] = { | ||
| 354 | static GenOpFunc *gen_op_arith_T0_T1_cc[8] = { | 327 | static GenOpFunc *gen_op_arith_T0_T1_cc[8] = { |
| 355 | gen_op_addl_T0_T1_cc, | 328 | gen_op_addl_T0_T1_cc, |
| 356 | gen_op_orl_T0_T1_cc, | 329 | gen_op_orl_T0_T1_cc, |
| 357 | - gen_op_adcl_T0_T1_cc, | ||
| 358 | - gen_op_sbbl_T0_T1_cc, | 330 | + NULL, |
| 331 | + NULL, | ||
| 359 | gen_op_andl_T0_T1_cc, | 332 | gen_op_andl_T0_T1_cc, |
| 360 | gen_op_subl_T0_T1_cc, | 333 | gen_op_subl_T0_T1_cc, |
| 361 | gen_op_xorl_T0_T1_cc, | 334 | gen_op_xorl_T0_T1_cc, |
| 362 | gen_op_cmpl_T0_T1_cc, | 335 | gen_op_cmpl_T0_T1_cc, |
| 363 | }; | 336 | }; |
| 364 | 337 | ||
| 338 | +static GenOpFunc *gen_op_arithc_T0_T1_cc[3][2] = { | ||
| 339 | + [OT_BYTE] = { | ||
| 340 | + gen_op_adcb_T0_T1_cc, | ||
| 341 | + gen_op_sbbb_T0_T1_cc, | ||
| 342 | + }, | ||
| 343 | + [OT_WORD] = { | ||
| 344 | + gen_op_adcw_T0_T1_cc, | ||
| 345 | + gen_op_sbbw_T0_T1_cc, | ||
| 346 | + }, | ||
| 347 | + [OT_LONG] = { | ||
| 348 | + gen_op_adcl_T0_T1_cc, | ||
| 349 | + gen_op_sbbl_T0_T1_cc, | ||
| 350 | + }, | ||
| 351 | +}; | ||
| 352 | + | ||
| 365 | static const int cc_op_arithb[8] = { | 353 | static const int cc_op_arithb[8] = { |
| 366 | CC_OP_ADDB, | 354 | CC_OP_ADDB, |
| 367 | CC_OP_LOGICB, | 355 | CC_OP_LOGICB, |
| @@ -406,6 +394,21 @@ static GenOpFunc *gen_op_shift_T0_T1_cc[3][8] = { | @@ -406,6 +394,21 @@ static GenOpFunc *gen_op_shift_T0_T1_cc[3][8] = { | ||
| 406 | }, | 394 | }, |
| 407 | }; | 395 | }; |
| 408 | 396 | ||
| 397 | +static GenOpFunc *gen_op_btx_T0_T1_cc[2][4] = { | ||
| 398 | + [0] = { | ||
| 399 | + gen_op_btw_T0_T1_cc, | ||
| 400 | + gen_op_btsw_T0_T1_cc, | ||
| 401 | + gen_op_btrw_T0_T1_cc, | ||
| 402 | + gen_op_btcw_T0_T1_cc, | ||
| 403 | + }, | ||
| 404 | + [1] = { | ||
| 405 | + gen_op_btl_T0_T1_cc, | ||
| 406 | + gen_op_btsl_T0_T1_cc, | ||
| 407 | + gen_op_btrl_T0_T1_cc, | ||
| 408 | + gen_op_btcl_T0_T1_cc, | ||
| 409 | + }, | ||
| 410 | +}; | ||
| 411 | + | ||
| 409 | static GenOpFunc *gen_op_lds_T0_A0[3] = { | 412 | static GenOpFunc *gen_op_lds_T0_A0[3] = { |
| 410 | gen_op_ldsb_T0_A0, | 413 | gen_op_ldsb_T0_A0, |
| 411 | gen_op_ldsw_T0_A0, | 414 | gen_op_ldsw_T0_A0, |
| @@ -644,18 +647,23 @@ static void gen_op(DisasContext *s1, int op, int ot, int d, int s) | @@ -644,18 +647,23 @@ static void gen_op(DisasContext *s1, int op, int ot, int d, int s) | ||
| 644 | gen_op_mov_TN_reg[ot][0][d](); | 647 | gen_op_mov_TN_reg[ot][0][d](); |
| 645 | if (s != OR_TMP1) | 648 | if (s != OR_TMP1) |
| 646 | gen_op_mov_TN_reg[ot][1][s](); | 649 | gen_op_mov_TN_reg[ot][1][s](); |
| 647 | - if ((op == OP_ADCL || op == OP_SBBL) && s1->cc_op != CC_OP_DYNAMIC) | ||
| 648 | - gen_op_set_cc_op(s1->cc_op); | ||
| 649 | - gen_op_arith_T0_T1_cc[op](); | 650 | + if (op == OP_ADCL || op == OP_SBBL) { |
| 651 | + if (s1->cc_op != CC_OP_DYNAMIC) | ||
| 652 | + gen_op_set_cc_op(s1->cc_op); | ||
| 653 | + gen_op_arithc_T0_T1_cc[ot][op - OP_ADCL](); | ||
| 654 | + s1->cc_op = CC_OP_DYNAMIC; | ||
| 655 | + } else { | ||
| 656 | + gen_op_arith_T0_T1_cc[op](); | ||
| 657 | + s1->cc_op = cc_op_arithb[op] + ot; | ||
| 658 | + } | ||
| 650 | if (d != OR_TMP0 && op != OP_CMPL) | 659 | if (d != OR_TMP0 && op != OP_CMPL) |
| 651 | gen_op_mov_reg_T0[ot][d](); | 660 | gen_op_mov_reg_T0[ot][d](); |
| 652 | - s1->cc_op = cc_op_arithb[op] + ot; | ||
| 653 | } | 661 | } |
| 654 | 662 | ||
| 655 | static void gen_opi(DisasContext *s1, int op, int ot, int d, int c) | 663 | static void gen_opi(DisasContext *s1, int op, int ot, int d, int c) |
| 656 | { | 664 | { |
| 657 | gen_op_movl_T1_im(c); | 665 | gen_op_movl_T1_im(c); |
| 658 | - gen_op(s1, op, ot, d, OR_TMP0); | 666 | + gen_op(s1, op, ot, d, OR_TMP1); |
| 659 | } | 667 | } |
| 660 | 668 | ||
| 661 | static void gen_inc(DisasContext *s1, int ot, int d, int c) | 669 | static void gen_inc(DisasContext *s1, int ot, int d, int c) |
| @@ -664,10 +672,13 @@ static void gen_inc(DisasContext *s1, int ot, int d, int c) | @@ -664,10 +672,13 @@ static void gen_inc(DisasContext *s1, int ot, int d, int c) | ||
| 664 | gen_op_mov_TN_reg[ot][0][d](); | 672 | gen_op_mov_TN_reg[ot][0][d](); |
| 665 | if (s1->cc_op != CC_OP_DYNAMIC) | 673 | if (s1->cc_op != CC_OP_DYNAMIC) |
| 666 | gen_op_set_cc_op(s1->cc_op); | 674 | gen_op_set_cc_op(s1->cc_op); |
| 667 | - if (c > 0) | 675 | + if (c > 0) { |
| 668 | gen_op_incl_T0_cc(); | 676 | gen_op_incl_T0_cc(); |
| 669 | - else | 677 | + s1->cc_op = CC_OP_INCB + ot; |
| 678 | + } else { | ||
| 670 | gen_op_decl_T0_cc(); | 679 | gen_op_decl_T0_cc(); |
| 680 | + s1->cc_op = CC_OP_DECB + ot; | ||
| 681 | + } | ||
| 671 | if (d != OR_TMP0) | 682 | if (d != OR_TMP0) |
| 672 | gen_op_mov_reg_T0[ot][d](); | 683 | gen_op_mov_reg_T0[ot][d](); |
| 673 | } | 684 | } |
| @@ -678,20 +689,12 @@ static void gen_shift(DisasContext *s1, int op, int ot, int d, int s) | @@ -678,20 +689,12 @@ static void gen_shift(DisasContext *s1, int op, int ot, int d, int s) | ||
| 678 | gen_op_mov_TN_reg[ot][0][d](); | 689 | gen_op_mov_TN_reg[ot][0][d](); |
| 679 | if (s != OR_TMP1) | 690 | if (s != OR_TMP1) |
| 680 | gen_op_mov_TN_reg[ot][1][s](); | 691 | gen_op_mov_TN_reg[ot][1][s](); |
| 681 | - switch(op) { | ||
| 682 | - case OP_ROL: | ||
| 683 | - case OP_ROR: | ||
| 684 | - case OP_RCL: | ||
| 685 | - case OP_RCR: | ||
| 686 | - /* only C and O are modified, so we must update flags dynamically */ | ||
| 687 | - if (s1->cc_op != CC_OP_DYNAMIC) | ||
| 688 | - gen_op_set_cc_op(s1->cc_op); | ||
| 689 | - gen_op_shift_T0_T1_cc[ot][op](); | ||
| 690 | - break; | ||
| 691 | - default: | ||
| 692 | - gen_op_shift_T0_T1_cc[ot][op](); | ||
| 693 | - break; | ||
| 694 | - } | 692 | + /* for zero counts, flags are not updated, so must do it dynamically */ |
| 693 | + if (s1->cc_op != CC_OP_DYNAMIC) | ||
| 694 | + gen_op_set_cc_op(s1->cc_op); | ||
| 695 | + | ||
| 696 | + gen_op_shift_T0_T1_cc[ot][op](); | ||
| 697 | + | ||
| 695 | if (d != OR_TMP0) | 698 | if (d != OR_TMP0) |
| 696 | gen_op_mov_reg_T0[ot][d](); | 699 | gen_op_mov_reg_T0[ot][d](); |
| 697 | s1->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */ | 700 | s1->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */ |
| @@ -785,12 +788,65 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ | @@ -785,12 +788,65 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ | ||
| 785 | } | 788 | } |
| 786 | gen_op_addl_A0_reg_sN[scale][reg2](); | 789 | gen_op_addl_A0_reg_sN[scale][reg2](); |
| 787 | } | 790 | } |
| 788 | - opreg = OR_A0; | ||
| 789 | } else { | 791 | } else { |
| 790 | - fprintf(stderr, "16 bit addressing not supported\n"); | ||
| 791 | - disp = 0; | ||
| 792 | - opreg = 0; | 792 | + switch (mod) { |
| 793 | + case 0: | ||
| 794 | + if (rm == 6) { | ||
| 795 | + disp = lduw(s->pc); | ||
| 796 | + s->pc += 2; | ||
| 797 | + gen_op_movl_A0_im(disp); | ||
| 798 | + goto no_rm; | ||
| 799 | + } else { | ||
| 800 | + disp = 0; | ||
| 801 | + } | ||
| 802 | + break; | ||
| 803 | + case 1: | ||
| 804 | + disp = (int8_t)ldub(s->pc++); | ||
| 805 | + break; | ||
| 806 | + default: | ||
| 807 | + case 2: | ||
| 808 | + disp = lduw(s->pc); | ||
| 809 | + s->pc += 2; | ||
| 810 | + break; | ||
| 811 | + } | ||
| 812 | + switch(rm) { | ||
| 813 | + case 0: | ||
| 814 | + gen_op_movl_A0_reg[R_EBX](); | ||
| 815 | + gen_op_addl_A0_reg_sN[0][R_ESI](); | ||
| 816 | + break; | ||
| 817 | + case 1: | ||
| 818 | + gen_op_movl_A0_reg[R_EBX](); | ||
| 819 | + gen_op_addl_A0_reg_sN[0][R_EDI](); | ||
| 820 | + break; | ||
| 821 | + case 2: | ||
| 822 | + gen_op_movl_A0_reg[R_EBP](); | ||
| 823 | + gen_op_addl_A0_reg_sN[0][R_ESI](); | ||
| 824 | + break; | ||
| 825 | + case 3: | ||
| 826 | + gen_op_movl_A0_reg[R_EBP](); | ||
| 827 | + gen_op_addl_A0_reg_sN[0][R_EDI](); | ||
| 828 | + break; | ||
| 829 | + case 4: | ||
| 830 | + gen_op_movl_A0_reg[R_ESI](); | ||
| 831 | + break; | ||
| 832 | + case 5: | ||
| 833 | + gen_op_movl_A0_reg[R_EDI](); | ||
| 834 | + break; | ||
| 835 | + case 6: | ||
| 836 | + gen_op_movl_A0_reg[R_EBP](); | ||
| 837 | + break; | ||
| 838 | + default: | ||
| 839 | + case 7: | ||
| 840 | + gen_op_movl_A0_reg[R_EBX](); | ||
| 841 | + break; | ||
| 842 | + } | ||
| 843 | + if (disp != 0) | ||
| 844 | + gen_op_addl_A0_im(disp); | ||
| 845 | + gen_op_andl_A0_ffff(); | ||
| 846 | + no_rm: ; | ||
| 793 | } | 847 | } |
| 848 | + opreg = OR_A0; | ||
| 849 | + disp = 0; | ||
| 794 | *reg_ptr = opreg; | 850 | *reg_ptr = opreg; |
| 795 | *offset_ptr = disp; | 851 | *offset_ptr = disp; |
| 796 | } | 852 | } |
| @@ -870,6 +926,12 @@ static void gen_jcc(DisasContext *s, int b, int val) | @@ -870,6 +926,12 @@ static void gen_jcc(DisasContext *s, int b, int val) | ||
| 870 | case CC_OP_ADDB: | 926 | case CC_OP_ADDB: |
| 871 | case CC_OP_ADDW: | 927 | case CC_OP_ADDW: |
| 872 | case CC_OP_ADDL: | 928 | case CC_OP_ADDL: |
| 929 | + case CC_OP_ADCB: | ||
| 930 | + case CC_OP_ADCW: | ||
| 931 | + case CC_OP_ADCL: | ||
| 932 | + case CC_OP_SBBB: | ||
| 933 | + case CC_OP_SBBW: | ||
| 934 | + case CC_OP_SBBL: | ||
| 873 | case CC_OP_LOGICB: | 935 | case CC_OP_LOGICB: |
| 874 | case CC_OP_LOGICW: | 936 | case CC_OP_LOGICW: |
| 875 | case CC_OP_LOGICL: | 937 | case CC_OP_LOGICL: |
| @@ -882,6 +944,9 @@ static void gen_jcc(DisasContext *s, int b, int val) | @@ -882,6 +944,9 @@ static void gen_jcc(DisasContext *s, int b, int val) | ||
| 882 | case CC_OP_SHLB: | 944 | case CC_OP_SHLB: |
| 883 | case CC_OP_SHLW: | 945 | case CC_OP_SHLW: |
| 884 | case CC_OP_SHLL: | 946 | case CC_OP_SHLL: |
| 947 | + case CC_OP_SARB: | ||
| 948 | + case CC_OP_SARW: | ||
| 949 | + case CC_OP_SARL: | ||
| 885 | switch(jcc_op) { | 950 | switch(jcc_op) { |
| 886 | case JCC_Z: | 951 | case JCC_Z: |
| 887 | func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op]; | 952 | func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op]; |
| @@ -1284,11 +1349,15 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr) | @@ -1284,11 +1349,15 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr) | ||
| 1284 | gen_inc(s, ot, OR_TMP0, 1); | 1349 | gen_inc(s, ot, OR_TMP0, 1); |
| 1285 | if (mod != 3) | 1350 | if (mod != 3) |
| 1286 | gen_op_st_T0_A0[ot](); | 1351 | gen_op_st_T0_A0[ot](); |
| 1352 | + else | ||
| 1353 | + gen_op_mov_reg_T0[ot][rm](); | ||
| 1287 | break; | 1354 | break; |
| 1288 | case 1: /* dec Ev */ | 1355 | case 1: /* dec Ev */ |
| 1289 | gen_inc(s, ot, OR_TMP0, -1); | 1356 | gen_inc(s, ot, OR_TMP0, -1); |
| 1290 | if (mod != 3) | 1357 | if (mod != 3) |
| 1291 | gen_op_st_T0_A0[ot](); | 1358 | gen_op_st_T0_A0[ot](); |
| 1359 | + else | ||
| 1360 | + gen_op_mov_reg_T0[ot][rm](); | ||
| 1292 | break; | 1361 | break; |
| 1293 | case 2: /* call Ev */ | 1362 | case 2: /* call Ev */ |
| 1294 | gen_op_movl_T1_im((long)s->pc); | 1363 | gen_op_movl_T1_im((long)s->pc); |
| @@ -1359,7 +1428,6 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr) | @@ -1359,7 +1428,6 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr) | ||
| 1359 | ot = dflag ? OT_LONG : OT_WORD; | 1428 | ot = dflag ? OT_LONG : OT_WORD; |
| 1360 | modrm = ldub(s->pc++); | 1429 | modrm = ldub(s->pc++); |
| 1361 | reg = ((modrm >> 3) & 7) + OR_EAX; | 1430 | reg = ((modrm >> 3) & 7) + OR_EAX; |
| 1362 | - | ||
| 1363 | gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0); | 1431 | gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0); |
| 1364 | if (b == 0x69) { | 1432 | if (b == 0x69) { |
| 1365 | val = insn_get(s, ot); | 1433 | val = insn_get(s, ot); |
| @@ -1372,9 +1440,9 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr) | @@ -1372,9 +1440,9 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr) | ||
| 1372 | } | 1440 | } |
| 1373 | 1441 | ||
| 1374 | if (ot == OT_LONG) { | 1442 | if (ot == OT_LONG) { |
| 1375 | - op_imull_T0_T1(); | 1443 | + gen_op_imull_T0_T1(); |
| 1376 | } else { | 1444 | } else { |
| 1377 | - op_imulw_T0_T1(); | 1445 | + gen_op_imulw_T0_T1(); |
| 1378 | } | 1446 | } |
| 1379 | gen_op_mov_reg_T0[ot][reg](); | 1447 | gen_op_mov_reg_T0[ot][reg](); |
| 1380 | s->cc_op = CC_OP_MUL; | 1448 | s->cc_op = CC_OP_MUL; |
| @@ -1522,7 +1590,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr) | @@ -1522,7 +1590,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr) | ||
| 1522 | offset_addr = insn_get(s, OT_LONG); | 1590 | offset_addr = insn_get(s, OT_LONG); |
| 1523 | else | 1591 | else |
| 1524 | offset_addr = insn_get(s, OT_WORD); | 1592 | offset_addr = insn_get(s, OT_WORD); |
| 1525 | - | 1593 | + gen_op_movl_A0_im(offset_addr); |
| 1526 | if ((b & 2) == 0) { | 1594 | if ((b & 2) == 0) { |
| 1527 | gen_op_ld_T0_A0[ot](); | 1595 | gen_op_ld_T0_A0[ot](); |
| 1528 | gen_op_mov_reg_T0[ot][R_EAX](); | 1596 | gen_op_mov_reg_T0[ot][R_EAX](); |
| @@ -1717,17 +1785,19 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr) | @@ -1717,17 +1785,19 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr) | ||
| 1717 | break; | 1785 | break; |
| 1718 | } | 1786 | } |
| 1719 | break; | 1787 | break; |
| 1720 | -#if 0 | 1788 | + case 0x0d: /* fldcw mem */ |
| 1789 | + gen_op_fldcw_A0(); | ||
| 1790 | + break; | ||
| 1791 | + case 0x0f: /* fnstcw mem */ | ||
| 1792 | + gen_op_fnstcw_A0(); | ||
| 1793 | + break; | ||
| 1721 | case 0x2f: /* fnstsw mem */ | 1794 | case 0x2f: /* fnstsw mem */ |
| 1722 | - gen_insn3(OP_FNSTS, OR_TMP0, OR_ZERO, OR_ZERO); | ||
| 1723 | - gen_st(OP_STW, OR_TMP0, reg_addr, offset_addr); | 1795 | + gen_op_fnstsw_A0(); |
| 1724 | break; | 1796 | break; |
| 1725 | - | ||
| 1726 | case 0x3c: /* fbld */ | 1797 | case 0x3c: /* fbld */ |
| 1727 | case 0x3e: /* fbstp */ | 1798 | case 0x3e: /* fbstp */ |
| 1728 | error("float BCD not hanlded"); | 1799 | error("float BCD not hanlded"); |
| 1729 | return -1; | 1800 | return -1; |
| 1730 | -#endif | ||
| 1731 | case 0x3d: /* fildll */ | 1801 | case 0x3d: /* fildll */ |
| 1732 | gen_op_fpush(); | 1802 | gen_op_fpush(); |
| 1733 | gen_op_fildll_ST0_A0(); | 1803 | gen_op_fildll_ST0_A0(); |
| @@ -1737,7 +1807,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr) | @@ -1737,7 +1807,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr) | ||
| 1737 | gen_op_fpop(); | 1807 | gen_op_fpop(); |
| 1738 | break; | 1808 | break; |
| 1739 | default: | 1809 | default: |
| 1740 | - error("unhandled memory FP\n"); | 1810 | + error("unhandled memory FP [op=0x%02x]\n", op); |
| 1741 | return -1; | 1811 | return -1; |
| 1742 | } | 1812 | } |
| 1743 | } else { | 1813 | } else { |
| @@ -1987,11 +2057,18 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr) | @@ -1987,11 +2057,18 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr) | ||
| 1987 | else | 2057 | else |
| 1988 | ot = dflag ? OT_LONG : OT_WORD; | 2058 | ot = dflag ? OT_LONG : OT_WORD; |
| 1989 | if (prefixes & PREFIX_REPNZ) { | 2059 | if (prefixes & PREFIX_REPNZ) { |
| 2060 | + if (s->cc_op != CC_OP_DYNAMIC) | ||
| 2061 | + gen_op_set_cc_op(s->cc_op); | ||
| 1990 | gen_op_scas[6 + ot](); | 2062 | gen_op_scas[6 + ot](); |
| 2063 | + s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */ | ||
| 1991 | } else if (prefixes & PREFIX_REPZ) { | 2064 | } else if (prefixes & PREFIX_REPZ) { |
| 2065 | + if (s->cc_op != CC_OP_DYNAMIC) | ||
| 2066 | + gen_op_set_cc_op(s->cc_op); | ||
| 1992 | gen_op_scas[3 + ot](); | 2067 | gen_op_scas[3 + ot](); |
| 2068 | + s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */ | ||
| 1993 | } else { | 2069 | } else { |
| 1994 | gen_op_scas[ot](); | 2070 | gen_op_scas[ot](); |
| 2071 | + s->cc_op = CC_OP_SUBB + ot; | ||
| 1995 | } | 2072 | } |
| 1996 | break; | 2073 | break; |
| 1997 | 2074 | ||
| @@ -2002,11 +2079,18 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr) | @@ -2002,11 +2079,18 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr) | ||
| 2002 | else | 2079 | else |
| 2003 | ot = dflag ? OT_LONG : OT_WORD; | 2080 | ot = dflag ? OT_LONG : OT_WORD; |
| 2004 | if (prefixes & PREFIX_REPNZ) { | 2081 | if (prefixes & PREFIX_REPNZ) { |
| 2082 | + if (s->cc_op != CC_OP_DYNAMIC) | ||
| 2083 | + gen_op_set_cc_op(s->cc_op); | ||
| 2005 | gen_op_cmps[6 + ot](); | 2084 | gen_op_cmps[6 + ot](); |
| 2085 | + s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */ | ||
| 2006 | } else if (prefixes & PREFIX_REPZ) { | 2086 | } else if (prefixes & PREFIX_REPZ) { |
| 2087 | + if (s->cc_op != CC_OP_DYNAMIC) | ||
| 2088 | + gen_op_set_cc_op(s->cc_op); | ||
| 2007 | gen_op_cmps[3 + ot](); | 2089 | gen_op_cmps[3 + ot](); |
| 2090 | + s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */ | ||
| 2008 | } else { | 2091 | } else { |
| 2009 | gen_op_cmps[ot](); | 2092 | gen_op_cmps[ot](); |
| 2093 | + s->cc_op = CC_OP_SUBB + ot; | ||
| 2010 | } | 2094 | } |
| 2011 | break; | 2095 | break; |
| 2012 | 2096 | ||
| @@ -2187,6 +2271,74 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr) | @@ -2187,6 +2271,74 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr) | ||
| 2187 | break; | 2271 | break; |
| 2188 | 2272 | ||
| 2189 | /************************/ | 2273 | /************************/ |
| 2274 | + /* bit operations */ | ||
| 2275 | + case 0x1ba: /* bt/bts/btr/btc Gv, im */ | ||
| 2276 | + ot = dflag ? OT_LONG : OT_WORD; | ||
| 2277 | + modrm = ldub(s->pc++); | ||
| 2278 | + op = (modrm >> 3) & 7; | ||
| 2279 | + mod = (modrm >> 6) & 3; | ||
| 2280 | + rm = modrm & 7; | ||
| 2281 | + if (mod != 3) { | ||
| 2282 | + gen_lea_modrm(s, modrm, ®_addr, &offset_addr); | ||
| 2283 | + gen_op_ld_T0_A0[ot](); | ||
| 2284 | + } else { | ||
| 2285 | + gen_op_mov_TN_reg[ot][0][rm](); | ||
| 2286 | + } | ||
| 2287 | + /* load shift */ | ||
| 2288 | + val = ldub(s->pc++); | ||
| 2289 | + gen_op_movl_T1_im(val); | ||
| 2290 | + if (op < 4) | ||
| 2291 | + return -1; | ||
| 2292 | + op -= 4; | ||
| 2293 | + gen_op_btx_T0_T1_cc[ot - OT_WORD][op](); | ||
| 2294 | + s->cc_op = CC_OP_SHLB + ot; | ||
| 2295 | + if (op != 0) { | ||
| 2296 | + if (mod != 3) | ||
| 2297 | + gen_op_st_T0_A0[ot](); | ||
| 2298 | + else | ||
| 2299 | + gen_op_mov_reg_T0[ot][rm](); | ||
| 2300 | + } | ||
| 2301 | + break; | ||
| 2302 | + case 0x1a3: /* bt Gv, Ev */ | ||
| 2303 | + op = 0; | ||
| 2304 | + goto do_btx; | ||
| 2305 | + case 0x1ab: /* bts */ | ||
| 2306 | + op = 1; | ||
| 2307 | + goto do_btx; | ||
| 2308 | + case 0x1b3: /* btr */ | ||
| 2309 | + op = 2; | ||
| 2310 | + goto do_btx; | ||
| 2311 | + case 0x1bb: /* btc */ | ||
| 2312 | + op = 3; | ||
| 2313 | + do_btx: | ||
| 2314 | + ot = dflag ? OT_LONG : OT_WORD; | ||
| 2315 | + modrm = ldub(s->pc++); | ||
| 2316 | + reg = (modrm >> 3) & 7; | ||
| 2317 | + mod = (modrm >> 6) & 3; | ||
| 2318 | + rm = modrm & 7; | ||
| 2319 | + gen_op_mov_TN_reg[OT_LONG][1][reg](); | ||
| 2320 | + if (mod != 3) { | ||
| 2321 | + gen_lea_modrm(s, modrm, ®_addr, &offset_addr); | ||
| 2322 | + /* specific case: we need to add a displacement */ | ||
| 2323 | + if (ot == OT_WORD) | ||
| 2324 | + gen_op_add_bitw_A0_T1(); | ||
| 2325 | + else | ||
| 2326 | + gen_op_add_bitl_A0_T1(); | ||
| 2327 | + gen_op_ld_T0_A0[ot](); | ||
| 2328 | + } else { | ||
| 2329 | + gen_op_mov_TN_reg[ot][0][rm](); | ||
| 2330 | + } | ||
| 2331 | + gen_op_btx_T0_T1_cc[ot - OT_WORD][op](); | ||
| 2332 | + s->cc_op = CC_OP_SHLB + ot; | ||
| 2333 | + if (op != 0) { | ||
| 2334 | + if (mod != 3) | ||
| 2335 | + gen_op_st_T0_A0[ot](); | ||
| 2336 | + else | ||
| 2337 | + gen_op_mov_reg_T0[ot][rm](); | ||
| 2338 | + } | ||
| 2339 | + break; | ||
| 2340 | + | ||
| 2341 | + /************************/ | ||
| 2190 | /* misc */ | 2342 | /* misc */ |
| 2191 | case 0x90: /* nop */ | 2343 | case 0x90: /* nop */ |
| 2192 | break; | 2344 | break; |
| @@ -2206,6 +2358,13 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr) | @@ -2206,6 +2358,13 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr) | ||
| 2206 | gen_op_into((long)pc_start, (long)s->pc); | 2358 | gen_op_into((long)pc_start, (long)s->pc); |
| 2207 | *is_jmp_ptr = 1; | 2359 | *is_jmp_ptr = 1; |
| 2208 | break; | 2360 | break; |
| 2361 | + case 0x1c8 ... 0x1cf: /* bswap reg */ | ||
| 2362 | + reg = b & 7; | ||
| 2363 | + gen_op_mov_TN_reg[OT_LONG][0][reg](); | ||
| 2364 | + gen_op_bswapl_T0(); | ||
| 2365 | + gen_op_mov_reg_T0[OT_LONG][reg](); | ||
| 2366 | + break; | ||
| 2367 | + | ||
| 2209 | #if 0 | 2368 | #if 0 |
| 2210 | case 0x1a2: /* cpuid */ | 2369 | case 0x1a2: /* cpuid */ |
| 2211 | gen_insn0(OP_ASM); | 2370 | gen_insn0(OP_ASM); |