]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
First draft of tree-based instruction selector.
authorJulian Seward <jseward@acm.org>
Wed, 30 Jun 2004 09:28:04 +0000 (09:28 +0000)
committerJulian Seward <jseward@acm.org>
Wed, 30 Jun 2004 09:28:04 +0000 (09:28 +0000)
git-svn-id: svn://svn.valgrind.org/vex/trunk@26

VEX/Makefile
VEX/host_regs.c [new file with mode: 0644]
VEX/include/host_regs.h [new file with mode: 0644]
VEX/include/ir_defs.h
VEX/include/x86h_defs.h [new file with mode: 0644]
VEX/ir_defs.c
VEX/isel_x86.c [new file with mode: 0644]
VEX/test_main.c [new file with mode: 0644]
VEX/x86h_defs.c [new file with mode: 0644]

index 0c3f6f08bff2ef1f974dda2a86121d5bfa63c9ce..0e6cbea328e391f2a334e481a094375d1eb88184 100644 (file)
@@ -1,8 +1,11 @@
 
-INCLUDES = include/basictypes.h
+INCLUDES = include/arena.h                             \
+          include/basictypes.h include/ir_defs.h       \
+          include/host_regs.h include/x86h_defs.h
 
 ##OBJS = basictypes.o ir_defs.o arena.o linker.o dispatch.o
-OBJS = basictypes.o ir_defs.o
+OBJS = basictypes.o ir_defs.o host_regs.o \
+       x86h_defs.o isel_x86.o test_main.o
 
 CC_OPTS = -g -Wall -Iinclude
 
@@ -16,6 +19,12 @@ basictypes.o: basictypes.c $(INCLUDES)
        gcc $(CC_OPTS) -c basictypes.c
 ir_defs.o: ir_defs.c $(INCLUDES)
        gcc $(CC_OPTS) -c ir_defs.c
+host_regs.o: host_regs.c $(INCLUDES)
+       gcc $(CC_OPTS) -c host_regs.c
+x86h_defs.o: x86h_defs.c $(INCLUDES)
+       gcc $(CC_OPTS) -c x86h_defs.c
+isel_x86.o: isel_x86.c $(INCLUDES)
+       gcc $(CC_OPTS) -c isel_x86.c
 arena.o: arena.c $(INCLUDES)
        gcc $(CC_OPTS) -c arena.c
 linker.o: linker.c $(INCLUDES)
@@ -23,4 +32,7 @@ linker.o: linker.c $(INCLUDES)
 dispatch.o: dispatch.c $(INCLUDES)
        gcc $(CC_OPTS) -c dispatch.c
 
+test_main.o: test_main.c $(INCLUDES)
+       gcc $(CC_OPTS) -c test_main.c
+
 
diff --git a/VEX/host_regs.c b/VEX/host_regs.c
new file mode 100644 (file)
index 0000000..2810896
--- /dev/null
@@ -0,0 +1,51 @@
+
+/*---------------------------------------------------------------*/
+/*---                                                         ---*/
+/*--- This file (host_regs.c) is                              ---*/
+/*--- Copyright (c) 2004 OpenWorks LLP.  All rights reserved. ---*/
+/*---                                                         ---*/
+/*---------------------------------------------------------------*/
+
+#include <stdio.h>
+
+#include "basictypes.h"
+#include "host_regs.h"
+
+
+HReg mkHReg ( UInt regno, HRegClass rc, Bool virtual )
+{
+   assert((regno & 0xFF000000) == 0);
+   return (regno << 8) | (((UInt)rc) << 4) | (virtual ? 1 : 0);
+}
+
+HRegClass hregClass ( HReg r )
+{
+   UInt rc = (r & 0x000000F0) >> 4;
+   assert(rc <= 2);
+   return (HRegClass)rc;
+}
+
+Bool hregIsVirtual ( HReg r )
+{
+   return (r & 1) ? True : False;
+}
+
+UInt hregNumber ( HReg r )
+{
+   return (((UInt)r) >> 8);
+}
+
+
+/* Generic printing for registers. */
+void ppHReg ( FILE* f, HReg r ) 
+{
+   Char* maybe_v = hregIsVirtual(r) ? "v" : "";
+   Int   regNo   = hregNumber(r);
+   switch (hregClass(r)) {
+      case HRcInt:    fprintf(f, "%%%sr%d", maybe_v, regNo); return;
+      case HRcFloat:  fprintf(f, "%%%sf%d", maybe_v, regNo); return;
+      case HRcVector: fprintf(f, "%%%sv%d", maybe_v, regNo); return;
+      default: panic("ppHReg");
+   }
+}
+
diff --git a/VEX/include/host_regs.h b/VEX/include/host_regs.h
new file mode 100644 (file)
index 0000000..a50b531
--- /dev/null
@@ -0,0 +1,50 @@
+
+/*---------------------------------------------------------------*/
+/*---                                                         ---*/
+/*--- This file (host_regs.h) is                              ---*/
+/*--- Copyright (c) 2004 OpenWorks LLP.  All rights reserved. ---*/
+/*---                                                         ---*/
+/*---------------------------------------------------------------*/
+
+#ifndef __HOST_REGS_H
+#define __HOST_REGS_H
+
+
+/* Host registers.  Stuff to represent:
+
+   - The register number
+   - The register class
+   - Whether or not the register is a virtual reg.
+
+   Registers are a 32-bit Int, thusly:
+
+     bits 31-8  register number
+     bits 7-4   are 0000b for real register, 0001b for virtual register
+     bits 3-0   are the register class.
+
+   There are currently 3 register classes:
+
+     int
+     floating
+     vector.
+*/
+
+typedef UInt HReg;
+
+typedef
+   enum { HRcInt=0, HRcFloat=1, HRcVector=2 }
+   HRegClass;
+
+
+/* Print an HReg in a generic (non-target-specific) way. */
+extern void ppHReg ( FILE*, HReg );
+
+/* Construct/destruct. */
+extern HReg mkHReg ( UInt regno, HRegClass rc, Bool virtual );
+
+extern HRegClass hregClass     ( HReg );
+extern Bool      hregIsVirtual ( HReg );
+extern UInt      hregNumber    ( HReg );
+
+
+#endif /* ndef __HOST_REGS_H */
index 7063a185b8ba7d195434a728b7690d6698cf7b31..e666146e201379b3e6320793192677f0b1ef083f 100644 (file)
@@ -9,45 +9,54 @@
 #ifndef __IR_DEFS_H
 #define __IR_DEFS_H
 
-#include <stdio.h>       /* FILE*  */
-
 
 /*---------------------------------------------------------------*/
 /*--- Type definitions for the IR                             ---*/
 /*---------------------------------------------------------------*/
 
-/* Types */
+/* ------------------ Types ------------------ */
 
 typedef 
    enum { Ity_Bit, Ity_I8, Ity_I16, Ity_I32, Ity_I64 }
    IRType;
 
+extern void ppIRType ( FILE* f, IRType );
+
 
-/* Constants */
+/* ------------------ Constants ------------------ */
 
 typedef
-   enum { Ico_u8, Ico_u16, Ico_u32, Ico_u64 }
+   enum { Ico_U8, Ico_U16, Ico_U32, Ico_U64 }
    IRConstTag;
 
 typedef
    struct _IRConst {
       IRConstTag tag;
       union {
-         UChar  u8;
-         UShort u16;
-         UInt   u32;
-         ULong  u64;
+         UChar  U8;
+         UShort U16;
+         UInt   U32;
+         ULong  U64;
       } Ico;
    }
    IRConst;
 
+extern IRConst* IRConst_U8  ( UChar );
+extern IRConst* IRConst_U16 ( UShort );
+extern IRConst* IRConst_U32 ( UInt );
+extern IRConst* IRConst_U64 ( ULong );
+
+extern void ppIRConst ( FILE* f, IRConst* );
 
-/* Temporaries */
+
+/* ------------------ Temporaries ------------------ */
 
 typedef int IRTemp;
 
+extern void ppIRTemp ( FILE* f, IRTemp );
+
 
-/* Binary and unary ops */
+/* ------------------ Binary and unary ops ------------------ */
 
 typedef
    enum { Iop_Add32, 
@@ -65,9 +74,11 @@ typedef
    }
    IROp;
 
+extern void ppIROp ( FILE* f, IROp );
 
-/* Expressions
 
+/* ------------------ Expressions ------------------ */
+/*
 data Expr
    = GET   Int Int         -- offset, size
    | TMP   Temp            -- value of temporary
@@ -111,9 +122,18 @@ typedef
    }
    IRExpr;
 
+extern IRExpr* IRExpr_Get   ( Int off, Int sz );
+extern IRExpr* IRExpr_Tmp   ( IRTemp tmp );
+extern IRExpr* IRExpr_Binop ( IROp op, IRExpr* arg1, IRExpr* arg2 );
+extern IRExpr* IRExpr_Unop  ( IROp op, IRExpr* arg );
+extern IRExpr* IRExpr_LDle  ( IRType ty, IRExpr* addr );
+extern IRExpr* IRExpr_Const ( IRConst* con );
+
+extern void ppIRExpr ( FILE* f, IRExpr* );
 
-/* Statements:
 
+/* ------------------ Statements ------------------ */
+/*
 data Stmt
    = PUT    Int Int Expr      -- offset, size, value
    | TMP    Temp Expr         -- store value in Temp
@@ -130,23 +150,30 @@ typedef
          struct {
             Int     offset;
             Int     size;
-            struct _IRExpr* expr;
+            IRExpr* expr;
          } Put;
          struct {
             IRTemp  tmp;
-            struct _IRExpr* expr;
+            IRExpr* expr;
          } Tmp;
          struct {
-            struct _IRExpr* addr;
-            struct _IRExpr* data;
+            IRExpr* addr;
+            IRExpr* data;
          } STle;
       } Ist;
       struct _IRStmt* link;
    }
    IRStmt;
 
+extern IRStmt* IRStmt_Put  ( Int off, Int sz, IRExpr* value );
+extern IRStmt* IRStmt_Tmp  ( IRTemp tmp, IRExpr* expr );
+extern IRStmt* IRStmt_STle ( IRExpr* addr, IRExpr* value );
+
+extern void ppIRStmt ( FILE* f, IRStmt* );
+
 
-/* Basic block enders.
+/* ------------------ Basic block enders. ------------------ */
+/*
    IRConst represents a guest address, which is either a
    32 or 64 bit integer, depending on the architecture we're simulating.
 
@@ -178,52 +205,64 @@ typedef
    }
    IRNext;
 
+extern IRNext* IRNext_UJump ( IRConst* dst );
+
+extern void ppIRNext ( FILE* f, IRNext* );
+
+
+/* ------------------ Basic Blocks ------------------ */
+
+/* A bunch of statements, expressions, etc, are incomplete without an
+   environment indicating the type of each IRTemp.  So this provides
+   one. 
+*/
+typedef
+   struct { 
+      IRTemp name; 
+      IRType type; 
+   }
+   IRTypeEnvMaplet;
+
+typedef
+   struct {
+      IRTypeEnvMaplet* map;
+      Int map_size;
+      Int map_used;
+   }
+   IRTypeEnv;
+
+extern void ppIRTypeEnv ( FILE* f, IRTypeEnv* );
+
 
 /* Basic blocks contain 3 fields:
-   - An association list, giving a type for each temp
+   - A table giving a type for each temp
    - A list of statements
    - A Next
 */
 typedef
    struct _IRBB {
-      struct _IRStmt* stmts;
-      struct _IRNext* next;
+      IRTypeEnv* tyenv;
+      IRStmt*    stmts;
+      IRNext*    next;
    }
    IRBB;
 
+extern IRBB* mk_IRBB ( IRTypeEnv*, IRStmt*, IRNext* );
+
+extern void ppIRBB ( FILE* f, IRBB* );
+
 
 /*---------------------------------------------------------------*/
-/*--- Basic functions for the IR                              ---*/
+/*--- Helper functions for the IR                             ---*/
 /*---------------------------------------------------------------*/
 
-/* Printers ... */
-extern void ppIRType    ( FILE* f, IRType     );
-extern void ppIRConst   ( FILE* f, IRConst*   );
-extern void ppIRTemp    ( FILE* f, IRTemp     );
-extern void ppIROp      ( FILE* f, IROp       );
-extern void ppIRExpr    ( FILE* f, IRExpr*    );
-extern void ppIRStmt    ( FILE* f, IRStmt*    );
-extern void ppIRNext    ( FILE* f, IRNext*    );
-extern void ppIRBB      ( FILE* f, IRBB*      );
-
-/* Constructors -- IRExpr */
-extern IRExpr* mkExGet   ( Int off, Int sz );
-extern IRExpr* mkExTmp   ( IRTemp tmp );
-extern IRExpr* mkExBinop ( IROp op, IRExpr* arg1, IRExpr* arg2 );
-extern IRExpr* mkExUnop  ( IROp op, IRExpr* arg );
-extern IRExpr* mkExLDle  ( IRType ty, IRExpr* addr );
-extern IRExpr* mkExConst ( IRConst* con );
-
-/* Constructors -- IRStmt */
-extern IRStmt* mkStPut  ( Int off, Int sz, IRExpr* value );
-extern IRStmt* mkStTmp  ( IRTemp tmp, IRExpr* expr );
-extern IRStmt* mkStSTle ( IRExpr* addr, IRExpr* value );
-
-/* Constructors -- IRNext */
-extern IRNext* mkNxUJump ( IRConst* dst );
-
-/* Constructors -- IRBB */
-extern IRBB* mkIRBB ( IRStmt* stmts, IRNext* next );
+/* For messing with IR type environments */
+extern IRTypeEnv* newIRTypeEnv    ( void );
+extern void       addToIRTypeEnv  ( IRTypeEnv*, IRTemp, IRType );
+extern IRType     lookupIRTypeEnv ( IRTypeEnv*, IRTemp );
+
+/* What is the type of this expression? */
+extern IRType typeOfIRExpr ( IRTypeEnv*, IRExpr* );
 
 
 #endif /* ndef __IR_DEFS_H */
diff --git a/VEX/include/x86h_defs.h b/VEX/include/x86h_defs.h
new file mode 100644 (file)
index 0000000..30c1185
--- /dev/null
@@ -0,0 +1,150 @@
+
+/*---------------------------------------------------------------*/
+/*---                                                         ---*/
+/*--- This file (x86h_defs.h) is                              ---*/
+/*--- Copyright (c) 2004 OpenWorks LLP.  All rights reserved. ---*/
+/*---                                                         ---*/
+/*---------------------------------------------------------------*/
+
+#ifndef __X86H_DEFS_H
+#define __X86H_DEFS_H
+
+
+/* --------- Registers. --------- */
+
+/* The usual HReg abstraction.  There are 8 real int regs,
+   6 real float regs, and 0 real vector regs. 
+*/
+
+extern void ppHRegX86 ( FILE*, HReg );
+
+
+/* --------- Memory address expressions (amodes). --------- */
+
+typedef
+   enum {
+     Xam_IR,
+     Xam_IRRS
+   }
+   X86AModeTag;
+
+typedef
+   struct {
+      X86AModeTag tag;
+      union {
+         struct {
+            UInt imm;
+            HReg reg;
+         } IR;
+         struct {
+            UInt imm;
+            HReg base;
+            HReg index;
+            Int  shift; /* 0, 1, 2 or 3 only */
+         } IRRS;
+      } Xam;
+   }
+   X86AMode;
+
+extern X86AMode* X86AMode_IR   ( UInt, HReg );
+extern X86AMode* X86AMode_IRRS ( UInt, HReg, HReg, Int );
+
+extern void ppX86AMode ( FILE*, X86AMode* );
+
+
+/* --------- Operands.  Not all are valid for all insns. --------- */
+
+typedef 
+   enum {
+      Xop_Imm,
+      Xop_Reg,
+      Xop_Mem
+   }
+   X86OperandTag;
+
+typedef
+   struct {
+      X86OperandTag tag;
+      union {
+         struct {
+            UInt imm32;
+         } Imm;
+         struct {
+            HReg reg;
+         } Reg;
+         struct {
+            X86AMode* am;
+         } Mem;
+      }
+      Xop;
+   }
+   X86Operand;
+
+extern X86Operand* X86Operand_Imm ( UInt );
+extern X86Operand* X86Operand_Reg ( HReg );
+extern X86Operand* X86Operand_Mem ( X86AMode* );
+
+extern void ppX86Operand ( FILE*, X86Operand* );
+
+
+/* --------- Instructions. --------- */
+
+typedef 
+   enum { Xalu_ADD, Xalu_SUB, Xalu_ADC, Xalu_SBB, Xalu_AND, Xalu_OR, Xalu_XOR }
+   X86AluOp;
+
+extern void ppX86AluOp ( FILE*, X86AluOp );
+
+
+typedef
+   enum {
+      Xin_LD32,     /* 32-bit integer load */
+      Xin_ST32,     /* 32-bit integer store */
+      Xin_Alu32,    /* 32-bit arith/logical, R-R, R-M, M-R */
+      Xin_Mov32,    /* 32-bit move R-R R-M M-R I-R I-M */
+      Xin_Alu16     /* 16-bit arith/logical, R-R, R-M, M-R */
+   }
+   X86InstrTag;
+
+/* Destinations are on the RIGHT (second operand). */
+
+typedef
+   struct {
+      X86InstrTag tag;
+      union {
+        struct {
+           HReg src;
+           X86AMode* dst;
+        } ST32;
+        struct {
+           X86AMode* src;
+           HReg dst;
+        } LD32;
+         struct {
+            X86AluOp    op;
+            X86Operand* src;
+            X86Operand* dst;
+         } Alu32;
+         struct {
+            X86Operand* src;
+            X86Operand* dst;
+         } Mov32;
+         struct {
+            X86AluOp    op;
+            X86Operand* src;
+            X86Operand* dst;
+         } Alu16;
+      } Xin;
+   }
+   X86Instr;
+
+extern X86Instr* X86Instr_ST32  ( HReg, X86AMode* );
+extern X86Instr* X86Instr_LD32  ( X86AMode*, HReg );
+extern X86Instr* X86Instr_Alu32 ( X86AluOp, X86Operand*, X86Operand* );
+extern X86Instr* X86Instr_Mov32 ( X86Operand*, X86Operand* );
+extern X86Instr* X86Instr_Alu16 ( X86AluOp, X86Operand*, X86Operand* );
+
+extern void ppX86Instr ( FILE*, X86Instr* );
+
+
+#endif /* ndef __X86H_DEFS_H */
index a4981acd023247ebb02e0fb52e40cb1800a903cc..27ca1abf683f781689b7304f06bfdb0a0ae5d57a 100644 (file)
@@ -6,10 +6,12 @@
 /*---                                                         ---*/
 /*---------------------------------------------------------------*/
 
+#include <stdio.h>
+#include <malloc.h>
+
 #include "basictypes.h"
 #include "ir_defs.h"
 
-#include <malloc.h>
 
 /*---------------------------------------------------------------*/
 /*--- Printing the IR                                         ---*/
@@ -30,10 +32,10 @@ void ppIRType ( FILE* f, IRType ty )
 void ppIRConst ( FILE* f, IRConst* con )
 {
   switch (con->tag) {
-    case Ico_u8:  fprintf(f, "0x%x",   (UInt)(con->Ico.u8)); break;
-    case Ico_u16: fprintf(f, "0x%x",   (UInt)(con->Ico.u16)); break;
-    case Ico_u32: fprintf(f, "0x%x",   (UInt)(con->Ico.u32)); break;
-    case Ico_u64: fprintf(f, "0x%llx", (ULong)(con->Ico.u64)); break;
+    case Ico_U8:  fprintf(f, "0x%x",   (UInt)(con->Ico.U8)); break;
+    case Ico_U16: fprintf(f, "0x%x",   (UInt)(con->Ico.U16)); break;
+    case Ico_U32: fprintf(f, "0x%x",   (UInt)(con->Ico.U32)); break;
+    case Ico_U64: fprintf(f, "0x%llx", (ULong)(con->Ico.U64)); break;
     default: panic("ppIRConst");
   }
 }
@@ -147,9 +149,28 @@ void ppIRNext ( FILE* f, IRNext* nx )
   }
 }
 
+void ppIRTypeEnv ( FILE* f, IRTypeEnv* env ) {
+   UInt i;
+   for (i = 0; i < env->map_used; i++) {
+      if (i % 8 == 0)
+         fprintf(f, "   ");
+      ppIRTemp(f, env->map[i].name);
+      fprintf(f, ":");
+      ppIRType(f, env->map[i].type);
+      if (i % 8 == 7) 
+         fprintf(f, "\n"); 
+      else 
+         fprintf(f, "   ");
+   }
+   if (env->map_used > 0 && env->map_used % 8 != 7) 
+         fprintf(f, "\n"); 
+}
+
+
 void ppIRBB ( FILE* f, IRBB* bb )
 {
    IRStmt* s;
+   ppIRTypeEnv(f, bb->tyenv);
    for (s = bb->stmts; s; s = s->link) {
       fprintf(f, "   ");
       ppIRStmt(f, s);
@@ -165,22 +186,55 @@ void ppIRBB ( FILE* f, IRBB* bb )
 /*--- Constructors                                            ---*/
 /*---------------------------------------------------------------*/
 
+
+/* Constructors -- IRConst */
+
+IRConst* IRConst_U8 ( UChar u8 )
+{
+   IRConst* c = malloc(sizeof(IRConst));
+   c->tag     = Ico_U8;
+   c->Ico.U8  = u8;
+   return c;
+}
+IRConst* IRConst_U16 ( UShort u16 )
+{
+   IRConst* c = malloc(sizeof(IRConst));
+   c->tag     = Ico_U16;
+   c->Ico.U16 = u16;
+   return c;
+}
+IRConst* IRConst_U32 ( UInt u32 )
+{
+   IRConst* c = malloc(sizeof(IRConst));
+   c->tag     = Ico_U32;
+   c->Ico.U32 = u32;
+   return c;
+}
+IRConst* IRConst_U64 ( ULong u64 )
+{
+   IRConst* c = malloc(sizeof(IRConst));
+   c->tag     = Ico_U64;
+   c->Ico.U64 = u64;
+   return c;
+}
+
+
 /* Constructors -- IRExpr */
 
-IRExpr* mkExGet ( Int off, Int sz ) {
+IRExpr* IRExpr_Get ( Int off, Int sz ) {
    IRExpr* e         = malloc(sizeof(IRExpr));
    e->tag            = Iex_Get;
    e->Iex.Get.offset = off;
    e->Iex.Get.size   = sz;
    return e;
 }
-IRExpr* mkExTmp ( IRTemp tmp ) {
+IRExpr* IRExpr_Tmp ( IRTemp tmp ) {
    IRExpr* e      = malloc(sizeof(IRExpr));
    e->tag         = Iex_Tmp;
    e->Iex.Tmp.tmp = tmp;
    return e;
 }
-IRExpr* mkExBinop ( IROp op, IRExpr* arg1, IRExpr* arg2 ) {
+IRExpr* IRExpr_Binop ( IROp op, IRExpr* arg1, IRExpr* arg2 ) {
    IRExpr* e         = malloc(sizeof(IRExpr));
    e->tag            = Iex_Binop;
    e->Iex.Binop.op   = op;
@@ -188,21 +242,21 @@ IRExpr* mkExBinop ( IROp op, IRExpr* arg1, IRExpr* arg2 ) {
    e->Iex.Binop.arg2 = arg2;
    return e;
 }
-IRExpr* mkExUnop ( IROp op, IRExpr* arg ) {
+IRExpr* IRExpr_Unop ( IROp op, IRExpr* arg ) {
    IRExpr* e       = malloc(sizeof(IRExpr));
    e->tag          = Iex_Unop;
    e->Iex.Unop.op  = op;
    e->Iex.Unop.arg = arg;
    return e;
 }
-IRExpr* mkExLDle  ( IRType ty, IRExpr* addr ) {
+IRExpr* IRExpr_LDle  ( IRType ty, IRExpr* addr ) {
    IRExpr* e        = malloc(sizeof(IRExpr));
    e->tag           = Iex_LDle;
    e->Iex.LDle.ty   = ty;
    e->Iex.LDle.addr = addr;
    return e;
 }
-IRExpr* mkExConst ( IRConst* con ) {
+IRExpr* IRExpr_Const ( IRConst* con ) {
    IRExpr* e        = malloc(sizeof(IRExpr));
    e->tag           = Iex_Const;
    e->Iex.Const.con = con;
@@ -212,24 +266,27 @@ IRExpr* mkExConst ( IRConst* con ) {
 
 /* Constructors -- IRStmt */
 
-IRStmt* mkStPut ( Int off, Int sz, IRExpr* value ) {
+IRStmt* IRStmt_Put ( Int off, Int sz, IRExpr* value ) {
    IRStmt* s         = malloc(sizeof(IRStmt));
    s->tag            = Ist_Put;
+   s->link           = NULL;
    s->Ist.Put.offset = off;
    s->Ist.Put.size   = sz;
    s->Ist.Put.expr   = value;
    return s;
 }
-IRStmt* mkStTmp ( IRTemp tmp, IRExpr* expr ) {
+IRStmt* IRStmt_Tmp ( IRTemp tmp, IRExpr* expr ) {
    IRStmt* s       = malloc(sizeof(IRStmt));
    s->tag          = Ist_Tmp;
+   s->link         = NULL;
    s->Ist.Tmp.tmp  = tmp;
    s->Ist.Tmp.expr = expr;
    return s;
 }
-IRStmt* mkStSTle ( IRExpr* addr, IRExpr* value ) {
+IRStmt* IRStmt_STle ( IRExpr* addr, IRExpr* value ) {
    IRStmt* s        = malloc(sizeof(IRStmt));
    s->tag           = Ist_STle;
+   s->link          = NULL;
    s->Ist.STle.addr = addr;
    s->Ist.STle.data = value;
    return s;
@@ -238,7 +295,7 @@ IRStmt* mkStSTle ( IRExpr* addr, IRExpr* value ) {
 
 /* Constructors -- IRNext */
 
-IRNext* mkNxUJump ( IRConst* dst ) {
+IRNext* IRNext_UJump ( IRConst* dst ) {
    IRNext* nx        = malloc(sizeof(IRNext));
    nx->tag           = Inx_UJump;
    nx->Inx.UJump.dst = dst;
@@ -248,13 +305,88 @@ IRNext* mkNxUJump ( IRConst* dst ) {
 
 /* Constructors -- IRBB */
 
-IRBB* mkIRBB ( IRStmt* stmts, IRNext* next ) {
+IRBB* mk_IRBB ( IRTypeEnv* env, IRStmt* stmts, IRNext* next ) {
    IRBB* bb  = malloc(sizeof(IRBB));
+   bb->tyenv = env;
    bb->stmts = stmts;
    bb->next  = next;
    return bb;
 }
 
 
+/*---------------------------------------------------------------*/
+/*--- Helper functions for the IR                             ---*/
+/*---------------------------------------------------------------*/
+
+IRTypeEnv* newIRTypeEnv ( void )
+{
+   IRTypeEnv* env = malloc(sizeof(IRTypeEnv));
+   env->map       = NULL;
+   env->map_size  = 0;
+   env->map_used  = 0;
+   return env;
+}
+
+
+void addToIRTypeEnv ( IRTypeEnv* env, IRTemp tmp, IRType ty )
+{
+   assert(env);
+   assert(env->map_used >= 0);
+   assert(env->map_size >= 0);
+   assert(env->map_used <= env->map_size);
+   if (env->map_used < env->map_size) {
+      env->map[env->map_used].name = tmp;
+      env->map[env->map_used].type = ty;
+      env->map_used++;
+   } else {
+      Int i;
+      Int new_size = env->map_size==0 ? 8 : 2*env->map_size;
+      IRTypeEnvMaplet* new_map = malloc(new_size * sizeof(IRTypeEnvMaplet));
+      for (i = 0; i < env->map_used; i++)
+         new_map[i] = env->map[i];
+      env->map      = new_map;
+      env->map_size = new_size;
+      return addToIRTypeEnv(env, tmp, ty);
+   }
+}
+
+
+IRType lookupIRTypeEnv ( IRTypeEnv* env, IRTemp tmp )
+{
+   Int i;
+   for (i = 0; i < env->map_used; i++)
+      if (env->map[i].name == tmp)
+         return env->map[i].type;
+   panic("lookupIRTypeEnv");
+}
 
 
+IRType typeOfIRExpr ( IRTypeEnv* tyenv, IRExpr* e )
+{
+   switch (e->tag) {
+      case Iex_Tmp:
+         return lookupIRTypeEnv(tyenv, e->Iex.Tmp.tmp);
+      case Iex_Const:
+         switch (e->Iex.Const.con->tag) {
+            case Ico_U8:  return Ity_I8;
+            case Ico_U16: return Ity_I16;
+            case Ico_U32: return Ity_I32;
+            case Ico_U64: return Ity_I64;
+            default: panic("typeOfIRExpr:Iex_Const");
+         }
+         break;
+      case Iex_Binop:
+         switch (e->Iex.Binop.op) {
+            case Iop_Add32: case Iop_Sub32: case Iop_Mul32: 
+            case Iop_Or32:  case Iop_And32: case Iop_Xor32:
+            case Iop_Shl32: case Iop_Shr32: case Iop_Sar32:
+               return Ity_I32;
+            default: break;
+         }
+         break;
+      default:
+         break;
+   }
+   ppIRExpr(stderr,e);
+   panic("typeOfIRExpr");
+}
diff --git a/VEX/isel_x86.c b/VEX/isel_x86.c
new file mode 100644 (file)
index 0000000..93ae6a3
--- /dev/null
@@ -0,0 +1,276 @@
+
+/*---------------------------------------------------------------*/
+/*---                                                         ---*/
+/*--- This file (isel_x86.c) is                               ---*/
+/*--- Copyright (c) 2004 OpenWorks LLP.  All rights reserved. ---*/
+/*---                                                         ---*/
+/*---------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <malloc.h>
+
+#include "basictypes.h"
+#include "ir_defs.h"
+#include "host_regs.h"
+#include "x86h_defs.h"
+
+
+/*---------------------------------------------------------*/
+/*--- ISelEnv                                           ---*/
+/*---------------------------------------------------------*/
+
+/* This carries around:
+
+   - A mapping from IRTemp to IRType, giving the type of any IRTemp we
+     might encounter.  This is computed before insn selection starts,
+     and does not change.
+
+   - A mapping from IRTemp to HReg.  This tells the insn selector
+     which virtual register is associated with each IRTemp temporary.
+     This is computed before insn selection starts, and does not
+     change.  We expect this mapping to map precisely the same set
+     of IRTemps as the type mapping does.
+
+   - The code array, that is, the insns selected so far.
+
+   - A counter, for generating new virtual registers.
+
+   Note, this is all host-independent.  
+*/
+
+typedef
+   struct {
+      IRTemp ir_name;
+      HReg   vreg;
+   }
+   VRegMaplet;
+
+typedef
+   struct {
+      IRTypeEnv* type_env;
+
+      VRegMaplet* vregmap;
+      Int n_vregmap;
+
+      void** code;  /* really, X86Instr**, or ArmInstr**, or whatever */
+      Int    code_size;
+      Int    code_used;
+
+      Int    ctr;
+   }
+   ISelEnv;
+
+
+static HReg lookupIRTemp ( ISelEnv* env, IRTemp tmp )
+{
+   Int i;
+   for (i = 0; i < env->n_vregmap; i++)
+      if (env->vregmap[i].ir_name == tmp)
+         return env->vregmap[i].vreg;
+   panic("lookupIRTemp");
+}
+
+static void addInstr ( ISelEnv* env, void* instr )
+{
+   assert(env->code_used < env->code_size);
+   env->code[env->code_used++] = instr;
+   ppX86Instr(stdout, instr);
+   printf("\n");
+}
+
+static HReg newVRegI ( ISelEnv* env )
+{
+   HReg reg = mkHReg(env->ctr, HRcInt, True/*virtual reg*/);
+   env->ctr++;
+   return reg;
+}
+
+
+/*---------------------------------------------------------*/
+/*--- ISEL: Integer expressions                         ---*/
+/*---------------------------------------------------------*/
+
+/* Select insns for an integer-typed expression, and add them to the
+   code list.  Return a vreg holding the result.  The vreg MUST NOT BE
+   MODIFIED.  If you want to modify it, ask for a new vreg, copy it in
+   there, and modify the copy.  The register allocator will do its
+   best to map both vregs to the same real register, so the copies
+   will often disappear later in the game.
+*/
+HReg iselExprI ( ISelEnv* env, IRExpr* e )
+{
+   assert(e);
+   assert(typeOfIRExpr(env->type_env,e) == Ity_I32);
+
+   switch (e->tag) {
+
+   case Iex_Tmp:
+   return lookupIRTemp(env, e->Iex.Tmp.tmp);
+
+   case Iex_Binop:
+      /* Add32(x,y) */
+      if (e->Iex.Binop.op == Iop_Add32) {
+         HReg res = newVRegI(env);
+         HReg src = iselExprI(env, e->Iex.Binop.arg1);
+         HReg dst = iselExprI(env, e->Iex.Binop.arg2);
+         addInstr(env, X86Instr_Mov32(
+                          X86Operand_Reg(dst),
+                          X86Operand_Reg(res)));
+         addInstr(env, X86Instr_Alu32(
+                          Xalu_ADD, X86Operand_Reg(src),
+                                    X86Operand_Reg(res)) );
+         return res;
+      }
+
+   /* 32-bit literals */
+   case Iex_Const: {
+      switch (e->Iex.Const.con->tag) {
+         case Ico_U32: {
+            HReg r = newVRegI(env);
+            addInstr(env,
+               X86Instr_Mov32(X86Operand_Imm(e->Iex.Const.con->Ico.U32),
+                             X86Operand_Reg(r)));
+            return r;
+         }
+         default: break;
+      }
+   }
+
+   default: 
+   break;
+   } /* switch (e->tag) */
+
+   /* We get here if no pattern matched. */
+   ppIRExpr(stderr, e);
+   panic("iselExprI: cannot reduce tree");
+}
+
+
+/* Similarly, return an AMode which computes the value of the
+   specified expression, possibly also adding insns to the code list
+   as a result.  
+*/
+X86AMode* iselAMode ( ISelEnv* env, IRExpr* e )
+{
+   assert(e);
+   assert(typeOfIRExpr(env->type_env,e) == Ity_I32);
+
+   /* Add32(expr1, Shl32(expr2, imm)) */
+   if (e->tag == Iex_Binop
+       && e->Iex.Binop.op == Iop_Add32
+       && e->Iex.Binop.arg2->tag == Iex_Binop
+       && e->Iex.Binop.arg2->Iex.Binop.op == Iop_Shl32
+       && e->Iex.Binop.arg2->Iex.Binop.arg2->tag == Iex_Const
+       && e->Iex.Binop.arg2->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U32) {
+      UInt shift = e->Iex.Binop.arg2->Iex.Binop.arg2->Iex.Const.con->Ico.U32;
+      if (shift == 2 || shift == 4 || shift == 8) {
+         HReg r1 = iselExprI(env, e->Iex.Binop.arg1);
+         HReg r2 = iselExprI(env, e->Iex.Binop.arg2->Iex.Binop.arg1 );
+         return X86AMode_IRRS(0, r1, r2, shift);
+      }
+   }
+
+   /* Add32(expr,i) */
+   if (e->tag == Iex_Binop 
+       && e->Iex.Binop.op == Iop_Add32
+       && e->Iex.Binop.arg2->tag == Iex_Const
+       && e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U32) {
+      HReg r1 = iselExprI(env,  e->Iex.Binop.arg1);
+      return X86AMode_IR(r1, e->Iex.Binop.arg2->Iex.Const.con->Ico.U32);
+   }
+
+   /* Doesn't match anything in particular.  Generate it into
+      a register and use that. */
+   {
+      HReg r1 = iselExprI(env, e);
+      return X86AMode_IR(r1, 0);
+   }
+}
+
+
+/*---------------------------------------------------------*/
+/*--- ISEL: Statements                                  ---*/
+/*---------------------------------------------------------*/
+
+void iselStmt ( ISelEnv* env, IRStmt* stmt )
+{
+   switch (stmt->tag) {
+
+   case Ist_Put:
+     if (stmt->Ist.Put.size == 4) {
+       HReg ebp = mkHReg(5, HRcInt, False);
+       HReg reg = iselExprI(env, stmt->Ist.Put.expr);
+       addInstr(env,
+               X86Instr_ST32(reg,
+                             X86AMode_IR(stmt->Ist.Put.offset,
+                                         ebp)
+                             ));
+       return;
+     }
+
+   default: break;
+   }
+   ppIRStmt(stderr, stmt);
+   panic("iselStmt");
+}
+
+
+/*---------------------------------------------------------*/
+/*--- ISEL: Basic block terminators (Nexts)             ---*/
+/*---------------------------------------------------------*/
+
+void iselNext ( ISelEnv* env, IRNext* next )
+{
+   switch (next->tag) {
+   default: 
+      ppIRNext(stderr, next);
+      panic("iselNext");
+   }
+}
+
+
+/*---------------------------------------------------------*/
+/*--- Insn selector top-level                           ---*/
+/*---------------------------------------------------------*/
+
+void /* not really, but for the time being ... */
+     iselBB ( IRBB* bb )
+{
+   Int     i;
+   HReg    hreg;
+   IRStmt* stmt;
+
+   /* Make up an initial environment to use. */
+   ISelEnv* env = malloc(sizeof(ISelEnv));
+   env->ctr = 0;
+
+   /* Set up output code array. */
+   env->code_used = 0;
+   env->code_size = 40;
+   env->code = malloc(env->code_size * sizeof(void*));
+
+   /* Copy BB's type env. */
+   env->type_env = bb->tyenv;
+
+   /* Make up an IRTemp -> virtual HReg mapping.  This doesn't
+      change as we go along. */
+   env->n_vregmap = bb->tyenv->map_used;
+   env->vregmap   = malloc(env->n_vregmap * sizeof(VRegMaplet));
+
+   /* For each IR temporary, allocate a suitably-kinded virtual
+      register. */
+   for (i = 0; i < env->n_vregmap; i++) {
+      env->vregmap[i].ir_name = bb->tyenv->map[i].name;
+      switch (bb->tyenv->map[i].type) {
+         case Ity_I32: hreg = mkHReg(i, HRcInt, True); break;
+         default: panic("iselBB: IRTemp type");
+      }
+      env->vregmap[i].vreg = hreg;
+   }
+
+   /* Ok, finally we can iterate over the statements. */
+   for (stmt = bb->stmts; stmt; stmt=stmt->link)
+      iselStmt(env,stmt);
+
+   iselNext(env,bb->next);
+}
diff --git a/VEX/test_main.c b/VEX/test_main.c
new file mode 100644 (file)
index 0000000..4af4155
--- /dev/null
@@ -0,0 +1,54 @@
+
+/*---------------------------------------------------------------*/
+/*---                                                         ---*/
+/*--- This file (test_main.c) is                              ---*/
+/*--- Copyright (c) 2004 OpenWorks LLP.  All rights reserved. ---*/
+/*---                                                         ---*/
+/*---------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "basictypes.h"
+#include "ir_defs.h"
+
+
+
+
+
+/*---------------------------------------------------------------*/
+/*--- Test                                                    ---*/
+/*---------------------------------------------------------------*/
+
+/* HACK */
+extern
+void /* not really, but for the time being ... */
+     iselBB ( IRBB* bb );
+
+int main ( void )
+{
+   IRBB*      bb;
+   IRTypeEnv* env = newIRTypeEnv();
+
+   IRTemp t1 = 1;
+   IRTemp t2 = 2;
+
+   addToIRTypeEnv ( env, t1, Ity_I32 );
+   addToIRTypeEnv ( env, t2, Ity_I32 );
+
+   IRStmt* s1 = IRStmt_Put(8,4, IRExpr_Const(IRConst_U32(99)) );
+   IRStmt* s2 = IRStmt_Put(7,4, IRExpr_Binop(Iop_Add32,
+                                             IRExpr_Tmp(t1),
+                                            IRExpr_Const(IRConst_U32(55))));
+   s1->link = s2;
+
+   bb = mk_IRBB(env, s1, IRNext_UJump(IRConst_U32(-65565)));
+
+   printf("bb is ...\n");
+   ppIRBB(stdout, bb);
+   printf("\n");
+
+   iselBB(bb);
+
+   return 0;
+}
diff --git a/VEX/x86h_defs.c b/VEX/x86h_defs.c
new file mode 100644 (file)
index 0000000..0f3549a
--- /dev/null
@@ -0,0 +1,226 @@
+
+/*---------------------------------------------------------------*/
+/*---                                                         ---*/
+/*--- This file (x86h_defs.c) is                              ---*/
+/*--- Copyright (c) 2004 OpenWorks LLP.  All rights reserved. ---*/
+/*---                                                         ---*/
+/*---------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <malloc.h>
+
+#include "basictypes.h"
+#include "host_regs.h"
+#include "x86h_defs.h"
+
+
+/* --------- Registers. --------- */
+
+void ppHRegX86 ( FILE* f, HReg reg ) 
+{
+   Int r;
+   static Char* ireg32_names[8] 
+     = { "%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi" };
+   /* Be generic for all virtual regs. */
+   if (hregIsVirtual(reg)) {
+      ppHReg(f, reg);
+      return;
+   }
+   /* But specific for real regs. */
+   switch (hregClass(reg)) {
+      case HRcInt:
+         r = hregNumber(reg);
+         assert(r >= 0 && r < 8);
+         fprintf(f, "%s", ireg32_names[r]);
+         return;
+      case HRcFloat:
+         r = hregNumber(reg);
+         assert(r >= 0 && r < 6);
+         fprintf(f, "%%fake%d", r);
+         return;
+      case HRcVector:
+         panic("ppHRegX86: real vector reg");
+     default:
+         panic("ppHRegX86");
+   }
+}
+
+
+/* --------- X86AMode: memory address expressions. --------- */
+
+X86AMode* X86AMode_IR ( UInt imm32, HReg reg ) {
+   X86AMode* am = malloc(sizeof(X86AMode));
+   am->tag = Xam_IR;
+   am->Xam.IR.imm = imm32;
+   am->Xam.IR.reg = reg;
+   return am;
+}
+
+X86AMode* X86AMode_IRRS ( UInt imm32, HReg base, HReg index, Int shift ) {
+   X86AMode* am = malloc(sizeof(X86AMode));
+   am->tag = Xam_IRRS;
+   am->Xam.IRRS.imm = imm32;
+   am->Xam.IRRS.base = base;
+   am->Xam.IRRS.index = index;
+   am->Xam.IRRS.shift = shift;
+   assert(shift >= 0 && shift <= 3);
+   return am;
+}
+
+void ppX86AMode ( FILE* f, X86AMode* am ) {
+   switch (am->tag) {
+      case Xam_IR: 
+         fprintf(f, "0x%x(", am->Xam.IR.imm);
+         ppHRegX86(f, am->Xam.IR.reg);
+         fprintf(f, ")");
+         return;
+      case Xam_IRRS:
+         fprintf(f, "0x%x(", am->Xam.IRRS.imm);
+         ppHRegX86(f, am->Xam.IRRS.base);
+         fprintf(f, ",");
+         ppHRegX86(f, am->Xam.IRRS.index);
+         fprintf(f, ",%d)", am->Xam.IRRS.shift);
+         return;
+      default:
+         panic("ppX86AMode");
+   }
+}
+
+
+/* --------- X86Operand.  Not all are valid for all insns. --------- */
+
+X86Operand* X86Operand_Imm ( UInt imm32 ) {
+   X86Operand* op    = malloc(sizeof(X86Operand));
+   op->tag           = Xop_Imm;
+   op->Xop.Imm.imm32 = imm32;
+   return op;
+}
+
+X86Operand* X86Operand_Reg ( HReg reg ) {
+   X86Operand* op  = malloc(sizeof(X86Operand));
+   op->tag         = Xop_Reg;
+   op->Xop.Reg.reg = reg;
+   return op;
+}
+
+X86Operand* X86Operand_Mem ( X86AMode* am ) {
+   X86Operand* op = malloc(sizeof(X86Operand));
+   op->tag        = Xop_Mem;
+   op->Xop.Mem.am = am;
+   return op;
+}
+
+void ppX86Operand ( FILE* f, X86Operand* op ) {
+   switch (op->tag) {
+      case Xop_Imm: 
+         fprintf(f, "$0x%x", op->Xop.Imm.imm32);
+         return;
+      case Xop_Reg: 
+         ppHRegX86(f, op->Xop.Reg.reg);
+         return;
+      case Xop_Mem: 
+         ppX86AMode(f, op->Xop.Mem.am);
+         return;
+     default: 
+         panic("ppX86Operand");
+   }
+}
+
+
+/* --------- Instructions. --------- */
+
+void ppX86AluOp ( FILE* f, X86AluOp op ) {
+   Char* name;
+   switch (op) {
+      case Xalu_ADD: name = "add"; break;
+      case Xalu_SUB: name = "sub"; break;
+      case Xalu_ADC: name = "adc"; break;
+      case Xalu_SBB: name = "sbb"; break;
+      case Xalu_AND: name = "and"; break;
+      case Xalu_OR:  name = "or";  break;
+      case Xalu_XOR: name = "xor"; break;
+      default: panic("ppX86AluOp");
+   }
+   fprintf(f, "%s", name);
+}
+
+X86Instr* X86Instr_ST32 ( HReg src, X86AMode* dst ) {
+   X86Instr* i     = malloc(sizeof(X86Instr));
+   i->tag          = Xin_ST32;
+   i->Xin.ST32.src = src;
+   i->Xin.ST32.dst = dst;
+   return i;
+}
+
+X86Instr* X86Instr_LD32 ( X86AMode* src, HReg dst ) {
+   X86Instr* i     = malloc(sizeof(X86Instr));
+   i->tag          = Xin_LD32;
+   i->Xin.LD32.src = src;
+   i->Xin.LD32.dst = dst;
+   return i;
+}
+
+X86Instr* X86Instr_Alu32 ( X86AluOp op, X86Operand* src, X86Operand* dst ) {
+   X86Instr* i      = malloc(sizeof(X86Instr));
+   i->tag           = Xin_Alu32;
+   i->Xin.Alu32.op  = op;
+   i->Xin.Alu32.src = src;
+   i->Xin.Alu32.dst = dst;
+   return i;
+}
+
+X86Instr* X86Instr_Mov32 ( X86Operand* src, X86Operand* dst ) {
+   X86Instr* i      = malloc(sizeof(X86Instr));
+   i->tag           = Xin_Mov32;
+   i->Xin.Mov32.src = src;
+   i->Xin.Mov32.dst = dst;
+   return i;
+}
+
+X86Instr* X86Instr_Alu16 ( X86AluOp op, X86Operand* src, X86Operand* dst ) {
+   X86Instr* i      = malloc(sizeof(X86Instr));
+   i->tag           = Xin_Alu16;
+   i->Xin.Alu16.op  = op;
+   i->Xin.Alu16.src = src;
+   i->Xin.Alu16.dst = dst;
+   return i;
+}
+
+void ppX86Instr ( FILE* f, X86Instr* i ) {
+   switch (i->tag) {
+      case Xin_ST32:
+         fprintf(f, "movl ");
+         ppHRegX86(f, i->Xin.ST32.src);
+         fprintf(f, ",");
+         ppX86AMode(f, i->Xin.ST32.dst);
+         return;
+      case Xin_LD32:
+         fprintf(f, "movl ");
+         ppX86AMode(f, i->Xin.LD32.src);
+         fprintf(f, ",");
+         ppHRegX86(f, i->Xin.LD32.dst);
+         return;
+      case Xin_Alu32:
+         ppX86AluOp(f, i->Xin.Alu32.op);
+         fprintf(f, "l ");
+         ppX86Operand(f, i->Xin.Alu32.src);
+         fprintf(f, ",");
+         ppX86Operand(f, i->Xin.Alu32.dst);
+         return;
+      case Xin_Mov32:
+         fprintf(f, "movl ");
+         ppX86Operand(f, i->Xin.Mov32.src);
+         fprintf(f, ",");
+         ppX86Operand(f, i->Xin.Mov32.dst);
+         return;
+      case Xin_Alu16:
+         ppX86AluOp(f, i->Xin.Alu16.op);
+         fprintf(f, "w ");
+         ppX86Operand(f, i->Xin.Alu16.src);
+         fprintf(f, ",");
+         ppX86Operand(f, i->Xin.Alu16.dst);
+         return;
+      default:
+         panic("ppX86Instr");
+   }
+}