Commit d57c4e01206ebc8b21702c243e7a19638f783b43

Authored by bellard
1 parent 4b74fe1f

added shiftd support - improved auto test


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@20 c046a42c-6fe2-441c-8c8c-71466251a162
Makefile
@@ -84,6 +84,7 @@ dis-asm.h gen-i386.h op-i386.h syscall.c\ @@ -84,6 +84,7 @@ dis-asm.h gen-i386.h op-i386.h syscall.c\
84 dis-buf.c i386-dis.c opreg_template.h syscall_defs.h\ 84 dis-buf.c i386-dis.c opreg_template.h syscall_defs.h\
85 i386.ld ppc.ld\ 85 i386.ld ppc.ld\
86 tests/test-i386.c tests/test-i386-shift.h tests/test-i386.h\ 86 tests/test-i386.c tests/test-i386-shift.h tests/test-i386.h\
  87 +tests/test-i386-muldiv.h\
87 tests/test2.c tests/hello.c tests/sha1.c tests/test1.c 88 tests/test2.c tests/hello.c tests/sha1.c tests/test1.c
88 89
89 FILE=gemu-$(VERSION) 90 FILE=gemu-$(VERSION)
cpu-i386.h
@@ -149,9 +149,8 @@ typedef struct CPUX86State { @@ -149,9 +149,8 @@ typedef struct CPUX86State {
149 uint32_t segs[6]; 149 uint32_t segs[6];
150 150
151 /* emulator internal variables */ 151 /* emulator internal variables */
152 -  
153 CPU86_LDouble ft0; 152 CPU86_LDouble ft0;
154 - 153 +
155 /* exception handling */ 154 /* exception handling */
156 jmp_buf jmp_env; 155 jmp_buf jmp_env;
157 int exception_index; 156 int exception_index;
ops_template.h
@@ -175,12 +175,13 @@ static int glue(compute_all_dec, SUFFIX)(void) @@ -175,12 +175,13 @@ static int glue(compute_all_dec, SUFFIX)(void)
175 static int glue(compute_all_shl, SUFFIX)(void) 175 static int glue(compute_all_shl, SUFFIX)(void)
176 { 176 {
177 int cf, pf, af, zf, sf, of; 177 int cf, pf, af, zf, sf, of;
178 - cf = CC_SRC & 1; 178 + cf = (CC_SRC >> (DATA_BITS - 1)) & CC_C;
179 pf = parity_table[(uint8_t)CC_DST]; 179 pf = parity_table[(uint8_t)CC_DST];
180 af = 0; /* undefined */ 180 af = 0; /* undefined */
181 zf = ((DATA_TYPE)CC_DST == 0) << 6; 181 zf = ((DATA_TYPE)CC_DST == 0) << 6;
182 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80; 182 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
183 - of = lshift(CC_SRC, 12 - DATA_BITS) & CC_O; /* only meaniful for shr with count == 1 */ 183 + /* of is defined if shift count == 1 */
  184 + of = lshift(CC_SRC ^ CC_DST, 12 - DATA_BITS) & CC_O;
184 return cf | pf | af | zf | sf | of; 185 return cf | pf | af | zf | sf | of;
185 } 186 }
186 187
@@ -199,7 +200,8 @@ static int glue(compute_all_sar, SUFFIX)(void) @@ -199,7 +200,8 @@ static int glue(compute_all_sar, SUFFIX)(void)
199 af = 0; /* undefined */ 200 af = 0; /* undefined */
200 zf = ((DATA_TYPE)CC_DST == 0) << 6; 201 zf = ((DATA_TYPE)CC_DST == 0) << 6;
201 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80; 202 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
202 - of = 0; /* only meaniful for shr with count == 1 */ 203 + /* of is defined if shift count == 1 */
  204 + of = lshift(CC_SRC ^ CC_DST, 12 - DATA_BITS) & CC_O;
203 return cf | pf | af | zf | sf | of; 205 return cf | pf | af | zf | sf | of;
204 } 206 }
205 207
@@ -415,13 +417,8 @@ void OPPROTO glue(glue(op_shl, SUFFIX), _T0_T1_cc)(void) @@ -415,13 +417,8 @@ void OPPROTO glue(glue(op_shl, SUFFIX), _T0_T1_cc)(void)
415 { 417 {
416 int count; 418 int count;
417 count = T1 & 0x1f; 419 count = T1 & 0x1f;
418 - if (count == 1) {  
419 - CC_SRC = T0;  
420 - T0 = T0 << 1;  
421 - CC_DST = T0;  
422 - CC_OP = CC_OP_ADDB + SHIFT;  
423 - } else if (count) {  
424 - CC_SRC = (DATA_TYPE)T0 >> (DATA_BITS - count); 420 + if (count) {
  421 + CC_SRC = (DATA_TYPE)T0 << (count - 1);
425 T0 = T0 << count; 422 T0 = T0 << count;
426 CC_DST = T0; 423 CC_DST = T0;
427 CC_OP = CC_OP_SHLB + SHIFT; 424 CC_OP = CC_OP_SHLB + SHIFT;
@@ -438,7 +435,7 @@ void OPPROTO glue(glue(op_shr, SUFFIX), _T0_T1_cc)(void) @@ -438,7 +435,7 @@ void OPPROTO glue(glue(op_shr, SUFFIX), _T0_T1_cc)(void)
438 CC_SRC = T0 >> (count - 1); 435 CC_SRC = T0 >> (count - 1);
439 T0 = T0 >> count; 436 T0 = T0 >> count;
440 CC_DST = T0; 437 CC_DST = T0;
441 - CC_OP = CC_OP_SHLB + SHIFT; 438 + CC_OP = CC_OP_SARB + SHIFT;
442 } 439 }
443 FORCE_RET(); 440 FORCE_RET();
444 } 441 }
@@ -449,7 +446,7 @@ void OPPROTO glue(glue(op_sar, SUFFIX), _T0_T1_cc)(void) @@ -449,7 +446,7 @@ void OPPROTO glue(glue(op_sar, SUFFIX), _T0_T1_cc)(void)
449 count = T1 & 0x1f; 446 count = T1 & 0x1f;
450 if (count) { 447 if (count) {
451 src = (DATA_STYPE)T0; 448 src = (DATA_STYPE)T0;
452 - CC_SRC = src >> (count - 1); 449 + CC_SRC = src >> (count - 1);
453 T0 = src >> count; 450 T0 = src >> count;
454 CC_DST = T0; 451 CC_DST = T0;
455 CC_OP = CC_OP_SARB + SHIFT; 452 CC_OP = CC_OP_SARB + SHIFT;
@@ -457,6 +454,129 @@ void OPPROTO glue(glue(op_sar, SUFFIX), _T0_T1_cc)(void) @@ -457,6 +454,129 @@ void OPPROTO glue(glue(op_sar, SUFFIX), _T0_T1_cc)(void)
457 FORCE_RET(); 454 FORCE_RET();
458 } 455 }
459 456
  457 +#if DATA_BITS == 16
  458 +/* XXX: overflow flag might be incorrect in some cases in shldw */
  459 +void OPPROTO glue(glue(op_shld, SUFFIX), _T0_T1_im_cc)(void)
  460 +{
  461 + int count;
  462 + unsigned int res;
  463 + count = PARAM1;
  464 + T1 &= 0xffff;
  465 + res = T1 | (T0 << 16);
  466 + CC_SRC = res >> (32 - count);
  467 + res <<= count;
  468 + if (count > 16)
  469 + res |= T1 << (count - 16);
  470 + T0 = res >> 16;
  471 + CC_DST = T0;
  472 +}
  473 +
  474 +void OPPROTO glue(glue(op_shld, SUFFIX), _T0_T1_ECX_cc)(void)
  475 +{
  476 + int count;
  477 + unsigned int res;
  478 + count = ECX & 0x1f;
  479 + if (count) {
  480 + T1 &= 0xffff;
  481 + res = T1 | (T0 << 16);
  482 + CC_SRC = res >> (32 - count);
  483 + res <<= count;
  484 + if (count > 16)
  485 + res |= T1 << (count - 16);
  486 + T0 = res >> 16;
  487 + CC_DST = T0;
  488 + CC_OP = CC_OP_SARB + SHIFT;
  489 + }
  490 +}
  491 +
  492 +void OPPROTO glue(glue(op_shrd, SUFFIX), _T0_T1_im_cc)(void)
  493 +{
  494 + int count;
  495 + unsigned int res;
  496 +
  497 + count = PARAM1;
  498 + res = (T0 & 0xffff) | (T1 << 16);
  499 + CC_SRC = res >> (count - 1);
  500 + res >>= count;
  501 + if (count > 16)
  502 + res |= T1 << (32 - count);
  503 + T0 = res;
  504 + CC_DST = T0;
  505 +}
  506 +
  507 +
  508 +void OPPROTO glue(glue(op_shrd, SUFFIX), _T0_T1_ECX_cc)(void)
  509 +{
  510 + int count;
  511 + unsigned int res;
  512 +
  513 + count = ECX & 0x1f;
  514 + if (count) {
  515 + res = (T0 & 0xffff) | (T1 << 16);
  516 + CC_SRC = res >> (count - 1);
  517 + res >>= count;
  518 + if (count > 16)
  519 + res |= T1 << (32 - count);
  520 + T0 = res;
  521 + CC_DST = T0;
  522 + CC_OP = CC_OP_SARB + SHIFT;
  523 + }
  524 +}
  525 +#endif
  526 +
  527 +#if DATA_BITS == 32
  528 +void OPPROTO glue(glue(op_shld, SUFFIX), _T0_T1_im_cc)(void)
  529 +{
  530 + int count;
  531 + count = PARAM1;
  532 + T0 &= DATA_MASK;
  533 + T1 &= DATA_MASK;
  534 + CC_SRC = T0 << (count - 1);
  535 + T0 = (T0 << count) | (T1 >> (DATA_BITS - count));
  536 + CC_DST = T0;
  537 +}
  538 +
  539 +void OPPROTO glue(glue(op_shld, SUFFIX), _T0_T1_ECX_cc)(void)
  540 +{
  541 + int count;
  542 + count = ECX & 0x1f;
  543 + if (count) {
  544 + T0 &= DATA_MASK;
  545 + T1 &= DATA_MASK;
  546 + CC_SRC = T0 << (count - 1);
  547 + T0 = (T0 << count) | (T1 >> (DATA_BITS - count));
  548 + CC_DST = T0;
  549 + CC_OP = CC_OP_SHLB + SHIFT;
  550 + }
  551 +}
  552 +
  553 +void OPPROTO glue(glue(op_shrd, SUFFIX), _T0_T1_im_cc)(void)
  554 +{
  555 + int count;
  556 + count = PARAM1;
  557 + T0 &= DATA_MASK;
  558 + T1 &= DATA_MASK;
  559 + CC_SRC = T0 >> (count - 1);
  560 + T0 = (T0 >> count) | (T1 << (DATA_BITS - count));
  561 + CC_DST = T0;
  562 +}
  563 +
  564 +
  565 +void OPPROTO glue(glue(op_shrd, SUFFIX), _T0_T1_ECX_cc)(void)
  566 +{
  567 + int count;
  568 + count = ECX & 0x1f;
  569 + if (count) {
  570 + T0 &= DATA_MASK;
  571 + T1 &= DATA_MASK;
  572 + CC_SRC = T0 >> (count - 1);
  573 + T0 = (T0 >> count) | (T1 << (DATA_BITS - count));
  574 + CC_DST = T0;
  575 + CC_OP = CC_OP_SARB + SHIFT;
  576 + }
  577 +}
  578 +#endif
  579 +
460 /* carry add/sub (we only need to set CC_OP differently) */ 580 /* carry add/sub (we only need to set CC_OP differently) */
461 581
462 void OPPROTO glue(glue(op_adc, SUFFIX), _T0_T1_cc)(void) 582 void OPPROTO glue(glue(op_adc, SUFFIX), _T0_T1_cc)(void)
tests/Makefile
@@ -19,7 +19,7 @@ test2: test2.c @@ -19,7 +19,7 @@ test2: test2.c
19 $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< 19 $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $<
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 test-i386-muldiv.h
23 $(CC) $(CFLAGS) $(LDFLAGS) -static -o $@ $< 23 $(CC) $(CFLAGS) $(LDFLAGS) -static -o $@ $<
24 24
25 test: test-i386 25 test: test-i386
tests/test-i386-muldiv.h 0 โ†’ 100644
  1 +
  2 +void glue(glue(test_, OP), b)(int op0, int op1)
  3 +{
  4 + int res, s1, s0, flags;
  5 + s0 = op0;
  6 + s1 = op1;
  7 + res = s0;
  8 + flags = 0;
  9 + asm ("push %4\n\t"
  10 + "popf\n\t"
  11 + stringify(OP)"b %b2\n\t"
  12 + "pushf\n\t"
  13 + "popl %1\n\t"
  14 + : "=a" (res), "=g" (flags)
  15 + : "q" (s1), "0" (res), "1" (flags));
  16 + printf("%-10s A=%08x B=%08x R=%08x CC=%04x\n",
  17 + stringify(OP) "b", s0, s1, res, flags & CC_MASK);
  18 +}
  19 +
  20 +void glue(glue(test_, OP), w)(int op0h, int op0, int op1)
  21 +{
  22 + int res, s1, flags, resh;
  23 + s1 = op1;
  24 + resh = op0h;
  25 + res = op0;
  26 + flags = 0;
  27 + asm ("push %5\n\t"
  28 + "popf\n\t"
  29 + stringify(OP) "w %w3\n\t"
  30 + "pushf\n\t"
  31 + "popl %1\n\t"
  32 + : "=a" (res), "=g" (flags), "=d" (resh)
  33 + : "q" (s1), "0" (res), "1" (flags), "2" (resh));
  34 + printf("%-10s AH=%08x AL=%08x B=%08x RH=%08x RL=%08x CC=%04x\n",
  35 + stringify(OP) "w", op0h, op0, s1, resh, res, flags & CC_MASK);
  36 +}
  37 +
  38 +void glue(glue(test_, OP), l)(int op0h, int op0, int op1)
  39 +{
  40 + int res, s1, flags, resh;
  41 + s1 = op1;
  42 + resh = op0h;
  43 + res = op0;
  44 + flags = 0;
  45 + asm ("push %5\n\t"
  46 + "popf\n\t"
  47 + stringify(OP) "l %3\n\t"
  48 + "pushf\n\t"
  49 + "popl %1\n\t"
  50 + : "=a" (res), "=g" (flags), "=d" (resh)
  51 + : "q" (s1), "0" (res), "1" (flags), "2" (resh));
  52 + printf("%-10s AH=%08x AL=%08x B=%08x RH=%08x RL=%08x CC=%04x\n",
  53 + stringify(OP) "l", op0h, op0, s1, resh, res, flags & CC_MASK);
  54 +}
  55 +
  56 +#undef OP
tests/test-i386-shift.h
@@ -4,7 +4,19 @@ @@ -4,7 +4,19 @@
4 #define exec_opw glue(glue(exec_, OP), w) 4 #define exec_opw glue(glue(exec_, OP), w)
5 #define exec_opb glue(glue(exec_, OP), b) 5 #define exec_opb glue(glue(exec_, OP), b)
6 6
7 -#define EXECSHIFT(size, res, s1, flags) \ 7 +#ifndef OP_SHIFTD
  8 +
  9 +#ifdef OP_NOBYTE
  10 +#define EXECSHIFT(size, res, s1, s2, flags) \
  11 + asm ("push %4\n\t"\
  12 + "popf\n\t"\
  13 + stringify(OP) size " %" size "2, %" size "0\n\t" \
  14 + "pushf\n\t"\
  15 + "popl %1\n\t"\
  16 + : "=g" (res), "=g" (flags)\
  17 + : "r" (s1), "0" (res), "1" (flags));
  18 +#else
  19 +#define EXECSHIFT(size, res, s1, s2, flags) \
8 asm ("push %4\n\t"\ 20 asm ("push %4\n\t"\
9 "popf\n\t"\ 21 "popf\n\t"\
10 stringify(OP) size " %%cl, %" size "0\n\t" \ 22 stringify(OP) size " %%cl, %" size "0\n\t" \
@@ -12,13 +24,14 @@ @@ -12,13 +24,14 @@
12 "popl %1\n\t"\ 24 "popl %1\n\t"\
13 : "=q" (res), "=g" (flags)\ 25 : "=q" (res), "=g" (flags)\
14 : "c" (s1), "0" (res), "1" (flags)); 26 : "c" (s1), "0" (res), "1" (flags));
  27 +#endif
15 28
16 -void exec_opl(int s0, int s1, int iflags) 29 +void exec_opl(int s2, int s0, int s1, int iflags)
17 { 30 {
18 int res, flags; 31 int res, flags;
19 res = s0; 32 res = s0;
20 flags = iflags; 33 flags = iflags;
21 - EXECSHIFT("", res, s1, flags); 34 + EXECSHIFT("", res, s1, s2, flags);
22 /* overflow is undefined if count != 1 */ 35 /* overflow is undefined if count != 1 */
23 if (s1 != 1) 36 if (s1 != 1)
24 flags &= ~CC_O; 37 flags &= ~CC_O;
@@ -26,12 +39,12 @@ void exec_opl(int s0, int s1, int iflags) @@ -26,12 +39,12 @@ void exec_opl(int s0, int s1, int iflags)
26 stringify(OP) "l", s0, s1, res, iflags, flags & CC_MASK); 39 stringify(OP) "l", s0, s1, res, iflags, flags & CC_MASK);
27 } 40 }
28 41
29 -void exec_opw(int s0, int s1, int iflags) 42 +void exec_opw(int s2, int s0, int s1, int iflags)
30 { 43 {
31 int res, flags; 44 int res, flags;
32 res = s0; 45 res = s0;
33 flags = iflags; 46 flags = iflags;
34 - EXECSHIFT("w", res, s1, flags); 47 + EXECSHIFT("w", res, s1, s2, flags);
35 /* overflow is undefined if count != 1 */ 48 /* overflow is undefined if count != 1 */
36 if (s1 != 1) 49 if (s1 != 1)
37 flags &= ~CC_O; 50 flags &= ~CC_O;
@@ -39,27 +52,69 @@ void exec_opw(int s0, int s1, int iflags) @@ -39,27 +52,69 @@ void exec_opw(int s0, int s1, int iflags)
39 stringify(OP) "w", s0, s1, res, iflags, flags & CC_MASK); 52 stringify(OP) "w", s0, s1, res, iflags, flags & CC_MASK);
40 } 53 }
41 54
  55 +#else
  56 +#define EXECSHIFT(size, res, s1, s2, flags) \
  57 + asm ("push %4\n\t"\
  58 + "popf\n\t"\
  59 + stringify(OP) size " %%cl, %" size "5, %" size "0\n\t" \
  60 + "pushf\n\t"\
  61 + "popl %1\n\t"\
  62 + : "=g" (res), "=g" (flags)\
  63 + : "c" (s1), "0" (res), "1" (flags), "r" (s2));
  64 +
  65 +void exec_opl(int s2, int s0, int s1, int iflags)
  66 +{
  67 + int res, flags;
  68 + res = s0;
  69 + flags = iflags;
  70 + EXECSHIFT("", res, s1, s2, flags);
  71 + /* overflow is undefined if count != 1 */
  72 + if (s1 != 1)
  73 + flags &= ~CC_O;
  74 + printf("%-10s A=%08x B=%08x C=%08x R=%08x CCIN=%04x CC=%04x\n",
  75 + stringify(OP) "l", s0, s2, s1, res, iflags, flags & CC_MASK);
  76 +}
  77 +
  78 +void exec_opw(int s2, int s0, int s1, int iflags)
  79 +{
  80 + int res, flags;
  81 + res = s0;
  82 + flags = iflags;
  83 + EXECSHIFT("w", res, s1, s2, flags);
  84 + /* overflow is undefined if count != 1 */
  85 + if (s1 != 1)
  86 + flags &= ~CC_O;
  87 + printf("%-10s A=%08x B=%08x C=%08x R=%08x CCIN=%04x CC=%04x\n",
  88 + stringify(OP) "w", s0, s2, s1, res, iflags, flags & CC_MASK);
  89 +}
  90 +
  91 +#endif
  92 +
  93 +#ifndef OP_NOBYTE
42 void exec_opb(int s0, int s1, int iflags) 94 void exec_opb(int s0, int s1, int iflags)
43 { 95 {
44 int res, flags; 96 int res, flags;
45 res = s0; 97 res = s0;
46 flags = iflags; 98 flags = iflags;
47 - EXECSHIFT("b", res, s1, flags); 99 + EXECSHIFT("b", res, s1, 0, flags);
48 /* overflow is undefined if count != 1 */ 100 /* overflow is undefined if count != 1 */
49 if (s1 != 1) 101 if (s1 != 1)
50 flags &= ~CC_O; 102 flags &= ~CC_O;
51 printf("%-10s A=%08x B=%08x R=%08x CCIN=%04x CC=%04x\n", 103 printf("%-10s A=%08x B=%08x R=%08x CCIN=%04x CC=%04x\n",
52 stringify(OP) "b", s0, s1, res, iflags, flags & CC_MASK); 104 stringify(OP) "b", s0, s1, res, iflags, flags & CC_MASK);
53 } 105 }
  106 +#endif
54 107
55 -void exec_op(int s0, int s1) 108 +void exec_op(int s2, int s0, int s1)
56 { 109 {
57 - exec_opl(s0, s1, 0);  
58 - exec_opw(s0, s1, 0); 110 + exec_opl(s2, s0, s1, 0);
  111 + exec_opw(s2, s0, s1, 0);
  112 +#ifndef OP_NOBYTE
59 exec_opb(s0, s1, 0); 113 exec_opb(s0, s1, 0);
  114 +#endif
60 #ifdef OP_CC 115 #ifdef OP_CC
61 - exec_opl(s0, s1, CC_C);  
62 - exec_opw(s0, s1, CC_C); 116 + exec_opl(s2, s0, s1, CC_C);
  117 + exec_opw(s2, s0, s1, CC_C);
63 exec_opb(s0, s1, CC_C); 118 exec_opb(s0, s1, CC_C);
64 #endif 119 #endif
65 } 120 }
@@ -68,12 +123,16 @@ void glue(test_, OP)(void) @@ -68,12 +123,16 @@ void glue(test_, OP)(void)
68 { 123 {
69 int i; 124 int i;
70 for(i = 0; i < 32; i++) 125 for(i = 0; i < 32; i++)
71 - exec_op(0x12345678, i); 126 + exec_op(0x21ad3d34, 0x12345678, i);
72 for(i = 0; i < 32; i++) 127 for(i = 0; i < 32; i++)
73 - exec_op(0x82345678, i); 128 + exec_op(0x813f3421, 0x82345678, i);
74 } 129 }
75 130
76 void *glue(_test_, OP) __init_call = glue(test_, OP); 131 void *glue(_test_, OP) __init_call = glue(test_, OP);
77 132
78 #undef OP 133 #undef OP
79 #undef OP_CC 134 #undef OP_CC
  135 +#undef OP_SHIFTD
  136 +#undef OP_NOBYTE
  137 +#undef EXECSHIFT
  138 +
tests/test-i386.c
@@ -92,6 +92,35 @@ static void *call_start __init_call = NULL; @@ -92,6 +92,35 @@ static void *call_start __init_call = NULL;
92 #define OP_CC 92 #define OP_CC
93 #include "test-i386-shift.h" 93 #include "test-i386-shift.h"
94 94
  95 +#define OP shld
  96 +#define OP_SHIFTD
  97 +#define OP_NOBYTE
  98 +#include "test-i386-shift.h"
  99 +
  100 +#define OP shrd
  101 +#define OP_SHIFTD
  102 +#define OP_NOBYTE
  103 +#include "test-i386-shift.h"
  104 +
  105 +/* XXX: should be more precise ? */
  106 +#undef CC_MASK
  107 +#define CC_MASK (CC_C)
  108 +
  109 +#define OP bt
  110 +#define OP_NOBYTE
  111 +#include "test-i386-shift.h"
  112 +
  113 +#define OP bts
  114 +#define OP_NOBYTE
  115 +#include "test-i386-shift.h"
  116 +
  117 +#define OP btr
  118 +#define OP_NOBYTE
  119 +#include "test-i386-shift.h"
  120 +
  121 +#define OP btc
  122 +#define OP_NOBYTE
  123 +#include "test-i386-shift.h"
95 124
96 /* lea test (modrm support) */ 125 /* lea test (modrm support) */
97 #define TEST_LEA(STR)\ 126 #define TEST_LEA(STR)\
@@ -403,15 +432,13 @@ int main(int argc, char **argv) @@ -403,15 +432,13 @@ int main(int argc, char **argv)
403 void **ptr; 432 void **ptr;
404 void (*func)(void); 433 void (*func)(void);
405 434
406 - test_mul();  
407 -#if 0  
408 ptr = &call_start + 1; 435 ptr = &call_start + 1;
409 while (*ptr != NULL) { 436 while (*ptr != NULL) {
410 func = *ptr++; 437 func = *ptr++;
411 func(); 438 func();
412 } 439 }
  440 + test_mul();
413 test_jcc(); 441 test_jcc();
414 test_lea(); 442 test_lea();
415 -#endif  
416 return 0; 443 return 0;
417 } 444 }
tests/test-i386.h 0 โ†’ 100644
  1 +
  2 +#define exec_op glue(exec_, OP)
  3 +#define exec_opl glue(glue(exec_, OP), l)
  4 +#define exec_opw glue(glue(exec_, OP), w)
  5 +#define exec_opb glue(glue(exec_, OP), b)
  6 +
  7 +#define EXECOP2(size, res, s1, flags) \
  8 + asm ("push %4\n\t"\
  9 + "popf\n\t"\
  10 + stringify(OP) size " %" size "2, %" size "0\n\t" \
  11 + "pushf\n\t"\
  12 + "popl %1\n\t"\
  13 + : "=q" (res), "=g" (flags)\
  14 + : "q" (s1), "0" (res), "1" (flags));
  15 +
  16 +#define EXECOP1(size, res, flags) \
  17 + asm ("push %3\n\t"\
  18 + "popf\n\t"\
  19 + stringify(OP) size " %" size "0\n\t" \
  20 + "pushf\n\t"\
  21 + "popl %1\n\t"\
  22 + : "=q" (res), "=g" (flags)\
  23 + : "0" (res), "1" (flags));
  24 +
  25 +#ifdef OP1
  26 +void exec_opl(int s0, int s1, int iflags)
  27 +{
  28 + int res, flags;
  29 + res = s0;
  30 + flags = iflags;
  31 + EXECOP1("", res, flags);
  32 + printf("%-10s A=%08x R=%08x CCIN=%04x CC=%04x\n",
  33 + stringify(OP) "l", s0, res, iflags, flags & CC_MASK);
  34 +}
  35 +
  36 +void exec_opw(int s0, int s1, int iflags)
  37 +{
  38 + int res, flags;
  39 + res = s0;
  40 + flags = iflags;
  41 + EXECOP1("w", res, flags);
  42 + printf("%-10s A=%08x R=%08x CCIN=%04x CC=%04x\n",
  43 + stringify(OP) "w", s0, res, iflags, flags & CC_MASK);
  44 +}
  45 +
  46 +void exec_opb(int s0, int s1, int iflags)
  47 +{
  48 + int res, flags;
  49 + res = s0;
  50 + flags = iflags;
  51 + EXECOP1("b", res, flags);
  52 + printf("%-10s A=%08x R=%08x CCIN=%04x CC=%04x\n",
  53 + stringify(OP) "b", s0, res, iflags, flags & CC_MASK);
  54 +}
  55 +#else
  56 +void exec_opl(int s0, int s1, int iflags)
  57 +{
  58 + int res, flags;
  59 + res = s0;
  60 + flags = iflags;
  61 + EXECOP2("", res, s1, flags);
  62 + printf("%-10s A=%08x B=%08x R=%08x CCIN=%04x CC=%04x\n",
  63 + stringify(OP) "l", s0, s1, res, iflags, flags & CC_MASK);
  64 +}
  65 +
  66 +void exec_opw(int s0, int s1, int iflags)
  67 +{
  68 + int res, flags;
  69 + res = s0;
  70 + flags = iflags;
  71 + EXECOP2("w", res, s1, flags);
  72 + printf("%-10s A=%08x B=%08x R=%08x CCIN=%04x CC=%04x\n",
  73 + stringify(OP) "w", s0, s1, res, iflags, flags & CC_MASK);
  74 +}
  75 +
  76 +void exec_opb(int s0, int s1, int iflags)
  77 +{
  78 + int res, flags;
  79 + res = s0;
  80 + flags = iflags;
  81 + EXECOP2("b", res, s1, flags);
  82 + printf("%-10s A=%08x B=%08x R=%08x CCIN=%04x CC=%04x\n",
  83 + stringify(OP) "b", s0, s1, res, iflags, flags & CC_MASK);
  84 +}
  85 +#endif
  86 +
  87 +void exec_op(int s0, int s1)
  88 +{
  89 + exec_opl(s0, s1, 0);
  90 + exec_opw(s0, s1, 0);
  91 + exec_opb(s0, s1, 0);
  92 +#ifdef OP_CC
  93 + exec_opl(s0, s1, CC_C);
  94 + exec_opw(s0, s1, CC_C);
  95 + exec_opb(s0, s1, CC_C);
  96 +#endif
  97 +}
  98 +
  99 +void glue(test_, OP)(void)
  100 +{
  101 + exec_op(0x12345678, 0x812FADA);
  102 + exec_op(0x12341, 0x12341);
  103 + exec_op(0x12341, -0x12341);
  104 + exec_op(0xffffffff, 0);
  105 + exec_op(0xffffffff, -1);
  106 + exec_op(0xffffffff, 1);
  107 + exec_op(0xffffffff, 2);
  108 + exec_op(0x7fffffff, 0);
  109 + exec_op(0x7fffffff, 1);
  110 + exec_op(0x7fffffff, -1);
  111 + exec_op(0x80000000, -1);
  112 + exec_op(0x80000000, 1);
  113 + exec_op(0x80000000, -2);
  114 + exec_op(0x12347fff, 0);
  115 + exec_op(0x12347fff, 1);
  116 + exec_op(0x12347fff, -1);
  117 + exec_op(0x12348000, -1);
  118 + exec_op(0x12348000, 1);
  119 + exec_op(0x12348000, -2);
  120 + exec_op(0x12347f7f, 0);
  121 + exec_op(0x12347f7f, 1);
  122 + exec_op(0x12347f7f, -1);
  123 + exec_op(0x12348080, -1);
  124 + exec_op(0x12348080, 1);
  125 + exec_op(0x12348080, -2);
  126 +}
  127 +
  128 +void *glue(_test_, OP) __init_call = glue(test_, OP);
  129 +
  130 +#undef OP
  131 +#undef OP_CC
translate-i386.c
@@ -394,6 +394,28 @@ static GenOpFunc *gen_op_shift_T0_T1_cc[3][8] = { @@ -394,6 +394,28 @@ static GenOpFunc *gen_op_shift_T0_T1_cc[3][8] = {
394 }, 394 },
395 }; 395 };
396 396
  397 +static GenOpFunc1 *gen_op_shiftd_T0_T1_im_cc[2][2] = {
  398 + [0] = {
  399 + gen_op_shldw_T0_T1_im_cc,
  400 + gen_op_shrdw_T0_T1_im_cc,
  401 + },
  402 + [1] = {
  403 + gen_op_shldl_T0_T1_im_cc,
  404 + gen_op_shrdl_T0_T1_im_cc,
  405 + },
  406 +};
  407 +
  408 +static GenOpFunc *gen_op_shiftd_T0_T1_ECX_cc[2][2] = {
  409 + [0] = {
  410 + gen_op_shldw_T0_T1_ECX_cc,
  411 + gen_op_shrdw_T0_T1_ECX_cc,
  412 + },
  413 + [1] = {
  414 + gen_op_shldl_T0_T1_ECX_cc,
  415 + gen_op_shrdl_T0_T1_ECX_cc,
  416 + },
  417 +};
  418 +
397 static GenOpFunc *gen_op_btx_T0_T1_cc[2][4] = { 419 static GenOpFunc *gen_op_btx_T0_T1_cc[2][4] = {
398 [0] = { 420 [0] = {
399 gen_op_btw_T0_T1_cc, 421 gen_op_btw_T0_T1_cc,
@@ -1689,6 +1711,59 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr) @@ -1689,6 +1711,59 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr)
1689 shift = 0; 1711 shift = 0;
1690 goto grp2; 1712 goto grp2;
1691 1713
  1714 + case 0x1a4: /* shld imm */
  1715 + op = 0;
  1716 + shift = 1;
  1717 + goto do_shiftd;
  1718 + case 0x1a5: /* shld cl */
  1719 + op = 0;
  1720 + shift = 0;
  1721 + goto do_shiftd;
  1722 + case 0x1ac: /* shrd imm */
  1723 + op = 1;
  1724 + shift = 1;
  1725 + goto do_shiftd;
  1726 + case 0x1ad: /* shrd cl */
  1727 + op = 1;
  1728 + shift = 0;
  1729 + do_shiftd:
  1730 + ot = dflag ? OT_LONG : OT_WORD;
  1731 + modrm = ldub(s->pc++);
  1732 + mod = (modrm >> 6) & 3;
  1733 + rm = modrm & 7;
  1734 + reg = (modrm >> 3) & 7;
  1735 +
  1736 + if (mod != 3) {
  1737 + gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
  1738 + gen_op_ld_T0_A0[ot]();
  1739 + } else {
  1740 + gen_op_mov_TN_reg[ot][0][rm]();
  1741 + }
  1742 + gen_op_mov_TN_reg[ot][1][reg]();
  1743 +
  1744 + if (shift) {
  1745 + val = ldub(s->pc++);
  1746 + val &= 0x1f;
  1747 + if (val) {
  1748 + gen_op_shiftd_T0_T1_im_cc[ot - OT_WORD][op](val);
  1749 + if (op == 0 && ot != OT_WORD)
  1750 + s->cc_op = CC_OP_SHLB + ot;
  1751 + else
  1752 + s->cc_op = CC_OP_SARB + ot;
  1753 + }
  1754 + } else {
  1755 + if (s->cc_op != CC_OP_DYNAMIC)
  1756 + gen_op_set_cc_op(s->cc_op);
  1757 + gen_op_shiftd_T0_T1_ECX_cc[ot - OT_WORD][op]();
  1758 + s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
  1759 + }
  1760 + if (mod != 3) {
  1761 + gen_op_st_T0_A0[ot]();
  1762 + } else {
  1763 + gen_op_mov_reg_T0[ot][rm]();
  1764 + }
  1765 + break;
  1766 +
1692 /************************/ 1767 /************************/
1693 /* floats */ 1768 /* floats */
1694 case 0xd8 ... 0xdf: 1769 case 0xd8 ... 0xdf:
@@ -2002,6 +2077,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr) @@ -2002,6 +2077,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr)
2002 break; 2077 break;
2003 #endif 2078 #endif
2004 default: 2079 default:
  2080 + error("unhandled FP df/4\n");
2005 return -1; 2081 return -1;
2006 } 2082 }
2007 break; 2083 break;
@@ -2291,7 +2367,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr) @@ -2291,7 +2367,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr)
2291 return -1; 2367 return -1;
2292 op -= 4; 2368 op -= 4;
2293 gen_op_btx_T0_T1_cc[ot - OT_WORD][op](); 2369 gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
2294 - s->cc_op = CC_OP_SHLB + ot; 2370 + s->cc_op = CC_OP_SARB + ot;
2295 if (op != 0) { 2371 if (op != 0) {
2296 if (mod != 3) 2372 if (mod != 3)
2297 gen_op_st_T0_A0[ot](); 2373 gen_op_st_T0_A0[ot]();
@@ -2329,7 +2405,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr) @@ -2329,7 +2405,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr)
2329 gen_op_mov_TN_reg[ot][0][rm](); 2405 gen_op_mov_TN_reg[ot][0][rm]();
2330 } 2406 }
2331 gen_op_btx_T0_T1_cc[ot - OT_WORD][op](); 2407 gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
2332 - s->cc_op = CC_OP_SHLB + ot; 2408 + s->cc_op = CC_OP_SARB + ot;
2333 if (op != 0) { 2409 if (op != 0) {
2334 if (mod != 3) 2410 if (mod != 3)
2335 gen_op_st_T0_A0[ot](); 2411 gen_op_st_T0_A0[ot]();
@@ -2417,7 +2493,8 @@ int cpu_x86_gen_code(uint8_t *gen_code_buf, int *gen_code_size_ptr, @@ -2417,7 +2493,8 @@ int cpu_x86_gen_code(uint8_t *gen_code_buf, int *gen_code_size_ptr,
2417 is_jmp = 0; 2493 is_jmp = 0;
2418 ret = disas_insn(dc, pc_start, &is_jmp); 2494 ret = disas_insn(dc, pc_start, &is_jmp);
2419 if (ret == -1) 2495 if (ret == -1)
2420 - error("unknown instruction at PC=0x%x", pc_start); 2496 + error("unknown instruction at PC=0x%x B=%02x %02x",
  2497 + pc_start, pc_start[0], pc_start[1]);
2421 /* we must store the eflags state if it is not already done */ 2498 /* we must store the eflags state if it is not already done */
2422 if (dc->cc_op != CC_OP_DYNAMIC) 2499 if (dc->cc_op != CC_OP_DYNAMIC)
2423 gen_op_set_cc_op(dc->cc_op); 2500 gen_op_set_cc_op(dc->cc_op);