Commit 2f593bbb by Srdjan Obucina Committed by Jim Stichnoth

Subzero, MIPS32: Introduction of floating point registers

This patch introduces floating point registers used for 32-bit operations, and basic handling of FP values in operands. It is partial work needed as a base for further work. R=stichnot@chromium.org Review URL: https://codereview.chromium.org/1993993004 . Patch from Srdjan Obucina <Srdjan.Obucina@imgtec.com>.
parent 032c3158
......@@ -65,16 +65,26 @@ template <> const char *InstMIPS32Lui::Opcode = "lui";
template <> const char *InstMIPS32La::Opcode = "la";
// Three-addr ops
template <> const char *InstMIPS32Add::Opcode = "add";
template <> const char *InstMIPS32Add_d::Opcode = "add.d";
template <> const char *InstMIPS32Add_s::Opcode = "add.s";
template <> const char *InstMIPS32Addu::Opcode = "addu";
template <> const char *InstMIPS32And::Opcode = "and";
template <> const char *InstMIPS32Andi::Opcode = "andi";
template <> const char *InstMIPS32Div::Opcode = "div";
template <> const char *InstMIPS32Div_d::Opcode = "div.d";
template <> const char *InstMIPS32Div_s::Opcode = "div.s";
template <> const char *InstMIPS32Divu::Opcode = "divu";
template <> const char *InstMIPS32Mfc1::Opcode = "mfc1";
template <> const char *InstMIPS32Mfhi::Opcode = "mfhi";
template <> const char *InstMIPS32Mflo::Opcode = "mflo";
template <> const char *InstMIPS32Mov_d::Opcode = "mov.d";
template <> const char *InstMIPS32Mov_s::Opcode = "mov.s";
template <> const char *InstMIPS32Mtc1::Opcode = "mtc1";
template <> const char *InstMIPS32Mthi::Opcode = "mthi";
template <> const char *InstMIPS32Mtlo::Opcode = "mtlo";
template <> const char *InstMIPS32Mul::Opcode = "mul";
template <> const char *InstMIPS32Mul_d::Opcode = "mul.d";
template <> const char *InstMIPS32Mul_s::Opcode = "mul.s";
template <> const char *InstMIPS32Mult::Opcode = "mult";
template <> const char *InstMIPS32Multu::Opcode = "multu";
template <> const char *InstMIPS32Or::Opcode = "or";
......@@ -90,6 +100,8 @@ template <> const char *InstMIPS32Srav::Opcode = "srav";
template <> const char *InstMIPS32Srl::Opcode = "srl";
template <> const char *InstMIPS32Srlv::Opcode = "srlv";
template <> const char *InstMIPS32Sub::Opcode = "sub";
template <> const char *InstMIPS32Sub_d::Opcode = "sub.d";
template <> const char *InstMIPS32Sub_s::Opcode = "sub.s";
template <> const char *InstMIPS32Subu::Opcode = "subu";
template <> const char *InstMIPS32Xor::Opcode = "xor";
template <> const char *InstMIPS32Xori::Opcode = "xori";
......@@ -278,6 +290,18 @@ void InstMIPS32::emitThreeAddr(const char *Opcode, const InstMIPS32 *Inst,
Inst->getSrc(1)->emit(Func);
}
void InstMIPS32::emitTwoAddr(const char *Opcode, const InstMIPS32 *Inst,
const Cfg *Func) {
if (!BuildDefs::dump())
return;
Ostream &Str = Func->getContext()->getStrEmit();
assert(Inst->getSrcSize() == 1);
Str << "\t" << Opcode << "\t";
Inst->getDest()->emit(Func);
Str << ", ";
Inst->getSrc(0)->emit(Func);
}
void InstMIPS32::emitThreeAddrLoHi(const char *Opcode, const InstMIPS32 *Inst,
const Cfg *Func) {
if (!BuildDefs::dump())
......
......@@ -107,11 +107,43 @@
ALIASES2(Reg_LO, Reg_LOHI)) \
X(Reg_HI, 0, "hi", 0, 0, 0, 0, 0, 0, 0, 0, 0, \
ALIASES2(Reg_HI, Reg_LOHI))
//#define X(val, encode, name, scratch, preserved, stackptr, frameptr,
// isInt, isI64Pair, isFP32, isFP64, isVec128, alias_init)
// TODO(reed kotler): List FP registers etc.
// Be able to grab even registers, and the corresponding odd register
// for each even register.
#define REGMIPS32_FPR_TABLE \
/* val, encode, name, scratch, preserved, stackptr, frameptr, \
isInt, isI64Pair, isFP32, isFP64, isVec128, alias_init */ \
X(Reg_F0, 0, "f0", 1,0,0,0, 0,0,1,0,0, ALIASES1(Reg_F0)) \
X(Reg_F1, 1, "f1", 1,0,0,0, 0,0,1,0,0, ALIASES1(Reg_F1)) \
X(Reg_F2, 2, "f2", 1,0,0,0, 0,0,1,0,0, ALIASES1(Reg_F2)) \
X(Reg_F3, 3, "f3", 1,0,0,0, 0,0,1,0,0, ALIASES1(Reg_F3)) \
X(Reg_F4, 4, "f4", 1,0,0,0, 0,0,1,0,0, ALIASES1(Reg_F4)) \
X(Reg_F5, 5, "f5", 1,0,0,0, 0,0,1,0,0, ALIASES1(Reg_F5)) \
X(Reg_F6, 6, "f6", 1,0,0,0, 0,0,1,0,0, ALIASES1(Reg_F6)) \
X(Reg_F7, 7, "f7", 1,0,0,0, 0,0,1,0,0, ALIASES1(Reg_F7)) \
X(Reg_F8, 8, "f8", 1,0,0,0, 0,0,1,0,0, ALIASES1(Reg_F8)) \
X(Reg_F9, 9, "f9", 1,0,0,0, 0,0,1,0,0, ALIASES1(Reg_F9)) \
X(Reg_F10, 10, "f10", 1,0,0,0, 0,0,1,0,0, ALIASES1(Reg_F10)) \
X(Reg_F11, 11, "f11", 1,0,0,0, 0,0,1,0,0, ALIASES1(Reg_F11)) \
X(Reg_F12, 12, "f12", 1,0,0,0, 0,0,1,0,0, ALIASES1(Reg_F12)) \
X(Reg_F13, 13, "f13", 1,0,0,0, 0,0,1,0,0, ALIASES1(Reg_F13)) \
X(Reg_F14, 14, "f14", 1,0,0,0, 0,0,1,0,0, ALIASES1(Reg_F14)) \
X(Reg_F15, 15, "f15", 1,0,0,0, 0,0,1,0,0, ALIASES1(Reg_F15)) \
X(Reg_F16, 16, "f16", 1,0,0,0, 0,0,1,0,0, ALIASES1(Reg_F16)) \
X(Reg_F17, 17, "f17", 1,0,0,0, 0,0,1,0,0, ALIASES1(Reg_F17)) \
X(Reg_F18, 18, "f18", 1,0,0,0, 0,0,1,0,0, ALIASES1(Reg_F18)) \
X(Reg_F19, 19, "f19", 1,0,0,0, 0,0,1,0,0, ALIASES1(Reg_F19)) \
X(Reg_F20, 20, "f20", 1,0,0,0, 0,0,1,0,0, ALIASES1(Reg_F20)) \
X(Reg_F21, 21, "f21", 1,0,0,0, 0,0,1,0,0, ALIASES1(Reg_F21)) \
X(Reg_F22, 22, "f22", 1,0,0,0, 0,0,1,0,0, ALIASES1(Reg_F22)) \
X(Reg_F23, 23, "f23", 1,0,0,0, 0,0,1,0,0, ALIASES1(Reg_F23)) \
X(Reg_F24, 24, "f24", 1,0,0,0, 0,0,1,0,0, ALIASES1(Reg_F24)) \
X(Reg_F25, 25, "f25", 1,0,0,0, 0,0,1,0,0, ALIASES1(Reg_F25)) \
X(Reg_F26, 26, "f26", 1,0,0,0, 0,0,1,0,0, ALIASES1(Reg_F26)) \
X(Reg_F27, 27, "f27", 1,0,0,0, 0,0,1,0,0, ALIASES1(Reg_F27)) \
X(Reg_F28, 28, "f28", 1,0,0,0, 0,0,1,0,0, ALIASES1(Reg_F28)) \
X(Reg_F29, 29, "f29", 1,0,0,0, 0,0,1,0,0, ALIASES1(Reg_F29)) \
X(Reg_F30, 30, "f30", 1,0,0,0, 0,0,1,0,0, ALIASES1(Reg_F30)) \
X(Reg_F31, 31, "f31", 1,0,0,0, 0,0,1,0,0, ALIASES1(Reg_F31))
//#define X(val, encode, name, scratch, preserved, stackptr, frameptr,
// isInt, isI64Pair, isFP32, isFP64, isVec128, alias_init)
// The following defines a table with the available pairs of consecutive i32
......@@ -151,6 +183,42 @@
//#define X(val, encode, name, scratch, preserved, stackptr, frameptr,
// isInt, isI64Pair, isFP32, isFP64, isVec128, alias_init)
#define REGMIPS32_F64PAIR_TABLE \
/* val, encode, name, scratch, preserved, stackptr, frameptr, \
isInt, isI64Pair, isFP32, isFP64, isVec128, alias_init */ \
X(Reg_F0F1, 0, "f0, f1", 1,0,0,0, 0,0,0,1,0, \
ALIASES3(Reg_F0, Reg_F1, Reg_F0F1)) \
X(Reg_F2F3, 2, "f2, f3", 1,0,0,0, 0,0,0,1,0, \
ALIASES3(Reg_F2, Reg_F3, Reg_F2F3)) \
X(Reg_F4F5, 4, "f4, f5", 1,0,0,0, 0,0,0,1,0, \
ALIASES3(Reg_F4, Reg_F5, Reg_F4F5)) \
X(Reg_F6F7, 6, "f6, f7", 1,0,0,0, 0,0,0,1,0, \
ALIASES3(Reg_F6, Reg_F7, Reg_F6F7)) \
X(Reg_F8F9, 8, "f8, f9", 1,0,0,0, 0,0,0,1,0, \
ALIASES3(Reg_F8, Reg_F9, Reg_F8F9)) \
X(Reg_F10F11, 10, "f10, f11", 1,0,0,0, 0,0,0,1,0, \
ALIASES3(Reg_F10, Reg_F11, Reg_F10F11)) \
X(Reg_F12F13, 12, "f12, f13", 1,0,0,0, 0,0,0,1,0, \
ALIASES3(Reg_F12, Reg_F13, Reg_F12F13)) \
X(Reg_F14F15, 14, "f14, f15", 1,0,0,0, 0,0,0,1,0, \
ALIASES3(Reg_F14, Reg_F15, Reg_F14F15)) \
X(Reg_F16F17, 16, "f16, f17", 1,0,0,0, 0,0,0,1,0, \
ALIASES3(Reg_F16, Reg_F17, Reg_F16F17)) \
X(Reg_F18F19, 18, "f18, f19", 1,0,0,0, 0,0,0,1,0, \
ALIASES3(Reg_F18, Reg_F19, Reg_F18F19)) \
X(Reg_F20F21, 20, "f20, f21", 1,0,0,0, 0,0,0,1,0, \
ALIASES3(Reg_F20, Reg_F21, Reg_F20F21)) \
X(Reg_F22F23, 22, "f22, f23", 1,0,0,0, 0,0,0,1,0, \
ALIASES3(Reg_F22, Reg_F23, Reg_F22F23)) \
X(Reg_F24F25, 24, "f24, f25", 1,0,0,0, 0,0,0,1,0, \
ALIASES3(Reg_F24, Reg_F25, Reg_F24F25)) \
X(Reg_F26F27, 26, "f26, f27", 1,0,0,0, 0,0,0,1,0, \
ALIASES3(Reg_F26, Reg_F27, Reg_F26F27)) \
X(Reg_F28F29, 28, "f28, f29", 1,0,0,0, 0,0,0,1,0, \
ALIASES3(Reg_F28, Reg_F29, Reg_F28F29)) \
X(Reg_F30F31, 30, "f30, f31", 1,0,0,0, 0,0,0,1,0, \
ALIASES3(Reg_F30, Reg_F31, Reg_F30F31))
// We also provide a combined table, so that there is a namespace where
// all of the registers are considered and have distinct numberings.
// This is in contrast to the above, where the "encode" is based on how
......@@ -159,7 +227,9 @@
/* val, encode, name, scratch, preserved, stackptr, frameptr, isInt, \
isFP32, isFP64, isVec128, alias_init */ \
REGMIPS32_GPR_TABLE \
REGMIPS32_I64PAIR_TABLE
REGMIPS32_FPR_TABLE \
REGMIPS32_I64PAIR_TABLE \
REGMIPS32_F64PAIR_TABLE
//#define X(val, encode, name, scratch, preserved, stackptr, frameptr,
// isInt, isI64Pair, isFP32, isFP64, isVec128, alias_init)
......@@ -167,8 +237,12 @@
/* val, init */ \
X(Reg_GPR_First, = Reg_ZERO) \
X(Reg_GPR_Last, = Reg_HI) \
X(Reg_FPR_First, = Reg_F0) \
X(Reg_FPR_Last, = Reg_F31) \
X(Reg_I64PAIR_First, = Reg_V0V1) \
X(Reg_I64PAIR_Last, = Reg_LOHI) \
X(Reg_F64PAIR_First, = Reg_F0F1) \
X(Reg_F64PAIR_Last, = Reg_F30F31) \
//define X(val, init)
#define ICEINSTMIPS32COND_TABLE \
......
......@@ -119,6 +119,8 @@ public:
enum InstKindMIPS32 {
k__Start = Inst::Target,
Add,
Add_d,
Add_s,
Addiu,
Addu,
And,
......@@ -126,16 +128,24 @@ public:
Br,
Call,
Div,
Div_d,
Div_s,
Divu,
La,
Label,
Lui,
Mfc1,
Mfhi,
Mflo,
Mov, // actually a pseudo op for addi rd, rs, 0
Mov_d,
Mov_s,
Mtc1,
Mthi,
Mtlo,
Mul,
Mul_d,
Mul_s,
Mult,
Multu,
Or,
......@@ -152,6 +162,8 @@ public:
Srl,
Srlv,
Sub,
Sub_d,
Sub_s,
Subu,
Xor,
Xori
......@@ -175,6 +187,8 @@ public:
const Cfg *Func);
static void emitUnaryopGPRTLoHi(const char *Opcode, const InstMIPS32 *Inst,
const Cfg *Func);
static void emitTwoAddr(const char *Opcode, const InstMIPS32 *Inst,
const Cfg *Func);
static void emitThreeAddr(const char *Opcode, const InstMIPS32 *Inst,
const Cfg *Func);
static void emitThreeAddrLoHi(const char *Opcode, const InstMIPS32 *Inst,
......@@ -259,6 +273,143 @@ private:
static const char *Opcode;
};
/// Instructions of the form opcode reg, reg.
template <InstMIPS32::InstKindMIPS32 K>
class InstMIPS32TwoAddrFPR : public InstMIPS32 {
InstMIPS32TwoAddrFPR() = delete;
InstMIPS32TwoAddrFPR(const InstMIPS32TwoAddrFPR &) = delete;
InstMIPS32TwoAddrFPR &operator=(const InstMIPS32TwoAddrFPR &) = delete;
public:
static InstMIPS32TwoAddrFPR *create(Cfg *Func, Variable *Dest,
Variable *Src0) {
return new (Func->allocate<InstMIPS32TwoAddrFPR>())
InstMIPS32TwoAddrFPR(Func, Dest, Src0);
}
void emit(const Cfg *Func) const override {
if (!BuildDefs::dump())
return;
emitTwoAddr(Opcode, this, Func);
}
void emitIAS(const Cfg *Func) const override {
(void)Func;
llvm_unreachable("Not yet implemented");
}
void dump(const Cfg *Func) const override {
if (!BuildDefs::dump())
return;
Ostream &Str = Func->getContext()->getStrDump();
dumpDest(Func);
Str << " = ";
dumpOpcode(Str, Opcode, getDest()->getType());
Str << " ";
dumpSources(Func);
}
static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
private:
InstMIPS32TwoAddrFPR(Cfg *Func, Variable *Dest, Variable *Src0)
: InstMIPS32(Func, K, 1, Dest) {
addSource(Src0);
}
static const char *Opcode;
};
/// Instructions of the form opcode reg, reg.
template <InstMIPS32::InstKindMIPS32 K>
class InstMIPS32TwoAddrGPR : public InstMIPS32 {
InstMIPS32TwoAddrGPR() = delete;
InstMIPS32TwoAddrGPR(const InstMIPS32TwoAddrGPR &) = delete;
InstMIPS32TwoAddrGPR &operator=(const InstMIPS32TwoAddrGPR &) = delete;
public:
static InstMIPS32TwoAddrGPR *create(Cfg *Func, Variable *Dest,
Variable *Src0) {
return new (Func->allocate<InstMIPS32TwoAddrGPR>())
InstMIPS32TwoAddrGPR(Func, Dest, Src0);
}
void emit(const Cfg *Func) const override {
if (!BuildDefs::dump())
return;
emitTwoAddr(Opcode, this, Func);
}
void emitIAS(const Cfg *Func) const override {
(void)Func;
llvm_unreachable("Not yet implemented");
}
void dump(const Cfg *Func) const override {
if (!BuildDefs::dump())
return;
Ostream &Str = Func->getContext()->getStrDump();
dumpDest(Func);
Str << " = ";
dumpOpcode(Str, Opcode, getDest()->getType());
Str << " ";
dumpSources(Func);
}
static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
private:
InstMIPS32TwoAddrGPR(Cfg *Func, Variable *Dest, Variable *Src0)
: InstMIPS32(Func, K, 1, Dest) {
addSource(Src0);
}
static const char *Opcode;
};
/// Instructions of the form x := y op z. May have the side-effect of setting
/// status flags.
template <InstMIPS32::InstKindMIPS32 K>
class InstMIPS32ThreeAddrFPR : public InstMIPS32 {
InstMIPS32ThreeAddrFPR() = delete;
InstMIPS32ThreeAddrFPR(const InstMIPS32ThreeAddrFPR &) = delete;
InstMIPS32ThreeAddrFPR &operator=(const InstMIPS32ThreeAddrFPR &) = delete;
public:
/// Create an ordinary binary-op instruction like add, and sub. Dest and Src1
/// must be registers.
static InstMIPS32ThreeAddrFPR *create(Cfg *Func, Variable *Dest,
Variable *Src0, Variable *Src1) {
return new (Func->allocate<InstMIPS32ThreeAddrFPR>())
InstMIPS32ThreeAddrFPR(Func, Dest, Src0, Src1);
}
void emit(const Cfg *Func) const override {
if (!BuildDefs::dump())
return;
emitThreeAddr(Opcode, this, Func);
}
void emitIAS(const Cfg *Func) const override {
(void)Func;
llvm_unreachable("Not yet implemented");
}
void dump(const Cfg *Func) const override {
if (!BuildDefs::dump())
return;
Ostream &Str = Func->getContext()->getStrDump();
dumpDest(Func);
Str << " = ";
dumpOpcode(Str, Opcode, getDest()->getType());
Str << " ";
dumpSources(Func);
}
static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
private:
InstMIPS32ThreeAddrFPR(Cfg *Func, Variable *Dest, Variable *Src0,
Variable *Src1)
: InstMIPS32(Func, K, 2, Dest) {
addSource(Src0);
addSource(Src1);
}
static const char *Opcode;
};
/// Instructions of the form x := y op z. May have the side-effect of setting
/// status flags.
template <InstMIPS32::InstKindMIPS32 K>
......@@ -498,19 +649,29 @@ private:
};
using InstMIPS32Add = InstMIPS32ThreeAddrGPR<InstMIPS32::Add>;
using InstMIPS32Add_d = InstMIPS32ThreeAddrFPR<InstMIPS32::Add_d>;
using InstMIPS32Add_s = InstMIPS32ThreeAddrFPR<InstMIPS32::Add_s>;
using InstMIPS32Addu = InstMIPS32ThreeAddrGPR<InstMIPS32::Addu>;
using InstMIPS32Addiu = InstMIPS32Imm16<InstMIPS32::Addiu, true>;
using InstMIPS32And = InstMIPS32ThreeAddrGPR<InstMIPS32::And>;
using InstMIPS32Andi = InstMIPS32Imm16<InstMIPS32::Andi>;
using InstMIPS32Div = InstMIPS32ThreeAddrGPR<InstMIPS32::Div>;
using InstMIPS32Div_d = InstMIPS32ThreeAddrFPR<InstMIPS32::Div_d>;
using InstMIPS32Div_s = InstMIPS32ThreeAddrFPR<InstMIPS32::Div_s>;
using InstMIPS32Divu = InstMIPS32ThreeAddrGPR<InstMIPS32::Divu>;
using InstMIPS32Lui = InstMIPS32Imm16<InstMIPS32::Lui>;
using InstMIPS32La = InstMIPS32UnaryopGPR<InstMIPS32::La>;
using InstMIPS32Mfc1 = InstMIPS32TwoAddrGPR<InstMIPS32::Mfc1>;
using InstMIPS32Mfhi = InstMIPS32UnaryopGPR<InstMIPS32::Mfhi>;
using InstMIPS32Mflo = InstMIPS32UnaryopGPR<InstMIPS32::Mflo>;
using InstMIPS32Mov_d = InstMIPS32TwoAddrFPR<InstMIPS32::Mov_d>;
using InstMIPS32Mov_s = InstMIPS32TwoAddrFPR<InstMIPS32::Mov_s>;
using InstMIPS32Mtc1 = InstMIPS32TwoAddrGPR<InstMIPS32::Mtc1>;
using InstMIPS32Mthi = InstMIPS32UnaryopGPR<InstMIPS32::Mthi>;
using InstMIPS32Mtlo = InstMIPS32UnaryopGPR<InstMIPS32::Mtlo>;
using InstMIPS32Mul = InstMIPS32ThreeAddrGPR<InstMIPS32::Mul>;
using InstMIPS32Mul_d = InstMIPS32ThreeAddrFPR<InstMIPS32::Mul_d>;
using InstMIPS32Mul_s = InstMIPS32ThreeAddrFPR<InstMIPS32::Mul_s>;
using InstMIPS32Mult = InstMIPS32ThreeAddrGPR<InstMIPS32::Mult>;
using InstMIPS32Multu = InstMIPS32ThreeAddrGPR<InstMIPS32::Multu>;
using InstMIPS32Or = InstMIPS32ThreeAddrGPR<InstMIPS32::Or>;
......@@ -526,6 +687,8 @@ using InstMIPS32Srav = InstMIPS32ThreeAddrGPR<InstMIPS32::Srav>;
using InstMIPS32Srl = InstMIPS32Imm16<InstMIPS32::Srl>;
using InstMIPS32Srlv = InstMIPS32ThreeAddrGPR<InstMIPS32::Srlv>;
using InstMIPS32Sub = InstMIPS32ThreeAddrGPR<InstMIPS32::Sub>;
using InstMIPS32Sub_d = InstMIPS32ThreeAddrFPR<InstMIPS32::Sub_d>;
using InstMIPS32Sub_s = InstMIPS32ThreeAddrFPR<InstMIPS32::Sub_s>;
using InstMIPS32Subu = InstMIPS32ThreeAddrGPR<InstMIPS32::Subu>;
using InstMIPS32Ori = InstMIPS32Imm16<InstMIPS32::Ori>;
using InstMIPS32Xor = InstMIPS32ThreeAddrGPR<InstMIPS32::Xor>;
......
......@@ -24,8 +24,8 @@ namespace Ice {
namespace MIPS32 {
namespace RegMIPS32 {
/// An enum of every register. The enum value may not match the encoding
/// used to binary encode register operands in instructions.
/// An enum of every register. The enum value may not match the encoding used to
/// binary encode register operands in instructions.
enum AllRegisters {
#define X(val, encode, name, scratch, preserved, stackptr, frameptr, isInt, \
isI64Pair, isFP32, isFP64, isVec128, alias_init) \
......@@ -38,8 +38,8 @@ enum AllRegisters {
#undef X
};
/// An enum of GPR Registers. The enum value does match the encoding used
/// to binary encode register operands in instructions.
/// An enum of GPR Registers. The enum value does match the encoding used to
/// binary encode register operands in instructions.
enum GPRRegister {
#define X(val, encode, name, scratch, preserved, stackptr, frameptr, isInt, \
isI64Pair, isFP32, isFP64, isVec128, alias_init) \
......@@ -50,6 +50,18 @@ enum GPRRegister {
Encoded_Not_GPR = -1
};
/// An enum of FPR Registers. The enum value does match the encoding used to
/// binary encode register operands in instructions.
enum FPRRegister {
#define X(val, encode, name, scratch, preserved, stackptr, frameptr, isInt, \
isI64Pair, isFP32, isFP64, isVec128, alias_init) \
\
Encoded_##val = encode,
REGMIPS32_FPR_TABLE
#undef X
Encoded_Not_FPR = -1
};
// TODO(jvoung): Floating point and vector registers...
// Need to model overlap and difference in encoding too.
......@@ -59,6 +71,22 @@ static inline GPRRegister getEncodedGPR(RegNumT RegNum) {
return GPRRegister(RegNum - Reg_GPR_First);
}
static inline bool isGPRReg(RegNumT RegNum) {
return (int(Reg_GPR_First) <= int(RegNum)) &&
(unsigned(RegNum) <= Reg_GPR_Last);
}
static inline FPRRegister getEncodedFPR(RegNumT RegNum) {
assert(int(Reg_FPR_First) <= int(RegNum));
assert(unsigned(RegNum) <= Reg_FPR_Last);
return FPRRegister(RegNum - Reg_FPR_First);
}
static inline bool isFPRReg(RegNumT RegNum) {
return (int(Reg_FPR_First) <= int(RegNum)) &&
(unsigned(RegNum) <= Reg_FPR_Last);
}
const char *getRegName(RegNumT RegNum);
} // end of namespace RegMIPS32
......
......@@ -177,6 +177,14 @@ public:
Context.insert<InstMIPS32Ret>(RA, Src0);
}
void _add_d(Variable *Dest, Variable *Src0, Variable *Src1) {
Context.insert<InstMIPS32Add_d>(Dest, Src0, Src1);
}
void _add_s(Variable *Dest, Variable *Src0, Variable *Src1) {
Context.insert<InstMIPS32Add_s>(Dest, Src0, Src1);
}
void _addiu(Variable *Dest, Variable *Src, uint32_t Imm) {
Context.insert<InstMIPS32Addiu>(Dest, Src, Imm);
}
......@@ -185,6 +193,14 @@ public:
Context.insert<InstMIPS32Div>(Dest, Src0, Src1);
}
void _div_d(Variable *Dest, Variable *Src0, Variable *Src1) {
Context.insert<InstMIPS32Div_d>(Dest, Src0, Src1);
}
void _div_s(Variable *Dest, Variable *Src0, Variable *Src1) {
Context.insert<InstMIPS32Div_s>(Dest, Src0, Src1);
}
void _divu(Variable *Dest, Variable *Src0, Variable *Src1) {
Context.insert<InstMIPS32Divu>(Dest, Src0, Src1);
}
......@@ -209,6 +225,18 @@ public:
}
}
void _mov_d(Variable *Dest, Variable *Src) {
Context.insert<InstMIPS32Mov_d>(Dest, Src);
}
void _mov_s(Variable *Dest, Variable *Src) {
Context.insert<InstMIPS32Mov_s>(Dest, Src);
}
void _mfc1(Variable *Dest, Variable *Src) {
Context.insert<InstMIPS32Mfc1>(Dest, Src);
}
void _mfhi(Variable *Dest, Operand *Src) {
Context.insert<InstMIPS32Mfhi>(Dest, Src);
}
......@@ -217,6 +245,10 @@ public:
Context.insert<InstMIPS32Mflo>(Dest, Src);
}
void _mtc1(Variable *Dest, Variable *Src) {
Context.insert<InstMIPS32Mtc1>(Dest, Src);
}
void _mthi(Variable *Dest, Operand *Src) {
Context.insert<InstMIPS32Mthi>(Dest, Src);
}
......@@ -229,6 +261,14 @@ public:
Context.insert<InstMIPS32Mul>(Dest, Src0, Src1);
}
void _mul_d(Variable *Dest, Variable *Src0, Variable *Src1) {
Context.insert<InstMIPS32Mul_d>(Dest, Src0, Src1);
}
void _mul_s(Variable *Dest, Variable *Src0, Variable *Src1) {
Context.insert<InstMIPS32Mul_s>(Dest, Src0, Src1);
}
void _mult(Variable *Dest, Variable *Src0, Variable *Src1) {
Context.insert<InstMIPS32Mult>(Dest, Src0, Src1);
}
......@@ -289,6 +329,14 @@ public:
Context.insert<InstMIPS32Sub>(Dest, Src0, Src1);
}
void _sub_d(Variable *Dest, Variable *Src0, Variable *Src1) {
Context.insert<InstMIPS32Sub_d>(Dest, Src0, Src1);
}
void _sub_s(Variable *Dest, Variable *Src0, Variable *Src1) {
Context.insert<InstMIPS32Sub_s>(Dest, Src0, Src1);
}
void _subu(Variable *Dest, Variable *Src0, Variable *Src1) {
Context.insert<InstMIPS32Subu>(Dest, Src0, Src1);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment