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 | 20 | $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< |
| 21 | 21 | |
| 22 | 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 | 27 | test: test-i386 |
| 27 | 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 | 81 | \ No newline at end of file | ... | ... |
tests/test-i386.c
| ... | ... | @@ -635,6 +635,65 @@ void test_bcd(void) |
| 635 | 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 | 698 | /* segmentation tests */ |
| 640 | 699 | |
| ... | ... | @@ -646,7 +705,7 @@ _syscall3(int, modify_ldt, int, func, void *, ptr, unsigned long, bytecount) |
| 646 | 705 | uint8_t seg_data1[4096]; |
| 647 | 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 | 710 | /* NOTE: we use Linux modify_ldt syscall */ |
| 652 | 711 | void test_segs(void) |
| ... | ... | @@ -715,65 +774,45 @@ void test_segs(void) |
| 715 | 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 | 816 | static void *call_end __init_call = NULL; |
| 778 | 817 | |
| 779 | 818 | int main(int argc, char **argv) |
| ... | ... | @@ -794,5 +833,6 @@ int main(int argc, char **argv) |
| 794 | 833 | test_xchg(); |
| 795 | 834 | test_lea(); |
| 796 | 835 | test_segs(); |
| 836 | + test_code16(); | |
| 797 | 837 | return 0; |
| 798 | 838 | } | ... | ... |