[llvm-commits] CVS: llvm/lib/Reoptimizer/BinInterface/analyze.cpp analyze.h bitmath.h construct.cpp emit.cpp fvector.h regmask.h salloc.cpp salloc.h select.cpp sparc9.cpp sparc9.h sparcbin.cpp sparcbin.h sparcdis.cpp sparcdis.h sparcpriv.h test.cpp machine.h
Cameron Buschardt
buschard at cs.uiuc.edu
Sun Dec 15 05:09:01 PST 2002
Changes in directory llvm/lib/Reoptimizer/BinInterface:
analyze.cpp updated: 1.6 -> 1.7
analyze.h updated: 1.4 -> 1.5
bitmath.h updated: 1.4 -> 1.5
construct.cpp updated: 1.1 -> 1.2
emit.cpp updated: 1.1 -> 1.2
fvector.h updated: 1.5 -> 1.6
regmask.h updated: 1.1 -> 1.2
salloc.cpp updated: 1.2 -> 1.3
salloc.h updated: 1.3 -> 1.4
select.cpp updated: 1.1 -> 1.2
sparc9.cpp updated: 1.1 -> 1.2
sparc9.h updated: 1.7 -> 1.8
sparcbin.cpp updated: 1.2 -> 1.3
sparcbin.h updated: 1.2 -> 1.3
sparcdis.cpp updated: 1.5 -> 1.6
sparcdis.h updated: 1.4 -> 1.5
sparcpriv.h updated: 1.1 -> 1.2
test.cpp updated: 1.1 -> 1.2
machine.h (r1.3) removed
---
Log message:
Formatted code, removed debug printouts, fixed compatibility with
GCC 3.2 when outputting 64-bit code.
---
Diffs of the changes:
Index: llvm/lib/Reoptimizer/BinInterface/analyze.cpp
diff -u llvm/lib/Reoptimizer/BinInterface/analyze.cpp:1.6 llvm/lib/Reoptimizer/BinInterface/analyze.cpp:1.7
--- llvm/lib/Reoptimizer/BinInterface/analyze.cpp:1.6 Sat Dec 14 19:40:40 2002
+++ llvm/lib/Reoptimizer/BinInterface/analyze.cpp Sun Dec 15 05:06:55 2002
@@ -1,5 +1,5 @@
//*****************************************************************************
-// SPARC Instruction Analysis
+// SPARC Instruction Analysis
//
// Analysis API Implementation
//
@@ -17,273 +17,343 @@
#include <stdio.h>
#include <stdlib.h>
-#include "sparc9.h" // SPARC 9 opcode and field definitions
-#include "bitmath.h"
-#include "analyze.h" // API library
+#include "sparc9.h" // SPARC 9 opcode and field definitions
+#include "bitmath.h" // Binary arithmatic library
+#include "analyze.h" // Defintion of analysis interface
#include <assert.h>
+//*****************************************************************************
+// unsigned sparc_analyzebr(unsigned instr)
//
// Analyze instructions with OP field set to OP_BRANCH
// (note not all of these instructions are branches!)
//
+//
+// Returns a mask stating which parameters (RS1/RS2/etc) are present
+// and whether we write to CC, etc. See analyze.h
+//
+//*****************************************************************************
+
unsigned sparc_analyzebr(unsigned instr)
{
- // look at the OP2 field
- if (RD_FLD(instr, INSTR_OP2)==OP2_SETHI)
- {
- // The sethi instruction zeroes the register
- // and loads the immediate into bits 10->31
- if (RD_FLD(instr, INSTR_RD) == 0)
- return 0; // This is the special encoding for NOP
- else
- return IF_RD | IF_W_RD;
- }
- else if (RD_FLD(instr, INSTR_OP2)==OP2_BICC)
- {
- // Branch on integer condition code
- return IF_RCC | IF_BR;
- }
- else if (RD_FLD(instr, INSTR_OP2)==OP2_BPR)
- {
- // Branch on integer register with prediction
- return IF_RCC | IF_RS1 | IF_R_RS1;
- }
- else{
- // There are a few opcodes missing from this field,
- // if we run into any of them we can add support
- // most appear to be systems level instructions
-
- printf("Unknown:OP=0b00 OP2 = 0x%04X\n", RD_FLD(instr, INSTR_OP2));
- assert(0);
- return 0;
- }
+ // look at the OP2 field
+ if (RD_FLD(instr, INSTR_OP2)==OP2_SETHI)
+ {
+ // The sethi instruction zeroes the register
+ // and loads the immediate into bits 10->31
+ if (RD_FLD(instr, INSTR_RD) == 0)
+ return 0; // This is the special encoding for NOP
+ else
+ return IF_RD | IF_W_RD;
+ }
+ else if (RD_FLD(instr, INSTR_OP2)==OP2_BICC)
+ {
+ // Branch on integer condition code
+ return IF_RCC | IF_BR;
+ }
+ else if (RD_FLD(instr, INSTR_OP2)==OP2_BPR)
+ {
+ // Branch on integer register with prediction
+ return IF_RCC | IF_RS1 | IF_R_RS1;
+ }
+ else{
+ // There are a few opcodes missing from this field,
+ // if we run into any of them we can add support
+ // most appear to be systems level instructions
+
+ printf("Unknown:OP=0b00 OP2 = 0x%04X\n", RD_FLD(instr, INSTR_OP2));
+ assert(0);
return 0;
+ }
+ return 0;
}
+//*****************************************************************************
+// unsigned sparc_analyze_c2(unsigned instr)
//
-// Analyze instructions with OP field set to 2
+// Analyze instructions with OP field set to OP_2
//
+//*****************************************************************************
+
unsigned sparc_analyze_c2(unsigned instr)
{
- switch(RD_FLD(instr, INSTR_OP3))
- {
- case OP3_DONERETRY:
- assert(0); // This appears to be a system instruction
- // either way though it acts like a branch
- // and should NOT appear in an trace
- return 0;
-
- case OP3_FCMP:
- case OP3_FPU:
- assert(0); // TODO: Add support when we do floating point
- // support!
- return 0;
-
- case OP3_FLUSHW: //OP=OP_2 I = 0
- return 0; // Flush has no negative side effects
-
- case OP3_FLUSH: //OP=OP_2 RS1 {I=0 -> IF_RS2, I=1->simm13}
- if (RD_FLD(instr, INSTR_I) == 0)
- return IF_RS1 | IF_RS2 | IF_R_RS1 | IF_R_RS2;
- else
- return IF_RS1 | IF_R_RS1;
-
- case OP3_JMPL: //OP=OP_2 RD, IF_RS1 {I=0-> IF_RS2, I=1->SIMM13}
- case OP3_ADD:
- case OP3_AND:
- case OP3_OR:
- case OP3_XOR:
- case OP3_SUB:
- case OP3_ANDN:
- case OP3_ORN:
- case OP3_XNOR:
- case OP3_MULX:
- case OP3_SDIVX:
- case OP3_UDIVX:
- case OP3_SLL:
- case OP3_SRL:
- case OP3_SRA:
- case OP3_SAVE:
- case OP3_RETURN:
- case OP3_RESTORE:
- if (RD_FLD(instr, INSTR_I) == 0)
- return IF_RD | IF_RS1 | IF_RS2 | IF_R_RS1 | IF_R_RS2 | IF_W_RD;
- else
- return IF_RD | IF_RS1 | IF_W_RD | IF_R_RS1;
-
- case OP3_ADDC:
- case OP3_SUBC:
- if (RD_FLD(instr, INSTR_I) == 0)
- return IF_RD| IF_RS1 | IF_RS2 | IF_RCC | IF_W_RD | IF_R_RS1 | IF_R_RS2;
- else
- return IF_RD| IF_RS1 | IF_RCC | IF_W_RD | IF_R_RS1;
-
-
-
- case OP3_XNORcc:
- case OP3_ANDNcc:
- case OP3_ANDcc:
- case OP3_ADDcc:
- case OP3_ORcc:
- case OP3_ORNcc:
- case OP3_SUBcc:
- case OP3_XORcc:
- if (RD_FLD(instr, INSTR_I) == 0)
- return IF_RD | IF_RS1 | IF_RS2 | IF_WCC | IF_W_RD | IF_R_RS1 | IF_R_RS2;
- else
- return IF_RD | IF_RS1 | IF_WCC | IF_W_RD | IF_R_RS1;
-
- case OP3_ADDCcc:
- case OP3_SUBCcc:
- if (RD_FLD(instr, INSTR_I) == 0)
- return IF_RD | IF_RS1 | IF_RS2 | IF_WCC | IF_RCC | IF_W_RD | IF_R_RS1 | IF_R_RS2;
- else
- return IF_RD | IF_RS1 | IF_WCC | IF_RCC | IF_W_RD | IF_R_RS1;
-
- case OP3_MOVcc:
- if (RD_FLD(instr, INSTR_I) == 0)
- {
- if (RD_FLD(instr, INSTR_COND_L)==COND_BA)
- return IF_RD | IF_RS2 | IF_W_RD | IF_R_RS2;
- else
- return IF_RD | IF_RS2 | IF_W_RD | IF_R_RS2 | IF_RCC;
- }
- else
- {
- if (RD_FLD(instr, INSTR_COND_L)==COND_BA)
- return IF_RD | IF_W_RD;
- else
- return IF_RD | IF_W_RD | IF_RCC;
- }
-
- default:
- printf("Unknown:OP=0b10 OP3 = 0x%04X\n", RD_FLD(instr, INSTR_OP3));
- assert(0);
-
- }
- return 0;
+ switch(RD_FLD(instr, INSTR_OP3))
+ {
+ case OP3_DONERETRY:
+ assert(0); // This appears to be a system instruction
+ // either way though it acts like a branch
+ // and should NOT appear in an trace
+ return 0;
+
+ case OP3_FCMP:
+ case OP3_FPU:
+ assert(0); // TODO: Add support when we do floating point
+ // support!
+ return 0;
+
+ case OP3_FLUSHW: //OP=OP_2 I = 0
+ return 0; // Flush has no negative side effects
+
+ case OP3_FLUSH: //OP=OP_2 RS1 {I=0 -> IF_RS2, I=1->simm13}
+ if (RD_FLD(instr, INSTR_I) == 0)
+ return IF_RS1 | IF_RS2 | IF_R_RS1 | IF_R_RS2;
+ else
+ return IF_RS1 | IF_R_RS1;
+
+ case OP3_JMPL: //OP=OP_2 RD, IF_RS1 {I=0-> IF_RS2, I=1->SIMM13}
+ case OP3_ADD:
+ case OP3_AND:
+ case OP3_OR:
+ case OP3_XOR:
+ case OP3_SUB:
+ case OP3_ANDN:
+ case OP3_ORN:
+ case OP3_XNOR:
+ case OP3_MULX:
+ case OP3_SDIVX:
+ case OP3_UDIVX:
+ case OP3_SLL:
+ case OP3_SRL:
+ case OP3_SRA:
+ case OP3_SAVE:
+ case OP3_RETURN:
+ case OP3_RESTORE:
+ if (RD_FLD(instr, INSTR_I) == 0)
+ return IF_RD | IF_RS1 | IF_RS2 | IF_R_RS1 | IF_R_RS2 | IF_W_RD;
+ else
+ return IF_RD | IF_RS1 | IF_W_RD | IF_R_RS1;
+
+ case OP3_ADDC:
+ case OP3_SUBC:
+ if (RD_FLD(instr, INSTR_I) == 0)
+ return IF_RD| IF_RS1 | IF_RS2 | IF_RCC | IF_W_RD | IF_R_RS1 | IF_R_RS2;
+ else
+ return IF_RD| IF_RS1 | IF_RCC | IF_W_RD | IF_R_RS1;
+
+
+
+ case OP3_XNORcc:
+ case OP3_ANDNcc:
+ case OP3_ANDcc:
+ case OP3_ADDcc:
+ case OP3_ORcc:
+ case OP3_ORNcc:
+ case OP3_SUBcc:
+ case OP3_XORcc:
+ if (RD_FLD(instr, INSTR_I) == 0)
+ return IF_RD | IF_RS1 | IF_RS2 | IF_WCC | IF_W_RD | IF_R_RS1 | IF_R_RS2;
+ else
+ return IF_RD | IF_RS1 | IF_WCC | IF_W_RD | IF_R_RS1;
+
+ case OP3_ADDCcc:
+ case OP3_SUBCcc:
+ if (RD_FLD(instr, INSTR_I) == 0)
+ return IF_RD | IF_RS1 | IF_RS2 | IF_WCC | IF_RCC | IF_W_RD | IF_R_RS1 | IF_R_RS2;
+ else
+ return IF_RD | IF_RS1 | IF_WCC | IF_RCC | IF_W_RD | IF_R_RS1;
+
+ case OP3_MOVcc:
+ if (RD_FLD(instr, INSTR_I) == 0)
+ {
+ if (RD_FLD(instr, INSTR_COND_L)==COND_BA)
+ return IF_RD | IF_RS2 | IF_W_RD | IF_R_RS2;
+ else
+ return IF_RD | IF_RS2 | IF_W_RD | IF_R_RS2 | IF_RCC;
+ }
+ else
+ {
+ if (RD_FLD(instr, INSTR_COND_L)==COND_BA)
+ return IF_RD | IF_W_RD;
+ else
+ return IF_RD | IF_W_RD | IF_RCC;
+ }
+
+ default:
+ printf("Unknown:OP=0b10 OP3 = 0x%04X\n", RD_FLD(instr, INSTR_OP3));
+ assert(0);
+
+ }
+ return 0;
}
+//*****************************************************************************
+// unsigned sparc_analyze3(unsigned instr)
+//
+// Analyze instructions with OP field set to OP_3
+//
+//*****************************************************************************
unsigned sparc_analyze3(unsigned instr)
{
- switch(RD_FLD(instr, INSTR_OP3))
- {
- //OP=OP_3 RD, IF_RS1 {I=0->IF_RS2, I=1->SIMM13}
- // BUG FIX! ST* does not write to RD, rather it reads!!
- case OP3_STB:
- case OP3_STH:
- case OP3_STW:
- case OP3_STX:
-
- if (RD_FLD(instr, INSTR_I) == 0)
- return IF_RD | IF_RS1 | IF_RS2 | IF_R_RS1 | IF_R_RS2 | IF_R_RD;
- else
- return IF_RD | IF_RS1 | IF_R_RS1 | IF_R_RS2 | IF_R_RD;
-
- case OP3_STFA:
- case OP3_STDFA:
- case OP3_STQFA:
- assert(0);
- return 0;
-
- case OP3_LDSB:
- case OP3_LDSH:
- case OP3_LDSW:
- case OP3_LDUB:
- case OP3_LDUH:
- case OP3_LDUW:
- case OP3_LDX:
- case OP3_LDSTUB:
- if (RD_FLD(instr, INSTR_I) == 0)
- return IF_RD | IF_RS1 | IF_RS2 | IF_W_RD | IF_R_RS1 | IF_R_RS2;
- else
- return IF_RD | IF_RS1 | IF_W_RD | IF_R_RS1;
-
-
- // compare and exchange r[rd] with value at r[rs1] depending on
- // comparison between r[rs1] and r[rs2]
- case OP3_CASXA:
- case OP3_CASA:
- return IF_RD | IF_RS1 | IF_RS2 | IF_W_RD | IF_R_RD | IF_RS1 | IF_RS2;
-
- // Cache line prefetch instructions
- case OP3_PREFETCHA:
- case OP3_PREFETCH:
- if (RD_FLD(instr, INSTR_I) == 0)
- return IF_RS1 | IF_RS2 | IF_R_RS1 | IF_R_RS2;
- else
- return IF_RS1 | IF_R_RS1;
-
- default:
- printf("Unknown OP_3: OP3 = %08X\n", RD_FLD(instr, INSTR_OP3));
- assert(0);
- }
- return 0;
+ switch(RD_FLD(instr, INSTR_OP3))
+ {
+ //OP=OP_3 RD, IF_RS1 {I=0->IF_RS2, I=1->SIMM13}
+ // BUG FIX! ST* does not write to RD, rather it reads!!
+ case OP3_STB:
+ case OP3_STH:
+ case OP3_STW:
+ case OP3_STX:
+
+ if (RD_FLD(instr, INSTR_I) == 0)
+ return IF_RD | IF_RS1 | IF_RS2 | IF_R_RS1 | IF_R_RS2 | IF_R_RD;
+ else
+ return IF_RD | IF_RS1 | IF_R_RS1 | IF_R_RS2 | IF_R_RD;
+
+ case OP3_STFA:
+ case OP3_STDFA:
+ case OP3_STQFA:
+ assert(0);
+ return 0;
+
+ case OP3_LDSB:
+ case OP3_LDSH:
+ case OP3_LDSW:
+ case OP3_LDUB:
+ case OP3_LDUH:
+ case OP3_LDUW:
+ case OP3_LDX:
+ case OP3_LDSTUB:
+ if (RD_FLD(instr, INSTR_I) == 0)
+ return IF_RD | IF_RS1 | IF_RS2 | IF_W_RD | IF_R_RS1 | IF_R_RS2;
+ else
+ return IF_RD | IF_RS1 | IF_W_RD | IF_R_RS1;
+
+
+ // compare and exchange r[rd] with value at r[rs1] depending on
+ // comparison between r[rs1] and r[rs2]
+ case OP3_CASXA:
+ case OP3_CASA:
+ return IF_RD | IF_RS1 | IF_RS2 | IF_W_RD | IF_R_RD | IF_RS1 | IF_RS2;
+
+ // Cache line prefetch instructions
+ case OP3_PREFETCHA:
+ case OP3_PREFETCH:
+ if (RD_FLD(instr, INSTR_I) == 0)
+ return IF_RS1 | IF_RS2 | IF_R_RS1 | IF_R_RS2;
+ else
+ return IF_RS1 | IF_R_RS1;
+
+ default:
+ printf("Unknown OP_3: OP3 = %08X\n", RD_FLD(instr, INSTR_OP3));
+ assert(0);
+ }
+ return 0;
}
+//*****************************************************************************
+// unsigned sparc_analyze_full(unsigned instr)
+//
+// Analyze general instructions.
+//
+//*****************************************************************************
+
unsigned sparc_analyze_full(unsigned instr)
{
- if (RD_FLD(instr,INSTR_OP)==OP_2)
- return sparc_analyze_c2(instr);
- else if (RD_FLD(instr,INSTR_OP)==OP_3)
- return sparc_analyze3(instr);
- else if (RD_FLD(instr,INSTR_OP)==OP_BRANCH)
- return sparc_analyzebr(instr);
- else
- return IF_CALL; // Call instruction not seen as branch
- // in that control flow change is transparent
- // to trace
- return 0;
+ if (RD_FLD(instr,INSTR_OP)==OP_2)
+ return sparc_analyze_c2(instr);
+ else if (RD_FLD(instr,INSTR_OP)==OP_3)
+ return sparc_analyze3(instr);
+ else if (RD_FLD(instr,INSTR_OP)==OP_BRANCH)
+ return sparc_analyzebr(instr);
+ else
+ return IF_CALL; // Call instruction not seen as branch
+ // in that control flow change is transparent
+ // to trace
+ return 0;
}
+//*****************************************************************************
+// unsigned sparc_analyze(unsigned instr)
+//
+// Certain registers namely G0 (since writes don't take)
+// must be ignored during dataflow analysis. Thus after
+// running the full analysis pass we read all parameters
+// that are marked as present - if the register is one of the
+// banned ones we pretend that field isn't read.
+//
+//*****************************************************************************
+
unsigned sparc_analyze(unsigned instr)
{
- unsigned flags = sparc_analyze_full(instr);
-
- // validate that none of these registers are R0 if
- // they are cancel read or write flags on that field
-
- if (flags & IF_RS1)
- if ((1 << RD_FLD(instr, INSTR_RS1)) & RM_IGNORE)
- flags &= ~IF_R_RS1;
- if (flags & IF_RS2)
- if ((1 << RD_FLD(instr, INSTR_RS2)) & RM_IGNORE)
- flags &= ~IF_R_RS2;
-
- if (flags & IF_RD)
- if ((1 << RD_FLD(instr, INSTR_RD)) & RM_IGNORE)
- flags &= ~(IF_R_RD | IF_W_RD);
+ unsigned flags = sparc_analyze_full(instr);
- return flags;
+ // validate that none of these registers are R0 if
+ // they are cancel read or write flags on that field
+
+ if (flags & IF_RS1)
+ if ((1 << RD_FLD(instr, INSTR_RS1)) & RM_IGNORE)
+ flags &= ~IF_R_RS1;
+ if (flags & IF_RS2)
+ if ((1 << RD_FLD(instr, INSTR_RS2)) & RM_IGNORE)
+ flags &= ~IF_R_RS2;
+
+ if (flags & IF_RD)
+ if ((1 << RD_FLD(instr, INSTR_RD)) & RM_IGNORE)
+ flags &= ~(IF_R_RD | IF_W_RD);
+
+ return flags;
}
+//*****************************************************************************
+// unsigned sparc_getwrites(unsigned mask, unsigned instr)
+//
+// Mask is the result from sparc_analyze.
+//
+// Returns a mask describing which registers were written to
+// CC0 isn't in here.
+//
+//*****************************************************************************
unsigned sparc_getwrites(unsigned mask, unsigned instr)
{
- if (mask & IF_RD)
- return (1 << RD_FLD(instr, INSTR_RD));
- else
- return 0;
+ if (mask & IF_W_RD)
+ return (1 << RD_FLD(instr, INSTR_RD));
+ else
+ return 0;
}
+//*****************************************************************************
+// unsigned sparc_getreads(unsigned mask, unsigned instr)
+//
+// Mask is the result from sparc_analyze.
+//
+// Returns a mask describing which registers were read from
+//
+//*****************************************************************************
unsigned sparc_getreads (unsigned mask, unsigned instr)
{
- unsigned m = 0;
-
- if (mask & IF_RS1)
- m |= (1 << RD_FLD(instr, INSTR_RS1));
+ unsigned m = 0;
+
+ if (mask & IF_R_RS1)
+ m |= (1 << RD_FLD(instr, INSTR_RS1));
- if (mask & IF_RS2)
- m |= (1 << RD_FLD(instr, INSTR_RS2));
+ if (mask & IF_R_RS2)
+ m |= (1 << RD_FLD(instr, INSTR_RS2));
+
+ if (mask & IF_R_RD)
+ m |= (1 << RD_FLD(instr, INSTR_RD));
- return m;
+ return m;
}
-unsigned sparc_getcc (unsigned mask, unsigned instr) // bit 0 -> CC READ , bit 1 -> CC write
+//*****************************************************************************
+// unsigned sparc_getcc(unsigned mask, unsigned instr)
+//
+// Mask is the result from sparc_analyze.
+//
+// Returns the part of the mask strictly dealing with WCC or RCC
+//
+//*****************************************************************************
+
+unsigned sparc_getcc (unsigned mask, unsigned instr)
{
- return (mask & (IF_WCC | IF_RCC));
+ return (mask & (IF_WCC | IF_RCC));
}
+//*****************************************************************************
+// unsigned sparc_getbrdest(unsigned instr)
+//
+// Returns the relative offset for the branch (in instruction words)
+// eg 1 means 1 instruction forward.
//
// Complete list of instructions that require relocation:
// BPr -> D16LO/D16HI field
@@ -292,54 +362,67 @@
// Bicc -> DISP22 field (deprecated)
// BPcc -> DISP19 field
// CALL -> DISP30 field
-
-// returns relative branch destination (in instruction words)
+//*****************************************************************************
+
signed sparc_getbrdest(unsigned instr)
{
- if (RD_FLD(instr, INSTR_OP)==OP_CALL)
- return SIGN_EXTEND(RD_FLD(instr, INSTR_DISP30),30);
- else
- {
- assert(RD_FLD(instr,INSTR_OP)==OP_BRANCH);
- switch(RD_FLD(instr, INSTR_OP2))
- {
- case OP2_BPR: // D16LO/D16HI
- return SIGN_EXTEND(RD_D16(instr), 16);
- case OP2_BICC: // DISP22 field
- case OP2_FB: // DISP22 field
- return SIGN_EXTEND(RD_FLD(instr, INSTR_DISP22), 22);
- case OP2_FBP: // DISP19 field
- case OP2_BPICC: // DISP19 field
- return SIGN_EXTEND(RD_FLD(instr, INSTR_DISP19), 19);
- default:
- assert(0);
- }
-
- }
+ if (RD_FLD(instr, INSTR_OP)==OP_CALL)
+ return SIGN_EXTEND(RD_FLD(instr, INSTR_DISP30),30);
+ else
+ {
+ assert(RD_FLD(instr,INSTR_OP)==OP_BRANCH);
+ switch(RD_FLD(instr, INSTR_OP2))
+ {
+ case OP2_BPR: // D16LO/D16HI
+ return SIGN_EXTEND(RD_D16(instr), 16);
+ case OP2_BICC: // DISP22 field
+ case OP2_FB: // DISP22 field
+ return SIGN_EXTEND(RD_FLD(instr, INSTR_DISP22), 22);
+ case OP2_FBP: // DISP19 field
+ case OP2_BPICC: // DISP19 field
+ return SIGN_EXTEND(RD_FLD(instr, INSTR_DISP19), 19);
+ default:
+ assert(0);
+ }
+
+ }
}
+//*****************************************************************************
+// unsigned sparc_setbrdest(unsigned instr, signed reladdr)
+//
+// Modifies the relative destination of a given branch
+//
+//*****************************************************************************
+
unsigned sparc_setbrdest(unsigned instr, signed reladdr)
{
-
- if (RD_FLD(instr,INSTR_OP)==OP_CALL)
- return MK_FLD(INSTR_OP, OP_CALL) | MK_FLD(INSTR_DISP30, unsigned(reladdr) & 0x3FFFFFFF);
- else
- {
- assert(RD_FLD(instr,INSTR_OP)==OP_BRANCH);
- switch(RD_FLD(instr, INSTR_OP2))
- {
- case OP2_BPR: // D16LO/D16HI
- return RM_FLD(INSTR_D16LO, RM_FLD(INSTR_D16HI, instr)) | MK_FLD(INSTR_D16LO, unsigned(reladdr) & 0x3FFF) | MK_FLD(INSTR_D16HI, (unsigned(reladdr) >> 14) & 3);
-
- case OP2_BICC: // DISP22 field
- case OP2_FB: // DISP22 field
- return RM_FLD(INSTR_DISP22, instr) | MK_FLD(INSTR_DISP22, unsigned(reladdr) & 0x003FFFFF);
- case OP2_FBP: // DISP19 field
- case OP2_BPICC: // DISP19 field
- return RM_FLD(INSTR_DISP19, instr) | MK_FLD(INSTR_DISP19, unsigned(reladdr) & 0x0007FFFF);
- default:
- assert(0);
- }
- }
+
+ if (RD_FLD(instr,INSTR_OP)==OP_CALL)
+ return MK_FLD(INSTR_OP, OP_CALL) |
+ MK_FLD(INSTR_DISP30, unsigned(reladdr) & 0x3FFFFFFF);
+ else
+ {
+ assert(RD_FLD(instr,INSTR_OP)==OP_BRANCH);
+
+ switch(RD_FLD(instr, INSTR_OP2))
+ {
+ case OP2_BPR: // D16LO/D16HI
+ return RM_FLD(INSTR_D16LO, RM_FLD(INSTR_D16HI, instr)) |
+ MK_FLD(INSTR_D16LO, unsigned(reladdr) & 0x3FFF) |
+ MK_FLD(INSTR_D16HI, (unsigned(reladdr) >> 14) & 3);
+
+ case OP2_BICC: // DISP22 field
+ case OP2_FB: // DISP22 field
+ return RM_FLD(INSTR_DISP22, instr) |
+ MK_FLD(INSTR_DISP22, unsigned(reladdr) & 0x003FFFFF);
+ case OP2_FBP: // DISP19 field
+ case OP2_BPICC: // DISP19 field
+ return RM_FLD(INSTR_DISP19, instr) |
+ MK_FLD(INSTR_DISP19, unsigned(reladdr) & 0x0007FFFF);
+ default:
+ assert(0);
+ }
+ }
}
Index: llvm/lib/Reoptimizer/BinInterface/analyze.h
diff -u llvm/lib/Reoptimizer/BinInterface/analyze.h:1.4 llvm/lib/Reoptimizer/BinInterface/analyze.h:1.5
--- llvm/lib/Reoptimizer/BinInterface/analyze.h:1.4 Sat Dec 14 19:31:33 2002
+++ llvm/lib/Reoptimizer/BinInterface/analyze.h Sun Dec 15 05:07:01 2002
@@ -1,5 +1,5 @@
//*****************************************************************************
-// SPARC Instruction Analysis
+// SPARC Instruction Analysis
//
// Analysis API Header
//
@@ -27,8 +27,8 @@
#define IF_R_RS2 0x200 // reads from RS2
#define IF_CALL 0x400 // Is call instruction? (affects live registers)
#define IF_USR 0x800 // Later in the code we wish to be able to pack other
- // flags along side these when we store them in the
- // SSA form. This is the first 'user' flag available
+// flags along side these when we store them in the
+// SSA form. This is the first 'user' flag available
Index: llvm/lib/Reoptimizer/BinInterface/bitmath.h
diff -u llvm/lib/Reoptimizer/BinInterface/bitmath.h:1.4 llvm/lib/Reoptimizer/BinInterface/bitmath.h:1.5
--- llvm/lib/Reoptimizer/BinInterface/bitmath.h:1.4 Sat Dec 14 19:31:33 2002
+++ llvm/lib/Reoptimizer/BinInterface/bitmath.h Sun Dec 15 05:07:01 2002
@@ -18,7 +18,7 @@
#ifndef __BITMATH_H__
#define __BITMATH_H__
-
+
//*********************************
// Misc functions
//*********************************
@@ -26,7 +26,7 @@
#define ROUNDUP_P2(x, k) ((x+P2KM1(k)) &~ P2KM1(k))
#define ROUNDUP32(x) ROUNDUP_P2(x,5) // round up to nearest mult of 32
-
+
//*********************************
// Bitfield manipulation Macros
//*********************************
@@ -44,7 +44,7 @@
//**********************************
#define SIGN_EXTEND13(x) (x & 0x1000 ? -(-x & 0x1FFF): x)
#define SIGN_EXTEND(x, bits) (x & (1 << (bits-1)) ? -(-x & ((1 << bits)-1)):x)
-
+
#define IS_POWER_2(x) !(x & (x-1))
#define LOWEST_BIT(x) (x & ~(x & (x-1)))
#define UPPER_BITS(x) (x & (x-1))
@@ -52,84 +52,84 @@
// Good if expected number of bits set < 4
static int countbits_sparse(unsigned m) //VALIDATED
{
- int c = 0;
- while (m)
- {
- c++;
- m = UPPER_BITS(m);
- }
- return c;
+ int c = 0;
+ while (m)
+ {
+ c++;
+ m = UPPER_BITS(m);
+ }
+ return c;
}
// base 2 sum of digits (hardwired for 32-bit)
static int countbits_dense(unsigned w) //VALIDATED
{
- w = (0x55555555 & w) + (0x55555555 & (w >> 1));
- w = (0x33333333 & w) + (0x33333333 & (w >> 2));
- w = (w + (w>>4)) & 0x0f0f0f0f;
- w = w + (w>>16);
- w = w + (w>>8);
- return w&0xFF;
+ w = (0x55555555 & w) + (0x55555555 & (w >> 1));
+ w = (0x33333333 & w) + (0x33333333 & (w >> 2));
+ w = (w + (w>>4)) & 0x0f0f0f0f;
+ w = w + (w>>16);
+ w = w + (w>>8);
+ return w&0xFF;
}
static bool ismod3(unsigned w) //VALIDATED
{
- w = (w >> 16) + (w&0xFFFF);
- w = (w >> 8) + (w&0xFF);
- w = (w >> 4) + (w&0xF);
- w = (w >> 2) + (w&0x3);
- return (0xB6DB6DB6 >> w) & 1;
+ w = (w >> 16) + (w&0xFFFF);
+ w = (w >> 8) + (w&0xFF);
+ w = (w >> 4) + (w&0xF);
+ w = (w >> 2) + (w&0x3);
+ return (0xB6DB6DB6 >> w) & 1;
}
static int mod3(unsigned w) //VALIDATED
{
- w = (w >> 16) + (w&0xFFFF);
- w = (w >> 8) + (w&0xFF);
- w = (w >> 4) + (w&0xF);
- w = (w >> 2) + (w&0x3);
- //use lookuptable
- return (0x24924924 >> (w<<1)) & 3;
+ w = (w >> 16) + (w&0xFFFF);
+ w = (w >> 8) + (w&0xFF);
+ w = (w >> 4) + (w&0xF);
+ w = (w >> 2) + (w&0x3);
+ //use lookuptable
+ return (0x24924924 >> (w<<1)) & 3;
}
static int parity(unsigned w) //VALIDATED
{
- w ^= w >> 16;
- w ^= w >> 8;
- w ^= w >> 4;
- w ^= w >> 2;
- w ^= w >> 1;
- return w & 1;
+ w ^= w >> 16;
+ w ^= w >> 8;
+ w ^= w >> 4;
+ w ^= w >> 2;
+ w ^= w >> 1;
+ return w & 1;
}
//
// Note: users of this function may depend on the fact
-// that log2(0) will return 0. Since it is
+// that log2(0) will return 0. Since it is
// undefined I have chosen this value.
//
-static int log2(unsigned w) //VALIDATED
+static int log2_bits32(unsigned w) //VALIDATED
{
- int n = 0;
+ int n = 0;
- if (w >> 16)
- {
- w >>= 16;
- n+=16;
- }
- if (w >> 8)
- {
- w >>= 8;
- n+=8;
- }
- if (w >> 4)
- {
- w >>= 4;
- n+=4;
- }
+ if (w >> 16)
+ {
+ w >>= 16;
+ n+=16;
+ }
+ if (w >> 8)
+ {
+ w >>= 8;
+ n+=8;
+ }
+ if (w >> 4)
+ {
+ w >>= 4;
+ n+=4;
+ }
- w <<= 1;
- return ((0xFFFFAA50 >> w) & 3)+n; // this is a LUT
+ w <<= 1;
+ return ((0xFFFFAA50 >> w) & 3)+n; // this is a LUT
}
Index: llvm/lib/Reoptimizer/BinInterface/construct.cpp
diff -u llvm/lib/Reoptimizer/BinInterface/construct.cpp:1.1 llvm/lib/Reoptimizer/BinInterface/construct.cpp:1.2
--- llvm/lib/Reoptimizer/BinInterface/construct.cpp:1.1 Sat Dec 14 19:31:37 2002
+++ llvm/lib/Reoptimizer/BinInterface/construct.cpp Sun Dec 15 05:07:11 2002
@@ -1,6 +1,6 @@
//*****************************************************************************
// SPARC Binary Manipulation Interface
-//
+//
// SSA Construction
//
// Interface Definition
@@ -13,226 +13,274 @@
#include <stdlib.h>
#include "salloc.h" // Stack allocator class
#include "fvector.h" // fast vector (sits on stack allocator)
-#include "analyze.h" // SPARC analysis library (gets flag masks for instrs)
+#include "analyze.h" // SPARC analysis library
#include "sparcbin.h" // Prototype for this class
-#include "sparcpriv.h" // Private definitions#include "machine.h" // machine constants for cache optimizations
+#include "sparcpriv.h" // Private definitions
#include "sparcdis.h" // prototype for sparc disassembler
#include "bitmath.h" // header of optimized binary math routines
-#include "sparc9.h" // SPARC 9 opcode definitions
+#include "sparc9.h" // SPARC 9 opcode definitions
+#include "regmask.h" // the register mask allocator
+
#include <vector>
+using std::pair; // use STL pair class
-using std::pair;
#include <assert.h>
-#include "regmask.h"
+//*****************************************************************************
+// process_markgen(unsigned s, unsigned map[32],
+// fvector<unsigned[32]> & regmaps)
+//
+// Second pass
+//
+// unsigned s - the section id to process
+// map[kreg] - the SSA id that is represented by reg 'kreg'
+// at section entry/exit. This routine
+// is responsible for replacing this with
+// the register state at the end of section.
+//
+// Any instructions that read from a register that has an SSA id of 0
+// is assumed to be live-in.
+//
+// The instructions will get their genrs1/genrs2/genrd fields expanded
+// in this fucntion
+//
+//*****************************************************************************
+void BinInterface::process_markgen (unsigned s, unsigned map[32])
+{
+ // iterate all instructions in this section
+ for (int i = begin(s); i!=end(s); )
+ {
+ // look at instruction
+ instruction * instr = itable[i];
+ unsigned flags = instr->flags;
+ // what uses?
+ if (flags & IF_R_RS1)
+ {
+ int rs1 = RD_FLD(instr->instr, INSTR_RS1);
+ if (!map[rs1])
+ // oops. we just made a reference to an incoming value. Instantiate
+ map[rs1] = allocnodelivein(sections[0],rs1);
-void BinInterface::process_markgen(unsigned s, unsigned map[32],fvector<unsigned[32]> & regmaps)
-{
- // iterate all instructions in this section
- for (int i = begin(s); i!=end(s); )
- {
- // look at instruction
- instruction * instr = itable[i];
- unsigned flags = instr->flags;
-
- // what uses?
- if (flags & IF_R_RS1)
- {
- int rs1 = RD_FLD(instr->instr, INSTR_RS1);
- if (!map[rs1])
- // oops. we just made a reference to an incoming value. Instantiate
- map[rs1] = allocnodelivein(sections[0],rs1);
-
- instr->alu.genrs1 = map[rs1];
- }
-
- if (flags & IF_R_RS2)
- {
- int rs2 = RD_FLD(instr->instr, INSTR_RS2);
- if (!map[rs2])
- map[rs2] = allocnodelivein(sections[0],rs2);
- instr->alu.genrs2 = map[rs2];
- }
-
- if (flags & IF_R_RD)
- {
- int rd = RD_FLD(instr->instr, INSTR_RD);
- if (!map[rd])
- map[rd] = allocnodelivein(sections[0], rd);
- instr->alu.genrd = map[rd];
- }
-
- // does he write to a register?
- if (flags & IF_W_RD)
- map[RD_FLD(instr->instr, INSTR_RD)] = i;
- else if (flags & IF_PHI)
- map[instr->instr] = instr->self; // use phi node for reg val
-
- // advance
- i = instr->next;
-
- }
+ instr->alu.genrs1 = map[rs1];
+ }
+
+ if (flags & IF_R_RS2)
+ {
+ int rs2 = RD_FLD(instr->instr, INSTR_RS2);
+ if (!map[rs2])
+ map[rs2] = allocnodelivein(sections[0],rs2);
+ instr->alu.genrs2 = map[rs2];
+ }
+
+ if (flags & IF_R_RD)
+ {
+ int rd = RD_FLD(instr->instr, INSTR_RD);
+ if (!map[rd])
+ map[rd] = allocnodelivein(sections[0], rd);
+ instr->alu.genrd = map[rd];
+ }
+
+ // does he write to a register?
+ if (flags & IF_W_RD)
+ map[RD_FLD(instr->instr, INSTR_RD)] = i;
+ else if (flags & IF_PHI)
+ map[instr->instr] = instr->self; // use phi node for reg val
+
+ // advance
+ i = instr->next;
+
+ }
}
+//*****************************************************************************
+// construct_merge(int s, int brdest, unsigned map[32],
+// fvector<unsigned[32]> & regmaps)
+//
+//
+//
+//*****************************************************************************
-void BinInterface::process_section(unsigned s, unsigned map[32],fvector<unsigned[32]> & regmaps)
+void BinInterface::construct_merge(int s, int brdest, unsigned map[32], fvector<unsigned[32]> & regmaps)
{
- // We inherit map from parent (p->t->e) -- FIX HANDLING OF MULTIPLE EPILOGS
- for (int v=0;v<32;v++)
- regmaps[s][v] = map[v];
-
- // iterate all instructions in this section
- for (int i = begin(s); i!=end(s); )
+ // Iterate across all registers
+ for (int q=0;q<32;q++)
+ if (!regmaps[brdest][q]) // section we branched to
+ // had no data on register q
+ regmaps[brdest][q] = map[q]; // inherit the value
+ // using the SSA contents at our
+ // point
+
+ else if (regmaps[brdest][q]!=map[q]) // not the same?
{
- // look at instruction
- instruction * instr = itable[i];
- unsigned flags = instr->flags;
+ // we need a phi node - or we need to append to one
+ instruction * d = itable[regmaps[brdest][q]];
+ if (d->flags & IF_PHI)
+ {
+ // nothing is in the register on our side
+ if (!map[q])
+ map[q] = allocnodelivein(s,q); //must have been livein
- // is the instruction a branch?
- if (flags & IF_BRINTERNAL)
+ d->phi.params->push_back(map[q]); // append to a phi node
+ }
+ else // There wasn't already a PHI node
{
-
- // follow the branch and MERGE the tables.
- int brdest = instr->ibranch.dest;
-
- for (int q=0;q<32;q++)
- if (!regmaps[brdest][q])
- regmaps[brdest][q] = map[q];
- else if (regmaps[brdest][q]!=map[q])
- {
- // we need a phi node - or we need to append to one
- instruction * d = itable[regmaps[brdest][q]];
- if (d->flags & IF_PHI)
- {
- if (!map[q])
- map[q] = allocnodelivein(s,q); //must have been livein
- d->phi.params->push_back(map[q]); // append to a phi node
- }
- else
- {
- // create a phi node
- instruction * phi = allocphi();
-
- // Live in check
- if (!regmaps[brdest][q])
- regmaps[brdest][q] = allocnodelivein(s,q);
-
- phi->phi.params->push_back(regmaps[brdest][q]);
-
- // live in check
- if (!map[q])
- map[q] = allocnodelivein(s,q);
-
- phi->phi.params->push_back(map[q]);
-
- // link in the phi node and update both maps
- insert_instr(sections[s], phi);
- map[q] = phi->self;
- regmaps[brdest][q] = phi->self;
- phi->instr = q; // the register it applies to
- }
- }
-
+ // create a phi node
+ instruction * phi = allocphi();
+
+ // Live in check
+ if (!regmaps[brdest][q])
+ regmaps[brdest][q] = allocnodelivein(s,q);
+
+ phi->phi.params->push_back(regmaps[brdest][q]);
+
+ // live in check
+ if (!map[q])
+ map[q] = allocnodelivein(s,q);
+
+ phi->phi.params->push_back(map[q]);
+
+ // link in the phi node and update both maps
+ insert_instr(sections[s], phi);
+ map[q] = phi->self;
+ regmaps[brdest][q] = phi->self;
+ phi->instr = q; // the register it applies to
}
-
- // does he write to a register?
- if (flags & IF_W_RD)
- map[RD_FLD(instr->instr, INSTR_RD)] = i;
-
- i = instr->next;
- }
+ }
+}
+
+//*****************************************************************************
+// process_section(unsigned s, unsigned map[32],
+// fvector<unsigned[32]> & regmaps)
+// unsigned s - the section to process
+// map[reg] - this routine fills this structure with the SSA
+// contents AFTER exiting the section
+// regmaps[s][r] - the SSA contents at the top of section 's' in reg 'r'
+//
+//*****************************************************************************
+
+
+void BinInterface::process_section(unsigned s, unsigned map[32],
+ fvector<unsigned[32]> & regmaps)
+{
+ // Inherit
+ for (int v=0;v<32;v++)
+ regmaps[s][v] = map[v];
+
+ // iterate all instructions in this section
+ for (int i = begin(s); i!=end(s); )
+ {
+ // look at instruction
+ instruction * instr = itable[i];
+ unsigned flags = instr->flags;
+
+ // is the instruction a branch?
+ if (flags & IF_BRINTERNAL)
+ {
+
+ // follow the branch and MERGE the tables.
+ int brdest = instr->ibranch.dest;
+ construct_merge( s, brdest, map, regmaps);
+
+ }
+
+ // does he write to a register?
+ if (flags & IF_W_RD)
+ map[RD_FLD(instr->instr, INSTR_RD)] = i;
+
+ i = instr->next;
+ }
}
-
+
+//*****************************************************************************
+// reduce()
+//
+// Must be called after complete(). Reduces the original binary code
+// into SSA form
+//
+//*****************************************************************************
void BinInterface::reduce()
{
- fvector<unsigned[32]> regmaps(alloca);
+ fvector<unsigned[32]> regmaps(alloca);
+ regmaps.resize(sections.size());
+
+ unsigned map[32];
+
+ // Initially all registers have unknown SSA values
+ for (int i = 0; i < 32; i++)
+ map[i] = 0;
+
+ // Clear header maps
+ for (int s=0;s<sections.size();s++)
+ for (int p=0;p<32;p++)
+ regmaps[s][p] = 0;
+
+ int scns = sections.size();
+
+ // Note we don't process epilogs since they are not
+ // allowed to have 'initial' code
- regmaps.resize(sections.size());
-
-
- unsigned map[32],mapepi[32]; // current map
-
-
- for (int i = 0; i < 32; i++)
- map[i] = 0; // instruction ID #0 is a loop header.
- // there is no way a register could
- // be generated by it. So we use 0
- // as a NULL marker
-
- // Clear header maps
- for (int s=0;s<sections.size();s++)
- for (int p=0;p<32;p++)
- regmaps[s][p] = 0;
-
- int scns = sections.size();
-
-
- process_section(SECTION_PROLOG, map, regmaps);
- process_section(SECTION_TRACE, map, regmaps);
-
- // iterate across sections
- for (int s=SECTION_TRACE+1;s<sections.size();s++)
- {
- for (int i = 0; i < 32; i++)
- mapepi[i] = map[i];
- process_section(s,mapepi, regmaps);
- }
-
- //
- // Phi nodes have been calculated - and most importantly placed in respective positions
- // phi->instr holds the register number in question
- //
- // Execute program in order and connect phi nodes
- //
-
- // clear the map
- for (int v=0;v<32;v++)
- map[v] = 0;
-
- process_markgen(SECTION_PROLOG, map, regmaps);
- process_markgen(SECTION_TRACE , map, regmaps);
-
-
- for (int s=SECTION_TRACE+1;s<sections.size();s++)
- {
- int i;
- for (i = 0; i < 32; i++)
- mapepi[i] = map[i];
- process_markgen(s, mapepi,regmaps);
-
- // mapepi contains the register map for this epilog. Check if any values reaching in registers
- // were marked liveout. If they are insert a REGSHUFFLE instruction at the end
- fvector<shufflepair> * shuffles = new fvector<shufflepair>(alloca);
- shuffles->sizehint(16);
-
-
- for (i=0;i<32; i++)
- {
- instruction * instr = itable[mapepi[i]];
- if (instr->flags & IF_PHI)
- {
- // if any of the PHI parameters are marked live out,
- // the phi node itself becomes liveout.
- unsigned flags;
- for (int s = 0; s< instr->phi.params->size(); s++)
- flags |= itable[(*instr->phi.params)[s]]->flags;
- if (flags & IF_LIVEOUT)
- {
- shuffles->push_back(shufflepair(i,mapepi[i]));
- }
- }
- if (itable[mapepi[i]]->flags & IF_LIVEOUT)
- {
- // this one is liveout. Let's do the insertion
- int mi = mapepi[i];
- shuffles->push_back(shufflepair(i,mapepi[i]));
- }
- }
- // place the shuffler node
- allocnodeshuffles(s, shuffles);
- }
+ // Calculate phi nodes and contents of registers
+ // at section start points
+ process_section(SECTION_PROLOG, map, regmaps);
+ process_section(SECTION_TRACE, map, regmaps);
+
+ // there is am implicit transition from TRACE->first epilog
+ construct_merge(SECTION_TRACE, SECTION_TRACE+1, map, regmaps);
+
+
+
+ // clear the map
+ for (int v=0;v<32;v++)
+ map[v] = 0;
+
+ // Update gen fields for instructions (can't be done
+ // in last pass due to insertion of PHI's)
+ process_markgen(SECTION_PROLOG, map);
+ process_markgen(SECTION_TRACE , map);
+
+ // For each epilog
+ for (int s=SECTION_TRACE+1;s<sections.size();s++)
+ {
+ int i;
+ // At this point regmaps[s][i] contains the SSA contents of register i
+ // Check if any of these values were marked SSA liveout. If they are
+ // add them to a register shuffle set.
+
+ fvector<shufflepair> * shuffles = new fvector<shufflepair>(alloca);
+
+ shuffles->sizehint(16);
+
+ for (i=1;i<32; i++)
+ {
+ unsigned ssaid = regmaps[s][i];
+
+ if (!ssaid)
+ continue;
+
+ instruction * instr = itable[ssaid];
+ if (instr->flags & IF_PHI)
+ {
+ // if any of the PHI parameters are marked live out,
+ // the phi node itself becomes liveout.
+ unsigned flags = 0;
+
+ for (int s = 0; s< instr->phi.params->size(); s++)
+ flags |= itable[(*instr->phi.params)[s]]->flags;
+
+ if (flags & IF_LIVEOUT)
+ shuffles->push_back(shufflepair(i,ssaid));
+ }
+ if (itable[ssaid]->flags & IF_LIVEOUT)
+ {
+ // this one is liveout. Let's do the insertion
+ shuffles->push_back(shufflepair(i,ssaid));
+ }
+ }
+ // place the shuffler node
+ allocnodeshuffles(s, shuffles);
+ }
}
Index: llvm/lib/Reoptimizer/BinInterface/emit.cpp
diff -u llvm/lib/Reoptimizer/BinInterface/emit.cpp:1.1 llvm/lib/Reoptimizer/BinInterface/emit.cpp:1.2
--- llvm/lib/Reoptimizer/BinInterface/emit.cpp:1.1 Sat Dec 14 19:31:37 2002
+++ llvm/lib/Reoptimizer/BinInterface/emit.cpp Sun Dec 15 05:07:16 2002
@@ -1,6 +1,6 @@
//*****************************************************************************
// SPARC Binary Manipulation Interface
-//
+//
// Code Emitter
//
// Interface Definition
@@ -13,326 +13,383 @@
#include <stdlib.h>
#include "salloc.h" // Stack allocator class
#include "fvector.h" // fast vector (sits on stack allocator)
-#include "analyze.h" // SPARC analysis library (gets flag masks for instrs)
+#include "analyze.h" // SPARC analysis library
#include "sparcbin.h" // Prototype for this class
-#include "sparcpriv.h" // Private definitions#include "machine.h" // machine constants for cache optimizations
+#include "sparcpriv.h" // Private definitions
#include "sparcdis.h" // prototype for sparc disassembler
#include "bitmath.h" // header of optimized binary math routines
-#include "sparc9.h" // SPARC 9 opcode definitions
-#include <vector>
+#include "sparc9.h" // SPARC 9 opcode definitions
+#include "regmask.h" // Register mask allocator
+#include <vector> // Use STL pair class
using std::pair;
-#include <assert.h>
-#include "regmask.h"
+#include <assert.h>
+//*****************************************************************************
+// prepare_exit(regalloc & regalloc,
+// fvector<shufflepair> * mod,
+// unsigned * & out)
+//
+// For liveout nodes this generates the series of instructions
+// needed to get the SSA values in 'mod' into their correct registers.
+// This is used during liveout transitions.
+//
+//*****************************************************************************
-void BinInterface::prepare_exit(const regalloc & regalloc, fvector<shufflepair> * mod, unsigned * & out)
+void BinInterface::prepare_exit(const regalloc & regalloc,
+ fvector<shufflepair> * mod,
+ unsigned * & out)
{
- fvector<unsigned> orig_reg(alloca); // what register is the value for each mod pair in
- fvector<unsigned> regs(alloca); // what 'mod' pair is in a given register
- int spillidx=0;
-
- orig_reg.sizehint((*mod).size());
- regs.resize(32);
- for (int k = 0; k<32;k++)
- regs[k] = 0;
-
- // lookup the registers each gen-site is in
- for (int k = 0; k<(*mod).size();k++)
- {
- int vr = regalloc.ssa_to_vreg[(*mod)[k].gen];
- int mr = regalloc.vregs[vr].mreg;
- orig_reg.push_back(regalloc.vregs[vr].mreg);
-
- if (mr < 32) // in a machine register?
- regs[mr] = k;
- }
-
- // load each one-by-one spilling registers as needed
- for (int k=0; k<(*mod).size(); k++)
- {
- int dreg = (*mod)[k].reg;
- int sreg = orig_reg[k];
-
- if (sreg==dreg)
- continue;
-
- // is that register free? if not spill it
- if (regs[dreg])
- {
- // spill whats in DREG to an unused register or memory location?
- unsigned spillm = regalloc.memspills[spillidx++];
- *out++=MK_STX_STACK(dreg, (spillm-32)*8);
- }
-
- // do move
- if (sreg > 32)
- *out++=MK_LDX_STACK(dreg, (sreg-32)*8);
- else
- {
- regs[sreg] = 0;
- *out++=MK_MOV_R_R(dreg, sreg);
- }
-
-
- }
-
+ // what register is the value for each mod pair in
+ fvector<unsigned> orig_reg(alloca);
+
+ // what 'mod' pair is in a given register
+ fvector<unsigned> regs(alloca);
+
+ int spillidx=0; // index into regalloc.memspills
+ // (memspills is a set of Stack
+ // locations that are safe to use)
+
+ orig_reg.sizehint((*mod).size());
+ regs.resize(32);
+
+ for (int k = 0; k<32;k++)
+ regs[k] = 0;
+
+ // lookup the registers each gen-site is in
+ for (int k = 0; k<(*mod).size();k++)
+ {
+ int vr = regalloc.ssa_to_vreg[(*mod)[k].gen];
+ int mr = regalloc.vregs[vr].mreg;
+ orig_reg.push_back(regalloc.vregs[vr].mreg);
+
+ if (VREG_ISREG(mr)) // in a machine register?
+ regs[mr] = k;
+ }
+
+ // load each one-by-one spilling registers as needed
+ for (int k=0; k<(*mod).size(); k++)
+ {
+ int dreg = (*mod)[k].reg;
+ int sreg = orig_reg[k];
+
+ if (sreg==dreg)
+ continue;
+
+ // is that register free? if not spill it
+ if (regs[dreg])
+ {
+ // spill whats in DREG to an unused register or memory location?
+ unsigned spillm = regalloc.memspills[spillidx++];
+ *out++=MK_STX_STACK(dreg, VREG_GETMEM(spillm));
+ }
+
+ // do move
+ if (VREG_ISMEM(sreg))
+ *out++=MK_LDX_STACK(dreg, VREG_GETMEM(sreg));
+ else
+ {
+ regs[sreg] = 0;
+ *out++=MK_MOV_R_R(dreg, sreg);
+ }
+ }
}
-int BinInterface::spill_load(int vreg, regmask32 & rmask, const int memspills[32],int & freereg, int spilled[32], int & spilled_cnt, unsigned * & out)
+
+//*****************************************************************************
+// prepare_exit(int vreg, regmask32 & rmask,
+// const int memspills[32],int & freereg,
+// int spilled[32], int & spilled_cnt,
+// unsigned * & out)
+//
+// spilled/spilled_cnt - the registers that were spilled (max of 3)
+// and must be reloaded
+// memspills - locations available for memory spilling
+// (there are 32) but we use the one corresponding
+// to the register we're spilling
+// freereg - register that's been reserved and is free
+// for spill-loads. This will be set to 0
+// when it is consumed
+// vreg - the value we want in memory
+// rmask - a mask containing 'available' candidates for spill
+// we need this so we don't double spill the same reg
+//
+// For liveout nodes this generates the series of instructions
+// needed to get the SSA values in 'mod' into their correct registers.
+// This is used during liveout transitions.
+//
+//*****************************************************************************
+int BinInterface::spill_load(int vreg, regmask32 & rmask,
+ const int memspills[32],int & freereg,
+ int spilled[32], int & spilled_cnt,
+ unsigned * & out)
{
- assert(vreg >= 32); // doesn't make sense if it is ALREADY a register
+ assert(VREG_ISMEM(vreg)); // doesn't make sense if it is ALREADY a register
+
+ int r = 0;
+ // can we used the set-aside register?
+ if (freereg)
+ {
+ r = freereg;
+ freereg = 0;
+ }
+ else
+ { // no? grab one from spill_candidates
+ r=rmask.allocreg();
+ assert(r);
+
+ // spill the value in that register out to memory
+ spilled[spilled_cnt] = r;
+ *out++=MK_STX_STACK(r, VREG_GETMEM(memspills[spilled_cnt]));
+ spilled_cnt++;
+ }
+ // now load the value from memory
+ *out++=MK_LDX_STACK(r, VREG_GETMEM(vreg));
- int r = 0;
- // can we used the set-aside register?
- if (freereg)
- {
- r = freereg;
- freereg = 0;
- }
- else
- { // no? grab one from spill_candidates
- r=rmask.allocreg();
- assert(r);
-
- // spill the value in that register out to memory
- spilled[spilled_cnt] = r;
- *out++=MK_STX_STACK(r, 8*(memspills[spilled_cnt] - 32));
- spilled_cnt++;
- }
- // now load the value from memory
- *out++=MK_LDX_STACK(r, 8*(vreg-32));
-
- return r;
+ return r;
}
+//*****************************************************************************
+// emit_gen(unsigned char * cde, const regalloc & regs)
+//
+// cde - the buffer to receive the code (sized using predict() )
+// regs - the result from register selection
+//
+//*****************************************************************************
unsigned BinInterface::emit_gen(unsigned char * cde, const regalloc & regs)
{
- int s;
- unsigned * out = (unsigned *) cde;
+ int s;
+ unsigned * out = (unsigned *) cde;
- const fvector<unsigned> & ssa_to_vreg = regs.ssa_to_vreg;
- const fvector<vreginfo> & vregs = regs.vregs;
- const int & spillreg = regs.spillreg;
- const unsigned & touched_regs = regs.touched_regs;
- const unsigned & liveout_regs = regs.liveout_regs;
-
-
- fvector<pair<unsigned *, unsigned> > fwdbranch(alloca); // pairs of instruction addrs +destination section #'s
- fvector<unsigned *> secaddr(alloca); // address of section
-
- regmask32 rmask;
- secaddr.inc(sections.size());
-
- unsigned stack_size = regs.stack_size;
-
- // calculate the set of registers we must save and alloc stack
- unsigned save_regs = regs.touched_regs & ~ regs.liveout_regs;
- unsigned save_area = stack_size;
- stack_size += countbits_dense(save_regs)*8;
-
- // allocate space at top of prolog
- *out++=MK_ADD_R_I(R_SP, R_SP, -stack_size);
-
- // save the registers
- for (unsigned m=save_regs, l = 0, a=save_area; l<32;l++, m>>=1)
- if (m & 1)
- {
- *out++=MK_STX_STACK(l, a);
- a+=8;
- }
-
- // Iterate across instructions
- for (s=0;s<sections.size();s++)
- {
- secaddr[s] = out; // mark down section start address for patching
- // jump instructions
- for (int i = begin(s); i!=end(s); i=next(i))
- {
- // Find what registers this instruction depends on.
- int rs1 = 0; // this register will contain the rs1 value
- int rs2 = 0; // this register will contain the rs2 value
- int r_rd = 0; // this register will contain the rd value
-
- instruction * instr = itable[i];
- unsigned flags = instr->flags;
-
- if (flags & (IF_REGSHUFFLE | IF_NODELIVEIN))
+ // pairs of instruction addrs +destination section #'s
+ // (used for branch resolution)
+ fvector<pair<unsigned *, unsigned> > fwdbranch(alloca);
+
+ // address of section when emitted
+ fvector<unsigned *> secaddr(alloca);
+
+ // mask to be used for spill candidates
+ regmask32 rmask;
+
+ secaddr.inc(sections.size());
+
+ // load stack size from allocator
+ unsigned stack_size = regs.stack_size;
+
+ // calculate the set of registers we must save and alloc stack
+ // and allocate space for them in the prolog (and save)
+ unsigned save_regs = regs.touched_regs & ~ regs.liveout_regs;
+ unsigned save_area = stack_size;
+ stack_size += countbits_dense(save_regs)*8;
+ *out++=MK_ADD_R_I(R_SP, R_SP, -stack_size);
+
+ for (unsigned m=save_regs, l = 0, a=save_area; l<32;l++, m>>=1)
+ if (m & 1)
+ {
+ *out++=MK_STX_STACK(l, a);
+ a+=8;
+ }
+
+ // Iterate across instructions
+ for (s=0;s<sections.size();s++)
+ {
+ secaddr[s] = out; // mark down section start address for patching
+ // jump instructions
+ for (int i = begin(s); i!=end(s); i=next(i))
+ {
+ // Find what registers this instruction depends on.
+ int rs1 = 0; // this register will contain the rs1 value
+ int rs2 = 0; // this register will contain the rs2 value
+ int r_rd = 0; // this register will contain the rd value
+
+ instruction * instr = itable[i];
+ unsigned flags = instr->flags;
+
+ if (flags & (IF_REGSHUFFLE | IF_NODELIVEIN))
+ {
+ if (flags & IF_REGSHUFFLE)
{
- if (flags & IF_REGSHUFFLE)
- {
- prepare_exit(regs, instr->regshuffle.shuffles,out);
-
- }
- else // nodelivein
- {
- int id = ssa_to_vreg[i];
- int dreg = vregs[id].mreg;
- int sreg = instr->livein.reg;
-
- if (dreg!=sreg)
- {
- if (dreg < 32)
- *out++=MK_MOV_R_R(dreg, sreg);
- else
- *out++=MK_STX_STACK(sreg, (dreg-32)*8);
- }
- }
- continue;
+ prepare_exit(regs, instr->regshuffle.shuffles,out);
+
}
-
- // make sure this is ACTUALLY an instruction and not a phi node
- if (! (flags & (IF_ALUOP | IF_BR)))
- continue;
-
- // Find out what registers the instruction is already using (since the values
- // were assigned to registers by defaults
- rmask.set(R_ALLOCREGS);
-
- if (flags & IF_R_RS1)
- {
- rs1 = vregs[ssa_to_vreg[instr->alu.genrs1]].mreg;
-
- if (rs1 < 32)
- rmask.grabreg(rs1);
- }
- if (flags & IF_R_RS2)
- {
- rs2 = vregs[ssa_to_vreg[instr->alu.genrs2]].mreg;
-
- if (rs2 < 32)
- rmask.grabreg(rs2);
- }
- if (flags & IF_R_RD)
- {
- r_rd = vregs[ssa_to_vreg[instr->alu.genrd]].mreg;
-
- if (r_rd < 32)
- rmask.grabreg(r_rd);
- }
-
-
- int freereg = spillreg; // the free spill register - this gets zerod when used
- int spilled[3]; // array containing the registers that were spilled
- // spilled[k] ALWAYS spills to memspills[k]
- int spilled_cnt = 0; // how many registers were spilled
-
- unsigned ins = instr->instr;
-
-
- // load parameters of instruction and spill as needed
- if (flags & IF_R_RS1)
- {
- if (rs1 >= 32)
- rs1 = spill_load(rs1, rmask, regs.memspills, freereg, spilled, spilled_cnt, out);
- ins = RM_FLD(INSTR_RS1, ins) | MK_FLD(INSTR_RS1, rs1);
- }
-
- if (flags & IF_R_RS2)
+ else // nodelivein
{
- if (rs2 >= 32)
- rs2 = spill_load(rs2, rmask, regs.memspills, freereg, spilled, spilled_cnt, out);
- ins = RM_FLD(INSTR_RS2, ins) | MK_FLD(INSTR_RS2, rs2);
- }
-
- if (flags & IF_R_RD)
+ int id = regs.ssa_to_vreg[i];
+ int dreg = regs.vregs[id].mreg;
+ int sreg = instr->livein.reg;
+
+ if (dreg!=sreg)
+ {
+ if (VREG_ISREG(dreg))
+ *out++=MK_MOV_R_R(dreg, sreg);
+ else
+ *out++=MK_STX_STACK(sreg, VREG_GETMEM(dreg));
+ }
+ }
+ continue;
+ }
+
+ // make sure this is ACTUALLY an instruction and not a phi node
+ if (! (flags & (IF_ALUOP | IF_BR)))
+ continue;
+
+ // Find out what registers the instruction is already using
+ // (since the values were assigned to registers by defaults
+ rmask.set(R_ALLOCREGS);
+
+ if (flags & IF_R_RS1)
+ {
+ rs1 = regs.vregs[regs.ssa_to_vreg[instr->alu.genrs1]].mreg;
+
+ if (VREG_ISREG(rs1))
+ rmask.grabreg(rs1);
+ }
+ if (flags & IF_R_RS2)
+ {
+ rs2 = regs.vregs[regs.ssa_to_vreg[instr->alu.genrs2]].mreg;
+
+ if (VREG_ISREG(rs2))
+ rmask.grabreg(rs2);
+ }
+ if (flags & IF_R_RD)
+ {
+ r_rd = regs.vregs[regs.ssa_to_vreg[instr->alu.genrd]].mreg;
+
+ if (VREG_ISREG(r_rd))
+ rmask.grabreg(r_rd);
+ }
+
+ // the free spill register - this gets zerod when used
+ int freereg = regs.spillreg;
+
+ // array containing the registers that were spilled
+ // NOTE: spilled[k] ALWAYS spills to memspills[k]
+ int spilled[3];
+ int spilled_cnt = 0; // how many registers are in spilled
+
+ unsigned ins = instr->instr;
+
+ // load parameters of instruction and spill as needed
+ if (flags & IF_R_RS1)
+ {
+ if (VREG_ISMEM(rs1))
+ rs1 = spill_load(rs1, rmask, regs.memspills,
+ freereg, spilled, spilled_cnt, out);
+
+ ins = RM_FLD(INSTR_RS1, ins) | MK_FLD(INSTR_RS1, rs1);
+ }
+
+ if (flags & IF_R_RS2)
+ {
+ if (VREG_ISMEM(rs2))
+ rs2 = spill_load(rs2, rmask, regs.memspills,
+ freereg, spilled, spilled_cnt, out);
+
+ ins = RM_FLD(INSTR_RS2, ins) | MK_FLD(INSTR_RS2, rs2);
+ }
+
+ if (flags & IF_R_RD)
+ {
+ if (VREG_ISMEM(r_rd))
+ r_rd = spill_load(r_rd, rmask, regs.memspills,
+ freereg, spilled, spilled_cnt, out);
+
+ ins = RM_FLD(INSTR_RD, ins) | MK_FLD(INSTR_RD, r_rd);
+ }
+ //
+ // Branch instructions must have their target fixed up
+ // (note that the next instruction emitted is guaranteed
+ // to be the actual instruction and not a spill fixup)
+ if (flags & IF_BR)
+ {
+ if (flags & IF_BRINTERNAL)
{
- if (r_rd >= 32)
- r_rd = spill_load(r_rd, rmask, regs.memspills, freereg, spilled, spilled_cnt, out);
- ins = RM_FLD(INSTR_RD, ins) | MK_FLD(INSTR_RD, r_rd);
- }
- //
- // Branch instructions must have their target fixed up
- // (note that the next instruction emitted is guaranteed
- // to be the actual instruction and not a spill fixup)
- if (flags & IF_BR)
+ // we need to fix up destination.
+ // forward branches we store a backtable FIXME
+ if (instr->ibranch.dest <= s)
+ {
+ unsigned rel = secaddr[instr->ibranch.dest] - out;
+ instr->instr = sparc_setbrdest(instr->instr,rel);
+ }
+ else
+ fwdbranch.push_back(
+ pair<unsigned *, unsigned>(out, instr->ibranch.dest));
+ }
+ else
{
- if (flags & IF_BRINTERNAL)
- {
- // we need to fix up destination. If this is a backward branch no problem
- // forward branches we store a backtable FIXME
- if (instr->ibranch.dest <= s)
- {
- unsigned rel = secaddr[instr->ibranch.dest] - out;
- instr->instr = sparc_setbrdest(instr->instr,rel);
- }
- else
- fwdbranch.push_back(pair<unsigned *, unsigned>(out, instr->ibranch.dest));
- }
- else
- {
- // do absolute jump
- unsigned rel = instr->ebranch.dest - out;
- instr->instr = sparc_setbrdest(instr->instr,rel);
- }
+ // do absolute jump
+ unsigned rel = instr->ebranch.dest - out;
+ instr->instr = sparc_setbrdest(instr->instr,rel);
}
+ }
+
+ if (flags & IF_W_RD)
+ {
+ int id = regs.ssa_to_vreg[i];
+
+ // We need to generate and store a result. We should check to see
+ // if any registers are currently 'free'. If not we must spill one.
- if (flags & IF_W_RD)
- {
- int id = ssa_to_vreg[i];
-
- // We need to generate and store a result. We should check to see
- // if any registers are currently 'free'. If not we must spill one.
-
- int dreg = vregs[id].mreg;
-
- if (dreg < 32)
- {
- ins = RM_FLD(INSTR_RD, ins) | MK_FLD(INSTR_RD, dreg);
- *out++=ins;
- }
- else
- {
- // always use the spillreg since it contains
- // a value that was loaded from memory that is
- // a SECOND copy.
- ins = RM_FLD(INSTR_RD, ins) | MK_FLD(INSTR_RD, spillreg);
- *out++=ins;
- *out++=MK_STX_STACK(spillreg, 8*(dreg - 32));
- }
- }
+ int dreg = regs.vregs[id].mreg;
+
+ if (VREG_ISREG(dreg))
+ {
+ ins = RM_FLD(INSTR_RD, ins) | MK_FLD(INSTR_RD, dreg);
+ *out++=ins;
+ }
else
- *out++=(ins); // no dreg? just emit it
-
- // now unspill everything
- for (int z=0;z<spilled_cnt;z++)
{
- // load (reg) spilled[z] with (mem) memspills[z]
- *out++=MK_LDX_STACK(spilled[z], 8*(regs.memspills[z] - 32));
+ // always use the spillreg since it contains
+ // a value that was loaded from memory that is
+ // a SECOND copy.
+ ins = RM_FLD(INSTR_RD, ins) | MK_FLD(INSTR_RD, regs.spillreg);
+ *out++=ins;
+ *out++=MK_STX_STACK(regs.spillreg, VREG_GETMEM(dreg));
+ }
+ }
+ else
+ *out++=(ins); // no dreg? just emit it
+
+ // now unspill everything
+ for (int z=0;z<spilled_cnt;z++)
+ {
+ // load (reg) spilled[z] with (mem) memspills[z]
+ *out++=MK_LDX_STACK(spilled[z], VREG_GETMEM(regs.memspills[z]));
+ }
+ }
+
+ //
+ // End of section handler
+ //
+ if (s > SECTION_TRACE) // epilog sections
+ {
+ // free space at top of prolog
+ // restore registers
+ for (unsigned m=save_regs, l = 0, a=save_area; l<32;l++, m>>=1)
+ if (m & 1)
+ {
+ *out++=MK_LDX_STACK(l, a);
+ a+=8;
}
- }
-
- //
- // End of section handler
- //
- if (s > 1) // epilog sections
- {
- // free space at top of prolog
- // restore registers
- for (unsigned m=save_regs, l = 0, a=save_area; l<32;l++, m>>=1)
- if (m & 1)
- {
- *out++=MK_LDX_STACK(l, a);
- a+=8;
- }
- *out++=MK_ADD_R_I(R_SP, R_SP, stack_size);
- }
- }
-
- //
- // Handle forward branches.
- //
- for(int t = 0; t<fwdbranch.size(); t++)
- {
- pair<unsigned *, unsigned> & i = fwdbranch[t];
-
- unsigned rel = secaddr[i.second] - out;
- *i.first = sparc_setbrdest(*i.first,rel);
- }
-
- return out- ((unsigned *)cde);
+ // free stack space
+ *out++=MK_ADD_R_I(R_SP, R_SP, stack_size);
+ }
+ }
+
+ //
+ // Handle forward branches.
+ //
+ for(int t = 0; t<fwdbranch.size(); t++)
+ {
+ pair<unsigned *, unsigned> & i = fwdbranch[t];
+
+ unsigned rel = secaddr[i.second] - out;
+ *i.first = sparc_setbrdest(*i.first,rel);
+ }
+
+ return out- ((unsigned *)cde);
}
Index: llvm/lib/Reoptimizer/BinInterface/fvector.h
diff -u llvm/lib/Reoptimizer/BinInterface/fvector.h:1.5 llvm/lib/Reoptimizer/BinInterface/fvector.h:1.6
--- llvm/lib/Reoptimizer/BinInterface/fvector.h:1.5 Sat Dec 14 20:04:27 2002
+++ llvm/lib/Reoptimizer/BinInterface/fvector.h Sun Dec 15 05:07:18 2002
@@ -3,7 +3,7 @@
//
// * Implementation of a vector class around
// the stack allocator. Couldn't use STL
-// because I need to support stored the
+// because I need to support stored the
// pointer to the allocator stack.
//
// 2002 Cameron Buschardt
@@ -14,137 +14,138 @@
#include "salloc.h"
#include <assert.h>
+#include <new>
template <class T>
class fvector
{
- T * v_begin;
- T * v_end;
- T * v_capacity;
- Allocator * alloc;
-
- // make sure we have MEMORY up to that element
- // does not construct those positions
- void validate(T * pos)
- {
- assert(alloc);
- if (pos < v_capacity)
+ T * v_begin;
+ T * v_end;
+ T * v_capacity;
+ Allocator * alloc;
+
+ // make sure we have MEMORY up to that element
+ // does not construct those positions
+ void validate(T * pos)
+ {
+ assert(alloc);
+ if (pos < v_capacity)
return;
- unsigned ns = v_capacity - v_begin;
- unsigned ms = pos - v_begin + 1;
- if (!ns)
+ unsigned ns = v_capacity - v_begin;
+ unsigned ms = pos - v_begin + 1;
+ if (!ns)
ns = 64;
- else
- while (ns < ms)
- ns *= 2;
-
- T * n = (T *)alloc->resize(v_begin, sizeof(T) * ns);
- v_end = (v_end - v_begin) + n;
- v_capacity = n + ns;
- v_begin = n;
-
- }
-
- fvector(const fvector &) {}
- fvector & operator = (const fvector &) {}
- void destroy(T * b, T * e)
- {
- while (b!=e)
- {
+ else
+ while (ns < ms)
+ ns *= 2;
+
+ T * n = (T *)alloc->resize(v_begin, sizeof(T) * ns);
+ v_end = (v_end - v_begin) + n;
+ v_capacity = n + ns;
+ v_begin = n;
+
+ }
+
+ fvector(const fvector &) {}
+ fvector & operator = (const fvector &) {}
+ void destroy(T * b, T * e)
+ {
+ while (b!=e)
+ {
b->~T();
b++;
- }
- }
- void construct(T * b, T * e)
- {
- while (b!=e)
- {
+ }
+ }
+ void construct(T * b, T * e)
+ {
+ while (b!=e)
+ {
new (b) T();
b++;
- }
- }
-public:
- typedef T * iterator;
-
- iterator begin() { return v_begin; }
- iterator end() { return v_end; }
- void clear()
- {
- assert(this);
- destroy(v_begin, v_end);
- if (v_begin)
+ }
+ }
+ public:
+ typedef T * iterator;
+
+ iterator begin() { return v_begin; }
+ iterator end() { return v_end; }
+ void clear()
+ {
+ assert(this);
+ destroy(v_begin, v_end);
+ if (v_begin)
alloc->free(v_begin);
- v_begin = v_capacity = v_end = NULL;
+ v_begin = v_capacity = v_end = NULL;
- }
- unsigned size()
- {
- assert(this);
- return v_end - v_begin;
- }
-
- fvector(Allocator * a)
- {
- v_begin = v_end = v_capacity = NULL;
- alloc = a;
- }
-
- fvector()
- {
- v_begin = v_end = v_capacity = NULL;
- alloc = NULL;
-
- }
-
- void setallocator(Allocator * a)
- {
- assert(!alloc);
- alloc = a;
- }
-
- void sizehint(unsigned v)
- {
- if (v_begin)
+ }
+ unsigned size()
+ {
+ assert(this);
+ return v_end - v_begin;
+ }
+
+ fvector(Allocator * a)
+ {
+ v_begin = v_end = v_capacity = NULL;
+ alloc = a;
+ }
+
+ fvector()
+ {
+ v_begin = v_end = v_capacity = NULL;
+ alloc = NULL;
+
+ }
+
+ void setallocator(Allocator * a)
+ {
+ assert(!alloc);
+ alloc = a;
+ }
+
+ void sizehint(unsigned v)
+ {
+ if (v_begin)
return;
- v_begin = (T*)alloc->alloc(sizeof(T) * v);
- v_end = v_begin;
- v_capacity = v_begin + v;
- }
-
- void push_back(const T & e) {
- assert(this);
- validate(v_end+1);
- new (v_end) T(e);
- v_end++;
- }
-
- void inc(unsigned amt) // increase size by this amt
- {
- validate(v_end + amt);
- construct(v_end, v_end+amt);
- v_end += amt;
- }
-
- void resize(unsigned amt)
- {
- if ((v_begin+amt) < v_end)
- {
+ v_begin = (T*)alloc->alloc(sizeof(T) * v);
+ v_end = v_begin;
+ v_capacity = v_begin + v;
+ }
+
+ void push_back(const T & e) {
+ assert(this);
+ validate(v_end);
+ new (v_end) T(e);
+ v_end++;
+ }
+
+ void inc(unsigned amt) // increase size by this amt
+ {
+ validate(v_end + amt);
+ construct(v_end, v_end+amt);
+ v_end += amt;
+ }
+
+ void resize(unsigned amt)
+ {
+ if ((v_begin+amt) < v_end)
+ {
// got shorter
destroy((v_begin+amt), v_end);
-
- }
- else
- {
+
+ }
+ else
+ {
// got longer
validate( v_begin+amt);
construct(v_end, v_begin+amt);
- }
- v_end = v_begin+amt;
- }
- T& operator[] (unsigned n) {
- return v_begin[n]; }
- const T & operator[] (unsigned n) const { return v_begin[n]; }
+ }
+ v_end = v_begin+amt;
+ }
+ T& operator[] (unsigned n) {
+ return v_begin[n]; }
+ const T & operator[] (unsigned n) const { return v_begin[n]; }
};
Index: llvm/lib/Reoptimizer/BinInterface/regmask.h
diff -u llvm/lib/Reoptimizer/BinInterface/regmask.h:1.1 llvm/lib/Reoptimizer/BinInterface/regmask.h:1.2
--- llvm/lib/Reoptimizer/BinInterface/regmask.h:1.1 Sat Dec 14 19:31:41 2002
+++ llvm/lib/Reoptimizer/BinInterface/regmask.h Sun Dec 15 05:07:22 2002
@@ -13,131 +13,135 @@
#include "bitmath.h"
+#define VREG_ISMEM(x) (x >= 32)
+#define VREG_ISREG(x) (x < 32)
+#define VREG_GETMEM(x) ((x-32) * 8)
+
class regmask32
{
-private:
- unsigned freemap;
+ private:
+ unsigned freemap;
-public:
+ public:
- // Construct freemap, initially mark everyone free
- regmask32()
- : freemap(~0)
- {
- }
-
- // returns 0 on failure
- unsigned allocreg()
- {
- unsigned mask = LOWEST_BIT(freemap); // on fail this will be 0
- freemap &= ~mask; // on fail this will be a nop
- return log2(mask); // log2(0) == log2(1) == 0 (in this implementation!)
- // I fully realize log2(0) is undefined
- // mathematically
- }
-
- // free a register
- void freereg(unsigned idx)
- {
- freemap |= 1 << (idx & 31); // mark it free
- }
-
- // force the register 'in-use'
- void grabreg(unsigned idx)
- {
- freemap &= ~(1 << (idx & 31)); // grab it
- }
-
- void set(unsigned mask)
- {
- freemap = mask;
- }
-
- // count how many are free in the lowest 32.
- unsigned count()
- {
- return countbits_dense(freemap);
- }
-
- // get the mask of free registers
- unsigned free()
- {
- return freemap;
- }
+ // Construct freemap, initially mark everyone free
+ regmask32()
+ : freemap(~0)
+ {
+ }
+
+ // returns 0 on failure
+ unsigned allocreg()
+ {
+ unsigned mask = LOWEST_BIT(freemap); // on fail this will be 0
+ freemap &= ~mask; // on fail this will be a nop
+ return log2_bits32(mask); // log2(0) == log2(1) == 0 (in this implementation!)
+ // I fully realize log2(0) is undefined
+ // mathematically
+ }
+
+ // free a register
+ void freereg(unsigned idx)
+ {
+ freemap |= 1 << (idx & 31); // mark it free
+ }
+
+ // force the register 'in-use'
+ void grabreg(unsigned idx)
+ {
+ freemap &= ~(1 << (idx & 31)); // grab it
+ }
+
+ void set(unsigned mask)
+ {
+ freemap = mask;
+ }
+
+ // count how many are free in the lowest 32.
+ unsigned count()
+ {
+ return countbits_dense(freemap);
+ }
+
+ // get the mask of free registers
+ unsigned free()
+ {
+ return freemap;
+ }
};
class regmask
{
-private:
- fvector<regmask32> freemap;
+ private:
+ fvector<regmask32> freemap;
- unsigned i_allocreg(int baseindex)
- {
- for (;baseindex<freemap.size(); baseindex++)
+ unsigned i_allocreg(int baseindex)
+ {
+ for (;baseindex<freemap.size(); baseindex++)
if (freemap[baseindex].free())
{
- return (baseindex << 5) + freemap[baseindex].allocreg();
+ return (baseindex << 5) + freemap[baseindex].allocreg();
}
- return 0;
- }
+ return 0;
+ }
-public:
- // Construct freemap, initially mark everyone free
- regmask(Allocator * a, unsigned maxregs)
- : freemap(a)
- {
- // make sure maxregs is a multiple of 32
- assert(!(maxregs & 0x1F));
-
- // calculate size of freemap
- freemap.inc( maxregs >> 5 );
- for (int k = 0; k < freemap.size(); k++)
- freemap[k].set(~0);
- }
-
- // returns 0 on failure
- unsigned allocreg()
- {
- return i_allocreg(0); // alloc physical or memory
- }
-
- unsigned allocmemreg()
- {
- return i_allocreg(1); // force memory
- }
-
- // returns 0 on failure
- unsigned allocreg32() // allocate register from first 32 only
- {
- return freemap[0].allocreg();
- }
-
- void freereg(unsigned idx)
- {
- freemap[idx >> 5].freereg(idx & 31);
- }
-
- void grabreg(unsigned idx)
- {
- freemap[idx >> 5].grabreg(idx & 31); // grab it
- }
-
- void set32(unsigned mask)
- {
- freemap[0].set(mask);
- }
-
- // count how many are free in the lowest 32.
- unsigned count32()
- {
- return freemap[0].count();
- }
-
- unsigned free32()
- {
- return freemap[0].free();
- }
+ public:
+ // Construct freemap, initially mark everyone free
+ regmask(Allocator * a, unsigned maxregs)
+ : freemap(a)
+ {
+ // make sure maxregs is a multiple of 32
+ assert(!(maxregs & 0x1F));
+
+ // calculate size of freemap
+ freemap.inc( maxregs >> 5 );
+ for (int k = 0; k < freemap.size(); k++)
+ freemap[k].set(~0);
+ }
+
+ // returns 0 on failure
+ unsigned allocreg()
+ {
+ return i_allocreg(0); // alloc physical or memory
+ }
+
+ unsigned allocmemreg()
+ {
+ return i_allocreg(1); // force memory
+ }
+
+ // returns 0 on failure
+ unsigned allocreg32() // allocate register from first 32 only
+ {
+ return freemap[0].allocreg();
+ }
+
+ void freereg(unsigned idx)
+ {
+ freemap[idx >> 5].freereg(idx & 31);
+ }
+
+ void grabreg(unsigned idx)
+ {
+ freemap[idx >> 5].grabreg(idx & 31); // grab it
+ }
+
+ void set32(unsigned mask)
+ {
+ freemap[0].set(mask);
+ }
+
+ // count how many are free in the lowest 32.
+ unsigned count32()
+ {
+ return freemap[0].count();
+ }
+
+ unsigned free32()
+ {
+ return freemap[0].free();
+ }
};
#endif
Index: llvm/lib/Reoptimizer/BinInterface/salloc.cpp
diff -u llvm/lib/Reoptimizer/BinInterface/salloc.cpp:1.2 llvm/lib/Reoptimizer/BinInterface/salloc.cpp:1.3
--- llvm/lib/Reoptimizer/BinInterface/salloc.cpp:1.2 Sat Dec 14 19:31:41 2002
+++ llvm/lib/Reoptimizer/BinInterface/salloc.cpp Sun Dec 15 05:07:24 2002
@@ -1,7 +1,7 @@
//*****************************************************************************
// Fast Stack Allocator
//
-// Implementation of Stack allocator
+// Implementation of Stack allocator
//
// 2002 Cameron Buschardt
//*****************************************************************************
@@ -12,92 +12,169 @@
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
-// work around incompetant compiler
-#define PRINTALLOC
+// All allocation will be aligned to 16-byte boundaries
+// if you change this DO NOT make it lower than 8 otherwise
+// pointer types will not be sufficiently aligned and SPARC
+// will throw an unaligned exception (as a bus error)
+#define ALIGN 4 // align blocks to 2^4 bytes (16 bytes)
// look up the size of a block by address
-#define BSIZE(x) *((unsigned *)((unsigned char *)x - sizeof (unsigned)))
+#define BSIZE(x) *(((unsigned *)x)-1)
-void * StackAllocator::alloc(unsigned size)
-{
- assert(top + size + sizeof(unsigned) <= end);
- *((unsigned *)top) = size;
- top+=sizeof(unsigned);
+//*****************************************************************************
+// adjust(size)
+//
+// rounds size up to the nearest multiple of 2^ALIGN
+//
+//*****************************************************************************
- unsigned char * r= top;
- top += size;
+unsigned adjust(unsigned size)
+{
+ return ROUNDUP_P2(size, ALIGN);
+}
+
+//*****************************************************************************
+// alloc(unsigned size)
+//
+// Allocate a block size off the top of the stack
+// note that an unsigned size field is stored RIGHT before the block
+//
+//*****************************************************************************
- return r;
+void * StackAllocator::alloc(unsigned size)
+{
+ unsigned fullsize = size+sizeof(unsigned);
+ fullsize = adjust(fullsize);
+ size = fullsize - sizeof(unsigned);
+ unsigned * sizeloc = (unsigned *)top;
+ unsigned char * block = (unsigned char *)(sizeloc+1);
+ unsigned char * eblock = top+fullsize;
+ assert(eblock <= end);
+ *sizeloc = size;
+ top = eblock;
+ return block;
}
+
+//*****************************************************************************
+// resize(void *block, unsigned size)
+//
+// Reallocate a block (in place if possible)
+//
+//*****************************************************************************
+
void * StackAllocator::resize(void * block , unsigned newsize)
{
- if (!block)
- {
- void * t = alloc(newsize);
- PRINTALLOC("Resize(%08X, %d) = new block: %08X \n", block, newsize, t);
- return t;
- }
- if ((BSIZE(block)+(unsigned char *)block)!=top)
- {
- unsigned char * r = (unsigned char *)alloc(newsize);
- unsigned oldsize=BSIZE(block);
- memcpy(r, block, oldsize);
- PRINTALLOC("Resize(%08X, %d) = new block: %08X \n", block, newsize, r);
- free(block);
- return r;
- }
- else
- {
- // was the last alloc
- unsigned oldsize = BSIZE(block);
- assert(top + newsize - oldsize <= end);
- BSIZE(block) = newsize;
- top += newsize -oldsize;
- PRINTALLOC("Resize(%08X, %d) = top resize: %08X \n", block, newsize, block);
+ if (!block)
+ return alloc(newsize);
+ if ((BSIZE(block)+(unsigned char *)block)!=top) // this block wasn't on top
+ {
+ unsigned char * r = (unsigned char *)alloc(newsize);
+ unsigned oldsize=BSIZE(block);
+ memcpy(r, block, oldsize);
+ this->free(block);
+ return r;
+ }
+ else
+ {
+ newsize=adjust(newsize+sizeof(unsigned))-sizeof(unsigned);
+ // was the last alloc
+ unsigned oldsize = BSIZE(block);
+ assert(top + newsize - oldsize <= end);
+ BSIZE(block) = newsize;
+ top += newsize -oldsize;
- return block;
- }
+ return block;
+ }
}
+//*****************************************************************************
+// free(void * x)
+//
+// Perform a stack free - only removes memory if x is on the top of the stack
+// otherwise we 'lose' that memory until the stack allocator is reset next
+//
+//*****************************************************************************
+
void StackAllocator::free(void * x)
-{
- if (!x)
- return;
-
- // NOT the top of the stack. cannot free
- if ((BSIZE(x)+(unsigned char *)x)!=top)
- {
- PRINTALLOC("Free(%08X) ignored.\n", x);
- return;
- }
- PRINTALLOC("Free(%08X) TOS.\n", x);
- top = (unsigned char *)x;
+{
+ if (!x)
+ return;
+
+ // NOT the top of the stack. cannot free
+ if ((BSIZE(x)+(unsigned char *)x)!=top)
+ return;
+
+ top = (unsigned char *)x;
}
+//*****************************************************************************
+// clear()
+//
+// Reset allocator
+//
+//*****************************************************************************
+
void StackAllocator::clear()
{
- top = begin;
+ top = begin;
}
+
+//*****************************************************************************
+// StackAllocator(unsigned heapsize)
+//
+// Allocates the heap using malloc and properly aligns everything.
+// Assumes malloc is returning a block aligned at LEAST to 8 bytes
+// (which should be true for SPARC64)
+//
+//*****************************************************************************
+
StackAllocator::StackAllocator(unsigned size)
{
- // round size up to next multiple of CACHE_LINE
- size=ROUNDUP32(size);
- begin = (unsigned char *)malloc(size);
- end = begin + size;
- top = begin;
- }
+ // round size up to next multiple of CACHE_LINE
+ size =ROUNDUP32(size+(1 << ALIGN));
+ begin = (unsigned char *)malloc(size);
+ end =begin + size;
+ begin+=((1<<ALIGN)-sizeof(unsigned)) & ((1<<ALIGN)-1);
+ // we want to guarantee that the START of the first block
+ // eg begin+sizeof(unsigned) is a multiple of ALIGN
+ top = begin;
+}
+
+//*****************************************************************************
+// ~StackAllocator()
+//
+// Destroy heap memory
+//
+//*****************************************************************************
StackAllocator::~StackAllocator()
{
+ if (begin)
free(begin);
}
+//*****************************************************************************
+// print()
+//
+// Print the status of the heap as well as all allocated blocks
+//
+//*****************************************************************************
+
void StackAllocator::print()
{
- printf("Stack alloc : %g kbytes used of %g kbytes\n", double(top-begin)/1000, double(end-begin)/1000);
+ printf("Stack allocator : %g kbytes used of %g kbytes\n",
+ double(top-begin)/1000, double(end-begin)/1000);
+ printf("\tBlocks:\n");
+ unsigned char * b = begin+sizeof(unsigned);
+ while (b>=begin && b<=top)
+ {
+ printf("\t%p: size=%d\n", b, BSIZE(b));
+ b+=BSIZE(b)+sizeof(unsigned);
+ }
}
+
Index: llvm/lib/Reoptimizer/BinInterface/salloc.h
diff -u llvm/lib/Reoptimizer/BinInterface/salloc.h:1.3 llvm/lib/Reoptimizer/BinInterface/salloc.h:1.4
--- llvm/lib/Reoptimizer/BinInterface/salloc.h:1.3 Sat Dec 14 19:40:48 2002
+++ llvm/lib/Reoptimizer/BinInterface/salloc.h Sun Dec 15 05:07:29 2002
@@ -1,7 +1,7 @@
//*****************************************************************************
// Fast Stack Allocator
//
-// Definitions of Base Allocator class and Stack allocator
+// Definitions of Base Allocator class and Stack allocator
//
//
//
@@ -19,15 +19,31 @@
class Allocator
{
-public:
- virtual void clear() = 0;
- virtual void*alloc(unsigned size) = 0;
- virtual void free(void * block) = 0;
- virtual void*resize(void * block , unsigned newsize) = 0;
- virtual ~Allocator() {}
+ public:
+ virtual void clear() = 0;
+ virtual void*alloc(unsigned size) = 0;
+ virtual void free(void * block) = 0;
+ virtual void*resize(void * block , unsigned newsize) = 0;
+ virtual ~Allocator() {}
+ virtual void print() = 0;
};
+//*********************************
+// C++ Allocator
+//*********************************
+
+class CAllocator: public Allocator
+{
+ public:
+ virtual void clear() {}
+ virtual void*alloc(unsigned size) { return malloc(size); }
+ virtual void free(void * block) { ::free(block); }
+ virtual void*resize(void * block , unsigned size) { return ::realloc(block, size); }
+ virtual ~CAllocator() {}
+ virtual void print() {}
+};
+
//*********************************
// Stack Allocator
@@ -35,18 +51,18 @@
class StackAllocator : public Allocator
{
- unsigned char * begin;
- unsigned char * end;
- unsigned char * top; // current free
-
-public:
- StackAllocator(unsigned size);
- ~StackAllocator();
- void clear();
- void * alloc(unsigned size);
- void * resize(void * block , unsigned newsize);
- void free(void * block);
- void print();
+ unsigned char * begin;
+ unsigned char * end;
+ unsigned char * top; // current free
+
+ public:
+ StackAllocator(unsigned size);
+ ~StackAllocator();
+ void clear();
+ void * alloc(unsigned size);
+ void * resize(void * block , unsigned newsize);
+ void free(void * block);
+ void print();
};
Index: llvm/lib/Reoptimizer/BinInterface/select.cpp
diff -u llvm/lib/Reoptimizer/BinInterface/select.cpp:1.1 llvm/lib/Reoptimizer/BinInterface/select.cpp:1.2
--- llvm/lib/Reoptimizer/BinInterface/select.cpp:1.1 Sat Dec 14 19:31:41 2002
+++ llvm/lib/Reoptimizer/BinInterface/select.cpp Sun Dec 15 05:07:29 2002
@@ -1,6 +1,6 @@
//*****************************************************************************
// SPARC Binary Manipulation Interface
-//
+//
// Register Allocator
//
// Interface Definition
@@ -15,334 +15,297 @@
#include <stdlib.h>
#include "salloc.h" // Stack allocator class
#include "fvector.h" // fast vector (sits on stack allocator)
-#include "analyze.h" // SPARC analysis library (gets flag masks for instrs)
+#include "analyze.h" // SPARC analysis library
#include "sparcbin.h" // Prototype for this class
#include "sparcpriv.h" // Private definitions
#include "sparcdis.h" // prototype for sparc disassembler
#include "bitmath.h" // header of optimized binary math routines
-#include "sparc9.h" // SPARC 9 opcode definitions
-#include <vector>
+#include "sparc9.h" // SPARC 9 opcode definitions
+#include "regmask.h" // Register mask allocator
+#include <vector> // Use STL pair class
using std::pair;
+
#include <assert.h>
-#include "regmask.h"
+//*****************************************************************************
+// select(regalloc & regs)
+//
+// Perform register allocation and store register assignments as well
+// as memory heap requirements, spill areas, etc into regs structure
+//
+//*****************************************************************************
void BinInterface::select(regalloc & regs)
{
- regs.touched_regs = 0; // mask containing all the touched registers
- regs.liveout_regs = 0;
- unsigned max_midx = 0; // max midx (32+stackelement)
- int free_vreg = 1, s,k,i,p; // first free
-
- fvector<unsigned> & ssa_to_vreg = regs.ssa_to_vreg;
- fvector<vreginfo> & vregs = regs.vregs;
-
-
- // Mark everyone as having no register assigned
- ssa_to_vreg.inc(itable.size());
- for (k = 0; k<ssa_to_vreg.size(); k++)
- ssa_to_vreg[k] = 0;
-
-
- // Condense PHI nodes
- for (s=0;s<sections.size();s++)
- for (i = begin(s); i!=end(s); i=next(i))
- {
- instruction * instr = itable[i];
- unsigned flags = instr->flags;
-
- if (flags & IF_PHI)
+ regs.touched_regs = 0; // mask containing all the touched registers
+ regs.liveout_regs = 0; // mask of JUST liveout registers
+
+ unsigned max_midx= 0; // maximal stack index that we access
+
+ // don't assign vreg of 0.
+ int free_vreg = 1, s,k,i,p; // first free
+
+ // This table stores the Virtual Registers that were
+ // assigned to each SSA node
+ fvector<unsigned> & ssa_to_vreg = regs.ssa_to_vreg;
+
+ // This table has the live-range and register assignments
+ // for a given virtual register
+ fvector<vreginfo> & vregs = regs.vregs;
+
+ // Mark everyone as having no register assigned
+ ssa_to_vreg.inc(itable.size());
+ for (k = 0; k<ssa_to_vreg.size(); k++)
+ ssa_to_vreg[k] = 0;
+
+ // Condense PHI nodes and assign virtual registers
+ // to PHI's ONLY
+ for (s=0;s<sections.size();s++)
+ for (i = begin(s); i!=end(s); i=next(i))
+ {
+ instruction * instr = itable[i];
+ unsigned flags = instr->flags;
+
+ if (flags & IF_PHI)
+ {
+ for (int p=0; p< instr->phi.params->size(); p++)
{
- for (int p=0; p< instr->phi.params->size(); p++)
- {
- int id = (*instr->phi.params)[p];
- ssa_to_vreg[id] = free_vreg;
- }
- ssa_to_vreg[i] = free_vreg;
- free_vreg++;
+ int id = (*instr->phi.params)[p];
+ ssa_to_vreg[id] = free_vreg;
}
- }
-
- // size the vreg structures and initialize
- vregs.inc(itable.size());
- for (p = 0 ; p < free_vreg; p++)
- vregs[p].uses = vregs[p].lastuse = vregs[p].mreg = 0;
-
-
- // Assign Vregs to non-phi parameters. Calculate usage information
- // for ALL virtual registers. Also calculate liveout reg set
- for (s=0;s<sections.size();s++)
- for (int i = begin(s); i!=end(s); i=next(i))
- {
- instruction * instr = itable[i];
- unsigned flags = instr->flags;
-
- if (!ssa_to_vreg[i]) //not got a vreg yet?
+ ssa_to_vreg[i] = free_vreg;
+ free_vreg++;
+ }
+ }
+
+ // size the vreg structures and initialize
+ vregs.inc(itable.size());
+ for (p = 0 ; p < free_vreg; p++)
+ vregs[p].uses = vregs[p].lastuse = vregs[p].mreg = 0;
+
+ // Assign Vregs to non-phi parameters. Calculate usage information
+ // for ALL virtual registers. Also calculate liveout reg set
+ for (s=0;s<sections.size();s++)
+ for (int i = begin(s); i!=end(s); i=next(i))
+ {
+ instruction * instr = itable[i];
+ unsigned flags = instr->flags;
+
+ if (!ssa_to_vreg[i]) //not got a vreg yet?
+ {
+ // allocate one
+ ssa_to_vreg[i] = free_vreg;
+ vregs.inc(1);
+
+ vregs[free_vreg].uses =
+ vregs[free_vreg].lastuse =
+ vregs[free_vreg].mreg = 0;
+
+ free_vreg++;
+ }
+
+ if (flags & IF_REGSHUFFLE)
+ {
+ fvector<shufflepair> * v = instr->regshuffle.shuffles;
+ for (int z=0;z<v->size();z++)
{
- // allocate one
- ssa_to_vreg[i] = free_vreg;
- vregs.inc(1);
- vregs[free_vreg].uses = vregs[free_vreg].lastuse = vregs[free_vreg].mreg = 0;
- free_vreg++;
+ int gen = (*v)[z].gen;
+ int vr = ssa_to_vreg[gen];
+ vregs[vr].uses++;
+ vregs[vr].lastuse = i;
+ regs.liveout_regs |= (1 << (*v)[z].reg); //liveout reg
}
-
- if (flags & IF_REGSHUFFLE)
+ continue;
+ }
+
+ // note since PHI nodes have been collapsed
+ // through the vreg assignment. we don't need to process them! =p
+ // Livein nodes are also skipped
+ if (flags & (IF_ALUOP | IF_BR))
+ {
+ if (flags & IF_R_RS1) // do we read from RS1?
{
- fvector<shufflepair> * v = instr->regshuffle.shuffles;
- for (int z=0;z<v->size();z++)
- {
- int gen = (*v)[z].gen;
- int vr = ssa_to_vreg[gen];
- vregs[vr].uses++;
- vregs[vr].lastuse = i;
- regs.liveout_regs |= (1 << (*v)[z].reg); //liveout reg
- }
- continue;
- }
-
- // note since PHI nodes have been collapsed
- // through the vreg assignment. we don't need to process them! =p
- // Livein nodes are also skipped
- if (flags & (IF_ALUOP | IF_BR))
+ int id = ssa_to_vreg[instr->alu.genrs1];
+ vregs[id].uses++;
+ vregs[id].lastuse = i;
+ }
+ if (flags & IF_R_RS2) // do we read from RS2?
{
- if (flags & IF_R_RS1) // do we read from RS1?
- {
- int id = ssa_to_vreg[instr->alu.genrs1];
- vregs[id].uses++;
- vregs[id].lastuse = i;
- }
- if (flags & IF_R_RS2) // do we read from RS2?
- {
- int id = ssa_to_vreg[instr->alu.genrs2];
- vregs[id].uses++;
- vregs[id].lastuse = i;
- }
- if (flags & IF_R_RD) // do we read from RD?
- {
- int id = ssa_to_vreg[instr->alu.genrd];
- vregs[id].uses++;
- vregs[id].lastuse = i;
- }
- }
- }
-
- // register allocation state
- regmask freeregs(alloca,ROUNDUP32(itable.size())+32); // includes stack positions
- unsigned hwregs[32]; // vreg index in that register
- freeregs.set32(R_ALLOCREGS); // mark candidate registers free
-
- for (s = 0; s< 32; s++)
- hwregs[s] = 0;
-
- // Allocate registers that are marked as live in values
- // note livein nodes are COPY instructions.
- for (p = 0; p<livein.size(); p++)
- {
- // Mark down the register assignment in vreg structure
- int mreg = itable[livein[p]]->livein.reg;
- vregs[ ssa_to_vreg[livein[p]] ].mreg = mreg;
-
- // Mark that register not free
- freeregs.grabreg(mreg);
- regs.touched_regs |= (1<<mreg);
- hwregs[mreg] = ssa_to_vreg[livein[p]];
- }
-
- // grab our spill registers
- regs.spillreg = freeregs.allocreg32();
- for (int z=0;z<32;z++)
- {
- regs.memspills[z] = freeregs.allocmemreg();
-
- if (regs.memspills[z] > max_midx)
- max_midx = regs.memspills[z];
- }
-
- // Iterate across instructions
- for (s=0;s<sections.size();s++)
- for (i = begin(s); i!=end(s); i=next(i))
- {
- // Find what registers this instruction depends on.
- int rs1; // this register will contain the rs1 value
- int rs2; // this register will contain the rs2 value
- int rd; // this register will contain the rd value
-
- instruction * instr = itable[i];
- unsigned flags = instr->flags;
-
-
- // make sure this is ACTUALLY an instruction and not a phi node
- if (! (flags & (IF_ALUOP | IF_BR)))
- continue;
-
- unsigned ins = instr->instr;
- // mask off and replace rs1
- if (flags & IF_R_RS1)
- {
- int vid = ssa_to_vreg[instr->alu.genrs1];
- if (vregs[vid].lastuse == i)
- {
- freeregs.freereg(vregs[vid].mreg);
-
- if (vregs[vid].mreg < 32)
- hwregs[vregs[vid].mreg] = 0;
- }
- }
-
- if (flags & IF_R_RS2)
- {
- int vid = ssa_to_vreg[instr->alu.genrs2];
- if (vregs[vid].lastuse == i)
- {
- freeregs.freereg(vregs[vid].mreg);
- if (vregs[vid].mreg < 32)
- hwregs[vregs[vid].mreg] = 0;
- }
- }
-
- if (flags & IF_R_RD)
- {
- int vid = ssa_to_vreg[instr->alu.genrd];
- if (vregs[vid].lastuse == i)
- {
- freeregs.freereg(vregs[vid].mreg);
- if (vregs[vid].mreg < 32)
- hwregs[vregs[vid].mreg] = 0;
- }
- }
-
- if (flags & IF_W_RD)
- {
- int id = ssa_to_vreg[i];
- int dreg = freeregs.allocreg();
-
-
- if (dreg >= 32)
- {
- if (dreg > max_midx)
- max_midx = dreg;
-
- // Select a live range to spill
- unsigned min_cnt = 0xFFFFFFFF;
- unsigned min_idx = 0;
-
- for (int j = 0; j < 32; j++)
- {
- if (!hwregs[j])
- continue;
-
- vreginfo & v = vregs[hwregs[j]];
- if (v.uses < min_cnt)
- {
- min_cnt = v.uses;
- min_idx = j;
- }
- }
-
- // mincnt/minidx now contain the smallest allocated
-
- if (min_cnt < vregs[id].uses)
- {
- // spill using this register
- int oid = hwregs[min_idx];
- vregs[id].mreg = min_idx;
- assert(min_idx < 32);
- hwregs[min_idx] = id;
-
- vregs[oid].mreg = dreg;
- }
- else
- {
- // no spill
- vregs[id].mreg = dreg;
- }
- }
- else
- {
- regs.touched_regs |= (1<<dreg);
- assert(dreg < 32);
- hwregs[dreg] = id;
- vregs[id].mreg = dreg;
- }
-
- vregs[id].mreg = dreg;
- }
- }
-
- // print register assignment
- /*for (int x=0;x<ssa_to_vreg.size();x++)
+ int id = ssa_to_vreg[instr->alu.genrs2];
+ vregs[id].uses++;
+ vregs[id].lastuse = i;
+ }
+ if (flags & IF_R_RD) // do we read from RD?
{
- int id = ssa_to_vreg[x];
- printf("l%d: -> v%d reg=%d\n", x,id, vregs[id].mreg);
- }*/
-
- // calculate amount of stack space needed
- regs.stack_size = ((max_midx+1) - 32) * 8;
-}
+ int id = ssa_to_vreg[instr->alu.genrd];
+ vregs[id].uses++;
+ vregs[id].lastuse = i;
+ }
+ }
+ }
-/*
-//
-// Spill load
-// - loads value into register (performing spill if needed)
-// - validates use constraints and identifies the end of a live-range
-//
-int BinInterface::spill_load(int useid, int id, unsigned * & out, fvector<vreginfo> & vregs, regmask & freeregs, unsigned hwregs[32])
-{
- int rs1 = vregs[id].mreg;
+ // register allocation state
- if (rs1 >= 32) // not a hardware register?
- {
- // First try allocating a candindate register
- int sreg = freeregs.allocreg();
-
- // if sreg wasn't a hardware register spill something into it
- // and return the register we spilled
- if (sreg >= 32)
- sreg = spillreg(sreg, out, vregs, freeregs, hwregs);
-
- // update the virtual register map
- hwregs[sreg] = id;
- vregs[id].mreg = sreg;
- freeregs.freereg(rs1); // free the old area since we're loading it
-
- // perform a spill load on the parameters
- *out++=(MK_LDX_STACK(sreg, 8*(rs1-32)));
-
-
- return sreg;
- }
- else
- return rs1; //it was already in a register
-}
-int BinInterface::spillreg(int spillloc, unsigned * & out, fvector<vreginfo> & vregs, regmask & freeregs, unsigned hwregs[32])
-{
+ //
+ // We need potentially 1 spill for each SSA node
+ // as well as the 32 generic spill slots (used for
+ // shuffle instructions)
+ //
+ regmask freeregs(alloca,ROUNDUP32(itable.size())+32);
- // Select a live range to spill
- unsigned min_cnt = 0xFFFFFFFF;
- unsigned min_idx = 0;
-
- for (int j = 0; j < 32; j++)
- {
- if (!hwregs[j])
+ unsigned hwregs[32]; // vreg index in that register
+ freeregs.set32(R_ALLOCREGS); // mark candidate registers free
+
+ for (s = 0; s< 32; s++)
+ hwregs[s] = 0;
+
+ // Allocate registers that are marked as live in values
+ // note livein nodes are COPY instructions.
+ for (p = 0; p<livein.size(); p++)
+ {
+ // Mark down the register assignment in vreg structure
+ int mreg = itable[livein[p]]->livein.reg;
+ vregs[ ssa_to_vreg[livein[p]] ].mreg = mreg;
+
+ // Mark that register not free
+ freeregs.grabreg(mreg);
+ regs.touched_regs |= (1<<mreg);
+ hwregs[mreg] = ssa_to_vreg[livein[p]];
+ }
+
+ // grab our spill registers
+ regs.spillreg = freeregs.allocreg32();
+ for (int z=0;z<32;z++)
+ {
+ regs.memspills[z] = freeregs.allocmemreg();
+
+ unsigned midx = VREG_GETMEM(regs.memspills[z]);
+ if (midx > max_midx)
+ max_midx = midx;
+ }
+
+ // Iterate across instructions
+ for (s=0;s<sections.size();s++)
+ for (i = begin(s); i!=end(s); i=next(i))
+ {
+ // Find what registers this instruction depends on.
+ int rs1; // this register will contain the rs1 value
+ int rs2; // this register will contain the rs2 value
+ int rd; // this register will contain the rd value
+
+ instruction * instr = itable[i];
+ unsigned flags = instr->flags;
+
+
+ // make sure this is ACTUALLY an instruction and not a phi node
+ if (! (flags & (IF_ALUOP | IF_BR)))
continue;
-
- vreginfo & v = vregs[hwregs[j]];
- if (v.uses < min_cnt)
- {
- min_cnt = v.uses;
- min_idx = j;
- }
- }
- // Spill the live range to the location we allocated
- vregs[hwregs[min_idx]].mreg = spillloc; // update map
-
- // spill the live-range
- *out++=(MK_STX_STACK(min_idx, 8*(spillloc - 32)));
-
- return min_idx;
-}
-*/
+ unsigned ins = instr->instr;
+ // mask off and replace rs1
+ if (flags & IF_R_RS1)
+ {
+ int vid = ssa_to_vreg[instr->alu.genrs1];
+ if (vregs[vid].lastuse == i)
+ {
+ freeregs.freereg(vregs[vid].mreg);
+ if (VREG_ISREG(vregs[vid].mreg))
+ hwregs[vregs[vid].mreg] = 0;
+ }
+ }
+
+ if (flags & IF_R_RS2)
+ {
+ int vid = ssa_to_vreg[instr->alu.genrs2];
+ if (vregs[vid].lastuse == i)
+ {
+ freeregs.freereg(vregs[vid].mreg);
+ if (VREG_ISREG(vregs[vid].mreg))
+ hwregs[vregs[vid].mreg] = 0;
+ }
+ }
+
+ if (flags & IF_R_RD)
+ {
+ int vid = ssa_to_vreg[instr->alu.genrd];
+ if (vregs[vid].lastuse == i)
+ {
+ freeregs.freereg(vregs[vid].mreg);
+ if (VREG_ISREG(vregs[vid].mreg))
+ hwregs[vregs[vid].mreg] = 0;
+ }
+ }
+
+ if (flags & IF_W_RD)
+ {
+ int id = ssa_to_vreg[i];
+ int dreg = freeregs.allocreg();
+
+
+ if (VREG_ISMEM(dreg))
+ {
+ unsigned midx = VREG_GETMEM(dreg);
+
+ if (midx > max_midx)
+ max_midx = midx;
+
+ // Select a live range to spill
+ unsigned min_cnt = 0xFFFFFFFF;
+ unsigned min_idx = 0;
+
+ for (int j = 0; j < 32; j++)
+ {
+ if (!hwregs[j])
+ continue;
+
+ vreginfo & v = vregs[hwregs[j]];
+ if (v.uses < min_cnt)
+ {
+ min_cnt = v.uses;
+ min_idx = j;
+ }
+ }
+
+ // mincnt/minidx now contain the smallest allocated
+
+ if (min_cnt < vregs[id].uses)
+ {
+ // spill using this register
+ int oid = hwregs[min_idx];
+ vregs[id].mreg = min_idx;
+
+ assert(min_idx < 32);
+ hwregs[min_idx] = id;
+ vregs[oid].mreg = dreg;
+ }
+ else
+ {
+ // no spill
+ vregs[id].mreg = dreg;
+ }
+ }
+ else
+ {
+ regs.touched_regs |= (1<<dreg);
+ assert(dreg < 32);
+ hwregs[dreg] = id;
+ vregs[id].mreg = dreg;
+ }
+
+ vregs[id].mreg = dreg;
+ }
+ }
+
+ // print register assignment
+ /*for (int x=0;x<ssa_to_vreg.size();x++)
+ {
+ int id = ssa_to_vreg[x];
+ printf("l%d: -> v%d reg=%d\n", x,id, vregs[id].mreg);
+ }*/
+
+ // calculate amount of stack space needed
+ regs.stack_size = max_midx+8;
+}
Index: llvm/lib/Reoptimizer/BinInterface/sparc9.cpp
diff -u llvm/lib/Reoptimizer/BinInterface/sparc9.cpp:1.1 llvm/lib/Reoptimizer/BinInterface/sparc9.cpp:1.2
--- llvm/lib/Reoptimizer/BinInterface/sparc9.cpp:1.1 Sat Dec 14 20:04:30 2002
+++ llvm/lib/Reoptimizer/BinInterface/sparc9.cpp Sun Dec 15 05:07:33 2002
@@ -9,25 +9,28 @@
#include "sparc9.h"
-char * cc_names[] = { "fcc0", "fcc1", "fcc2", "fcc3", "icc", "c101", "xcc", "c111"};
+char * cc_names[] = { "fcc0", "fcc1", "fcc2", "fcc3",
+ "icc", "c101", "xcc", "c111"};
//**********************************
// Name Lookup tables
// index is Condition code
//**********************************
-char * fcond_names[] = {"FBN","FBNE","FBLG","FBUL","FBL","FBUG","FBG","FBU","FBA","FBE",
- "FBUE","FBGE","FBUGE","FBLE","FBULE","FBO"};
+char * fcond_names[] = {"FBN","FBNE","FBLG","FBUL","FBL","FBUG","FBG","FBU",
+ "FBA","FBE", "FBUE","FBGE","FBUGE","FBLE","FBULE",
+ "FBO"};
-char * icond_names[] = {"n","e","le","l","leu","cs","neg","vs","a","ne","g","ge",
- "gu","cc","pos","vc"};
+char * icond_names[] = {"n","e","le","l","leu","cs","neg","vs","a","ne",
+ "g","ge","gu","cc","pos","vc"};
-char * rcond_names[] = {"r000", "RZ", "RLEZ", "r011", "r100", "RNZ", "RGZ", "RGEZ"};
+char * rcond_names[] = {"r000", "RZ", "RLEZ", "r011", "r100", "RNZ", "RGZ",
+ "RGEZ"};
char * reg_names[32] = { "G0", "G1", "G2", "G3", "G4", "G5", "G6", "G7",
- "O0", "O1", "O2", "O3", "O4", "O5", "O6(SP)", "O7",
- "L0", "L1", "L2", "L3", "L4", "L5", "L6", "L7",
- "I0", "I1", "I2", "I3", "I4", "I5", "I6(FP)", "I7"};
+ "O0", "O1", "O2", "O3", "O4", "O5", "O6(SP)", "O7",
+ "L0", "L1", "L2", "L3", "L4", "L5", "L6", "L7",
+ "I0", "I1", "I2", "I3", "I4", "I5", "I6(FP)", "I7"};
Index: llvm/lib/Reoptimizer/BinInterface/sparc9.h
diff -u llvm/lib/Reoptimizer/BinInterface/sparc9.h:1.7 llvm/lib/Reoptimizer/BinInterface/sparc9.h:1.8
--- llvm/lib/Reoptimizer/BinInterface/sparc9.h:1.7 Sat Dec 14 19:31:49 2002
+++ llvm/lib/Reoptimizer/BinInterface/sparc9.h Sun Dec 15 05:07:33 2002
@@ -6,9 +6,9 @@
// 2002 Cameron Buschardt
//*****************************************************************************
-//*********************************
+//*****************************************************************************
// Register Names
-//*********************************
+//*****************************************************************************
#define R_I7 31
#define R_I6 30
#define R_I5 29
@@ -50,9 +50,9 @@
extern char * reg_names[];
-//**********************************
-// Instruction bitfield definitions
-//**********************************
+//*****************************************************************************
+// Instruction bitfield definitions
+//*****************************************************************************
#define INSTR_OP 31:30
#define INSTR_A 29:29
#define INSTR_FCN 29:25
@@ -101,17 +101,17 @@
#define RD_D16(i) ((RD_FLD(i, INSTR_D16HI) << 14) | RD_FLD(i, INSTR_D16LO))
-//**********************************
-// Op-code classification
-//**********************************
+//*****************************************************************************
+// Op-code classification
+//*****************************************************************************
#define OP_CALL 0x00000001 /* 0b01 */
#define OP_BRANCH 0x00000000 /* 0b00 */
#define OP_2 0x00000002 /* 0b10 */
#define OP_3 0x00000003 /* 0b11 */
-//**********************************
+//*****************************************************************************
// Branch Class Instructions
-//**********************************
+//*****************************************************************************
#define OP2_ILLTRAP 0x00000000 /* 0b000 */ //OP=OP_BRANCH
#define OP2_NOP 0x00000004 /* 0b100 */ //BRANCH
#define OP2_SETHI 0x00000004 /* 0b100 */ //BRANCH - uhh? duplicate? DOH =p
@@ -121,18 +121,18 @@
#define OP2_FBP 0x00000005 /* 0b101 */
#define OP2_BPICC 0x00000001 /* 0b001 */
-//**********************************
+//*****************************************************************************
// Register Condition Codes
-//**********************************
+//*****************************************************************************
#define RCOND_RZ 0x00000001 /* 0b001 */
#define RCOND_RLEZ 0x00000002 /* 0b010 */
#define RCOND_RNZ 0x00000005 /* 0b101 */
#define RCOND_RGZ 0x00000006 /* 0b110 */
#define RCOND_RGEZ 0x00000007 /* 0b111 */
-//**********************************
+//*****************************************************************************
// FPU Branch Conditions
-//**********************************
+//*****************************************************************************
#define COND_FBN 0x00000000 /* 0b0000 */
#define COND_FBNE 0x00000001 /* 0b0001 */
#define COND_FBLG 0x00000002 /* 0b0010 */
@@ -150,9 +150,9 @@
#define COND_FBULE 0x0000000E /* 0b1110 */
#define COND_FBO 0x0000000F /* 0b1111 */
-//**********************************
+//*****************************************************************************
// Integer Branch Conditions
-//**********************************
+//*****************************************************************************
#define COND_BN 0x00000000 /* 0b0000 */
#define COND_BE 0x00000001 /* 0b0001 */
#define COND_BLE 0x00000002 /* 0b0010 */
@@ -171,18 +171,18 @@
#define COND_BVC 0x0000000F /* 0b1111 */
-//**********************************
+//*****************************************************************************
// Name Lookup tables
// index is Condition code
-//**********************************
+//*****************************************************************************
extern char * fcond_names[];
extern char * icond_names[];
extern char * rcond_names[];
-//**********************************
-// Flag register encoding
-//**********************************
+//*****************************************************************************
+// Flag register encoding
+//*****************************************************************************
#define FLAG_FCC0 0x00000000 /* 0b000 */
#define FLAG_FCC1 0x00000001 /* 0b001 */
@@ -194,8 +194,8 @@
extern char * cc_names[];
-//**********************************
-// OP_2 class instructions
+//*****************************************************************************
+// OP_2 class instructions
//
// present members:
// RD, OP3, RS1
@@ -203,7 +203,7 @@
// RS2
// else
// SIMM13
-//**********************************
+//*****************************************************************************
#define OP3_ADD 0x00000000 /* 0b000000 */
#define OP3_ADDC 0x00000008 /* 0b001000 */
@@ -363,9 +363,9 @@
MK_FLD(INSTR_RS1, R_SP) | \
MK_FLD(INSTR_I , 1 ) | \
MK_FLD(INSTR_SIMM13, stackoffs))
-
-// Move a value between two registers
+
+// Move a value between two registers
#define MK_MOV_R_R(dreg, sreg) \
(MK_FLD(INSTR_OP, OP_2) | \
MK_FLD(INSTR_RD, dreg) | \
@@ -376,7 +376,7 @@
MK_FLD(INSTR_CC2 , 1 ) | \
MK_FLD(INSTR_MOV_CC1 , 1 ) | \
MK_FLD(INSTR_MOV_CC0, 0 ))
-
+
// Store a word in sreg to O6/SP + stackoffs
#define MK_STX_STACK(sreg, stackoffs) \
(MK_FLD(INSTR_OP, OP_3) | \
@@ -385,7 +385,7 @@
MK_FLD(INSTR_RS1, R_SP) | \
MK_FLD(INSTR_I , 1 ) | \
MK_FLD(INSTR_SIMM13, stackoffs))
-
+
// Add a constant to a register
#define MK_ADD_R_I(dreg, sreg, imm) \
(MK_FLD(INSTR_OP, OP_2) | \
Index: llvm/lib/Reoptimizer/BinInterface/sparcbin.cpp
diff -u llvm/lib/Reoptimizer/BinInterface/sparcbin.cpp:1.2 llvm/lib/Reoptimizer/BinInterface/sparcbin.cpp:1.3
--- llvm/lib/Reoptimizer/BinInterface/sparcbin.cpp:1.2 Sat Dec 14 19:32:10 2002
+++ llvm/lib/Reoptimizer/BinInterface/sparcbin.cpp Sun Dec 15 05:07:37 2002
@@ -6,13 +6,13 @@
// Current flaws:
// * Makes no attempts to handle the difficulties of call instructions
// need to add 'affinity' for register allocator to handle efficient
-// selection of Ixx registers.
+// selection of Ixx registers.
// * Needs to save parameter registers
//
// Goals
// * Performance - Efficient use of memory and allocation code
// * Minimal Algorithms- 100% linear time, and make as many assumptions
-// based on our definition of trace as possible
+// based on our definition of trace as possible
//
// 2002 Cameron Buschardt
//*****************************************************************************
@@ -21,360 +21,493 @@
#include <stdlib.h>
#include "salloc.h" // Stack allocator class
#include "fvector.h" // fast vector (sits on stack allocator)
-#include "analyze.h" // SPARC analysis library (gets flag masks for instrs)
+#include "analyze.h" // SPARC analysis library
#include "sparcbin.h" // Prototype for this class
-#include "sparcpriv.h" // Private definitions#include "machine.h" // machine constants for cache optimizations
+#include "sparcpriv.h" // Private definitions
#include "sparcdis.h" // prototype for sparc disassembler
#include "bitmath.h" // header of optimized binary math routines
-#include "sparc9.h" // SPARC 9 opcode definitions
-#include <vector>
+#include "sparc9.h" // SPARC 9 opcode definitions
+#include <vector> // Bring in STL pair class
using std::pair;
-#include <assert.h>
-
-// 512kb initial size
-#define BIN_INIT_HEAP_SIZE 0x80000
-#define MAX_SECTIONS 16
+#include <assert.h>
#include <new>
-
+//*****************************************************************************
+// liveout(unsigned instr)
//
-// liveout: Marks an instruction liveout. Can only be called AFTER
-// complete() and before reduce().
-// Only values marked liveout will be in the original/correct
-// register by end of epilog!
+// Marks an instruction liveout. Can only be called AFTER
+// complete() and before reduce().
+// Only values marked liveout will be in the original/correct
+// register by end of epilog!
//
+//*****************************************************************************
void BinInterface::liveout(unsigned instr)
{
- itable[instr]->flags |= IF_LIVEOUT;
+ itable[instr]->flags |= IF_LIVEOUT;
}
+//*****************************************************************************
+// emit(unsigned char * out)
+//
+// Do register selection and emit the code
+// The user supplies the buffer
+// (user knows "max" size through a call to predict)
+//
+//*****************************************************************************
+unsigned BinInterface::emit(unsigned char * out)
+{
+ //
+ // This structure receives the register allocation
+ // and spill register information to be passed
+ // on to the emitter.
+ //
+ regalloc regs(alloca);
+ // Fill structure
+ select(regs);
+ // Compile code
+ return emit_gen(out, regs);
+}
-
+//*****************************************************************************
+// predict()
//
-// Perform a fast linear scan register allocation.
-// * Dynamically allocates spill registers
-// * Guarantees all parameters of a PHI node
-// get mapped to the same register
+// This function will correctly guess the largest size
+// the buffer needs to be.
//
+//*****************************************************************************
-
-
-
-unsigned BinInterface::emit(unsigned char * out)
+unsigned BinInterface::predict()
{
- int spillreg;
- int memspills[32];
- unsigned touched, stack;
- // Table to look up virtual register for SSA node
- // this is done to condense PHI node references
- regalloc regs(alloca);
-
-
- select(regs); // condense phi nodes and calculate
- // live ranges
-
- return emit_gen(out, regs); // do linear scan register allocation
- // interleaved with code generation
+ return (4 * itable.size() + 32*4) * sizeof(unsigned);
}
+//*****************************************************************************
+// allocphi()
+//
+// Allocate a PHI node from the user heap and link it in.
+//
+//*****************************************************************************
+instruction * BinInterface::allocphi()
+{
+ instruction * phi = (instruction *)alloca->alloc(sizeof(instruction));
+ phi->flags = IF_PHI;
+ phi->next = phi->prev = phi->self = itable.size();
+ itable.push_back(phi);
+ // allocate memory for fvector AND call constructor
+ phi->phi.params =
+ (fvector<unsigned> *) alloca->alloc(sizeof(fvector<unsigned>));
+
+ new ((void *)phi->phi.params) fvector<unsigned>(alloca);
+ return phi;
+}
+//*****************************************************************************
+// process_branch(
+//
+// brdest[section] - the original address of the first instruction
+// in that section
+// scns - number of sections
+// insertion i - the queued insertion command, contains the list
+// of instructions
+//
+// This function inserts the insertion into partial SSA instructions
+// the only SSA fields that will be valid after this are the branch
+// destinations
+//
+//*****************************************************************************
-
-unsigned BinInterface::predict()
+void BinInterface::process_branch(
+ const insertion & i, unsigned ** brdest, int scns)
{
- return 16 * itable.size();
-}
+ unsigned cid = i.idstart;
+ unsigned *ibegin = i.begin;
+ unsigned *iend = i.end;
+ unsigned tail = sections[i.section];
-instruction * BinInterface::allocphi()
-{
- instruction * phi = (instruction *)alloca->alloc(sizeof(instruction));
-
- phi->flags = IF_PHI;
- phi->next = phi->prev = phi->self = itable.size();
- itable.push_back(phi);
-
- // allocate memory for fvector AND call constructor
- phi->phi.params = (fvector<unsigned> *)alloca->alloc(sizeof(fvector<unsigned>));
- new ((void *)phi->phi.params) fvector<unsigned>(alloca);
+ while(ibegin!=iend)
+ {
+ // Analyze the instruction
+ unsigned flags = sparc_analyze(*ibegin);
-
- return phi;
-}
+ instruction * instr;
-void BinInterface::process_branch(const insertion & i, unsigned ** brdest, int scns)
-{
- unsigned cid = i.idstart;
- unsigned *ibegin = i.begin;
- unsigned *iend = i.end;
- unsigned tail = sections[i.section];
+ // Branch?
+ if (flags & IF_BR)
+ {
+ int fwd = sparc_getbrdest(*ibegin); // Relative adress
+ unsigned * dest = ibegin + fwd; // eval
-
- while(ibegin!=iend)
- {
- // look at the instruction
- unsigned flags = sparc_analyze(*ibegin);
-
- instruction * instr;
-
- if (flags & IF_BR)
- {
- int fwd = sparc_getbrdest(*ibegin);
- unsigned * dest = ibegin + fwd;
+ // allocate the SSA node
+ instr = (instruction *)alloca->alloc(sizeof(instruction));
- // create a branch instruction
- instr = (instruction *)alloca->alloc(sizeof(instruction));
+ instr->flags = flags;
- instr->flags = flags;
- // scan for branch destination
- for (int l = 0; l<scns; l++)
+ // scan for branch destination
+ for (int l = 0; l<scns; l++)
+ {
+ if (dest == brdest[l])
{
- if (dest == brdest[l])
- {
- instr->ibranch.dest = l;
- instr->flags |= IF_BRINTERNAL;
- goto ibfound;
- }
+ // found? this must be an internal
+ // branch!
+ instr->ibranch.dest = l;
+ instr->flags |= IF_BRINTERNAL;
+ goto ibfound;
}
- // must have been external
- instr->ebranch.dest = dest;
-
- ibfound: // internal branch found
- ;
-
- }
- else
- {
- // create a generic ALU instruction
- instr = (instruction *)alloca->alloc(sizeof(instruction));
- instr->flags = flags | IF_ALUOP;
- instr->alu.genccf = instr->alu.genrs1 = instr->alu.genrs2 = 0; // zero reg
- }
-
- instr->instr = *ibegin;
- instr->self = cid;
-
-
- itable[cid] = instr;
-
- insert_instr(tail, instr);
- tail = cid;
-
- cid++;
- ibegin++;
-
- }
-
+ }
+ // must have been external (eg out of trace)
+ instr->ebranch.dest = dest;
+
+ibfound: // internal branch found
+ ;
+
+ }
+ else
+ {
+ // create a generic ALU instruction since it wasn't
+ // a branch
+ instr = (instruction *)alloca->alloc(sizeof(instruction));
+ instr->flags = flags | IF_ALUOP;
+
+ // zero out SSA parameters
+ instr->alu.genccf = instr->alu.genrs1 = instr->alu.genrs2 = 0;
+ }
+
+ // Store instruction data and store instruction ID # in
+ // the node
+ instr->instr = *ibegin;
+ instr->self = cid;
+
+ // Add the instruction to the ID table
+ itable[cid] = instr;
+
+ // Add instruction into linked list for given section
+ insert_instr(tail, instr);
+ tail = cid;
+
+ cid++;
+ ibegin++;
+
+ }
+
}
+//*****************************************************************************
+// complete()
+//
+// Since insertions into sections are queued (for branch resolution)
+// this function is responsible for emptying the queues and inserting
+// the instructions
+//
+//*****************************************************************************
+
void BinInterface::complete()
{
- int p;
- assert(sections.size() <= MAX_SECTIONS);
- // Compute branch destination table by section
- unsigned * brdest[MAX_SECTIONS];
-
- for (p = 0; p<sections.size(); p++)
- brdest[p] = NULL;
+ int p;
+ assert(sections.size() <= MAX_SECTIONS);
+
+ // Compute branch destination table by section
+ unsigned * brdest[MAX_SECTIONS];
+
+ // We nullify the structure before the scan
+ // step since not EVERY section has an instruction
+ // in it.
+ for (p = 0; p<sections.size(); p++)
+ brdest[p] = NULL;
+
+ // Look for the first insertion for each section
+ // and mark down address
+ for (p = 0; p<queue.size(); p++)
+ if (!brdest[queue[p].section])
+ brdest[queue[p].section] = queue[p].begin;
+
+ // Complete delayed insertion per section
+ for (p = 0; p<queue.size(); p++)
+ process_branch(queue[p], brdest,sections.size());
- for (p = 0; p<queue.size(); p++)
- if (!brdest[queue[p].section])
- brdest[queue[p].section] = queue[p].begin;
-
- // Complete delayed insertion
- for (p = 0; p<queue.size(); p++)
- process_branch(queue[p], brdest,sections.size());
-
- // Instructions are internalized
- queue.clear();
-
- // Before adding phi nodes we need to add the LIVEOUT nodes
- // that are responsible for restoring the state
-
- // perform both passes and generate phi nodes
- // (after this stage all the register use information
- // is useless)
+ // Throw away queue
+ queue.clear();
}
+//*****************************************************************************
+// print(unsigned section)
+//
+// For debug purposes only. Prints out a *SINGLE* section and its
+// instructions in SSA form. Shows livein/liveout nodes as well
+//
+// (must be called after reduce)
+//
+//*****************************************************************************
+
void BinInterface::print(unsigned section)
{
- unsigned u = begin(section);
+ unsigned u = begin(section);
- while (u!=end(section))
- {
- instruction * instr = itable[u];
-
-
- if (instr->flags & IF_NODELIVEIN)
- {
- printf("l%04d: livein[r%d]\n", instr->self,instr->livein.reg);
- }
- else if (instr->flags & IF_REGSHUFFLE)
- {
- for (int k = 0; k<instr->regshuffle.shuffles->size(); k++)
- printf("r%02d: liveout[l%04d]\n", (*instr->regshuffle.shuffles)[k].reg, (*instr->regshuffle.shuffles)[k].gen);
- }
- else if (instr->flags & IF_PHI)
- {
- printf("l%04d: phi[", instr->self);
- for (int i=0;i<(*instr->phi.params).size();++i)
- printf("%d ", (*instr->phi.params)[i]);
- printf("]\n");
- }
- else if (instr->flags & IF_BR)
- {
- printf("l%04d: ", instr->self);
- if (instr->flags & IF_BRINTERNAL)
- printf("{dest:s%02d} ", instr->ibranch.dest);
- else
- printf("{dest:0x%08X} ", instr->ebranch.dest);
-
- sparc_print_pseudo(instr->instr, instr->alu.genrs1, instr->alu.genrs2, -1, instr->alu.genccf);
- printf("\n");
-
- }
- else
- {
- printf("l%04d: ", instr->self);
- sparc_print_pseudo(instr->instr, instr->alu.genrs1, instr->alu.genrs2, -1, instr->alu.genccf);
- printf("\n");
- }
+ while (u!=end(section))
+ {
+ instruction * instr = itable[u];
+
+ if (instr->flags & IF_NODELIVEIN)
+ {
+ printf("l%04d: livein[r%d]\n", instr->self,instr->livein.reg);
+ }
+ else if (instr->flags & IF_REGSHUFFLE)
+ {
+ for (int k = 0; k<instr->regshuffle.shuffles->size(); k++)
+ printf("r%02d: liveout[l%04d]\n",
+ (*instr->regshuffle.shuffles)[k].reg,
+ (*instr->regshuffle.shuffles)[k].gen);
+ }
+ else if (instr->flags & IF_PHI)
+ {
+ printf("l%04d: phi[", instr->self);
+ for (int i=0;i<(*instr->phi.params).size();++i)
+ printf("%d ", (*instr->phi.params)[i]);
+ printf("]\n");
+ }
+ else if (instr->flags & IF_BR)
+ {
+ printf("l%04d: ", instr->self);
+ if (instr->flags & IF_BRINTERNAL)
+ printf("{dest:s%02d} ", instr->ibranch.dest);
+ else
+ printf("{dest:0x%08X} ", instr->ebranch.dest);
+
+ sparc_print_pseudo(instr->instr,
+ instr->alu.genrs1,
+ instr->alu.genrs2,
+ -1,
+ instr->alu.genccf);
+ printf("\n");
+
+ }
+ else
+ {
+ printf("l%04d: ", instr->self);
+
+ sparc_print_pseudo(instr->instr,
+ instr->alu.genrs1,
+ instr->alu.genrs2,
+ -1,
+ instr->alu.genccf);
+ printf("\n");
+ }
- u = instr->next;
- }
+ u = instr->next;
+ }
}
+//*****************************************************************************
+// print()
+//
+// Prints all sections in SSA form
+//
+//*****************************************************************************
+
void BinInterface::print()
{
- //alloca->print();
+ alloca->print();
- for (int p = 0; p< sections.size(); p++)
- {
- printf("Section %d\n",p);
- print(p);
- }
+ for (int p = 0; p< sections.size(); p++)
+ {
+ printf("Section %d\n",p);
+ print(p);
+ }
}
+//*****************************************************************************
+// newepilog()
+//
+// Allocates a new epilog node and returns the instruction ID
+//
+//*****************************************************************************
unsigned BinInterface::newepilog()
{
- unsigned v = sections.size();
- push_section();
- return v;
+ unsigned v = sections.size();
+ push_section();
+ return v;
}
+//*****************************************************************************
+// insert_instr(unsigned instr_id, instruction *instr)
+//
+// Links instr into the linked list of instruction AFTER instr_id.
+// instr->self must have been previously initialized
+//
+//*****************************************************************************
void BinInterface::insert_instr(unsigned instr_id, instruction * instr)
{
- unsigned a = instr_id;
- unsigned c = itable[a]->next;
-
- itable[a]->next = instr->self;
- instr->prev = a;
-
- instr->next = c;
- itable[c]->prev = instr->self;
+ unsigned a = instr_id;
+ unsigned c = itable[a]->next;
+
+ itable[a]->next = instr->self;
+ instr->prev = a;
+
+ instr->next = c;
+ itable[c]->prev = instr->self;
}
+//*****************************************************************************
+// push_section()
//
-// AFTER AFTER->NEXT
-//
+// Adds a new section. Initialized empty.
//
-// AFTER INSTR AFTER->NEXT
-void BinInterface::push_section()
+//*****************************************************************************
+void BinInterface::push_section()
{
- // create header node
- instruction * instr = (instruction *)alloca->alloc(sizeof(instruction));
- instr->next = itable.size();
- instr->prev = itable.size();
- instr->flags = 0;
- instr->self = itable.size();
- sections.push_back(itable.size());
- itable.push_back(instr);
+ // create header node
+ instruction * instr = (instruction *)alloca->alloc(sizeof(instruction));
+ instr->next = itable.size();
+ instr->prev = itable.size();
+ instr->flags = 0;
+ instr->self = itable.size();
+ sections.push_back(itable.size());
+ itable.push_back(instr);
}
+//*****************************************************************************
+// BinInterface(unsigned heapsize)
+//
+// Heapsize must be sufficiently large or memory allocations will fail!
+//
+//
+//*****************************************************************************
-BinInterface::BinInterface(unsigned instr_count)
+BinInterface::BinInterface(unsigned heapsize)
{
- alloca = new StackAllocator(BIN_INIT_HEAP_SIZE + instr_count*16);
- itable.setallocator(alloca);
- sections.setallocator(alloca);
- queue.setallocator(alloca);
- livein.setallocator(alloca);
- // create prolog and trace link nodes
- push_section();
- push_section();
+ alloca = new StackAllocator(heapsize);
+ itable.setallocator(alloca);
+ sections.setallocator(alloca);
+ queue.setallocator(alloca);
+ livein.setallocator(alloca);
+ // create prolog and trace link nodes
+ push_section();
+ push_section();
}
+//*****************************************************************************
+// allocnodelivein(int s, int reg)
+//
+// Allocates a livein node and links it into the start of section 's'.
+// the node is livein for given register. Instruction ID Is returned
+//
+//*****************************************************************************
+
unsigned BinInterface::allocnodelivein(int s, int reg)
{
- int idx = itable.size();
- instruction * instr = (instruction *)alloca->alloc(sizeof(instruction));
- instr->flags = IF_NODELIVEIN;
- instr->livein.reg = reg;
- instr->self = idx;
- itable.push_back(instr);
- livein.push_back(idx);
- insert_instr(sections[s], instr);
- return idx;
-
+ int idx = itable.size();
+ instruction * instr = (instruction *)alloca->alloc(sizeof(instruction));
+ instr->flags = IF_NODELIVEIN;
+ instr->livein.reg = reg;
+ instr->self = idx;
+ itable.push_back(instr);
+ livein.push_back(idx);
+ insert_instr(sections[s], instr);
+ return idx;
+
}
+//*****************************************************************************
+// allocnodeshuffles(int s, fvector<shufflepair> * shuffles)
+//
+// Allocates a shuffle node and links it into the start of section 's'.
+// The shuffle node arranges for a set of SSA values to be in specific
+// registers (used for liveout). Shuffles is a list of pairs of
+// registers/instruction IDs.
+//
+//*****************************************************************************
+
unsigned BinInterface::allocnodeshuffles(int s, fvector<shufflepair> * shuffles)
{
- int idx = itable.size();
- instruction * instr = (instruction *)alloca->alloc(sizeof(instruction));
- instr->flags = IF_REGSHUFFLE;
- instr->regshuffle.shuffles = shuffles;
-
- instr->self = idx;
- itable.push_back(instr);
- insert_instr(end(s), instr);
- return idx;
+ int idx = itable.size();
+ instruction * instr = (instruction *)alloca->alloc(sizeof(instruction));
+ instr->flags = IF_REGSHUFFLE;
+ instr->regshuffle.shuffles = shuffles;
+
+ instr->self = idx;
+ itable.push_back(instr);
+ insert_instr(end(s), instr);
+ return idx;
}
+//*****************************************************************************
+// insert(unsigned section, unsigned *ibegin, unsigned *iend)
+//
+// Queues an contiguous series of instructions for insertion upon
+// completion of the complete() function
+//
+// NOTE: just like iterations iend is the first address NOT to insert.
+//
+//*****************************************************************************
-unsigned BinInterface::insert(unsigned section, unsigned *ibegin, unsigned * iend) {
- insertion i;
- i.begin = ibegin;
- i.end = iend;
- i.section = section;
- i.idstart = itable.size();
+unsigned BinInterface::insert(unsigned section,
+ unsigned *ibegin, unsigned * iend)
+{
+ // you're not allowed to have machine instructions
+ // INITIALLY in the epilogs
+ assert(section==SECTION_TRACE || section==SECTION_PROLOG);
+
+ insertion i;
+ i.begin = ibegin;
+ i.end = iend;
+ i.section = section;
+ i.idstart = itable.size();
- itable.inc(iend - ibegin);
- queue.push_back(i);
+ itable.inc(iend - ibegin);
+ queue.push_back(i);
- return i.idstart;
+ return i.idstart;
}
+//*****************************************************************************
+// clear()
+//
+// Reset the state of the binary interface so that we may compile a new
+// trace (Very fast)
+//
+//*****************************************************************************
+
void BinInterface::clear()
{
- itable.clear();
- sections.clear();
- queue.clear();
- livein.clear();
- alloca->clear();
- // create prolog and trace link nodes
- push_section();
- push_section();
+ itable.clear();
+ sections.clear();
+ queue.clear();
+ livein.clear();
+ alloca->clear();
+ // create prolog and trace link nodes
+ push_section();
+ push_section();
}
+//*****************************************************************************
+// ~BinInterface()
+//
+// The only memory that we don't manage in our allocator is the heap block
+// itself. Thus the only object that needs destroyed
+//
+//*****************************************************************************
+BinInterface::~BinInterface()
+{
+ delete alloca;
+}
Index: llvm/lib/Reoptimizer/BinInterface/sparcbin.h
diff -u llvm/lib/Reoptimizer/BinInterface/sparcbin.h:1.2 llvm/lib/Reoptimizer/BinInterface/sparcbin.h:1.3
--- llvm/lib/Reoptimizer/BinInterface/sparcbin.h:1.2 Sat Dec 14 19:32:13 2002
+++ llvm/lib/Reoptimizer/BinInterface/sparcbin.h Sun Dec 15 05:07:41 2002
@@ -22,147 +22,168 @@
struct regalloc;
struct shufflepair;
+
static const unsigned SECTION_PROLOG =0;
static const unsigned SECTION_TRACE =1;
class BinInterface
{
-private:
+ private:
+
+ Allocator * alloca; // primary stack allocator
+ fvector<instruction *> itable; // maps an unsigned ID
+ // to an instruction
+
+ fvector<unsigned> sections;
+ fvector<unsigned> livein; // pointers to all livein nodes
+
+ // make SURE instr has already has its SELF index
+ // assigned!
+ void insert_instr(unsigned instr_id, instruction * instr);
+ void push_section();
+
+
+ // insertions are delayed to facilitate branch analysis
+ struct insertion
+ {
+ unsigned * begin;
+ unsigned * end;
+ unsigned section;
+ unsigned idstart;
+ };
+
+ void process_branch(const insertion & i,
+ unsigned ** brdest, int scns);
+
+ void construct_merge(int s, int brdest, unsigned map[32],
+ fvector<unsigned[32]> & regmaps);
+
+ void process_section(unsigned s, unsigned map[32],
+ fvector<unsigned[32]> & regmaps);
+
+ void process_markgen(unsigned s, unsigned map[32]);
+
+
+ fvector<insertion> queue;
+ instruction * allocphi();
+
+ // returns itable index for new live in node
+ unsigned allocnodelivein(int s, int reg);
+ unsigned allocnodeshuffles(int s, fvector<shufflepair> * shuffles);
+ int spill_load(int vreg, regmask32 & rmask,
+ const int memspills[32], int & freereg,
+ int spills[3], int & spill_cnt,
+ unsigned * & out);
+
+ void select(regalloc & regs);
+
+ int spillreg(int spillloc, unsigned * & out,
+ fvector<vreginfo> & vregs, regmask & freeregs,
+ unsigned hwregs[32]);
+
+
+ void prepare_exit(const regalloc & regalloc,
+ fvector<shufflepair> * mod,
+ unsigned * & out);
+
+ unsigned emit_gen(unsigned char * out, const regalloc & regs);
+
+
+ public:
+
+
+ // Call newepilog() to get the ID of a new epilog section
+ unsigned newepilog();
+ // IDs of prolog and trace sections
+
+ // initial instruction block insertion. specify section number
+ // and iterator to machine instructions
+ // (iend is the first instruction not to insert)
+ unsigned insert(unsigned section, unsigned *ibegin, unsigned * iend);
+
+ // Returns the ID of the first instruction in the section
+ unsigned begin(unsigned sectionid)
+ { return (itable[sections[sectionid]])->next; }
+ // Returns the ID to stop iterating on (header node)
+ unsigned end (unsigned sectionid)
+ { return sections[sectionid]; }
+
+ // Find predecessor/sucessor of instructions
+ unsigned next(unsigned t)
+ { return itable[t]->next; }
+
+ unsigned prev(unsigned t)
+ { return itable[t]->prev; }
+
+ // Delete any instruction by instruction ID
+ void remove(unsigned);
+
+ // Move instruction mbegin and stopping before mend to directly after
+ // an instruction. (mbegin and mend do not point to consecutive
+ // instruction numbers)
+ void move(unsigned mbegin, unsigned mend, unsigned after_this);
+
+ // Swap the locations of 2 instructions
+ void swap(unsigned a, unsigned b);
+
+ // Get the opcode associated with a given instruction
+ unsigned getopcode(unsigned);
+
+ // Query to get the RS1/RS2/CC0 generation information. Returns
+ // the instruction it is getting the result from. Make
+ // SURE the instruction is not a branch or PHI node or else
+ // these results will be gibberish
+ unsigned getrs1(unsigned);
+ unsigned getrs2(unsigned);
+ unsigned getcc0(unsigned);
+
+
+
+ // Instructions exist outside of any section when created
+ // you must place them using 'move'!
+
+ // New relative branch, destination is an instruction ID (returns
+ // branch instruction ID)
+ unsigned newbranch(unsigned op, unsigned dest);
+
+ // New absolute address branch
+ unsigned newabsbranch(unsigned op, void * dest);
+
+ // General operation generation
+ unsigned newalu (unsigned op, unsigned rs1, unsigned rs2);
+ unsigned newalucc(unsigned op, unsigned rs1, unsigned rs2, unsigned cc0);
+
+ // Must be called before any manipulations ->
+ // this translates the instruction insert with 'insert'
+ // into SSA form
+
+ // The liveout is a mask of registers that are live out
+ // if you want to make it assume all registers are pot
+ // live out -> pass in 0xFFFFFFFE (reg 0 cannot be liveout)
+ void reduce();
+ void complete();
+ void liveout(unsigned live);
+
+
+ // Predicts size (within a power of 2) of neccesary code
+ // buffer
+ unsigned predict();
+
+ // Emit code into user specified buffer
+ unsigned emit(unsigned char * out);
- Allocator *alloca; // primary stack allocator
- fvector<instruction *> itable; // maps an unsigned ID
- // to an instruction
-
- fvector<unsigned> sections;
- fvector<unsigned> livein; // pointers to all livein nodes
-
- // make SURE instr has already has its SELF index
- // assigned!
- void insert_instr(unsigned instr_id, instruction * instr);
- void push_section();
-
-
- // insertions are delayed to facilitate branch analysis
-
- struct insertion
- {
- unsigned * begin;
- unsigned * end;
- unsigned section;
- unsigned idstart;
- };
-
- void process_branch(const insertion & i, unsigned ** brdest, int scns);
- void process_section(unsigned s, unsigned map[32],fvector<unsigned[32]> & regmaps);
- void process_markgen(unsigned s, unsigned map[32],fvector<unsigned[32]> & regmaps);
-
-
- fvector<insertion> queue;
- instruction * allocphi();
-
- // returns itable index for new live in node
- unsigned allocnodelivein(int s, int reg);
- unsigned allocnodeshuffles(int s, fvector<shufflepair> * shuffles);
- int spill_load(int vreg, regmask32 & rmask,const int memspills[32], int & freereg, int spills[3], int & spill_cnt, unsigned * & out);
- void select(regalloc & regs);
-
- int spillreg(int spillloc, unsigned * & out, fvector<vreginfo> & vregs, regmask & freeregs, unsigned hwregs[32]);
-
-
- void prepare_exit(const regalloc & regalloc, fvector<shufflepair> * mod, unsigned * & out);
- unsigned emit_gen(unsigned char * out, const regalloc & regs);
-
-
-public:
-
-
- // Call newepilog() to get the ID of a new epilog section
- unsigned newepilog();
- // IDs of prolog and trace sections
-
- // initial instruction block insertion. specify section number
- // and iterator to machine instructions
- // (iend is the first instruction not to insert)
- unsigned insert(unsigned section, unsigned *ibegin, unsigned * iend);
-
- // Returns the ID of the first instruction in the section
- unsigned begin(unsigned sectionid) { return (itable[sections[sectionid]])->next; }
- // Returns the ID to stop iterating on (header node)
- unsigned end (unsigned sectionid) { return sections[sectionid]; }
-
- // Find predecessor/sucessor of instructions
- unsigned next(unsigned t) { return itable[t]->next; }
- unsigned prev(unsigned t) { return itable[t]->prev; }
-
- // Delete any instruction by instruction ID
- void remove(unsigned);
-
- // Move instruction mbegin and stopping before mend to directly after
- // an instruction. (mbegin and mend do not point to consecutive
- // instruction numbers)
- void move(unsigned mbegin, unsigned mend, unsigned after_this);
-
- // Swap the locations of 2 instructions
- void swap(unsigned a, unsigned b);
-
- // Get the opcode associated with a given instruction
- unsigned getopcode(unsigned);
-
- // Query to get the RS1/RS2/CC0 generation information. Returns
- // the instruction it is getting the result from. Make
- // SURE the instruction is not a branch or PHI node or else
- // these results will be gibberish
- unsigned getrs1(unsigned);
- unsigned getrs2(unsigned);
- unsigned getcc0(unsigned);
-
-
-
- // Instructions exist outside of any section when created
- // you must place them using 'move'!
-
- // New relative branch, destination is an instruction ID (returns
- // branch instruction ID)
- unsigned newbranch(unsigned op, unsigned dest);
-
- // New absolute address branch
- unsigned newabsbranch(unsigned op, void * dest);
-
- // General operation generation
- unsigned newalu (unsigned op, unsigned rs1, unsigned rs2);
- unsigned newalucc (unsigned op, unsigned rs1, unsigned rs2, unsigned cc0);
-
- // Must be called before any manipulations ->
- // this translates the instruction insert with 'insert'
- // into SSA form
-
- // The liveout is a mask of registers that are live out
- // if you want to make it assume all registers are pot
- // live out -> pass in 0xFFFFFFFE (reg 0 cannot be liveout)
- void reduce();
- void complete();
- void liveout(unsigned live);
-
-
- // Predicts size (within a power of 2) of neccesary code
- // buffer
- unsigned predict();
-
- // Emit code into user specified buffer
- unsigned emit(unsigned char * out);
-
- // Debug printing
- void print();
- void print(unsigned scn);
+ // Debug printing
+ void print();
+ void print(unsigned scn);
- // Use to reset for a second pass (internally stack allocation is used)
- void clear();
+ // Use to reset for a second pass (internally stack allocation is used)
+ void clear();
-
- BinInterface(unsigned instr_count);
+ BinInterface(unsigned heapsize);
+ ~BinInterface();
};
#endif
Index: llvm/lib/Reoptimizer/BinInterface/sparcdis.cpp
diff -u llvm/lib/Reoptimizer/BinInterface/sparcdis.cpp:1.5 llvm/lib/Reoptimizer/BinInterface/sparcdis.cpp:1.6
--- llvm/lib/Reoptimizer/BinInterface/sparcdis.cpp:1.5 Sat Dec 14 19:32:14 2002
+++ llvm/lib/Reoptimizer/BinInterface/sparcdis.cpp Sun Dec 15 05:07:42 2002
@@ -1,5 +1,5 @@
//*****************************************************************************
-// SPARC Instruction Disassembler
+// SPARC Instruction Disassembler
//
// Disassembler API Header
//
@@ -28,619 +28,686 @@
void sparc_printop_rs1(unsigned instr, int labelrs1)
{
- if (labelrs1)
- printf("l%d", labelrs1);
- else
- printf("%s", reg_names[RD_FLD(instr, INSTR_RS1)]);
+ if (labelrs1)
+ printf("l%d", labelrs1);
+ else
+ printf("%s", reg_names[RD_FLD(instr, INSTR_RS1)]);
}
void sparc_printop_rs2(unsigned instr, int labelrs2)
{
- if (labelrs2)
- printf("l%d", labelrs2);
- else
- printf("%s", reg_names[RD_FLD(instr, INSTR_RS2)]);
+ if (labelrs2)
+ printf("l%d", labelrs2);
+ else
+ printf("%s", reg_names[RD_FLD(instr, INSTR_RS2)]);
}
void sparc_printop_rrd(unsigned instr, int labelrrd)
{
- if (labelrrd)
- printf("l%d", labelrrd);
- else
- printf("%s", reg_names[RD_FLD(instr, INSTR_RD)]);
+ if (labelrrd)
+ printf("l%d", labelrrd);
+ else
+ printf("%s", reg_names[RD_FLD(instr, INSTR_RD)]);
}
void sparc_printbr(unsigned instr, bool labels, int labelrs1, int labelrs2, int labelrd, int labelccf)
{
- // look at the OP2 field
- if (RD_FLD(instr,INSTR_OP2)==OP2_ILLTRAP)
- printf("ILLTRAP");
- else if (RD_FLD(instr, INSTR_OP2)==OP2_SETHI)
- {
- if (RD_FLD(instr, INSTR_RD) == 0)
- printf("NOP");
- else
- {
- printf("SETHI %%hi(%08X), ", RD_FLD(instr, INSTR_IMM22) << 10);
- sparc_printop_rrd(instr, labelrd);
- }
- }
- else if (RD_FLD(instr, INSTR_OP2)==OP2_BICC)
- {
- printf("b%s disp:%08X",icond_names[RD_FLD(instr, INSTR_COND_H)], SIGN_EXTEND(RD_FLD(instr,INSTR_DISP22),22));
- }
- else if (RD_FLD(instr, INSTR_OP2)==OP2_BPR)
- {
- //A, RCOND_H, D16HI, P, RS1, D16LO
- printf("P%s%s%s ", rcond_names[RD_FLD(instr, INSTR_RCOND_H)],
- RD_FLD(instr, INSTR_A) ? ",a" : "",
- RD_FLD(instr, INSTR_P) ? ",pt" : ",pn");
- sparc_printop_rs1(instr, labelrs1);
- }
- else if (RD_FLD(instr, INSTR_OP2)==OP2_FB)
- {
- // cond, A, disp22
- printf("%s%s %08X", fcond_names[RD_FLD(instr, INSTR_COND_H)],
- RD_FLD(instr, INSTR_A) ? ",a" : "",
- RD_FLD(instr, INSTR_DISP22));
- }
- else{
- printf("Unknown:OP=0b00 OP2 = 0x%04X", RD_FLD(instr, INSTR_OP2));
- assert(0);
- }
-}
-
-void sparc_printalu(char * basename , unsigned instr, bool labels, int labelrs1, int labelrs2, int labelrd, int labelccf)
-{
- // OP=OP_2 : RD, OP3, RS1: {I=0 -> RS2 I=1->SIMM13}
- if (RD_FLD(instr, INSTR_I)==0)
- {
- printf("%s ", basename);
- if (!labels)
- printf("%s, ", reg_names[RD_FLD(instr, INSTR_RD)]);
- sparc_printop_rs1(instr, labelrs1);
- printf(" ,");
- sparc_printop_rs2(instr, labelrs2);
- }
- else
- {
- printf("%s ", basename);
- if (!labels)
- printf("%s, ", reg_names[RD_FLD(instr, INSTR_RD)]);
- sparc_printop_rs1(instr, labelrs1);
- printf(" , %d", SIGN_EXTEND13(RD_FLD(instr, INSTR_SIMM13)));
- }
-}
-
-void sparc_printshf(char * basename, unsigned instr, bool labels, int labelrs1, int labelrs2, int labelrd, int labelccf)
-{
- //OP=OP_2: RD, OP_3 RS1: {I=0 -> X & RS2 ,I=1 -> {X=0 -> SHCNT32 X=1->SHCNT64 }}
- if (RD_FLD(instr, INSTR_I)==0)
- {
- printf("%s%d ", (RD_FLD(instr, INSTR_X)==0 ? 32 : 64));
- if (!labels)
- printf("%s, ", reg_names[RD_FLD(instr, INSTR_RD)]);
-
- sparc_printop_rs1(instr, labelrs1);
- printf(", ");
- sparc_printop_rs2(instr, labelrs2);
- }
- else
- {
- printf("%s%d ", (RD_FLD(instr, INSTR_X)==0 ? 32 : 64));
- if (!labels)
- printf("%s, ", reg_names[RD_FLD(instr, INSTR_RD)]);
-
- sparc_printop_rs1(instr, labelrs1);
- printf(", 0x%04X", (RD_FLD(instr, INSTR_X)==0 ? RD_FLD(instr, INSTR_SHCNT32) : RD_FLD(instr, INSTR_SHCNT64)));
- }
+ // look at the OP2 field
+ if (RD_FLD(instr,INSTR_OP2)==OP2_ILLTRAP)
+ printf("ILLTRAP");
+ else if (RD_FLD(instr, INSTR_OP2)==OP2_SETHI)
+ {
+ if (RD_FLD(instr, INSTR_RD) == 0)
+ printf("NOP");
+ else
+ {
+ printf("SETHI %%hi(%08X), ", RD_FLD(instr, INSTR_IMM22) << 10);
+ sparc_printop_rrd(instr, labelrd);
+ }
+ }
+ else if (RD_FLD(instr, INSTR_OP2)==OP2_BICC)
+ {
+ printf("b%s disp:%08X",icond_names[RD_FLD(instr, INSTR_COND_H)], SIGN_EXTEND(RD_FLD(instr,INSTR_DISP22),22));
+ }
+ else if (RD_FLD(instr, INSTR_OP2)==OP2_BPR)
+ {
+ //A, RCOND_H, D16HI, P, RS1, D16LO
+ printf("P%s%s%s ", rcond_names[RD_FLD(instr, INSTR_RCOND_H)],
+ RD_FLD(instr, INSTR_A) ? ",a" : "",
+ RD_FLD(instr, INSTR_P) ? ",pt" : ",pn");
+ sparc_printop_rs1(instr, labelrs1);
+ }
+ else if (RD_FLD(instr, INSTR_OP2)==OP2_FB)
+ {
+ // cond, A, disp22
+ printf("%s%s %08X", fcond_names[RD_FLD(instr, INSTR_COND_H)],
+ RD_FLD(instr, INSTR_A) ? ",a" : "",
+ RD_FLD(instr, INSTR_DISP22));
+ }
+ else{
+ printf("Unknown:OP=0b00 OP2 = 0x%04X", RD_FLD(instr, INSTR_OP2));
+ assert(0);
+ }
+}
+
+void sparc_printalu(char * basename , unsigned instr, bool labels,
+ int labelrs1, int labelrs2, int labelrd, int labelccf)
+{
+ // OP=OP_2 : RD, OP3, RS1: {I=0 -> RS2 I=1->SIMM13}
+ if (RD_FLD(instr, INSTR_I)==0)
+ {
+ printf("%s ", basename);
+ if (!labels)
+ printf("%s, ", reg_names[RD_FLD(instr, INSTR_RD)]);
+ sparc_printop_rs1(instr, labelrs1);
+ printf(" ,");
+ sparc_printop_rs2(instr, labelrs2);
+ }
+ else
+ {
+ printf("%s ", basename);
+ if (!labels)
+ printf("%s, ", reg_names[RD_FLD(instr, INSTR_RD)]);
+ sparc_printop_rs1(instr, labelrs1);
+ printf(" , %d", SIGN_EXTEND13(RD_FLD(instr, INSTR_SIMM13)));
+ }
+}
+
+void sparc_printshf(char * basename, unsigned instr, bool labels,
+ int labelrs1, int labelrs2, int labelrd, int labelccf)
+{
+ //OP=OP_2: RD, OP_3 RS1: {I=0 -> X & RS2 ,I=1 ->
+ // {X=0 -> SHCNT32 X=1->SHCNT64 }}
+ if (RD_FLD(instr, INSTR_I)==0)
+ {
+ printf("%s%d ", (RD_FLD(instr, INSTR_X)==0 ? 32 : 64));
+ if (!labels)
+ printf("%s, ", reg_names[RD_FLD(instr, INSTR_RD)]);
+
+ sparc_printop_rs1(instr, labelrs1);
+ printf(", ");
+ sparc_printop_rs2(instr, labelrs2);
+ }
+ else
+ {
+ printf("%s%d ", (RD_FLD(instr, INSTR_X)==0 ? 32 : 64));
+ if (!labels)
+ printf("%s, ", reg_names[RD_FLD(instr, INSTR_RD)]);
+
+ sparc_printop_rs1(instr, labelrs1);
+ printf(", 0x%04X", (RD_FLD(instr, INSTR_X)==0
+ ? RD_FLD(instr, INSTR_SHCNT32)
+ : RD_FLD(instr, INSTR_SHCNT64)));
+ }
}
// Op2 class instructions
-void sparc_printfpu(unsigned instr, bool labels, int labelrs1, int labelrs2, int labelrd, int labelccf)
+void sparc_printfpu(unsigned instr, bool labels, int labelrs1, int labelrs2,
+ int labelrd, int labelccf)
{
- switch(RD_FLD(instr, INSTR_OPF) &~ OPF_MASK_ON)
- {
- case OPF_FADDn:
- printf("FADDn");
- return;
- case OPF_FSUBn:
- printf("FSUBn");
- return;
- case OPF_FMOVn:
- printf("FMOVn");
- return;
- case OPF_FNEGn:
- printf("FNEGn");
- return;
- case OPF_FABSn:
- printf("FABSn");
- return;
- case OPF_FMULn:
- printf("FMULn");
- return;
- case OPF_FDIVn:
- printf("FDIVn");
- return;
- case OPF_FSQRTn:
- printf("FSQRTn");
- return;
- }
- switch (RD_FLD(instr, INSTR_OPF) &~OPF_MASK_TO)
- {
- case OPF_FxTOt:
- printf("FxTOt");
- return;
- case OPF_FiTOt:
- printf("FiTOt");
- return;
- }
-
- switch(RD_FLD(instr, INSTR_OPF))
- {
- case OPF_FsTOx:
- printf("OPF_FsTOx");
- return;
- case OPF_FsTOi:
- printf("OPF_FsTOi");
- return;
- case OPF_FsTOd:
- printf("OPF_FsTOd");
- return;
- case OPF_FsTOq:
- printf("OPF_FsTOq");
- return;
- case OPF_FdTOx:
- printf("OPF_FdTOx");
- return;
- case OPF_FdTOi:
- printf("OPF_FdTOi");
- return;
- case OPF_FqTOx:
- printf("OPF_FqTOx");
- return;
- case OPF_FdTOs:
- printf("OPF_FdTOs");
- return;
- case OPF_FdTOq:
- printf("OPF_FdTOq");
- return;
- case OPF_FqTOi:
- printf("OPF_FqTOi");
- return;
- case OPF_FqTOs:
- printf("OPF_FqTOs");
- return;
- case OPF_FqTOd:
- printf("OPF_FqTOd");
- return;
- case OPF_FsMULd:
- printf("OPF_FsMULd");
- return;
- case OPF_FdMULq:
- printf("OPF_FdMULq");
- return;
- }
-
- assert(0); // we don't know the FPU instruction yet
-}
-
-void sparc_print2(unsigned instr, bool labels, int labelrs1, int labelrs2, int labelrd, int labelccf)
-{
- switch(RD_FLD(instr, INSTR_OP3))
- {
-
- case OP3_MOVcc:
- {
- printf("mov%s(%s) ", icond_names[RD_FLD(instr, INSTR_COND_L)],
- cc_names[(RD_FLD(instr, INSTR_CC2) << 2) | (RD_FLD(instr, INSTR_MOV_CC1) << 1) | RD_FLD(instr, INSTR_MOV_CC0)]);
-
- if (!labels)
+ switch(RD_FLD(instr, INSTR_OPF) &~ OPF_MASK_ON)
+ {
+ case OPF_FADDn:
+ printf("FADDn");
+ return;
+ case OPF_FSUBn:
+ printf("FSUBn");
+ return;
+ case OPF_FMOVn:
+ printf("FMOVn");
+ return;
+ case OPF_FNEGn:
+ printf("FNEGn");
+ return;
+ case OPF_FABSn:
+ printf("FABSn");
+ return;
+ case OPF_FMULn:
+ printf("FMULn");
+ return;
+ case OPF_FDIVn:
+ printf("FDIVn");
+ return;
+ case OPF_FSQRTn:
+ printf("FSQRTn");
+ return;
+ }
+ switch (RD_FLD(instr, INSTR_OPF) &~OPF_MASK_TO)
+ {
+ case OPF_FxTOt:
+ printf("FxTOt");
+ return;
+ case OPF_FiTOt:
+ printf("FiTOt");
+ return;
+ }
+
+ switch(RD_FLD(instr, INSTR_OPF))
+ {
+ case OPF_FsTOx:
+ printf("OPF_FsTOx");
+ return;
+ case OPF_FsTOi:
+ printf("OPF_FsTOi");
+ return;
+ case OPF_FsTOd:
+ printf("OPF_FsTOd");
+ return;
+ case OPF_FsTOq:
+ printf("OPF_FsTOq");
+ return;
+ case OPF_FdTOx:
+ printf("OPF_FdTOx");
+ return;
+ case OPF_FdTOi:
+ printf("OPF_FdTOi");
+ return;
+ case OPF_FqTOx:
+ printf("OPF_FqTOx");
+ return;
+ case OPF_FdTOs:
+ printf("OPF_FdTOs");
+ return;
+ case OPF_FdTOq:
+ printf("OPF_FdTOq");
+ return;
+ case OPF_FqTOi:
+ printf("OPF_FqTOi");
+ return;
+ case OPF_FqTOs:
+ printf("OPF_FqTOs");
+ return;
+ case OPF_FqTOd:
+ printf("OPF_FqTOd");
+ return;
+ case OPF_FsMULd:
+ printf("OPF_FsMULd");
+ return;
+ case OPF_FdMULq:
+ printf("OPF_FdMULq");
+ return;
+ }
+
+ assert(0); // we don't know the FPU instruction yet
+}
+
+void sparc_print2(unsigned instr, bool labels, int labelrs1, int labelrs2,
+ int labelrd, int labelccf)
+{
+ switch(RD_FLD(instr, INSTR_OP3))
+ {
+
+ case OP3_MOVcc:
+ {
+ printf("mov%s(%s) ", icond_names[RD_FLD(instr, INSTR_COND_L)],
+ cc_names[(RD_FLD(instr, INSTR_CC2) << 2) | (RD_FLD(instr, INSTR_MOV_CC1) << 1) | RD_FLD(instr, INSTR_MOV_CC0)]);
+
+ if (!labels)
printf("%s, ", reg_names[RD_FLD(instr, INSTR_RD)]);
-
- if (RD_FLD(instr, INSTR_I)==0) // RS2
+
+ if (RD_FLD(instr, INSTR_I)==0) // RS2
sparc_printop_rs2(instr, labelrs2);
- else
- printf("%d", SIGN_EXTEND(RD_FLD(instr, INSTR_SIMM11), 11));
-
-
- return;
- }
-
-
- case OP3_ADD:
- sparc_printalu("ADD", instr, labels, labelrs1, labelrs2, labelrd, labelccf);
- return;
-
- case OP3_ADDcc:
- sparc_printalu("ADDcc", instr, labels, labelrs1, labelrs2, labelrd, labelccf);
- return;
-
- case OP3_ADDC:
- sparc_printalu("ADDC", instr, labels, labelrs1, labelrs2, labelrd, labelccf);
- return;
-
- case OP3_ADDCcc:
- sparc_printalu("ADDCcc", instr, labels, labelrs1, labelrs2, labelrd, labelccf);
- return;
-
- case OP3_AND:
- sparc_printalu("AND", instr, labels, labelrs1, labelrs2, labelrd, labelccf);
- return;
-
- case OP3_ANDcc:
- sparc_printalu("ANDcc", instr, labels, labelrs1, labelrs2, labelrd, labelccf);
- return;
-
- case OP3_OR:
- sparc_printalu("OR", instr, labels, labelrs1, labelrs2, labelrd, labelccf);
- return;
-
- case OP3_ORcc:
- sparc_printalu("ORcc", instr, labels, labelrs1, labelrs2, labelrd, labelccf);
- return;
-
- case OP3_XOR:
- sparc_printalu("XOR", instr, labels, labelrs1, labelrs2, labelrd, labelccf);
- return;
-
- case OP3_XORcc:
- sparc_printalu("XORcc", instr, labels, labelrs1, labelrs2, labelrd, labelccf);
- return;
-
- case OP3_SUB:
- sparc_printalu("SUB", instr, labels, labelrs1, labelrs2, labelrd, labelccf);
- return;
-
- case OP3_SUBcc:
- sparc_printalu("SUBcc", instr, labels, labelrs1, labelrs2, labelrd, labelccf);
- return;
-
- case OP3_ANDN:
- sparc_printalu("ANDN", instr, labels, labelrs1, labelrs2, labelrd, labelccf);
- return;
-
- case OP3_ANDNcc:
- sparc_printalu("ANDNcc", instr, labels, labelrs1, labelrs2, labelrd, labelccf);
- return;
-
- case OP3_ORN:
- sparc_printalu("ORN", instr, labels, labelrs1, labelrs2, labelrd, labelccf);
- return;
-
- case OP3_ORNcc:
- sparc_printalu("ORNcc", instr, labels, labelrs1, labelrs2, labelrd, labelccf);
- return;
-
- case OP3_XNOR:
- sparc_printalu("XNOR", instr, labels, labelrs1, labelrs2, labelrd, labelccf);
- return;
-
- case OP3_XNORcc:
- sparc_printalu("XNORcc", instr, labels, labelrs1, labelrs2, labelrd, labelccf);
- return;
-
- case OP3_SUBC:
- sparc_printalu("SUBC", instr, labels, labelrs1, labelrs2, labelrd, labelccf);
- return;
-
- case OP3_SUBCcc:
- sparc_printalu("SUBCcc", instr, labels, labelrs1, labelrs2, labelrd, labelccf);
- return;
-
- case OP3_MULX:
- sparc_printalu("MULX", instr, labels, labelrs1, labelrs2, labelrd, labelccf);
- return;
-
- case OP3_SDIVX:
- sparc_printalu("SDIVX", instr, labels, labelrs1, labelrs2, labelrd, labelccf);
- return;
-
- case OP3_UDIVX:
- sparc_printalu("UDIVX", instr, labels, labelrs1, labelrs2, labelrd, labelccf);
- return;
-
- case OP3_SLL:
- sparc_printshf("SLL",instr, labels, labelrs1, labelrs2, labelrd, labelccf);
- return;
- case OP3_SRL:
- sparc_printshf("SRL",instr, labels, labelrs1, labelrs2, labelrd, labelccf);
- return;
- case OP3_SRA:
- sparc_printshf("SRA",instr, labels, labelrs1, labelrs2, labelrd, labelccf);
- return;
-
- case OP3_DONERETRY:
- {
- if (RD_FLD(instr, INSTR_FCN)==FCN_DONE)
- printf("DONE");
- else if (RD_FLD(instr, INSTR_FCN)==FCN_RETRY)
- printf("RETRY");
- return;
- }
-
- case OP3_FCMP:
- {
- unsigned fop_n =RD_FLD(instr, INSTR_OPF) &~ OPF_MASK_ON;
- if (fop_n==OPF_FCMPn)
- printf("FCMP");
- else if (fop_n==OPF_FCMPEn)
- printf("FCMPE");
- return;
- }
-
- case OP3_FPU:
- sparc_printfpu(instr, labels, labelrs1, labelrs2, labelrd, labelccf);
- return;
-
- case OP3_FLUSH: //OP=OP_2 RS1 {I=0 -> rs2, I=1->simm13}
- printf("OP3_FLUSH");
- return;
- case OP3_FLUSHW: //OP=OP_2 I = 0
- printf("OP3_FLUSHW");
- return;
- case OP3_JMPL: //OP=OP_2 RD, RS1 {I=0-> RS2, I=1->SIMM13}
- if (RD_FLD(instr, INSTR_I)==0)
- {
- printf("jmpl link:");
- sparc_printop_rrd(instr, labelrd);
- printf(", to: ");
- sparc_printop_rs1(instr, labelrs1);
- printf("+");
- sparc_printop_rs2(instr, labelrs2);
- }
- else
- {
- printf("jmpl link:");
- sparc_printop_rrd(instr, labelrd);
- printf(", to: ");
- sparc_printop_rs1(instr, labelrs1);
- printf("+%d",SIGN_EXTEND13(RD_FLD(instr, INSTR_SIMM13)));
- }
- return;
-
- case OP3_POPC:
- printf("POPC ????");
- return;
-
- case OP3_RETURN:
- if (RD_FLD(instr, INSTR_I) == 0)
- {
- printf("return ");
- sparc_printop_rs1(instr, labelrs1);
- printf("+");
- sparc_printop_rs2(instr, labelrs2);
- }
- else
- {
- printf("return ");
- sparc_printop_rs1(instr, labelrs1);
- printf("+%d",SIGN_EXTEND13(RD_FLD(instr, INSTR_SIMM13)));
- }
- return;
-
- case OP3_SAVE:
- if (RD_FLD(instr, INSTR_I) == 0)
- {
- printf("save ");
- sparc_printop_rs1(instr, labelrs1);
- printf(", ");
- sparc_printop_rs2(instr, labelrs2);
- printf(", ");
- sparc_printop_rrd(instr, labelrd);
- }
- else
- {
- printf("save ");
- sparc_printop_rs1(instr, labelrs1);
- printf(", %d, ", SIGN_EXTEND13(RD_FLD(instr, INSTR_SIMM13)));
- sparc_printop_rrd(instr, labelrd);
- }
- return;
-
- case OP3_RESTORE:
- if (RD_FLD(instr, INSTR_I) == 0)
- {
- printf("restore ");
- sparc_printop_rs1(instr, labelrs1);
- printf(", ");
- sparc_printop_rs2(instr, labelrs2);
- printf(", ");
- sparc_printop_rrd(instr, labelrd);
- }
- else
- {
- printf("restore ");
- sparc_printop_rs1(instr, labelrs1);
- printf(", %d, ", SIGN_EXTEND13(RD_FLD(instr, INSTR_SIMM13)));
- sparc_printop_rrd(instr, labelrd);
- }
- return;
-
-
- }
-
- printf("Unknown:OP=0b10 OP3 = 0x%04X", RD_FLD(instr, INSTR_OP3));
- assert(0);
-}
-
-void sparc_printload(char * basename, unsigned instr, bool labels, int labelrs1, int labelrs2, int labelrd , int labelccf)
-{
- if (RD_FLD(instr, INSTR_I)==0)
- {
- printf("%s ", basename);
- if (!labels)
- {
- sparc_printop_rrd(instr, labelrd);
- printf(", ");
- }
- sparc_printop_rs1(instr, labelrs1);
- printf("+");
- sparc_printop_rs2(instr, labelrs2);
- }
- else
- {
- printf("%s ", basename);
- if (!labels)
- {
- sparc_printop_rrd(instr, labelrd);
- printf(", ");
- }
- sparc_printop_rs1(instr, labelrs1);
- printf("+%d", SIGN_EXTEND13(RD_FLD(instr, INSTR_SIMM13)));
- }
-}
-
-void sparc_printstore(char * basename, unsigned instr, bool labels, int labelrs1, int labelrs2, int labelrd , int labelccf)
-{
- if (RD_FLD(instr, INSTR_I)==0)
- {
- printf("%s ", basename);
- sparc_printop_rrd(instr, labelrd);
- printf(", ");
- sparc_printop_rs1(instr, labelrs1);
- printf("+");
- sparc_printop_rs2(instr, labelrs2);
-
- }
- else
- {
- printf("%s ", basename);
- sparc_printop_rrd(instr, labelrd);
- printf(", ");
- sparc_printop_rs1(instr, labelrs1);
- printf("+%d", SIGN_EXTEND13(RD_FLD(instr, INSTR_SIMM13)));
- }
-}
-void sparc_print3(unsigned instr, bool labels, int labelrs1, int labelrs2, int labelrd, int labelccf)
-{
-//#define OP3_LDFA 0b110000 //OP=OP_3 RD, Rs1, {I=0->IMM_ASI, RS2 I=1->SIMM13}
-//#define OP3_LDDFA 0b110011 //OP=OP_3 RD, Rs1, {I=0->IMM_ASI, RS2 I=1->SIMM13}
-//#define OP3_LDQFA 0b110010 //OP=OP_3 RD, Rs1, {I=0->IMM_ASI, RS2 I=1->SIMM13}
-//#define OP3_LDSTUB 0b001101 //OP=OP_3 RD, Rs1 {I=0->RS2, I=1->SIMM13}
-//#define OP3_LDSTUBA 0b011101 //OP=OP_3 RD, RS1 {I=0->RS2, IMM_ASI, I=1->SIMM13}
- switch(RD_FLD(instr, INSTR_OP3))
- {
- //OP=OP_3 RD, Rs1 {I=0->RS2, I=1->SIMM13}
- case OP3_LDSTUB:
- sparc_printload("LDSTUB", instr,labels,labelrs1, labelrs2, labelrd, labelccf);
- return;
-
- case OP3_STB:
- sparc_printstore("STB", instr,labels,labelrs1, labelrs2, labelrd, labelccf);
- return;
-
- case OP3_STH:
- sparc_printstore("STH", instr,labels,labelrs1, labelrs2, labelrd, labelccf);
- return;
-
- case OP3_STW:
- sparc_printstore("STW", instr,labels,labelrs1, labelrs2, labelrd, labelccf);
- return;
-
- case OP3_STX:
- sparc_printstore("STX", instr,labels,labelrs1, labelrs2, labelrd, labelccf);
- return;
-
- case OP3_LDSB:
- sparc_printload("LDSB", instr,labels,labelrs1, labelrs2, labelrd, labelccf);
- return;
-
- case OP3_LDSH:
- sparc_printload("LDSH", instr,labels,labelrs1, labelrs2, labelrd, labelccf);
- return;
-
- case OP3_LDSW:
- sparc_printload("LDSW", instr,labels,labelrs1, labelrs2, labelrd, labelccf);
- return;
-
- case OP3_LDUB:
- sparc_printload("LDUB", instr,labels,labelrs1, labelrs2, labelrd, labelccf);
- return;
-
- case OP3_LDUH:
- sparc_printload("LDUH", instr,labels,labelrs1, labelrs2, labelrd, labelccf);
- return;
-
- case OP3_LDUW:
- sparc_printload("LDUW", instr,labels,labelrs1, labelrs2, labelrd, labelccf);
- return;
-
- case OP3_LDX:
- sparc_printload("LDX", instr,labels,labelrs1, labelrs2, labelrd, labelccf);
- return;
-
- case OP3_CASA:
- if (RD_FLD(instr, INSTR_I)==0)
- {
- if (!labels)
- printf("CASA [r%d] %%%d, r%d, r%d", RD_FLD(instr, INSTR_RS1),RD_FLD(instr, INSTR_IMMASI), RD_FLD(instr, INSTR_RS2), RD_FLD(instr, INSTR_RD));
- else
- printf("CASA [l%d] %%%d, l%d, l%d", labelrs1,RD_FLD(instr, INSTR_IMMASI), labelrs2, labelrd);
- }
- else
- {
- if (!labels)
- printf("CASA [r%d] , r%d, r%d", RD_FLD(instr, INSTR_RS1), RD_FLD(instr, INSTR_RS2), RD_FLD(instr, INSTR_RD));
- else
- printf("CASA [l%d] , l%d, l%d", labelrs1, labelrs2, labelrd);
- }
-
- sparc_printalu("CASA", instr,labels,labelrs1, labelrs2, labelrd, labelccf);
-
- return;
-
- case OP3_CASXA:
- sparc_printalu("CASXA", instr,labels,labelrs1, labelrs2, labelrd, labelccf);
- return;
- case OP3_STFA:
- sparc_printalu("STFA",instr,labels,labelrs1, labelrs2, labelrd, labelccf);
- return;
- case OP3_STDFA:
- sparc_printalu("STDFA",instr,labels,labelrs1, labelrs2, labelrd, labelccf);
- return;
- case OP3_STQFA:
- sparc_printalu("STQFA",instr,labels,labelrs1, labelrs2, labelrd, labelccf);
- return;
-
- case OP3_PREFETCH:
- printf("PREFETCH ??? ");
- return;
-
- case OP3_PREFETCHA:
- printf("PREFETCHA ??? ");
- return;
- }
+ else
+ printf("%d", SIGN_EXTEND(RD_FLD(instr, INSTR_SIMM11), 11));
+
+
+ return;
+ }
+
+
+ case OP3_ADD:
+ sparc_printalu("ADD", instr, labels,
+ labelrs1, labelrs2, labelrd, labelccf);
+ return;
+
+ case OP3_ADDcc:
+ sparc_printalu("ADDcc", instr, labels,
+ labelrs1, labelrs2, labelrd, labelccf);
+ return;
+
+ case OP3_ADDC:
+ sparc_printalu("ADDC", instr, labels,
+ labelrs1, labelrs2, labelrd, labelccf);
+ return;
+
+ case OP3_ADDCcc:
+ sparc_printalu("ADDCcc", instr, labels,
+ labelrs1, labelrs2, labelrd, labelccf);
+ return;
+
+ case OP3_AND:
+ sparc_printalu("AND", instr, labels,
+ labelrs1, labelrs2, labelrd, labelccf);
+ return;
+
+ case OP3_ANDcc:
+ sparc_printalu("ANDcc", instr, labels,
+ labelrs1, labelrs2, labelrd, labelccf);
+ return;
+
+ case OP3_OR:
+ sparc_printalu("OR", instr, labels,
+ labelrs1, labelrs2, labelrd, labelccf);
+ return;
+
+ case OP3_ORcc:
+ sparc_printalu("ORcc", instr, labels,
+ labelrs1, labelrs2, labelrd, labelccf);
+ return;
+
+ case OP3_XOR:
+ sparc_printalu("XOR", instr, labels,
+ labelrs1, labelrs2, labelrd, labelccf);
+ return;
+
+ case OP3_XORcc:
+ sparc_printalu("XORcc", instr, labels,
+ labelrs1, labelrs2, labelrd, labelccf);
+ return;
+
+ case OP3_SUB:
+ sparc_printalu("SUB", instr, labels,
+ labelrs1, labelrs2, labelrd, labelccf);
+ return;
+
+ case OP3_SUBcc:
+ sparc_printalu("SUBcc", instr, labels,
+ labelrs1, labelrs2, labelrd, labelccf);
+ return;
+
+ case OP3_ANDN:
+ sparc_printalu("ANDN", instr, labels,
+ labelrs1, labelrs2, labelrd, labelccf);
+ return;
+
+ case OP3_ANDNcc:
+ sparc_printalu("ANDNcc", instr, labels,
+ labelrs1, labelrs2, labelrd, labelccf);
+ return;
+
+ case OP3_ORN:
+ sparc_printalu("ORN", instr, labels,
+ labelrs1, labelrs2, labelrd, labelccf);
+ return;
+
+ case OP3_ORNcc:
+ sparc_printalu("ORNcc", instr, labels,
+ labelrs1, labelrs2, labelrd, labelccf);
+ return;
+
+ case OP3_XNOR:
+ sparc_printalu("XNOR", instr, labels,
+ labelrs1, labelrs2, labelrd, labelccf);
+ return;
+
+ case OP3_XNORcc:
+ sparc_printalu("XNORcc", instr, labels,
+ labelrs1, labelrs2, labelrd, labelccf);
+ return;
+
+ case OP3_SUBC:
+ sparc_printalu("SUBC", instr, labels,
+ labelrs1, labelrs2, labelrd, labelccf);
+ return;
+
+ case OP3_SUBCcc:
+ sparc_printalu("SUBCcc", instr, labels,
+ labelrs1, labelrs2, labelrd, labelccf);
+ return;
+
+ case OP3_MULX:
+ sparc_printalu("MULX", instr, labels,
+ labelrs1, labelrs2, labelrd, labelccf);
+ return;
+
+ case OP3_SDIVX:
+ sparc_printalu("SDIVX", instr, labels,
+ labelrs1, labelrs2, labelrd, labelccf);
+ return;
+
+ case OP3_UDIVX:
+ sparc_printalu("UDIVX", instr, labels,
+ labelrs1, labelrs2, labelrd, labelccf);
+ return;
+
+ case OP3_SLL:
+ sparc_printshf("SLL",instr, labels,
+ labelrs1, labelrs2, labelrd, labelccf);
+ return;
+ case OP3_SRL:
+ sparc_printshf("SRL",instr, labels,
+ labelrs1, labelrs2, labelrd, labelccf);
+ return;
+ case OP3_SRA:
+ sparc_printshf("SRA",instr, labels,
+ labelrs1, labelrs2, labelrd, labelccf);
+ return;
+
+ case OP3_DONERETRY:
+ {
+ if (RD_FLD(instr, INSTR_FCN)==FCN_DONE)
+ printf("DONE");
+ else if (RD_FLD(instr, INSTR_FCN)==FCN_RETRY)
+ printf("RETRY");
+ return;
+ }
+
+ case OP3_FCMP:
+ {
+ unsigned fop_n =RD_FLD(instr, INSTR_OPF) &~ OPF_MASK_ON;
+ if (fop_n==OPF_FCMPn)
+ printf("FCMP");
+ else if (fop_n==OPF_FCMPEn)
+ printf("FCMPE");
+ return;
+ }
+
+ case OP3_FPU:
+ sparc_printfpu(instr, labels, labelrs1, labelrs2, labelrd, labelccf);
+ return;
+
+ case OP3_FLUSH: //OP=OP_2 RS1 {I=0 -> rs2, I=1->simm13}
+ printf("OP3_FLUSH");
+ return;
+ case OP3_FLUSHW: //OP=OP_2 I = 0
+ printf("OP3_FLUSHW");
+ return;
+ case OP3_JMPL: //OP=OP_2 RD, RS1 {I=0-> RS2, I=1->SIMM13}
+ if (RD_FLD(instr, INSTR_I)==0)
+ {
+ printf("jmpl link:");
+ sparc_printop_rrd(instr, labelrd);
+ printf(", to: ");
+ sparc_printop_rs1(instr, labelrs1);
+ printf("+");
+ sparc_printop_rs2(instr, labelrs2);
+ }
+ else
+ {
+ printf("jmpl link:");
+ sparc_printop_rrd(instr, labelrd);
+ printf(", to: ");
+ sparc_printop_rs1(instr, labelrs1);
+ printf("+%d",SIGN_EXTEND13(RD_FLD(instr, INSTR_SIMM13)));
+ }
+ return;
+
+ case OP3_POPC:
+ printf("POPC ????");
+ return;
+
+ case OP3_RETURN:
+ if (RD_FLD(instr, INSTR_I) == 0)
+ {
+ printf("return ");
+ sparc_printop_rs1(instr, labelrs1);
+ printf("+");
+ sparc_printop_rs2(instr, labelrs2);
+ }
+ else
+ {
+ printf("return ");
+ sparc_printop_rs1(instr, labelrs1);
+ printf("+%d",SIGN_EXTEND13(RD_FLD(instr, INSTR_SIMM13)));
+ }
+ return;
+
+ case OP3_SAVE:
+ if (RD_FLD(instr, INSTR_I) == 0)
+ {
+ printf("save ");
+ sparc_printop_rs1(instr, labelrs1);
+ printf(", ");
+ sparc_printop_rs2(instr, labelrs2);
+ printf(", ");
+ sparc_printop_rrd(instr, labelrd);
+ }
+ else
+ {
+ printf("save ");
+ sparc_printop_rs1(instr, labelrs1);
+ printf(", %d, ", SIGN_EXTEND13(RD_FLD(instr, INSTR_SIMM13)));
+ sparc_printop_rrd(instr, labelrd);
+ }
+ return;
+
+ case OP3_RESTORE:
+ if (RD_FLD(instr, INSTR_I) == 0)
+ {
+ printf("restore ");
+ sparc_printop_rs1(instr, labelrs1);
+ printf(", ");
+ sparc_printop_rs2(instr, labelrs2);
+ printf(", ");
+ sparc_printop_rrd(instr, labelrd);
+ }
+ else
+ {
+ printf("restore ");
+ sparc_printop_rs1(instr, labelrs1);
+ printf(", %d, ", SIGN_EXTEND13(RD_FLD(instr, INSTR_SIMM13)));
+ sparc_printop_rrd(instr, labelrd);
+ }
+ return;
+
+
+ }
+
+ printf("Unknown:OP=0b10 OP3 = 0x%04X", RD_FLD(instr, INSTR_OP3));
+ assert(0);
+}
+
+void sparc_printload(char * basename, unsigned instr, bool labels,
+ int labelrs1, int labelrs2, int labelrd , int labelccf)
+{
+ if (RD_FLD(instr, INSTR_I)==0)
+ {
+ printf("%s ", basename);
+ if (!labels)
+ {
+ sparc_printop_rrd(instr, labelrd);
+ printf(", ");
+ }
+ sparc_printop_rs1(instr, labelrs1);
+ printf("+");
+ sparc_printop_rs2(instr, labelrs2);
+ }
+ else
+ {
+ printf("%s ", basename);
+ if (!labels)
+ {
+ sparc_printop_rrd(instr, labelrd);
+ printf(", ");
+ }
+ sparc_printop_rs1(instr, labelrs1);
+ printf("+%d", SIGN_EXTEND13(RD_FLD(instr, INSTR_SIMM13)));
+ }
+}
+
+void sparc_printstore(char * basename, unsigned instr, bool labels,
+ int labelrs1, int labelrs2, int labelrd , int labelccf)
+{
+ if (RD_FLD(instr, INSTR_I)==0)
+ {
+ printf("%s ", basename);
+ sparc_printop_rrd(instr, labelrd);
+ printf(", ");
+ sparc_printop_rs1(instr, labelrs1);
+ printf("+");
+ sparc_printop_rs2(instr, labelrs2);
+
+ }
+ else
+ {
+ printf("%s ", basename);
+ sparc_printop_rrd(instr, labelrd);
+ printf(", ");
+ sparc_printop_rs1(instr, labelrs1);
+ printf("+%d", SIGN_EXTEND13(RD_FLD(instr, INSTR_SIMM13)));
+ }
+}
+void sparc_print3(unsigned instr, bool labels, int labelrs1, int labelrs2,
+ int labelrd, int labelccf)
+{
+ // OP3_LDF OP=OP_3 RD, Rs1, {I=0->IMM_ASI, RS2 I=1->SIMM13}
+ // OP3_LDDFA OP=OP_3 RD, Rs1, {I=0->IMM_ASI, RS2 I=1->SIMM13}
+ // OP3_LDQFA OP=OP_3 RD, Rs1, {I=0->IMM_ASI, RS2 I=1->SIMM13}
+ // OP3_LDSTUB OP=OP_3 RD, Rs1 {I=0->RS2, I=1->SIMM13}
+ // OP3_LDSTUBA OP=OP_3 RD, RS1 {I=0->RS2, IMM_ASI, I=1->SIMM13}
+
+
+ switch(RD_FLD(instr, INSTR_OP3))
+ {
+ //OP=OP_3 RD, Rs1 {I=0->RS2, I=1->SIMM13}
+ case OP3_LDSTUB:
+ sparc_printload("LDSTUB", instr,labels,
+ labelrs1, labelrs2, labelrd, labelccf);
+ return;
+
+ case OP3_STB:
+ sparc_printstore("STB", instr,labels,
+ labelrs1, labelrs2, labelrd, labelccf);
+ return;
+
+ case OP3_STH:
+ sparc_printstore("STH", instr,labels,
+ labelrs1, labelrs2, labelrd, labelccf);
+ return;
+
+ case OP3_STW:
+ sparc_printstore("STW", instr,labels,
+ labelrs1, labelrs2, labelrd, labelccf);
+ return;
+
+ case OP3_STX:
+ sparc_printstore("STX", instr,labels,
+ labelrs1, labelrs2, labelrd, labelccf);
+ return;
+
+ case OP3_LDSB:
+ sparc_printload("LDSB", instr,labels,
+ labelrs1, labelrs2, labelrd, labelccf);
+ return;
+
+ case OP3_LDSH:
+ sparc_printload("LDSH", instr,labels,
+ labelrs1, labelrs2, labelrd, labelccf);
+ return;
+
+ case OP3_LDSW:
+ sparc_printload("LDSW", instr,labels,
+ labelrs1, labelrs2, labelrd, labelccf);
+ return;
+
+ case OP3_LDUB:
+ sparc_printload("LDUB", instr,labels,
+ labelrs1, labelrs2, labelrd, labelccf);
+ return;
+
+ case OP3_LDUH:
+ sparc_printload("LDUH", instr,labels,
+ labelrs1, labelrs2, labelrd, labelccf);
+ return;
+
+ case OP3_LDUW:
+ sparc_printload("LDUW", instr,labels,
+ labelrs1, labelrs2, labelrd, labelccf);
+ return;
+
+ case OP3_LDX:
+ sparc_printload("LDX", instr,labels,
+ labelrs1, labelrs2, labelrd, labelccf);
+ return;
+
+ case OP3_CASA:
+ if (RD_FLD(instr, INSTR_I)==0)
+ {
+ if (!labels)
+ printf("CASA [r%d] %%%d, r%d, r%d",
+ RD_FLD(instr, INSTR_RS1),
+ RD_FLD(instr, INSTR_IMMASI),
+ RD_FLD(instr, INSTR_RS2),
+ RD_FLD(instr, INSTR_RD));
+
+ else
+ printf("CASA [l%d] %%%d, l%d, l%d",
+ labelrs1,
+ RD_FLD(instr, INSTR_IMMASI),
+ labelrs2,
+ labelrd);
+ }
+ else
+ {
+ if (!labels)
+ printf("CASA [r%d] , r%d, r%d",
+ RD_FLD(instr, INSTR_RS1),
+ RD_FLD(instr, INSTR_RS2),
+ RD_FLD(instr, INSTR_RD));
+ else
+ printf("CASA [l%d] , l%d, l%d", labelrs1, labelrs2, labelrd);
+ }
+
+ sparc_printalu("CASA", instr,labels,
+ labelrs1, labelrs2, labelrd, labelccf);
+
+ return;
+
+ case OP3_CASXA:
+ sparc_printalu("CASXA", instr,labels,
+ labelrs1, labelrs2, labelrd, labelccf);
+ return;
+ case OP3_STFA:
+ sparc_printalu("STFA",instr,labels,
+ labelrs1, labelrs2, labelrd, labelccf);
+ return;
+ case OP3_STDFA:
+ sparc_printalu("STDFA",instr,labels,
+ labelrs1, labelrs2, labelrd, labelccf);
+ return;
+ case OP3_STQFA:
+ sparc_printalu("STQFA",instr,labels,
+ labelrs1, labelrs2, labelrd, labelccf);
+ return;
+
+ case OP3_PREFETCH:
+ printf("PREFETCH ??? ");
+ return;
+
+ case OP3_PREFETCHA:
+ printf("PREFETCHA ??? ");
+ return;
+ }
- printf("Unknown OP_3: OP3 = %08X", RD_FLD(instr, INSTR_OP3));
- assert(0);
+ printf("Unknown OP_3: OP3 = %08X", RD_FLD(instr, INSTR_OP3));
+ assert(0);
}
void sparc_print_pseudo(unsigned instr, int labelrs1, int labelrs2, int labelrd, int labelccf)
{
- if (RD_FLD(instr,INSTR_OP)==OP_CALL)
- printf("CALL disp:+%08X", instr & 0x3FFFFFFF);
- else if (RD_FLD(instr,INSTR_OP)==OP_BRANCH)
- sparc_printbr(instr,true,labelrs1, labelrs2, labelrd, labelccf);
- else if (RD_FLD(instr,INSTR_OP)==OP_2)
- sparc_print2(instr,true,labelrs1, labelrs2, labelrd, labelccf);
- else if (RD_FLD(instr,INSTR_OP)==OP_3)
- sparc_print3(instr,true,labelrs1, labelrs2, labelrd, labelccf);
+ if (RD_FLD(instr,INSTR_OP)==OP_CALL)
+ printf("CALL disp:+%08X", instr & 0x3FFFFFFF);
+ else if (RD_FLD(instr,INSTR_OP)==OP_BRANCH)
+ sparc_printbr(instr,true,labelrs1, labelrs2, labelrd, labelccf);
+ else if (RD_FLD(instr,INSTR_OP)==OP_2)
+ sparc_print2(instr,true,labelrs1, labelrs2, labelrd, labelccf);
+ else if (RD_FLD(instr,INSTR_OP)==OP_3)
+ sparc_print3(instr,true,labelrs1, labelrs2, labelrd, labelccf);
}
void sparc_print(unsigned instr)
{
- if (RD_FLD(instr,INSTR_OP)==OP_CALL)
- printf("CALL disp:+%08X", instr & 0x3FFFFFFF);
- else if (RD_FLD(instr,INSTR_OP)==OP_BRANCH)
- sparc_printbr(instr,false,0, 0, 0, 0);
- else if (RD_FLD(instr,INSTR_OP)==OP_2)
- sparc_print2(instr,false,0, 0, 0, 0);
- else if (RD_FLD(instr,INSTR_OP)==OP_3)
- sparc_print3(instr,false,0, 0, 0, 0 );
+ if (RD_FLD(instr,INSTR_OP)==OP_CALL)
+ printf("CALL disp:+%08X", instr & 0x3FFFFFFF);
+ else if (RD_FLD(instr,INSTR_OP)==OP_BRANCH)
+ sparc_printbr(instr,false,0, 0, 0, 0);
+ else if (RD_FLD(instr,INSTR_OP)==OP_2)
+ sparc_print2(instr,false,0, 0, 0, 0);
+ else if (RD_FLD(instr,INSTR_OP)==OP_3)
+ sparc_print3(instr,false,0, 0, 0, 0 );
}
Index: llvm/lib/Reoptimizer/BinInterface/sparcdis.h
diff -u llvm/lib/Reoptimizer/BinInterface/sparcdis.h:1.4 llvm/lib/Reoptimizer/BinInterface/sparcdis.h:1.5
--- llvm/lib/Reoptimizer/BinInterface/sparcdis.h:1.4 Sat Dec 14 19:32:18 2002
+++ llvm/lib/Reoptimizer/BinInterface/sparcdis.h Sun Dec 15 05:07:46 2002
@@ -1,36 +1,36 @@
-//*****************************************************************************
-// SPARC Instruction Disassembler
-//
-// Disassembler API Header
-//
-// * Initial implementation
-// * Added support for MOVcc (somehow I missed it?!)
-// * Added support for pseudo-disassembly
-// ( In the print routine for bin-interface we want
-// to be able to print the internal SSA form with
-// labels instead of registers. And we wish to
-// ommit RD from the view when we are not explicitly
-// reading from it)
-//
-// Todo:
-// * On the instructions that don't read from RD
-// do not print the label field (we get l-1 when we print)
-//
-// 2002 Cameron Buschardt
-//*****************************************************************************
-
-#ifndef __SPARCDIS__
-#define __SPARCDIS__
-// Conventional Disassembly. Prints instruction (no newline)
-void sparc_print(unsigned instr);
-
-// Pseudo disasm
-// uses the integers in labelrs1, labelrs2, labelrd, and labelccf as
-// gen labels for the parameter sources
-// instead of printing rxx for rs1, it will print l__labelrs1__
-void sparc_print_pseudo(unsigned instr, int labelrs1, int labelrs2, int labelrd, int labelccf);
-
-
-#endif
-
-
+//*****************************************************************************
+// SPARC Instruction Disassembler
+//
+// Disassembler API Header
+//
+// * Initial implementation
+// * Added support for MOVcc (somehow I missed it?!)
+// * Added support for pseudo-disassembly
+// ( In the print routine for bin-interface we want
+// to be able to print the internal SSA form with
+// labels instead of registers. And we wish to
+// ommit RD from the view when we are not explicitly
+// reading from it)
+//
+// Todo:
+// * On the instructions that don't read from RD
+// do not print the label field (we get l-1 when we print)
+//
+// 2002 Cameron Buschardt
+//*****************************************************************************
+
+#ifndef __SPARCDIS__
+#define __SPARCDIS__
+// Conventional Disassembly. Prints instruction (no newline)
+void sparc_print(unsigned instr);
+
+// Pseudo disasm
+// uses the integers in labelrs1, labelrs2, labelrd, and labelccf as
+// gen labels for the parameter sources
+// instead of printing rxx for rs1, it will print l__labelrs1__
+void sparc_print_pseudo(unsigned instr, int labelrs1, int labelrs2, int labelrd, int labelccf);
+
+
+#endif
+
+
Index: llvm/lib/Reoptimizer/BinInterface/sparcpriv.h
diff -u llvm/lib/Reoptimizer/BinInterface/sparcpriv.h:1.1 llvm/lib/Reoptimizer/BinInterface/sparcpriv.h:1.2
--- llvm/lib/Reoptimizer/BinInterface/sparcpriv.h:1.1 Sat Dec 14 19:32:27 2002
+++ llvm/lib/Reoptimizer/BinInterface/sparcpriv.h Sun Dec 15 05:07:48 2002
@@ -1,99 +1,114 @@
+//*****************************************************************************
+// BinInterface private structures and constants
+//
+//
+//
+//
+// 2002 Cameron Buschardt
+//*****************************************************************************
+
#ifndef __SPARC_PRIV_H__
#define __SPARC_PRIV_H__
#include "fvector.h"
+
//
// Instruction flag definitions
-//
-#define IF_ALUOP (IF_USR << 1)
-#define IF_PHI (IF_USR << 2)
+//
+#define IF_ALUOP (IF_USR << 1) // generic ALU
+#define IF_PHI (IF_USR << 2) // phi node
#define IF_NODELIVEIN (IF_USR << 3) // instr field is register to bind to
#define IF_REGSHUFFLE (IF_USR << 5) // register shuffle (calls and liveouts)
-#define IF_BRINTERNAL (IF_USR << 6) // is this an INTERNAL branch if so use ibranch
-#define IF_LIVEOUT (IF_USR << 7) // do we think this instruction is liveout?
+#define IF_BRINTERNAL (IF_USR << 6) // is this an INTERNAL branch
+#define IF_LIVEOUT (IF_USR << 7) // this instruction is liveout?
// a call instruction will spill all the outgoing registers O0->O7 (R8-R15)
#define R_CALLSPILLS 0x0000FF00
-#define R_ALLOCREGS (~0 & ~(1 | (1<<R_O6) | (1 << R_I6))) // allocate all regs except R0(G0), O6(R14)(SP), I6(FP)
+
// a mask of registers that if a trace
// reads/writes to we IGNORE dataflow
// implications (stack register and null register)
#define RM_IGNORE ((1 << R_SP) | 1 | (1 << R_BP))
+// allocate all regs except R0(G0), O6(R14)(SP), I6(FP)
+#define R_ALLOCREGS (0xFFFFFFFF & ~ RM_IGNORE)
+// Max of 62 epilogs (64 sections in all)
+#define MAX_SECTIONS 64
+
struct vreginfo
{
- unsigned uses;
- unsigned lastuse;
- int mreg;
+ unsigned uses; // number of times virtual register is referenced
+ unsigned lastuse; // latest use
+ int mreg; // mreg mapped to (use VREG_ISMEM/VREG_ISREG)
};
-// This is the data passed back from the register allocator
+// This is the data passed back from the register allocator
struct regalloc
{
- fvector<unsigned> ssa_to_vreg; // map of SSA Id's to virtual registers
- fvector<vreginfo> vregs; // virtual register descriptors
- int spillreg;
- int memspills[32];
- unsigned touched_regs;
- unsigned stack_size;
- unsigned liveout_regs;
-
- regalloc(Allocator * alloc)
- : ssa_to_vreg(alloc), vregs(alloc) {}
+ fvector<unsigned> ssa_to_vreg; // map of SSA Id's to virtual registers
+ fvector<vreginfo> vregs; // virtual register descriptors
+ int spillreg;
+ int memspills[32];
+ unsigned touched_regs;
+ unsigned stack_size;
+ unsigned liveout_regs;
+
+ regalloc(Allocator * alloc)
+ : ssa_to_vreg(alloc), vregs(alloc) {}
};
struct shufflepair
{
- int reg;
- int gen;
- shufflepair() {}
- shufflepair(int r, int g) : reg(r), gen(g) {}
+ int reg;
+ int gen;
+ shufflepair() {}
+ shufflepair(int r, int g) : reg(r), gen(g) {}
};
struct instruction
{
- unsigned next;
- unsigned prev;
- unsigned self;
- unsigned flags;
-
- unsigned instr;
- union
- {
- struct
- {
- unsigned genrs1;
- unsigned genrs2;
- unsigned genccf;
- unsigned genrd; //ingenious SUN.. we can read from RD!?!
- } alu;
- struct
- {
- unsigned dest; // id # of destination section
- } ibranch; // internal branch
- struct
- {
- unsigned * dest;
- } ebranch; // external branch
- struct
- {
- fvector<unsigned> * params;
- }phi;
- struct
- {
- unsigned reg;
- } livein;
- struct
- {
- fvector<shufflepair> * shuffles;
- } regshuffle;
- };
+ unsigned next;
+ unsigned prev;
+ unsigned self;
+ unsigned flags;
+
+ unsigned instr;
+ union
+ {
+ struct
+ {
+ unsigned genrs1;
+ unsigned genrs2;
+ unsigned genccf;
+ unsigned genrd; //wonderful SUN.. we can read from RD (STX)
+ } alu;
+ struct
+ {
+ unsigned dest; // id # of destination section
+ } ibranch; // internal branch
+ struct
+ {
+ unsigned * dest;
+ } ebranch; // external branch
+ struct
+ {
+ fvector<unsigned> * params;
+ }phi;
+ struct
+ {
+ unsigned reg;
+ } livein;
+ struct
+ {
+ fvector<shufflepair> * shuffles;
+ } regshuffle;
+ };
};
#endif
Index: llvm/lib/Reoptimizer/BinInterface/test.cpp
diff -u llvm/lib/Reoptimizer/BinInterface/test.cpp:1.1 llvm/lib/Reoptimizer/BinInterface/test.cpp:1.2
--- llvm/lib/Reoptimizer/BinInterface/test.cpp:1.1 Sat Dec 14 19:32:30 2002
+++ llvm/lib/Reoptimizer/BinInterface/test.cpp Sun Dec 15 05:07:48 2002
@@ -1,3 +1,11 @@
+//*****************************************************************************
+// SPARC Binary Interface Test
+//
+// Simple test and benchmark
+//
+// 2002 Cameron Buschardt
+//*****************************************************************************
+
#include <stdio.h>
#include <stdlib.h>
#include "sparc9.h"
@@ -10,125 +18,147 @@
#include "sparcbin.h"
#include "sparcpriv.h" // Private definitions
-//*********************************
-// Fast Vector Class
-//*********************************
+#define arrsize(x) (sizeof(x) / sizeof(*x))
+unsigned ex1_prolog[] = {0x86100008};
+unsigned ex1_trace[] = {0x8400FFFF, 0x8688C002 ,0x12BFFFFE, 0x92026001};
-#define arrsize(x) (sizeof(x) / sizeof(*x))
+void bench1()
+{
+ BinInterface bin(512*1024);
+ for (int t=0;t<1000;t++)
+ {
+ bin.clear();
+ unsigned epilog = bin.newepilog();
+ bin.insert(SECTION_PROLOG,ex1_prolog, ex1_prolog + arrsize(ex1_prolog));
+ bin.insert(SECTION_TRACE,ex1_trace, ex1_trace + arrsize(ex1_trace));
+ bin.complete();
+ bin.liveout(3);
+ bin.liveout(5);
-unsigned ex1_prolog[] = {0x86100008};
-unsigned ex1_trace[] = {0x8400FFFF, 0x8688C002 ,0x12BFFFFE, 0x92026001};
-unsigned ex1_epilog[] = {0x81C3E008};
+ bin.reduce();
-void bench1()
+ unsigned buffer[1024];
+ unsigned size = bin.emit((unsigned char *)&buffer);
+ }
+}
+
+
+void bench2()
{
- BinInterface bin(1024);
+ BinInterface bin(512*1024);
+ // Generate trace (do a NOP on each reg basically reg-reg move same src/dst)
+ // Generate prolog (read from random addr into all registers in R_ALLOCREGS except on
+ unsigned ex2_prolog[32];
+ int ex2_pidx = 0;
+ unsigned mask = R_ALLOCREGS;
+ for (int k=0;k<32;k++)
+ if (( mask >> k ) & 1)
+ ex2_prolog[ex2_pidx++] = MK_LDX_ROFFS(k, R_BP,8*k);
+ unsigned ex2_trace[32];
+ int ex2_tidx = 0;
+ for (int k=0;k<32;k++)
+ if (( mask >> k) & 1)
+ ex2_trace[ex2_tidx++] = MK_MOV_R_R(k,k);
+ for (int t=0;t<1000;t++)
+ {
+ bin.clear();
+ unsigned epilog = bin.newepilog();
+ bin.insert(SECTION_PROLOG,ex2_prolog, ex2_prolog + ex2_pidx);
+ int trace_base=bin.insert(SECTION_TRACE,ex2_trace, ex2_trace + ex2_tidx);
+ bin.complete();
+
+ // all trace elements are liveout
+ for (int k=0;k<ex2_tidx;k++)
+ bin.liveout(trace_base + k);
- for (int t=0;t<1000;t++)
- {
- bin.clear();
- unsigned epilog = bin.newepilog();
- bin.insert(SECTION_PROLOG,ex1_prolog, ex1_prolog + arrsize(ex1_prolog));
- bin.insert(SECTION_TRACE,ex1_trace, ex1_trace + arrsize(ex1_trace));
- bin.insert(epilog,ex1_epilog, ex1_epilog + arrsize(ex1_epilog));
-
-
- bin.complete();
-
- bin.liveout(3);
- bin.liveout(5);
-
- bin.reduce();
-
- unsigned buffer[1024];
- unsigned size = bin.emit((unsigned char *)&buffer);
- }
-}
+ bin.reduce();
+ unsigned buffer[1024];
+ unsigned size = bin.emit((unsigned char *)&buffer);
+ }
+}
void test1()
{
- BinInterface bin(1024);
+ BinInterface bin(512*1024);
- printf("Test Case #1:\n");
- printf("-- SSA form --\n");
- unsigned epilog = bin.newepilog();
- bin.insert(SECTION_PROLOG,ex1_prolog, ex1_prolog + arrsize(ex1_prolog));
- bin.insert(SECTION_TRACE,ex1_trace, ex1_trace + arrsize(ex1_trace));
- bin.insert(epilog,ex1_epilog, ex1_epilog + arrsize(ex1_epilog));
-
- bin.complete();
-
- bin.liveout(3);
- bin.liveout(5);
-
- bin.reduce();
- bin.print();
-
- printf("\n-- Output -- \n");
- unsigned buffer[1024];
- unsigned size = bin.emit((unsigned char *)&buffer);
-
- for (int k = 0; k < size; k++)
- {
- sparc_print(buffer[k]);
- printf("\n");
- }
+ printf("Test Case #1:\n");
+ printf("-- SSA form --\n");
+ unsigned epilog = bin.newepilog();
+ bin.insert(SECTION_PROLOG,ex1_prolog, ex1_prolog + arrsize(ex1_prolog));
+ bin.insert(SECTION_TRACE,ex1_trace, ex1_trace + arrsize(ex1_trace));
+
+ bin.complete();
+
+ bin.liveout(3);
+ bin.liveout(5);
+
+ bin.reduce();
+ bin.print();
+
+ printf("\n-- Output -- \n");
+ unsigned buffer[1024];
+ unsigned size = bin.emit((unsigned char *)&buffer);
+
+ for (int k = 0; k < size; k++)
+ {
+ sparc_print(buffer[k]);
+ printf("\n");
+ }
}
void test2()
{
- BinInterface bin(1024);
+ BinInterface bin(512*1024);
- printf("\n\nRegister Contention test:\n");
- printf("-- SSA form --\n");
- unsigned epilog = bin.newepilog();
-
- // Generate prolog (read from random addr into all registers in R_ALLOCREGS except on
- unsigned ex2_prolog[32];
- int ex2_pidx = 0;
- unsigned mask = R_ALLOCREGS;
- for (int k=0;k<32;k++)
- if (( mask >> k ) & 1)
- ex2_prolog[ex2_pidx++] = MK_LDX_ROFFS(k, R_BP,8*k);
-
- // Generate trace (do a NOP on each reg basically reg-reg move same src/dst)
- unsigned ex2_trace[32];
- int ex2_tidx = 0;
- for (int k=0;k<32;k++)
- if (( mask >> k) & 1)
- ex2_trace[ex2_tidx++] = MK_MOV_R_R(k,k);
-
- bin.insert(SECTION_PROLOG,ex2_prolog, ex2_prolog + ex2_pidx);
- int trace_base= bin.insert(SECTION_TRACE,ex2_trace, ex2_trace + ex2_tidx);
- bin.insert(epilog,NULL, NULL); // no epilog
-
- bin.complete();
-
- // all trace elements are liveout
- for (int k=0;k<ex2_tidx;k++)
- bin.liveout(trace_base + k);
-
- bin.reduce();
- bin.print();
-
- printf("\n-- Output -- \n");
- unsigned buffer[1024];
- unsigned size = bin.emit((unsigned char *)&buffer);
-
- for (int k = 0; k < size; k++)
- {
- sparc_print(buffer[k]);
- printf("\n");
- }
+ printf("\n\nRegister Contention test:\n");
+ printf("-- SSA form --\n");
+ unsigned epilog = bin.newepilog();
+
+ // Generate prolog (read from random addr into all registers in R_ALLOCREGS except on
+ unsigned ex2_prolog[32];
+ int ex2_pidx = 0;
+ unsigned mask = R_ALLOCREGS;
+ for (int k=0;k<32;k++)
+ if (( mask >> k ) & 1)
+ ex2_prolog[ex2_pidx++] = MK_LDX_ROFFS(k, R_BP,8*k);
+
+ // Generate trace (do a NOP on each reg basically reg-reg move same src/dst)
+ unsigned ex2_trace[32];
+ int ex2_tidx = 0;
+ for (int k=0;k<32;k++)
+ if (( mask >> k) & 1)
+ ex2_trace[ex2_tidx++] = MK_MOV_R_R(k,k);
+
+ bin.insert(SECTION_PROLOG,ex2_prolog, ex2_prolog + ex2_pidx);
+ int trace_base= bin.insert(SECTION_TRACE,ex2_trace, ex2_trace + ex2_tidx);
+
+ bin.complete();
+
+ // all trace elements are liveout
+ for (int k=0;k<ex2_tidx;k++)
+ bin.liveout(trace_base + k);
+
+ bin.reduce();
+ bin.print();
+
+ printf("\n-- Output -- \n");
+ unsigned buffer[1024];
+ unsigned size = bin.emit((unsigned char *)&buffer);
+
+ for (int k = 0; k < size; k++)
+ {
+ sparc_print(buffer[k]);
+ printf("\n");
+ }
}
-void bench()
+void bencha()
{
timeval begin, end;
gettimeofday(&begin, NULL);
@@ -139,13 +169,25 @@
long total_usec = sec_elap * 1000000 + usec_elap;
printf("usec/iteration = %ld\n", total_usec);
}
+void benchb()
+{
+ timeval begin, end;
+ gettimeofday(&begin, NULL);
+ bench2();
+ gettimeofday(&end, NULL);
+ long sec_elap = end.tv_sec - begin.tv_sec;
+ signed long usec_elap = end.tv_usec - begin.tv_usec; // could be negative
+ long total_usec = sec_elap * 1000000 + usec_elap;
+ printf("usec/iteration = %ld\n", total_usec);
+}
int main()
{
- bench();
- test1();
- test2();
- return 0;
+ bencha();
+ benchb();
+ test1();
+ test2();
+ return 0;
}
-
+
More information about the llvm-commits
mailing list