From 9b2bee8a4a16950acca25c41865c2207f618e486 Mon Sep 17 00:00:00 2001 From: David Schleef Date: Tue, 17 Mar 2009 15:34:24 -0700 Subject: [PATCH] Add a compile/disassemble/compare test, and fix some bugs --- orc/orccompiler.c | 1 + orc/orcprogram-sse.c | 3 +- orc/orcrules-sse.c | 73 ++++++++++++++++++++++++++++---- orc/x86.c | 15 ++++--- testsuite/Makefile.am | 4 +- testsuite/test5.c | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 193 insertions(+), 16 deletions(-) create mode 100644 testsuite/test5.c diff --git a/orc/orccompiler.c b/orc/orccompiler.c index 867fee0..512d7d8 100644 --- a/orc/orccompiler.c +++ b/orc/orccompiler.c @@ -106,6 +106,7 @@ orc_program_compile_for_target (OrcProgram *program, OrcTarget *target) if (compiler->error) goto error; program->asm_code = compiler->asm_code; + program->code_size = compiler->codeptr - program->code; return TRUE; error: diff --git a/orc/orcprogram-sse.c b/orc/orcprogram-sse.c index d610e0a..554c9f9 100644 --- a/orc/orcprogram-sse.c +++ b/orc/orcprogram-sse.c @@ -156,7 +156,8 @@ sse_emit_load_src (OrcCompiler *compiler, OrcVariable *var) x86_emit_mov_memoffset_sse (compiler, 16, 0, ptr_reg, var->alloc); break; default: - ORC_PROGRAM_ERROR(compiler,"unimplemented"); + ORC_PROGRAM_ERROR(compiler,"bad load size %d", + var->size << compiler->loop_shift); break; } } diff --git a/orc/orcrules-sse.c b/orc/orcrules-sse.c index 4726f67..7f2079f 100644 --- a/orc/orcrules-sse.c +++ b/orc/orcrules-sse.c @@ -221,6 +221,7 @@ BINARY(subl,"psubd",0xfa) BINARY(xorl,"pxor",0xef) +#if 0 static void sse_rule_shlw (OrcCompiler *p, void *user, OrcInstruction *insn) { @@ -304,19 +305,68 @@ sse_rule_shrsw (OrcCompiler *p, void *user, OrcInstruction *insn) ORC_PROGRAM_ERROR(p,"rule only works with constants or params"); } } +#endif + +static void +sse_rule_shift (OrcCompiler *p, void *user, OrcInstruction *insn) +{ + int type = (int)user; + int imm_code1[] = { 0x71, 0x71, 0x71, 0x72, 0x72, 0x72 }; + int imm_code2[] = { 6, 2, 4, 6, 2, 4 }; + int reg_code[] = { 0xf1, 0xd1, 0xe1, 0xf2, 0xd2, 0xe2 }; + //const char *code[] = { "psllw", "psrlw", "psraw", "pslld", "psrld", "psrad" }; + + if (p->vars[insn->src_args[1]].vartype == ORC_VAR_TYPE_CONST) { + ORC_ASM_CODE(p," %s $%d, %%%s\n", code[type], + p->vars[insn->src_args[1]].value, + x86_get_regname_sse(p->vars[insn->dest_args[0]].alloc)); + + *p->codeptr++ = 0x66; + *p->codeptr++ = 0x0f; + *p->codeptr++ = imm_code1[type]; + x86_emit_modrm_reg (p, p->vars[insn->dest_args[0]].alloc, imm_code2[type]); + *p->codeptr++ = p->vars[insn->src_args[1]].value; + } else if (p->vars[insn->src_args[1]].vartype == ORC_VAR_TYPE_PARAM) { + /* FIXME this is a gross hack to reload the register with a + * 64-bit version of the parameter. */ + ORC_ASM_CODE(p," movd %d(%%%s), %%%s\n", + (int)ORC_STRUCT_OFFSET(OrcExecutor, params[insn->src_args[1]]), + x86_get_regname_ptr(x86_exec_ptr), + x86_get_regname_sse(p->vars[insn->src_args[1]].alloc)); + *p->codeptr++ = 0x66; + *p->codeptr++ = 0x0f; + *p->codeptr++ = 0x6e; + x86_emit_modrm_memoffset (p, + p->vars[insn->src_args[1]].alloc, + (int)ORC_STRUCT_OFFSET(OrcExecutor, params[insn->src_args[1]]), + x86_exec_ptr); + + ORC_ASM_CODE(p," %s %%%s, %%%s\n", code[type], + x86_get_regname_sse(p->vars[insn->src_args[1]].alloc), + x86_get_regname_sse(p->vars[insn->dest_args[0]].alloc)); + + *p->codeptr++ = 0x66; + *p->codeptr++ = 0x0f; + *p->codeptr++ = reg_code[type]; + x86_emit_modrm_reg (p, p->vars[insn->src_args[1]].alloc, + p->vars[insn->dest_args[0]].alloc); + } else { + ORC_PROGRAM_ERROR(p,"rule only works with constants or params"); + } +} static void sse_rule_convsbw (OrcCompiler *p, void *user, OrcInstruction *insn) { ORC_ASM_CODE(p," punpcklbw %%%s, %%%s\n", - x86_get_regname_sse(p->vars[insn->src_args[1]].alloc), + x86_get_regname_sse(p->vars[insn->src_args[0]].alloc), x86_get_regname_sse(p->vars[insn->dest_args[0]].alloc)); *p->codeptr++ = 0x66; *p->codeptr++ = 0x0f; *p->codeptr++ = 0x60; x86_emit_modrm_reg (p, p->vars[insn->dest_args[0]].alloc, - p->vars[insn->src_args[1]].alloc); + p->vars[insn->src_args[0]].alloc); ORC_ASM_CODE(p," psraw $8, %%%s\n", x86_get_regname_sse(p->vars[insn->dest_args[0]].alloc)); @@ -334,14 +384,14 @@ sse_rule_convubw (OrcCompiler *p, void *user, OrcInstruction *insn) /* FIXME should do this by unpacking with a zero reg */ ORC_ASM_CODE(p," punpcklbw %%%s, %%%s\n", - x86_get_regname_sse(p->vars[insn->src_args[1]].alloc), + x86_get_regname_sse(p->vars[insn->src_args[0]].alloc), x86_get_regname_sse(p->vars[insn->dest_args[0]].alloc)); *p->codeptr++ = 0x66; *p->codeptr++ = 0x0f; *p->codeptr++ = 0x60; x86_emit_modrm_reg (p, p->vars[insn->dest_args[0]].alloc, - p->vars[insn->src_args[1]].alloc); + p->vars[insn->src_args[0]].alloc); ORC_ASM_CODE(p," psrlw $8, %%%s\n", x86_get_regname_sse(p->vars[insn->dest_args[0]].alloc)); @@ -358,14 +408,14 @@ static void sse_rule_convsuswb (OrcCompiler *p, void *user, OrcInstruction *insn) { ORC_ASM_CODE(p," packuswb %%%s, %%%s\n", - x86_get_regname_sse(p->vars[insn->src_args[1]].alloc), + x86_get_regname_sse(p->vars[insn->src_args[0]].alloc), x86_get_regname_sse(p->vars[insn->dest_args[0]].alloc)); *p->codeptr++ = 0x66; *p->codeptr++ = 0x0f; *p->codeptr++ = 0x67; x86_emit_modrm_reg (p, p->vars[insn->dest_args[0]].alloc, - p->vars[insn->src_args[1]].alloc); + p->vars[insn->src_args[0]].alloc); } void @@ -454,8 +504,15 @@ orc_compiler_sse_register_rules (OrcTarget *target) orc_rule_register (rule_set, "copyw", sse_rule_copyx, NULL); orc_rule_register (rule_set, "copyl", sse_rule_copyx, NULL); - orc_rule_register (rule_set, "shlw", sse_rule_shlw, NULL); - orc_rule_register (rule_set, "shrsw", sse_rule_shrsw, NULL); + //orc_rule_register (rule_set, "shlw", sse_rule_shlw, NULL); + //orc_rule_register (rule_set, "shrsw", sse_rule_shrsw, NULL); + + orc_rule_register (rule_set, "shlw", sse_rule_shift, (void *)0); + orc_rule_register (rule_set, "shruw", sse_rule_shift, (void *)1); + orc_rule_register (rule_set, "shrsw", sse_rule_shift, (void *)2); + orc_rule_register (rule_set, "shll", sse_rule_shift, (void *)3); + orc_rule_register (rule_set, "shrul", sse_rule_shift, (void *)4); + orc_rule_register (rule_set, "shrsl", sse_rule_shift, (void *)5); orc_rule_register (rule_set, "convsbw", sse_rule_convsbw, NULL); orc_rule_register (rule_set, "convubw", sse_rule_convubw, NULL); diff --git a/orc/x86.c b/orc/x86.c index 4651903..5f2855b 100644 --- a/orc/x86.c +++ b/orc/x86.c @@ -856,7 +856,8 @@ x86_add_label (OrcCompiler *compiler, unsigned char *ptr, int label) void x86_emit_jmp (OrcCompiler *compiler, int label) { - ORC_ASM_CODE(compiler," jmp .L%d\n", label); + ORC_ASM_CODE(compiler," jmp %d%c\n", label, + (compiler->labels[label]!=NULL) ? 'b' : 'f'); if (compiler->long_jumps) { ORC_PROGRAM_ERROR(compiler, "unimplemented"); @@ -869,7 +870,8 @@ void x86_emit_jmp (OrcCompiler *compiler, int label) void x86_emit_jle (OrcCompiler *compiler, int label) { - ORC_ASM_CODE(compiler," jle .L%d\n", label); + ORC_ASM_CODE(compiler," jle %d%c\n", label, + (compiler->labels[label]!=NULL) ? 'b' : 'f'); if (compiler->long_jumps) { ORC_PROGRAM_ERROR(compiler, "unimplemented"); @@ -882,7 +884,8 @@ void x86_emit_jle (OrcCompiler *compiler, int label) void x86_emit_je (OrcCompiler *compiler, int label) { - ORC_ASM_CODE(compiler," je .L%d\n", label); + ORC_ASM_CODE(compiler," je %d%c\n", label, + (compiler->labels[label]!=NULL) ? 'b' : 'f'); if (compiler->long_jumps) { *compiler->codeptr++ = 0x0f; @@ -901,7 +904,8 @@ void x86_emit_je (OrcCompiler *compiler, int label) void x86_emit_jne (OrcCompiler *compiler, int label) { - ORC_ASM_CODE(compiler," jne .L%d\n", label); + ORC_ASM_CODE(compiler," jne %d%c\n", label, + (compiler->labels[label]!=NULL) ? 'b' : 'f'); if (compiler->long_jumps) { *compiler->codeptr++ = 0x0f; @@ -920,7 +924,7 @@ void x86_emit_jne (OrcCompiler *compiler, int label) void x86_emit_label (OrcCompiler *compiler, int label) { - ORC_ASM_CODE(compiler,".L%d:\n", label); + ORC_ASM_CODE(compiler,"%d:\n", label); x86_add_label (compiler, compiler->codeptr, label); } @@ -957,6 +961,7 @@ void x86_emit_prologue (OrcCompiler *compiler) { orc_compiler_append_code(compiler,".global %s\n", compiler->program->name); + orc_compiler_append_code(compiler,".p2align 4\n"); orc_compiler_append_code(compiler,"%s:\n", compiler->program->name); if (x86_64) { int i; diff --git a/testsuite/Makefile.am b/testsuite/Makefile.am index 30aaefd..d5b47ed 100644 --- a/testsuite/Makefile.am +++ b/testsuite/Makefile.am @@ -1,7 +1,7 @@ -TESTS = test1 test2 test3 test4 +TESTS = test1 test2 test3 test4 test5 -noinst_PROGRAMS = test1 test2 test3 test4 +noinst_PROGRAMS = test1 test2 test3 test4 test5 AM_CFLAGS = $(ORC_CFLAGS) LIBS = $(ORC_LIBS) diff --git a/testsuite/test5.c b/testsuite/test5.c new file mode 100644 index 0000000..a4968e4 --- /dev/null +++ b/testsuite/test5.c @@ -0,0 +1,113 @@ + +#include "config.h" + +#include +#include + +#include + + +int error = FALSE; + +void test_opcode (const char *name); + +int +main (int argc, char *argv[]) +{ + int i; + OrcOpcodeSet *opcode_set; + + orc_init(); + + opcode_set = orc_opcode_set_get ("sys"); + + for(i=0;in_opcodes;i++){ + printf("/* %s %d,%d,%d %p */\n", + opcode_set->opcodes[i].name, + opcode_set->opcodes[i].dest_size[0], + opcode_set->opcodes[i].src_size[0], + opcode_set->opcodes[i].src_size[1], + opcode_set->opcodes[i].emulate); + test_opcode (opcode_set->opcodes[i].name); + } + + if (error) return 1; + return 0; +} + +void +test_opcode (const char *name) +{ + OrcProgram *p; + char s[40]; + char cmd[200]; + int ret; + FILE *file; + + p = orc_program_new_dss (2,2,2); + + sprintf(s, "test_%s", name); + orc_program_set_name (p, s); + orc_program_add_constant (p, 2, 1, "c1"); + + orc_program_append_str (p, name, "d1", "s1", "c1"); + + ret = orc_program_compile (p); + if (!ret) { + error = TRUE; + goto out; + } + + fflush (stdout); + + file = fopen ("tmp-test5.s", "w"); + fprintf(file, "%s", orc_program_get_asm_code (p)); + fclose (file); + + file = fopen ("dump", "w"); + ret = fwrite(p->code, p->code_size, 1, file); + fclose (file); + + ret = system ("gcc -Wall -c tmp-test5.s"); + if (ret != 0) { + printf("gcc failed\n"); + error = TRUE; + } + + ret = system ("objdump -dr tmp-test5.o >tmp-test5.dis"); + if (ret != 0) { + printf("objdump failed\n"); + error = TRUE; + goto out; + } + + sprintf (cmd, "objcopy -I binary -O elf32-i386 -B i386 " + "--rename-section .data=.text " + "--redefine-sym _binary_dump_start=%s " + "dump tmp-test5.o", s); + ret = system (cmd); + if (ret != 0) { + printf("objcopy failed\n"); + error = TRUE; + goto out; + } + + ret = system ("objdump -Dr tmp-test5.o >tmp-test5-dump.dis"); + if (ret != 0) { + printf("objdump failed\n"); + error = TRUE; + goto out; + } + + ret = system ("diff -u tmp-test5.dis tmp-test5-dump.dis"); + if (ret != 0) { + printf("diff failed\n"); + error = TRUE; + goto out; + } + +out: + orc_program_free (p); +} + + -- 2.7.4