Commit e591824733ec698d92d1f09c2ffb9b86b799d6da
1 parent
04369ff2
added code16 tests
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@37 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
3 changed files
with
177 additions
and
56 deletions
tests/Makefile
| @@ -20,8 +20,9 @@ test2: test2.c | @@ -20,8 +20,9 @@ test2: test2.c | ||
| 20 | $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< | 20 | $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< |
| 21 | 21 | ||
| 22 | # i386 emulation test (test various opcodes) */ | 22 | # i386 emulation test (test various opcodes) */ |
| 23 | -test-i386: test-i386.c test-i386.h test-i386-shift.h test-i386-muldiv.h | ||
| 24 | - $(CC) $(CFLAGS) $(LDFLAGS) -static -o $@ $< -lm | 23 | +test-i386: test-i386.c test-i386-code16.S \ |
| 24 | + test-i386.h test-i386-shift.h test-i386-muldiv.h | ||
| 25 | + $(CC) $(CFLAGS) $(LDFLAGS) -static -o $@ test-i386.c test-i386-code16.S -lm | ||
| 25 | 26 | ||
| 26 | test: test-i386 | 27 | test: test-i386 |
| 27 | ifeq ($(ARCH),i386) | 28 | ifeq ($(ARCH),i386) |
tests/test-i386-code16.S
0 → 100644
| 1 | + .code16 | ||
| 2 | + .globl code16_start | ||
| 3 | + .globl code16_end | ||
| 4 | + | ||
| 5 | +CS_SEG = 0xf | ||
| 6 | + | ||
| 7 | +code16_start: | ||
| 8 | + | ||
| 9 | + .globl code16_func1 | ||
| 10 | + | ||
| 11 | + /* basic test */ | ||
| 12 | +code16_func1 = . - code16_start | ||
| 13 | + mov $1, %eax | ||
| 14 | + data32 lret | ||
| 15 | + | ||
| 16 | +/* test push/pop in 16 bit mode */ | ||
| 17 | + .globl code16_func2 | ||
| 18 | +code16_func2 = . - code16_start | ||
| 19 | + xor %eax, %eax | ||
| 20 | + mov $0x12345678, %ebx | ||
| 21 | + movl %esp, %ecx | ||
| 22 | + push %bx | ||
| 23 | + subl %esp, %ecx | ||
| 24 | + pop %ax | ||
| 25 | + data32 lret | ||
| 26 | + | ||
| 27 | +/* test various jmp opcodes */ | ||
| 28 | + .globl code16_func3 | ||
| 29 | +code16_func3 = . - code16_start | ||
| 30 | + jmp 1f | ||
| 31 | + nop | ||
| 32 | +1: | ||
| 33 | + mov $4, %eax | ||
| 34 | + mov $0x12345678, %ebx | ||
| 35 | + xor %bx, %bx | ||
| 36 | + jz 2f | ||
| 37 | + add $2, %ax | ||
| 38 | +2: | ||
| 39 | + | ||
| 40 | + call myfunc | ||
| 41 | + | ||
| 42 | + lcall $CS_SEG, $(myfunc2 - code16_start) | ||
| 43 | + | ||
| 44 | + ljmp $CS_SEG, $(myjmp1 - code16_start) | ||
| 45 | +myjmp1_next: | ||
| 46 | + | ||
| 47 | + cs lcall myfunc2_addr - code16_start | ||
| 48 | + | ||
| 49 | + cs ljmp myjmp2_addr - code16_start | ||
| 50 | +myjmp2_next: | ||
| 51 | + | ||
| 52 | + data32 lret | ||
| 53 | + | ||
| 54 | +myfunc2_addr: | ||
| 55 | + .short myfunc2 - code16_start | ||
| 56 | + .short CS_SEG | ||
| 57 | + | ||
| 58 | +myjmp2_addr: | ||
| 59 | + .short myjmp2 - code16_start | ||
| 60 | + .short CS_SEG | ||
| 61 | + | ||
| 62 | +myjmp1: | ||
| 63 | + add $8, %ax | ||
| 64 | + jmp myjmp1_next | ||
| 65 | + | ||
| 66 | +myjmp2: | ||
| 67 | + add $16, %ax | ||
| 68 | + jmp myjmp2_next | ||
| 69 | + | ||
| 70 | +myfunc: | ||
| 71 | + add $1, %ax | ||
| 72 | + ret | ||
| 73 | + | ||
| 74 | +myfunc2: | ||
| 75 | + add $4, %ax | ||
| 76 | + lret | ||
| 77 | + | ||
| 78 | + | ||
| 79 | +code16_end: | ||
| 80 | + | ||
| 0 | \ No newline at end of file | 81 | \ No newline at end of file |
tests/test-i386.c
| @@ -635,6 +635,65 @@ void test_bcd(void) | @@ -635,6 +635,65 @@ void test_bcd(void) | ||
| 635 | TEST_BCD(aad, 0x12340407, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A)); | 635 | TEST_BCD(aad, 0x12340407, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A)); |
| 636 | } | 636 | } |
| 637 | 637 | ||
| 638 | +#define TEST_XCHG(op, size, opconst)\ | ||
| 639 | +{\ | ||
| 640 | + int op0, op1;\ | ||
| 641 | + op0 = 0x12345678;\ | ||
| 642 | + op1 = 0xfbca7654;\ | ||
| 643 | + asm(#op " %" size "0, %" size "1" \ | ||
| 644 | + : "=q" (op0), opconst (op1) \ | ||
| 645 | + : "0" (op0), "1" (op1));\ | ||
| 646 | + printf("%-10s A=%08x B=%08x\n",\ | ||
| 647 | + #op, op0, op1);\ | ||
| 648 | +} | ||
| 649 | + | ||
| 650 | +#define TEST_CMPXCHG(op, size, opconst, eax)\ | ||
| 651 | +{\ | ||
| 652 | + int op0, op1;\ | ||
| 653 | + op0 = 0x12345678;\ | ||
| 654 | + op1 = 0xfbca7654;\ | ||
| 655 | + asm(#op " %" size "0, %" size "1" \ | ||
| 656 | + : "=q" (op0), opconst (op1) \ | ||
| 657 | + : "0" (op0), "1" (op1), "a" (eax));\ | ||
| 658 | + printf("%-10s EAX=%08x A=%08x C=%08x\n",\ | ||
| 659 | + #op, eax, op0, op1);\ | ||
| 660 | +} | ||
| 661 | + | ||
| 662 | +void test_xchg(void) | ||
| 663 | +{ | ||
| 664 | + TEST_XCHG(xchgl, "", "=q"); | ||
| 665 | + TEST_XCHG(xchgw, "w", "=q"); | ||
| 666 | + TEST_XCHG(xchgb, "b", "=q"); | ||
| 667 | + | ||
| 668 | + TEST_XCHG(xchgl, "", "=m"); | ||
| 669 | + TEST_XCHG(xchgw, "w", "=m"); | ||
| 670 | + TEST_XCHG(xchgb, "b", "=m"); | ||
| 671 | + | ||
| 672 | + TEST_XCHG(xaddl, "", "=q"); | ||
| 673 | + TEST_XCHG(xaddw, "w", "=q"); | ||
| 674 | + TEST_XCHG(xaddb, "b", "=q"); | ||
| 675 | + | ||
| 676 | + TEST_XCHG(xaddl, "", "=m"); | ||
| 677 | + TEST_XCHG(xaddw, "w", "=m"); | ||
| 678 | + TEST_XCHG(xaddb, "b", "=m"); | ||
| 679 | + | ||
| 680 | + TEST_CMPXCHG(cmpxchgl, "", "=q", 0xfbca7654); | ||
| 681 | + TEST_CMPXCHG(cmpxchgw, "w", "=q", 0xfbca7654); | ||
| 682 | + TEST_CMPXCHG(cmpxchgb, "b", "=q", 0xfbca7654); | ||
| 683 | + | ||
| 684 | + TEST_CMPXCHG(cmpxchgl, "", "=q", 0xfffefdfc); | ||
| 685 | + TEST_CMPXCHG(cmpxchgw, "w", "=q", 0xfffefdfc); | ||
| 686 | + TEST_CMPXCHG(cmpxchgb, "b", "=q", 0xfffefdfc); | ||
| 687 | + | ||
| 688 | + TEST_CMPXCHG(cmpxchgl, "", "=m", 0xfbca7654); | ||
| 689 | + TEST_CMPXCHG(cmpxchgw, "w", "=m", 0xfbca7654); | ||
| 690 | + TEST_CMPXCHG(cmpxchgb, "b", "=m", 0xfbca7654); | ||
| 691 | + | ||
| 692 | + TEST_CMPXCHG(cmpxchgl, "", "=m", 0xfffefdfc); | ||
| 693 | + TEST_CMPXCHG(cmpxchgw, "w", "=m", 0xfffefdfc); | ||
| 694 | + TEST_CMPXCHG(cmpxchgb, "b", "=m", 0xfffefdfc); | ||
| 695 | +} | ||
| 696 | + | ||
| 638 | /**********************************************/ | 697 | /**********************************************/ |
| 639 | /* segmentation tests */ | 698 | /* segmentation tests */ |
| 640 | 699 | ||
| @@ -646,7 +705,7 @@ _syscall3(int, modify_ldt, int, func, void *, ptr, unsigned long, bytecount) | @@ -646,7 +705,7 @@ _syscall3(int, modify_ldt, int, func, void *, ptr, unsigned long, bytecount) | ||
| 646 | uint8_t seg_data1[4096]; | 705 | uint8_t seg_data1[4096]; |
| 647 | uint8_t seg_data2[4096]; | 706 | uint8_t seg_data2[4096]; |
| 648 | 707 | ||
| 649 | -#define MK_SEL(n) (((n) << 3) | 4) | 708 | +#define MK_SEL(n) (((n) << 3) | 7) |
| 650 | 709 | ||
| 651 | /* NOTE: we use Linux modify_ldt syscall */ | 710 | /* NOTE: we use Linux modify_ldt syscall */ |
| 652 | void test_segs(void) | 711 | void test_segs(void) |
| @@ -715,65 +774,45 @@ void test_segs(void) | @@ -715,65 +774,45 @@ void test_segs(void) | ||
| 715 | printf("SS[tmp] = %02x\n", res2); | 774 | printf("SS[tmp] = %02x\n", res2); |
| 716 | } | 775 | } |
| 717 | 776 | ||
| 718 | -#define TEST_XCHG(op, size, opconst)\ | ||
| 719 | -{\ | ||
| 720 | - int op0, op1;\ | ||
| 721 | - op0 = 0x12345678;\ | ||
| 722 | - op1 = 0xfbca7654;\ | ||
| 723 | - asm(#op " %" size "0, %" size "1" \ | ||
| 724 | - : "=q" (op0), opconst (op1) \ | ||
| 725 | - : "0" (op0), "1" (op1));\ | ||
| 726 | - printf("%-10s A=%08x B=%08x\n",\ | ||
| 727 | - #op, op0, op1);\ | ||
| 728 | -} | ||
| 729 | - | ||
| 730 | -#define TEST_CMPXCHG(op, size, opconst, eax)\ | ||
| 731 | -{\ | ||
| 732 | - int op0, op1;\ | ||
| 733 | - op0 = 0x12345678;\ | ||
| 734 | - op1 = 0xfbca7654;\ | ||
| 735 | - asm(#op " %" size "0, %" size "1" \ | ||
| 736 | - : "=q" (op0), opconst (op1) \ | ||
| 737 | - : "0" (op0), "1" (op1), "a" (eax));\ | ||
| 738 | - printf("%-10s EAX=%08x A=%08x C=%08x\n",\ | ||
| 739 | - #op, eax, op0, op1);\ | ||
| 740 | -} | 777 | +/* 16 bit code test */ |
| 778 | +extern char code16_start, code16_end; | ||
| 779 | +extern char code16_func1; | ||
| 780 | +extern char code16_func2; | ||
| 781 | +extern char code16_func3; | ||
| 741 | 782 | ||
| 742 | -void test_xchg(void) | 783 | +void test_code16(void) |
| 743 | { | 784 | { |
| 744 | - TEST_XCHG(xchgl, "", "=q"); | ||
| 745 | - TEST_XCHG(xchgw, "w", "=q"); | ||
| 746 | - TEST_XCHG(xchgb, "b", "=q"); | ||
| 747 | - | ||
| 748 | - TEST_XCHG(xchgl, "", "=m"); | ||
| 749 | - TEST_XCHG(xchgw, "w", "=m"); | ||
| 750 | - TEST_XCHG(xchgb, "b", "=m"); | ||
| 751 | - | ||
| 752 | - TEST_XCHG(xaddl, "", "=q"); | ||
| 753 | - TEST_XCHG(xaddw, "w", "=q"); | ||
| 754 | - TEST_XCHG(xaddb, "b", "=q"); | ||
| 755 | - | ||
| 756 | - TEST_XCHG(xaddl, "", "=m"); | ||
| 757 | - TEST_XCHG(xaddw, "w", "=m"); | ||
| 758 | - TEST_XCHG(xaddb, "b", "=m"); | ||
| 759 | - | ||
| 760 | - TEST_CMPXCHG(cmpxchgl, "", "=q", 0xfbca7654); | ||
| 761 | - TEST_CMPXCHG(cmpxchgw, "w", "=q", 0xfbca7654); | ||
| 762 | - TEST_CMPXCHG(cmpxchgb, "b", "=q", 0xfbca7654); | ||
| 763 | - | ||
| 764 | - TEST_CMPXCHG(cmpxchgl, "", "=q", 0xfffefdfc); | ||
| 765 | - TEST_CMPXCHG(cmpxchgw, "w", "=q", 0xfffefdfc); | ||
| 766 | - TEST_CMPXCHG(cmpxchgb, "b", "=q", 0xfffefdfc); | 785 | + struct modify_ldt_ldt_s ldt; |
| 786 | + int res, res2; | ||
| 767 | 787 | ||
| 768 | - TEST_CMPXCHG(cmpxchgl, "", "=m", 0xfbca7654); | ||
| 769 | - TEST_CMPXCHG(cmpxchgw, "w", "=m", 0xfbca7654); | ||
| 770 | - TEST_CMPXCHG(cmpxchgb, "b", "=m", 0xfbca7654); | 788 | + /* build a code segment */ |
| 789 | + ldt.entry_number = 1; | ||
| 790 | + ldt.base_addr = (unsigned long)&code16_start; | ||
| 791 | + ldt.limit = &code16_end - &code16_start; | ||
| 792 | + ldt.seg_32bit = 0; | ||
| 793 | + ldt.contents = MODIFY_LDT_CONTENTS_CODE; | ||
| 794 | + ldt.read_exec_only = 0; | ||
| 795 | + ldt.limit_in_pages = 0; | ||
| 796 | + ldt.seg_not_present = 0; | ||
| 797 | + ldt.useable = 1; | ||
| 798 | + modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */ | ||
| 771 | 799 | ||
| 772 | - TEST_CMPXCHG(cmpxchgl, "", "=m", 0xfffefdfc); | ||
| 773 | - TEST_CMPXCHG(cmpxchgw, "w", "=m", 0xfffefdfc); | ||
| 774 | - TEST_CMPXCHG(cmpxchgb, "b", "=m", 0xfffefdfc); | 800 | + /* call the first function */ |
| 801 | + asm volatile ("lcall %1, %2" | ||
| 802 | + : "=a" (res) | ||
| 803 | + : "i" (MK_SEL(1)), "i" (&code16_func1): "memory", "cc"); | ||
| 804 | + printf("func1() = 0x%08x\n", res); | ||
| 805 | + asm volatile ("lcall %2, %3" | ||
| 806 | + : "=a" (res), "=c" (res2) | ||
| 807 | + : "i" (MK_SEL(1)), "i" (&code16_func2): "memory", "cc"); | ||
| 808 | + printf("func2() = 0x%08x spdec=%d\n", res, res2); | ||
| 809 | + asm volatile ("lcall %1, %2" | ||
| 810 | + : "=a" (res) | ||
| 811 | + : "i" (MK_SEL(1)), "i" (&code16_func3): "memory", "cc"); | ||
| 812 | + printf("func3() = 0x%08x\n", res); | ||
| 775 | } | 813 | } |
| 776 | 814 | ||
| 815 | + | ||
| 777 | static void *call_end __init_call = NULL; | 816 | static void *call_end __init_call = NULL; |
| 778 | 817 | ||
| 779 | int main(int argc, char **argv) | 818 | int main(int argc, char **argv) |
| @@ -794,5 +833,6 @@ int main(int argc, char **argv) | @@ -794,5 +833,6 @@ int main(int argc, char **argv) | ||
| 794 | test_xchg(); | 833 | test_xchg(); |
| 795 | test_lea(); | 834 | test_lea(); |
| 796 | test_segs(); | 835 | test_segs(); |
| 836 | + test_code16(); | ||
| 797 | return 0; | 837 | return 0; |
| 798 | } | 838 | } |