Add a compile/disassemble/compare test, and fix some bugs
authorDavid Schleef <ds@schleef.org>
Tue, 17 Mar 2009 22:34:24 +0000 (15:34 -0700)
committerDavid Schleef <ds@schleef.org>
Tue, 17 Mar 2009 22:34:24 +0000 (15:34 -0700)
orc/orccompiler.c
orc/orcprogram-sse.c
orc/orcrules-sse.c
orc/x86.c
testsuite/Makefile.am
testsuite/test5.c [new file with mode: 0644]

index 867fee0..512d7d8 100644 (file)
@@ -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:
index d610e0a..554c9f9 100644 (file)
@@ -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;
   }
 }
index 4726f67..7f2079f 100644 (file)
@@ -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);
index 4651903..5f2855b 100644 (file)
--- 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;
index 30aaefd..d5b47ed 100644 (file)
@@ -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 (file)
index 0000000..a4968e4
--- /dev/null
@@ -0,0 +1,113 @@
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <orc/orc.h>
+
+
+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;i<opcode_set->n_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);
+}
+
+