|
From: <sv...@va...> - 2015-04-13 10:47:22
|
Author: sewardj
Date: Mon Apr 13 11:47:13 2015
New Revision: 3127
Log:
Add new NInstrs: NIn_ShiftWrr, NIn_AluWrr for shifts and add/and where
both operands are registers.
amd64 back end: emit code for the above 2 new NInstrs
Modified:
branches/NCODE/priv/host_amd64_defs.c
branches/NCODE/priv/host_amd64_defs.h
branches/NCODE/priv/ir_defs.c
branches/NCODE/pub/libvex_ir.h
Modified: branches/NCODE/priv/host_amd64_defs.c
==============================================================================
--- branches/NCODE/priv/host_amd64_defs.c (original)
+++ branches/NCODE/priv/host_amd64_defs.c Mon Apr 13 11:47:13 2015
@@ -4218,23 +4218,69 @@
break;
}
+ case Nin_ShiftWrr: {
+ NShift how = ni->Nin.ShiftWrr.how;
+ HReg amt = mapNReg(nregMap, ni->Nin.ShiftWrr.amt);
+ HReg src = mapNReg(nregMap, ni->Nin.ShiftWrr.srcL);
+ HReg dst = mapNReg(nregMap, ni->Nin.ShiftWrr.dst);
+
+ AMD64ShiftOp shOp = Ash_INVALID;
+ switch (how) {
+ case Nsh_SHR: shOp = Ash_SHR; break;
+ default: break;
+ }
+ vassert(shOp != Ash_INVALID);
+
+ if (!sameHReg(src, dst)) {
+ HI( mk_iMOVsd_RR(src, dst) );
+ }
+ /* Now, we have the shift amount in register |amt|. Problem
+ is that it needs to be in %rcx, but we don't know whether
+ or not that is live. Rather than do this nicely, we can
+ take advantage of the fact that r11 is a guaranteed
+ available scratch temp, and temporarily store rcx in it.
+ Note that rcx could be live even through it isn't
+ allocatable, since the insn selector uses it to put
+ variable shift amounts in. So we can't safely trash it
+ here. */
+ HI( mk_iMOVsd_RR(hregAMD64_RCX(), hregAMD64_R11()) ); // save rcx
+ HI( mk_iMOVsd_RR(amt, hregAMD64_RCX()) ); // amt->rcx
+ HI( AMD64Instr_Sh64(shOp, 0/*meaning %cl*/, dst) );
+ HI( mk_iMOVsd_RR(hregAMD64_R11(), hregAMD64_RCX()) ); // restore rcx
+ break;
+ }
+
case Nin_AluWri: {
NAlu how = ni->Nin.AluWri.how;
HReg dstR = mapNReg(nregMap, ni->Nin.AluWri.dst);
HReg srcLR = mapNReg(nregMap, ni->Nin.AluWri.srcL);
HWord imm = ni->Nin.AluWri.srcR;
- // Verified correct, but currently unused
- //if (how == Nalu_AND && fitsIn32Bits((ULong)imm)) {
- // if (!sameHReg(srcLR, dstR)) {
- // HI( mk_iMOVsd_RR(srcLR, dstR) );
- // }
- // HI( AMD64Instr_Alu64R(Aalu_AND, AMD64RMI_Imm(imm), dstR) );
- // break;
- //}
if (how == Nalu_AND && imm == 0xFFFFULL) {
HI( AMD64Instr_MovxWQ(False/*!syned*/, srcLR, dstR) );
break;
}
+ if (how == Nalu_AND && fitsIn32Bits((ULong)imm)) {
+ if (!sameHReg(srcLR, dstR)) {
+ HI( mk_iMOVsd_RR(srcLR, dstR) );
+ }
+ HI( AMD64Instr_Alu64R(Aalu_AND, AMD64RMI_Imm(imm), dstR) );
+ break;
+ }
+ goto unhandled;
+ }
+
+ case Nin_AluWrr: {
+ NAlu how = ni->Nin.AluWrr.how;
+ HReg dstR = mapNReg(nregMap, ni->Nin.AluWrr.dst);
+ HReg srcLR = mapNReg(nregMap, ni->Nin.AluWrr.srcL);
+ HReg srcRR = mapNReg(nregMap, ni->Nin.AluWrr.srcR);
+ if (how == Nalu_ADD) {
+ if (!sameHReg(srcLR, dstR)) {
+ HI( mk_iMOVsd_RR(srcLR, dstR) );
+ }
+ HI( AMD64Instr_Alu64R(Aalu_ADD, AMD64RMI_Reg(srcRR), dstR) );
+ break;
+ }
goto unhandled;
}
@@ -4345,7 +4391,6 @@
const AMD64InstrNCode* hi_details = hi->Ain.NCode.details;
const NCodeTemplate* tmpl = hi_details->tmpl;
const RRegSet* rregsLiveAfter = hi_details->rrLiveAfter;
- const RRegUniverse* univ = RRegSet__getUniverse(rregsLiveAfter);
NRegMap nregMap;
nregMap.regsR = hi_details->regsR;
Modified: branches/NCODE/priv/host_amd64_defs.h
==============================================================================
--- branches/NCODE/priv/host_amd64_defs.h (original)
+++ branches/NCODE/priv/host_amd64_defs.h Mon Apr 13 11:47:13 2015
@@ -358,7 +358,7 @@
Ain_Imm64, /* Generate 64-bit literal to register */
Ain_Alu64R, /* 64-bit mov/arith/logical, dst=REG */
Ain_Alu64M, /* 64-bit mov/arith/logical, dst=MEM */
- Ain_Sh64, /* 64-bit shift/rotate, dst=REG or MEM */
+ Ain_Sh64, /* 64-bit shift, dst=REG, by imm or %cl */
Ain_Test64, /* 64-bit test (AND, set flags, discard result) */
Ain_Unary64, /* 64-bit not and neg */
Ain_Lea64, /* 64-bit compute EA into a reg */
Modified: branches/NCODE/priv/ir_defs.c
==============================================================================
--- branches/NCODE/priv/ir_defs.c (original)
+++ branches/NCODE/priv/ir_defs.c Mon Apr 13 11:47:13 2015
@@ -77,6 +77,7 @@
static const HChar* nameNAlu ( NAlu nal ) {
switch (nal) {
case Nalu_AND: return "and";
+ case Nalu_ADD: return "add";
default: return "nameNAlu???";
}
}
@@ -182,6 +183,14 @@
ppNReg(ni->Nin.ShiftWri.srcL);
vex_printf(", #%u", (UInt)ni->Nin.ShiftWri.amt);
break;
+ case Nin_ShiftWrr:
+ vex_printf("%s.w ", nameNShift(ni->Nin.ShiftWrr.how));
+ ppNReg(ni->Nin.ShiftWrr.dst);
+ vex_printf(", ");
+ ppNReg(ni->Nin.ShiftWrr.srcL);
+ vex_printf(", ");
+ ppNReg(ni->Nin.ShiftWrr.amt);
+ break;
case Nin_AluWri:
vex_printf("%s.w ", nameNAlu(ni->Nin.AluWri.how));
ppNReg(ni->Nin.AluWri.dst);
@@ -189,6 +198,14 @@
ppNReg(ni->Nin.AluWri.srcL);
vex_printf(", #0x%llx", (ULong)ni->Nin.AluWri.srcR);
break;
+ case Nin_AluWrr:
+ vex_printf("%s.w ", nameNAlu(ni->Nin.AluWrr.how));
+ ppNReg(ni->Nin.AluWrr.dst);
+ vex_printf(", ");
+ ppNReg(ni->Nin.AluWrr.srcL);
+ vex_printf(", ");
+ ppNReg(ni->Nin.AluWrr.srcR);
+ break;
case Nin_SetFlagsWri:
vex_printf("%s.w ", nameNSetFlags(ni->Nin.SetFlagsWri.how));
ppNReg(ni->Nin.SetFlagsWri.srcL);
@@ -2064,6 +2081,17 @@
in->Nin.ShiftWri.amt = amt;
return in;
}
+NInstr* NInstr_ShiftWrr ( NAlloc na,
+ NShift how, NReg dst, NReg srcL, NReg amt )
+{
+ NInstr* in = na(sizeof(NInstr));
+ in->tag = Nin_ShiftWrr;
+ in->Nin.ShiftWrr.how = how;
+ in->Nin.ShiftWrr.dst = dst;
+ in->Nin.ShiftWrr.srcL = srcL;
+ in->Nin.ShiftWrr.amt = amt;
+ return in;
+}
NInstr* NInstr_AluWri ( NAlloc na, NAlu how, NReg dst, NReg srcL, HWord srcR )
{
NInstr* in = na(sizeof(NInstr));
@@ -2074,6 +2102,16 @@
in->Nin.AluWri.srcR = srcR;
return in;
}
+NInstr* NInstr_AluWrr ( NAlloc na, NAlu how, NReg dst, NReg srcL, NReg srcR )
+{
+ NInstr* in = na(sizeof(NInstr));
+ in->tag = Nin_AluWrr;
+ in->Nin.AluWrr.how = how;
+ in->Nin.AluWrr.dst = dst;
+ in->Nin.AluWrr.srcL = srcL;
+ in->Nin.AluWrr.srcR = srcR;
+ return in;
+}
NInstr* NInstr_SetFlagsWri ( NAlloc na, NSetFlags how, NReg srcL, HWord srcR )
{
NInstr* in = na(sizeof(NInstr));
Modified: branches/NCODE/pub/libvex_ir.h
==============================================================================
--- branches/NCODE/pub/libvex_ir.h (original)
+++ branches/NCODE/pub/libvex_ir.h Mon Apr 13 11:47:13 2015
@@ -2673,7 +2673,8 @@
typedef
enum {
- Nalu_AND=0x1D30
+ Nalu_AND=0x1D30,
+ Nalu_ADD
}
NAlu;
@@ -2766,7 +2767,9 @@
Nin_Call,
Nin_ImmW,
Nin_ShiftWri,
+ Nin_ShiftWrr,
Nin_AluWri,
+ Nin_AluWrr,
Nin_SetFlagsWri,
Nin_MovW,
Nin_LoadU,
@@ -2802,12 +2805,24 @@
UInt amt; /* 1 .. host-word-size-1 only */
} ShiftWri;
struct {
+ NShift how;
+ NReg dst;
+ NReg srcL;
+ NReg amt; /* 0 .. host-word-size-1 only */
+ } ShiftWrr;
+ struct {
NAlu how;
NReg dst;
NReg srcL;
HWord srcR;
} AluWri;
struct {
+ NAlu how;
+ NReg dst;
+ NReg srcL;
+ NReg srcR;
+ } AluWrr;
+ struct {
NSetFlags how;
NReg srcL;
HWord srcR;
@@ -2839,8 +2854,12 @@
extern NInstr* NInstr_ImmW ( NAlloc na, NReg dst, HWord imm );
extern NInstr* NInstr_ShiftWri ( NAlloc na,
NShift how, NReg dst, NReg srcL, UInt amt );
+extern NInstr* NInstr_ShiftWrr ( NAlloc na,
+ NShift how, NReg dst, NReg srcL, NReg amt );
extern NInstr* NInstr_AluWri ( NAlloc na,
NAlu how, NReg dst, NReg srcL, HWord srcR );
+extern NInstr* NInstr_AluWrr ( NAlloc na,
+ NAlu how, NReg dst, NReg srcL, NReg srcR );
extern NInstr* NInstr_SetFlagsWri ( NAlloc na,
NSetFlags how, NReg srcL, HWord srcR );
extern NInstr* NInstr_MovW ( NAlloc na, NReg dst, NReg src );
|