From 4d1135e486fcdd3b00caf524f01af7f0d56a0af7 Mon Sep 17 00:00:00 2001 From: bellard Date: Mon, 24 Feb 2003 20:14:06 +0000 Subject: [PATCH] i386 emulator test git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@11 c046a42c-6fe2-441c-8c8c-71466251a162 --- tests/Makefile | 38 +++++++ tests/hello.c | 26 +++++ tests/test-i386.c | 261 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 325 insertions(+) create mode 100644 tests/Makefile create mode 100644 tests/hello.c create mode 100644 tests/test-i386.c diff --git a/tests/Makefile b/tests/Makefile new file mode 100644 index 0000000000..cbe80e2974 --- /dev/null +++ b/tests/Makefile @@ -0,0 +1,38 @@ +CC=gcc +CFLAGS=-Wall -O2 -g +LDFLAGS= + +TESTS=hello test1 test2 sha1 test-i386 +GEMU=../gemu + +all: $(TESTS) + +hello: hello.c + $(CC) -nostdlib $(CFLAGS) -static $(LDFLAGS) -o $@ $< + +test1: test1.c + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< + +test2: test2.c + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< + +# i386 emulation test (dump various opcodes) */ +test-i386: test-i386.c test-i386.h + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< + +test: test-i386 + ./test-i386 > test-i386.ref + $(GEMU) test-i386 > test-i386.out + @if diff -u test-i386.ref test-i386.out ; then echo "Auto Test OK"; fi + +# speed test +sha1: sha1.c + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< + +speed: sha1 + time ./sha1 + time $(GEMU) sha1 + +# interpreter test +interp: interp.c interploop.c + $(CC) $(CFLAGS) -fomit-frame-pointer $(LDFLAGS) -o $@ $^ diff --git a/tests/hello.c b/tests/hello.c new file mode 100644 index 0000000000..89bd15b829 --- /dev/null +++ b/tests/hello.c @@ -0,0 +1,26 @@ +#include + +extern inline volatile void exit(int status) +{ + int __res; + __asm__ volatile ("movl %%ecx,%%ebx\n"\ + "int $0x80" \ + : "=a" (__res) : "0" (__NR_exit),"c" ((long)(status))); +} + +extern inline int write(int fd, const char * buf, int len) +{ + int status; + __asm__ volatile ("pushl %%ebx\n"\ + "movl %%esi,%%ebx\n"\ + "int $0x80\n" \ + "popl %%ebx\n"\ + : "=a" (status) \ + : "0" (__NR_write),"S" ((long)(fd)),"c" ((long)(buf)),"d" ((long)(len))); +} + +void _startup(void) +{ + write(1, "Hello World\n", 12); + exit(0); +} diff --git a/tests/test-i386.c b/tests/test-i386.c new file mode 100644 index 0000000000..943bbf07b5 --- /dev/null +++ b/tests/test-i386.c @@ -0,0 +1,261 @@ +#include +#include +#include + +#define xglue(x, y) x ## y +#define glue(x, y) xglue(x, y) +#define stringify(s) tostring(s) +#define tostring(s) #s + +#define CC_C 0x0001 +#define CC_P 0x0004 +#define CC_A 0x0010 +#define CC_Z 0x0040 +#define CC_S 0x0080 +#define CC_O 0x0800 + +/* XXX: currently no A flag */ +#define CC_MASK (CC_C | CC_P | CC_Z | CC_S | CC_O) + +#define __init_call __attribute__ ((unused,__section__ (".initcall.init"))) + +static void *call_start __init_call = NULL; + +#define OP add +#include "test-i386.h" + +#define OP sub +#include "test-i386.h" + +#define OP xor +#include "test-i386.h" + +#define OP and +#include "test-i386.h" + +#define OP or +#include "test-i386.h" + +#define OP cmp +#include "test-i386.h" + +#define OP adc +#define OP_CC +#include "test-i386.h" + +#define OP sbb +#define OP_CC +#include "test-i386.h" + +#define OP inc +#define OP_CC +#define OP1 +#include "test-i386.h" + +#define OP dec +#define OP_CC +#define OP1 +#include "test-i386.h" + +#define OP neg +#define OP_CC +#define OP1 +#include "test-i386.h" + +#define OP not +#define OP_CC +#define OP1 +#include "test-i386.h" + +/* lea test (modrm support) */ +#define TEST_LEA(STR)\ +{\ + asm("leal " STR ", %0"\ + : "=r" (res)\ + : "a" (eax), "b" (ebx), "c" (ecx), "d" (edx), "S" (esi), "D" (edi));\ + printf("lea %s = %08x\n", STR, res);\ +} + +#define TEST_LEA16(STR)\ +{\ + asm(".code16 ; .byte 0x67 ; leal " STR ", %0 ; .code32"\ + : "=wq" (res)\ + : "a" (eax), "b" (ebx), "c" (ecx), "d" (edx), "S" (esi), "D" (edi));\ + printf("lea %s = %08x\n", STR, res);\ +} + + +void test_lea(void) +{ + int eax, ebx, ecx, edx, esi, edi, res; + eax = 0x0001; + ebx = 0x0002; + ecx = 0x0004; + edx = 0x0008; + esi = 0x0010; + edi = 0x0020; + + TEST_LEA("0x4000"); + + TEST_LEA("(%%eax)"); + TEST_LEA("(%%ebx)"); + TEST_LEA("(%%ecx)"); + TEST_LEA("(%%edx)"); + TEST_LEA("(%%esi)"); + TEST_LEA("(%%edi)"); + + TEST_LEA("0x40(%%eax)"); + TEST_LEA("0x40(%%ebx)"); + TEST_LEA("0x40(%%ecx)"); + TEST_LEA("0x40(%%edx)"); + TEST_LEA("0x40(%%esi)"); + TEST_LEA("0x40(%%edi)"); + + TEST_LEA("0x4000(%%eax)"); + TEST_LEA("0x4000(%%ebx)"); + TEST_LEA("0x4000(%%ecx)"); + TEST_LEA("0x4000(%%edx)"); + TEST_LEA("0x4000(%%esi)"); + TEST_LEA("0x4000(%%edi)"); + + TEST_LEA("(%%eax, %%ecx)"); + TEST_LEA("(%%ebx, %%edx)"); + TEST_LEA("(%%ecx, %%ecx)"); + TEST_LEA("(%%edx, %%ecx)"); + TEST_LEA("(%%esi, %%ecx)"); + TEST_LEA("(%%edi, %%ecx)"); + + TEST_LEA("0x40(%%eax, %%ecx)"); + TEST_LEA("0x4000(%%ebx, %%edx)"); + + TEST_LEA("(%%ecx, %%ecx, 2)"); + TEST_LEA("(%%edx, %%ecx, 4)"); + TEST_LEA("(%%esi, %%ecx, 8)"); + + TEST_LEA("(,%%eax, 2)"); + TEST_LEA("(,%%ebx, 4)"); + TEST_LEA("(,%%ecx, 8)"); + + TEST_LEA("0x40(,%%eax, 2)"); + TEST_LEA("0x40(,%%ebx, 4)"); + TEST_LEA("0x40(,%%ecx, 8)"); + + + TEST_LEA("-10(%%ecx, %%ecx, 2)"); + TEST_LEA("-10(%%edx, %%ecx, 4)"); + TEST_LEA("-10(%%esi, %%ecx, 8)"); + + TEST_LEA("0x4000(%%ecx, %%ecx, 2)"); + TEST_LEA("0x4000(%%edx, %%ecx, 4)"); + TEST_LEA("0x4000(%%esi, %%ecx, 8)"); + + /* limited 16 bit addressing test */ + TEST_LEA16("0x4000"); + TEST_LEA16("(%%bx)"); + TEST_LEA16("(%%si)"); + TEST_LEA16("(%%di)"); + TEST_LEA16("0x40(%%bx)"); + TEST_LEA16("0x40(%%si)"); + TEST_LEA16("0x40(%%di)"); + TEST_LEA16("0x4000(%%bx)"); + TEST_LEA16("0x4000(%%si)"); + TEST_LEA16("(%%bx,%%si)"); + TEST_LEA16("(%%bx,%%di)"); + TEST_LEA16("0x40(%%bx,%%si)"); + TEST_LEA16("0x40(%%bx,%%di)"); + TEST_LEA16("0x4000(%%bx,%%si)"); + TEST_LEA16("0x4000(%%bx,%%di)"); +} + +#define TEST_JCC(JCC, v1, v2)\ +{\ + asm("movl $1, %0\n\t"\ + "cmpl %2, %1\n\t"\ + JCC " 1f\n\t"\ + "movl $0, %0\n\t"\ + "1:\n\t"\ + : "=r" (res)\ + : "r" (v1), "r" (v2));\ + printf("%-10s %d\n", JCC, res);\ +} + +/* various jump tests */ +void test_jcc(void) +{ + int res; + + TEST_JCC("jne", 1, 1); + TEST_JCC("jne", 1, 0); + + TEST_JCC("je", 1, 1); + TEST_JCC("je", 1, 0); + + TEST_JCC("jl", 1, 1); + TEST_JCC("jl", 1, 0); + TEST_JCC("jl", 1, -1); + + TEST_JCC("jle", 1, 1); + TEST_JCC("jle", 1, 0); + TEST_JCC("jle", 1, -1); + + TEST_JCC("jge", 1, 1); + TEST_JCC("jge", 1, 0); + TEST_JCC("jge", -1, 1); + + TEST_JCC("jg", 1, 1); + TEST_JCC("jg", 1, 0); + TEST_JCC("jg", 1, -1); + + TEST_JCC("jb", 1, 1); + TEST_JCC("jb", 1, 0); + TEST_JCC("jb", 1, -1); + + TEST_JCC("jbe", 1, 1); + TEST_JCC("jbe", 1, 0); + TEST_JCC("jbe", 1, -1); + + TEST_JCC("jae", 1, 1); + TEST_JCC("jae", 1, 0); + TEST_JCC("jae", 1, -1); + + TEST_JCC("ja", 1, 1); + TEST_JCC("ja", 1, 0); + TEST_JCC("ja", 1, -1); + + + TEST_JCC("jp", 1, 1); + TEST_JCC("jp", 1, 0); + + TEST_JCC("jnp", 1, 1); + TEST_JCC("jnp", 1, 0); + + TEST_JCC("jo", 0x7fffffff, 0); + TEST_JCC("jo", 0x7fffffff, -1); + + TEST_JCC("jno", 0x7fffffff, 0); + TEST_JCC("jno", 0x7fffffff, -1); + + TEST_JCC("js", 0, 1); + TEST_JCC("js", 0, -1); + TEST_JCC("js", 0, 0); + + TEST_JCC("jns", 0, 1); + TEST_JCC("jns", 0, -1); + TEST_JCC("jns", 0, 0); +} + +static void *call_end __init_call = NULL; + +int main(int argc, char **argv) +{ + void **ptr; + void (*func)(void); + ptr = &call_start + 1; + while (*ptr != NULL) { + func = *ptr++; + func(); + } + test_lea(); + test_jcc(); + return 0; +}