Index: src/IceAssemblerMIPS32.cpp |
diff --git a/src/IceAssemblerMIPS32.cpp b/src/IceAssemblerMIPS32.cpp |
index b9ddff1cf3dddca2e063e13dd7fe942b85ebc64f..54188b256d27d571415ab60f69eddda30119e345 100644 |
--- a/src/IceAssemblerMIPS32.cpp |
+++ b/src/IceAssemblerMIPS32.cpp |
@@ -102,6 +102,8 @@ void AssemblerMIPS32::bindCfgNodeLabel(const CfgNode *Node) { |
this->bind(L); |
} |
+namespace { |
+ |
// Checks that Offset can fit in imm16 constant of branch instruction. |
void assertCanEncodeBranchOffset(IOffsetT Offset) { |
(void)Offset; |
@@ -118,34 +120,26 @@ IValueT encodeBranchOffset(IOffsetT Offset, IValueT Inst) { |
return (Inst & ~kBranchOffsetMask) | Offset; |
} |
-IOffsetT AssemblerMIPS32::decodeBranchOffset(IValueT Inst) { |
- int16_t imm = (Inst & kBranchOffsetMask); |
- IOffsetT Offset = imm; |
- Offset = Offset << 2; |
- return (Offset + kPCReadOffset); |
-} |
- |
-void AssemblerMIPS32::bind(Label *L) { |
- IOffsetT BoundPc = Buffer.size(); |
- assert(!L->isBound()); // Labels can only be bound once. |
- while (L->isLinked()) { |
- IOffsetT Position = L->getLinkPosition(); |
- IOffsetT Dest = BoundPc - Position; |
- IValueT Inst = Buffer.load<IValueT>(Position); |
- Buffer.store<IValueT>(Position, encodeBranchOffset(Dest, Inst)); |
- L->setPosition(decodeBranchOffset(Inst)); |
- } |
- L->bindTo(BoundPc); |
-} |
- |
enum RegSetWanted { WantGPRegs, WantFPRegs }; |
IValueT getEncodedGPRegNum(const Variable *Var) { |
- assert(Var->hasReg()); |
+ assert(Var->hasReg() && isScalarIntegerType(Var->getType())); |
const auto Reg = Var->getRegNum(); |
return RegMIPS32::getEncodedGPR(Reg); |
} |
+IValueT getEncodedFPRegNum(const Variable *Var) { |
+ assert(Var->hasReg() && isScalarFloatingType(Var->getType())); |
+ const auto Reg = Var->getRegNum(); |
+ IValueT RegEncoding; |
+ if (RegMIPS32::isFPRReg(Reg)) { |
+ RegEncoding = RegMIPS32::getEncodedFPR(Reg); |
+ } else { |
+ RegEncoding = RegMIPS32::getEncodedFPR64(Reg); |
+ } |
+ return RegEncoding; |
+} |
+ |
bool encodeOperand(const Operand *Opnd, IValueT &Value, |
RegSetWanted WantedRegSet) { |
Value = 0; |
@@ -155,7 +149,8 @@ bool encodeOperand(const Operand *Opnd, IValueT &Value, |
case WantGPRegs: |
Value = getEncodedGPRegNum(Var); |
break; |
- default: |
+ case WantFPRegs: |
+ Value = getEncodedFPRegNum(Var); |
break; |
} |
return true; |
@@ -179,6 +174,32 @@ IValueT encodeGPRegister(const Operand *OpReg, const char *RegName, |
return encodeRegister(OpReg, WantGPRegs, RegName, InstName); |
} |
+IValueT encodeFPRegister(const Operand *OpReg, const char *RegName, |
+ const char *InstName) { |
+ return encodeRegister(OpReg, WantFPRegs, RegName, InstName); |
+} |
+} |
+ |
+IOffsetT AssemblerMIPS32::decodeBranchOffset(IValueT Inst) { |
+ int16_t imm = (Inst & kBranchOffsetMask); |
+ IOffsetT Offset = imm; |
+ Offset = Offset << 2; |
+ return (Offset + kPCReadOffset); |
+} |
+ |
+void AssemblerMIPS32::bind(Label *L) { |
+ IOffsetT BoundPc = Buffer.size(); |
+ assert(!L->isBound()); // Labels can only be bound once. |
+ while (L->isLinked()) { |
+ IOffsetT Position = L->getLinkPosition(); |
+ IOffsetT Dest = BoundPc - Position; |
+ IValueT Inst = Buffer.load<IValueT>(Position); |
+ Buffer.store<IValueT>(Position, encodeBranchOffset(Dest, Inst)); |
+ L->setPosition(decodeBranchOffset(Inst)); |
+ } |
+ L->bindTo(BoundPc); |
+} |
+ |
void AssemblerMIPS32::emitRtRsImm16(IValueT Opcode, const Operand *OpRt, |
const Operand *OpRs, const uint32_t Imm, |
const char *InsnName) { |
@@ -192,6 +213,19 @@ void AssemblerMIPS32::emitRtRsImm16(IValueT Opcode, const Operand *OpRt, |
emitInst(Opcode); |
} |
+void AssemblerMIPS32::emitFtRsImm16(IValueT Opcode, const Operand *OpFt, |
+ const Operand *OpRs, const uint32_t Imm, |
+ const char *InsnName) { |
+ const IValueT Ft = encodeFPRegister(OpFt, "Ft", InsnName); |
+ const IValueT Rs = encodeGPRegister(OpRs, "Rs", InsnName); |
+ |
+ Opcode |= Rs << 21; |
+ Opcode |= Ft << 16; |
+ Opcode |= Imm & 0xffff; |
+ |
+ emitInst(Opcode); |
+} |
+ |
void AssemblerMIPS32::emitRdRtSa(IValueT Opcode, const Operand *OpRd, |
const Operand *OpRt, const uint32_t Sa, |
const char *InsnName) { |
@@ -219,22 +253,96 @@ void AssemblerMIPS32::emitRdRsRt(IValueT Opcode, const Operand *OpRd, |
emitInst(Opcode); |
} |
+void AssemblerMIPS32::emitCOP1FmtFsFd(IValueT Opcode, FPInstDataFormat Format, |
+ const Operand *OpFd, const Operand *OpFs, |
+ const char *InsnName) { |
+ const IValueT Fd = encodeFPRegister(OpFd, "Fd", InsnName); |
+ const IValueT Fs = encodeFPRegister(OpFs, "Fs", InsnName); |
+ |
+ Opcode |= Fd << 6; |
+ Opcode |= Fs << 11; |
+ Opcode |= Format << 21; |
+ |
+ emitInst(Opcode); |
+} |
+ |
+void AssemblerMIPS32::emitCOP1FmtFtFsFd(IValueT Opcode, FPInstDataFormat Format, |
+ const Operand *OpFd, |
+ const Operand *OpFs, |
+ const Operand *OpFt, |
+ const char *InsnName) { |
+ const IValueT Fd = encodeFPRegister(OpFd, "Fd", InsnName); |
+ const IValueT Fs = encodeFPRegister(OpFs, "Fs", InsnName); |
+ const IValueT Ft = encodeFPRegister(OpFt, "Ft", InsnName); |
+ |
+ Opcode |= Fd << 6; |
+ Opcode |= Fs << 11; |
+ Opcode |= Ft << 16; |
+ Opcode |= Format << 21; |
+ |
+ emitInst(Opcode); |
+} |
+ |
+void AssemblerMIPS32::emitCOP1FmtRtFsFd(IValueT Opcode, FPInstDataFormat Format, |
+ const Operand *OpFd, |
+ const Operand *OpFs, |
+ const Operand *OpRt, |
+ const char *InsnName) { |
+ const IValueT Fd = encodeFPRegister(OpFd, "Fd", InsnName); |
+ const IValueT Fs = encodeFPRegister(OpFs, "Fs", InsnName); |
+ const IValueT Rt = encodeGPRegister(OpRt, "Rt", InsnName); |
+ |
+ Opcode |= Fd << 6; |
+ Opcode |= Fs << 11; |
+ Opcode |= Rt << 16; |
+ Opcode |= Format << 21; |
+ |
+ emitInst(Opcode); |
+} |
+ |
+void AssemblerMIPS32::emitCOP1MovRtFs(IValueT Opcode, const Operand *OpRt, |
+ const Operand *OpFs, |
+ const char *InsnName) { |
+ const IValueT Rt = encodeGPRegister(OpRt, "Rt", InsnName); |
+ const IValueT Fs = encodeFPRegister(OpFs, "Fs", InsnName); |
+ Opcode |= Fs << 11; |
+ Opcode |= Rt << 16; |
+ |
+ emitInst(Opcode); |
+} |
+ |
+void AssemblerMIPS32::abs_d(const Operand *OpFd, const Operand *OpFs) { |
+ static constexpr IValueT Opcode = 0x44000005; |
+ emitCOP1FmtFsFd(Opcode, DoublePrecision, OpFd, OpFs, "abs.d"); |
+} |
+ |
+void AssemblerMIPS32::abs_s(const Operand *OpFd, const Operand *OpFs) { |
+ static constexpr IValueT Opcode = 0x44000005; |
+ emitCOP1FmtFsFd(Opcode, SinglePrecision, OpFd, OpFs, "abs.s"); |
+} |
+ |
+void AssemblerMIPS32::add_d(const Operand *OpFd, const Operand *OpFs, |
+ const Operand *OpFt) { |
+ static constexpr IValueT Opcode = 0x44000000; |
+ emitCOP1FmtFtFsFd(Opcode, DoublePrecision, OpFd, OpFs, OpFt, "add.d"); |
+} |
+ |
+void AssemblerMIPS32::add_s(const Operand *OpFd, const Operand *OpFs, |
+ const Operand *OpFt) { |
+ static constexpr IValueT Opcode = 0x44000000; |
+ emitCOP1FmtFtFsFd(Opcode, SinglePrecision, OpFd, OpFs, OpFt, "add.s"); |
+} |
+ |
void AssemblerMIPS32::addiu(const Operand *OpRt, const Operand *OpRs, |
const uint32_t Imm) { |
static constexpr IValueT Opcode = 0x24000000; |
emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "addiu"); |
} |
-void AssemblerMIPS32::slti(const Operand *OpRt, const Operand *OpRs, |
- const uint32_t Imm) { |
- static constexpr IValueT Opcode = 0x28000000; |
- emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "slti"); |
-} |
- |
-void AssemblerMIPS32::sltiu(const Operand *OpRt, const Operand *OpRs, |
- const uint32_t Imm) { |
- static constexpr IValueT Opcode = 0x2c000000; |
- emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "sltiu"); |
+void AssemblerMIPS32::addu(const Operand *OpRd, const Operand *OpRs, |
+ const Operand *OpRt) { |
+ static constexpr IValueT Opcode = 0x00000021; |
+ emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "addu"); |
} |
void AssemblerMIPS32::and_(const Operand *OpRd, const Operand *OpRs, |
@@ -249,6 +357,186 @@ void AssemblerMIPS32::andi(const Operand *OpRt, const Operand *OpRs, |
emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "andi"); |
} |
+void AssemblerMIPS32::b(Label *TargetLabel) { |
+ static constexpr Operand *OpRsNone = nullptr; |
+ static constexpr Operand *OpRtNone = nullptr; |
+ if (TargetLabel->isBound()) { |
+ const int32_t Dest = TargetLabel->getPosition() - Buffer.size(); |
+ emitBr(CondMIPS32::AL, OpRsNone, OpRtNone, Dest); |
+ return; |
+ } |
+ const IOffsetT Position = Buffer.size(); |
+ emitBr(CondMIPS32::AL, OpRsNone, OpRtNone, TargetLabel->getEncodedPosition()); |
+ TargetLabel->linkTo(*this, Position); |
+} |
+ |
+void AssemblerMIPS32::cvt_d_l(const Operand *OpFd, const Operand *OpFs) { |
+ static constexpr IValueT Opcode = 0x44000021; |
+ emitCOP1FmtFsFd(Opcode, Long, OpFd, OpFs, "cvt.d.l"); |
+} |
+ |
+void AssemblerMIPS32::cvt_d_s(const Operand *OpFd, const Operand *OpFs) { |
+ static constexpr IValueT Opcode = 0x44000021; |
+ emitCOP1FmtFsFd(Opcode, SinglePrecision, OpFd, OpFs, "cvt.d.s"); |
+} |
+ |
+void AssemblerMIPS32::cvt_d_w(const Operand *OpFd, const Operand *OpFs) { |
+ static constexpr IValueT Opcode = 0x44000021; |
+ emitCOP1FmtFsFd(Opcode, Word, OpFd, OpFs, "cvt.d.w"); |
+} |
+ |
+void AssemblerMIPS32::cvt_s_d(const Operand *OpFd, const Operand *OpFs) { |
+ static constexpr IValueT Opcode = 0x44000020; |
+ emitCOP1FmtFsFd(Opcode, DoublePrecision, OpFd, OpFs, "cvt.s.d"); |
+} |
+ |
+void AssemblerMIPS32::cvt_s_l(const Operand *OpFd, const Operand *OpFs) { |
+ static constexpr IValueT Opcode = 0x44000020; |
+ emitCOP1FmtFsFd(Opcode, Long, OpFd, OpFs, "cvt.s.l"); |
+} |
+ |
+void AssemblerMIPS32::cvt_s_w(const Operand *OpFd, const Operand *OpFs) { |
+ static constexpr IValueT Opcode = 0x44000020; |
+ emitCOP1FmtFsFd(Opcode, Word, OpFd, OpFs, "cvt.s.w"); |
+} |
+ |
+void AssemblerMIPS32::div_d(const Operand *OpFd, const Operand *OpFs, |
+ const Operand *OpFt) { |
+ static constexpr IValueT Opcode = 0x44000003; |
+ emitCOP1FmtFtFsFd(Opcode, DoublePrecision, OpFd, OpFs, OpFt, "div.d"); |
+} |
+ |
+void AssemblerMIPS32::div_s(const Operand *OpFd, const Operand *OpFs, |
+ const Operand *OpFt) { |
+ static constexpr IValueT Opcode = 0x44000003; |
+ emitCOP1FmtFtFsFd(Opcode, SinglePrecision, OpFd, OpFs, OpFt, "div.s"); |
+} |
+ |
+void AssemblerMIPS32::lw(const Operand *OpRt, const Operand *OpBase, |
+ const uint32_t Offset) { |
+ switch (OpRt->getType()) { |
+ case IceType_i1: |
+ case IceType_i8: { |
+ static constexpr IValueT Opcode = 0x80000000; |
+ emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "lb"); |
+ } |
+ case IceType_i16: { |
+ static constexpr IValueT Opcode = 0x84000000; |
+ emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "lh"); |
+ } |
+ case IceType_i32: { |
+ static constexpr IValueT Opcode = 0x8C000000; |
+ emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "lw"); |
+ break; |
+ } |
+ case IceType_f32: { |
+ static constexpr IValueT Opcode = 0xC4000000; |
+ emitFtRsImm16(Opcode, OpRt, OpBase, Offset, "lwc1"); |
+ } |
+ case IceType_f64: { |
+ static constexpr IValueT Opcode = 0xD4000000; |
+ emitFtRsImm16(Opcode, OpRt, OpBase, Offset, "ldc1"); |
+ break; |
+ } |
+ default: { UnimplementedError(getFlags()); } |
+ } |
+} |
+ |
+void AssemblerMIPS32::mfc1(const Operand *OpRt, const Operand *OpFs) { |
+ static constexpr IValueT Opcode = 0x44000000; |
+ emitCOP1MovRtFs(Opcode, OpRt, OpFs, "mfc1"); |
+} |
+ |
+void AssemblerMIPS32::mov_d(const Operand *OpFd, const Operand *OpFs) { |
+ static constexpr IValueT Opcode = 0x44000006; |
+ emitCOP1FmtFsFd(Opcode, DoublePrecision, OpFd, OpFs, "mov.d"); |
+} |
+ |
+void AssemblerMIPS32::mov_s(const Operand *OpFd, const Operand *OpFs) { |
+ static constexpr IValueT Opcode = 0x44000006; |
+ emitCOP1FmtFsFd(Opcode, SinglePrecision, OpFd, OpFs, "mov.s"); |
+} |
+ |
+void AssemblerMIPS32::move(const Operand *OpRd, const Operand *OpRs) { |
+ |
+ const Type DstType = OpRd->getType(); |
+ const Type SrcType = OpRs->getType(); |
+ |
+ if ((isScalarIntegerType(DstType) && isScalarFloatingType(SrcType)) || |
+ (isScalarFloatingType(DstType) && isScalarIntegerType(SrcType))) { |
+ if (isScalarFloatingType(DstType)) { |
+ mtc1(OpRd, OpRs); |
+ } else { |
+ mfc1(OpRd, OpRs); |
+ } |
+ } else { |
+ switch (DstType) { |
+ case IceType_f32: |
+ mov_s(OpRd, OpRs); |
+ break; |
+ case IceType_f64: |
+ mov_d(OpRd, OpRs); |
+ break; |
+ case IceType_i1: |
+ case IceType_i8: |
+ case IceType_i16: |
+ case IceType_i32: { |
+ IValueT Opcode = 0x00000021; |
+ const IValueT Rd = encodeGPRegister(OpRd, "Rd", "pseudo-move"); |
+ const IValueT Rs = encodeGPRegister(OpRs, "Rs", "pseudo-move"); |
+ const IValueT Rt = 0; // $0 |
+ Opcode |= Rs << 21; |
+ Opcode |= Rt << 16; |
+ Opcode |= Rd << 11; |
+ emitInst(Opcode); |
+ break; |
+ } |
+ default: { UnimplementedError(getFlags()); } |
+ } |
+ } |
+} |
+ |
+void AssemblerMIPS32::movn_d(const Operand *OpFd, const Operand *OpFs, |
+ const Operand *OpFt) { |
+ static constexpr IValueT Opcode = 0x44000013; |
+ emitCOP1FmtFtFsFd(Opcode, SinglePrecision, OpFd, OpFs, OpFt, "movn.d"); |
+} |
+ |
+void AssemblerMIPS32::movn_s(const Operand *OpFd, const Operand *OpFs, |
+ const Operand *OpFt) { |
+ static constexpr IValueT Opcode = 0x44000013; |
+ emitCOP1FmtFtFsFd(Opcode, SinglePrecision, OpFd, OpFs, OpFt, "movn.s"); |
+} |
+ |
+void AssemblerMIPS32::movz_d(const Operand *OpFd, const Operand *OpFs, |
+ const Operand *OpFt) { |
+ static constexpr IValueT Opcode = 0x44000012; |
+ emitCOP1FmtFtFsFd(Opcode, SinglePrecision, OpFd, OpFs, OpFt, "movz.d"); |
+} |
+ |
+void AssemblerMIPS32::movz_s(const Operand *OpFd, const Operand *OpFs, |
+ const Operand *OpFt) { |
+ static constexpr IValueT Opcode = 0x44000012; |
+ emitCOP1FmtFtFsFd(Opcode, SinglePrecision, OpFd, OpFs, OpFt, "movz.s"); |
+} |
+ |
+void AssemblerMIPS32::mtc1(const Operand *OpRt, const Operand *OpFs) { |
+ static constexpr IValueT Opcode = 0x44800000; |
+ emitCOP1MovRtFs(Opcode, OpRt, OpFs, "mtc1"); |
+} |
+ |
+void AssemblerMIPS32::mul_d(const Operand *OpFd, const Operand *OpFs, |
+ const Operand *OpFt) { |
+ static constexpr IValueT Opcode = 0x44000002; |
+ emitCOP1FmtFtFsFd(Opcode, DoublePrecision, OpFd, OpFs, OpFt, "mul.d"); |
+} |
+ |
+void AssemblerMIPS32::mul_s(const Operand *OpFd, const Operand *OpFs, |
+ const Operand *OpFt) { |
+ static constexpr IValueT Opcode = 0x44000002; |
+ emitCOP1FmtFtFsFd(Opcode, SinglePrecision, OpFd, OpFs, OpFt, "mul.s"); |
+} |
+ |
void AssemblerMIPS32::or_(const Operand *OpRd, const Operand *OpRs, |
const Operand *OpRt) { |
static constexpr IValueT Opcode = 0x00000025; |
@@ -261,16 +549,10 @@ void AssemblerMIPS32::ori(const Operand *OpRt, const Operand *OpRs, |
emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "ori"); |
} |
-void AssemblerMIPS32::xor_(const Operand *OpRd, const Operand *OpRs, |
- const Operand *OpRt) { |
- static constexpr IValueT Opcode = 0x00000026; |
- emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "xor"); |
-} |
- |
-void AssemblerMIPS32::xori(const Operand *OpRt, const Operand *OpRs, |
- const uint32_t Imm) { |
- static constexpr IValueT Opcode = 0x38000000; |
- emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "xori"); |
+void AssemblerMIPS32::ret(void) { |
+ static constexpr IValueT Opcode = 0x03E00008; // JR $31 |
+ emitInst(Opcode); |
+ nop(); // delay slot |
} |
void AssemblerMIPS32::sll(const Operand *OpRd, const Operand *OpRt, |
@@ -279,10 +561,38 @@ void AssemblerMIPS32::sll(const Operand *OpRd, const Operand *OpRt, |
emitRdRtSa(Opcode, OpRd, OpRt, Sa, "sll"); |
} |
-void AssemblerMIPS32::srl(const Operand *OpRd, const Operand *OpRt, |
- const uint32_t Sa) { |
- static constexpr IValueT Opcode = 0x00000002; |
- emitRdRtSa(Opcode, OpRd, OpRt, Sa, "srl"); |
+void AssemblerMIPS32::slt(const Operand *OpRd, const Operand *OpRs, |
+ const Operand *OpRt) { |
+ static constexpr IValueT Opcode = 0x0000002A; |
+ emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "slt"); |
+} |
+ |
+void AssemblerMIPS32::slti(const Operand *OpRt, const Operand *OpRs, |
+ const uint32_t Imm) { |
+ static constexpr IValueT Opcode = 0x28000000; |
+ emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "slti"); |
+} |
+ |
+void AssemblerMIPS32::sltu(const Operand *OpRd, const Operand *OpRs, |
+ const Operand *OpRt) { |
+ static constexpr IValueT Opcode = 0x0000002B; |
+ emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "sltu"); |
+} |
+ |
+void AssemblerMIPS32::sltiu(const Operand *OpRt, const Operand *OpRs, |
+ const uint32_t Imm) { |
+ static constexpr IValueT Opcode = 0x2c000000; |
+ emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "sltiu"); |
+} |
+ |
+void AssemblerMIPS32::sqrt_d(const Operand *OpFd, const Operand *OpFs) { |
+ static constexpr IValueT Opcode = 0x44000004; |
+ emitCOP1FmtFsFd(Opcode, DoublePrecision, OpFd, OpFs, "sqrt.d"); |
+} |
+ |
+void AssemblerMIPS32::sqrt_s(const Operand *OpFd, const Operand *OpFs) { |
+ static constexpr IValueT Opcode = 0x44000004; |
+ emitCOP1FmtFsFd(Opcode, SinglePrecision, OpFd, OpFs, "sqrt.s"); |
} |
void AssemblerMIPS32::sra(const Operand *OpRd, const Operand *OpRt, |
@@ -291,51 +601,87 @@ void AssemblerMIPS32::sra(const Operand *OpRd, const Operand *OpRt, |
emitRdRtSa(Opcode, OpRd, OpRt, Sa, "sra"); |
} |
-void AssemblerMIPS32::move(const Operand *OpRd, const Operand *OpRs) { |
- IValueT Opcode = 0x00000021; |
- const IValueT Rd = encodeGPRegister(OpRd, "Rd", "pseudo-move"); |
- const IValueT Rs = encodeGPRegister(OpRs, "Rs", "pseudo-move"); |
- const IValueT Rt = 0; // $0 |
- Opcode |= Rs << 21; |
- Opcode |= Rt << 16; |
- Opcode |= Rd << 11; |
- emitInst(Opcode); |
-} |
- |
-void AssemblerMIPS32::addu(const Operand *OpRd, const Operand *OpRs, |
- const Operand *OpRt) { |
- static constexpr IValueT Opcode = 0x00000021; |
- emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "addu"); |
+void AssemblerMIPS32::srl(const Operand *OpRd, const Operand *OpRt, |
+ const uint32_t Sa) { |
+ static constexpr IValueT Opcode = 0x00000002; |
+ emitRdRtSa(Opcode, OpRd, OpRt, Sa, "srl"); |
} |
-void AssemblerMIPS32::sltu(const Operand *OpRd, const Operand *OpRs, |
- const Operand *OpRt) { |
- static constexpr IValueT Opcode = 0x0000002B; |
- emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "sltu"); |
+void AssemblerMIPS32::sub_d(const Operand *OpFd, const Operand *OpFs, |
+ const Operand *OpFt) { |
+ static constexpr IValueT Opcode = 0x44000001; |
+ emitCOP1FmtFtFsFd(Opcode, DoublePrecision, OpFd, OpFs, OpFt, "sub.d"); |
} |
-void AssemblerMIPS32::slt(const Operand *OpRd, const Operand *OpRs, |
- const Operand *OpRt) { |
- static constexpr IValueT Opcode = 0x0000002A; |
- emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "slt"); |
+void AssemblerMIPS32::sub_s(const Operand *OpFd, const Operand *OpFs, |
+ const Operand *OpFt) { |
+ static constexpr IValueT Opcode = 0x44000001; |
+ emitCOP1FmtFtFsFd(Opcode, SinglePrecision, OpFd, OpFs, OpFt, "sub.s"); |
} |
void AssemblerMIPS32::sw(const Operand *OpRt, const Operand *OpBase, |
const uint32_t Offset) { |
- static constexpr IValueT Opcode = 0xAC000000; |
- emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "sw"); |
+ switch (OpRt->getType()) { |
+ case IceType_i1: |
+ case IceType_i8: { |
+ static constexpr IValueT Opcode = 0xA0000000; |
+ emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "sb"); |
+ break; |
+ } |
+ case IceType_i16: { |
+ static constexpr IValueT Opcode = 0xA4000000; |
+ emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "sh"); |
+ break; |
+ } |
+ case IceType_i32: { |
+ static constexpr IValueT Opcode = 0xAC000000; |
+ emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "sw"); |
+ break; |
+ } |
+ case IceType_f32: { |
+ static constexpr IValueT Opcode = 0xE4000000; |
+ emitFtRsImm16(Opcode, OpRt, OpBase, Offset, "swc1"); |
+ break; |
+ } |
+ case IceType_f64: { |
+ static constexpr IValueT Opcode = 0xF4000000; |
+ emitFtRsImm16(Opcode, OpRt, OpBase, Offset, "sdc1"); |
+ break; |
+ } |
+ default: { UnimplementedError(getFlags()); } |
+ } |
} |
-void AssemblerMIPS32::lw(const Operand *OpRt, const Operand *OpBase, |
- const uint32_t Offset) { |
- static constexpr IValueT Opcode = 0x8C000000; |
- emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "lw"); |
+void AssemblerMIPS32::trunc_l_d(const Operand *OpFd, const Operand *OpFs) { |
+ static constexpr IValueT Opcode = 0x4400000D; |
+ emitCOP1FmtFsFd(Opcode, Long, OpFd, OpFs, "trunc.l.d"); |
} |
-void AssemblerMIPS32::ret(void) { |
- static constexpr IValueT Opcode = 0x03E00008; // JR $31 |
- emitInst(Opcode); |
- nop(); // delay slot |
+void AssemblerMIPS32::trunc_l_s(const Operand *OpFd, const Operand *OpFs) { |
+ static constexpr IValueT Opcode = 0x4400000D; |
+ emitCOP1FmtFsFd(Opcode, Long, OpFd, OpFs, "trunc.l.s"); |
+} |
+ |
+void AssemblerMIPS32::trunc_w_d(const Operand *OpFd, const Operand *OpFs) { |
+ static constexpr IValueT Opcode = 0x4400000D; |
+ emitCOP1FmtFsFd(Opcode, Word, OpFd, OpFs, "trunc.w.d"); |
+} |
+ |
+void AssemblerMIPS32::trunc_w_s(const Operand *OpFd, const Operand *OpFs) { |
+ static constexpr IValueT Opcode = 0x4400000D; |
+ emitCOP1FmtFsFd(Opcode, Word, OpFd, OpFs, "trunc.w.s"); |
+} |
+ |
+void AssemblerMIPS32::xor_(const Operand *OpRd, const Operand *OpRs, |
+ const Operand *OpRt) { |
+ static constexpr IValueT Opcode = 0x00000026; |
+ emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "xor"); |
+} |
+ |
+void AssemblerMIPS32::xori(const Operand *OpRt, const Operand *OpRs, |
+ const uint32_t Imm) { |
+ static constexpr IValueT Opcode = 0x38000000; |
+ emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "xori"); |
} |
void AssemblerMIPS32::emitBr(const CondMIPS32::Cond Cond, const Operand *OpRs, |
@@ -387,19 +733,6 @@ void AssemblerMIPS32::emitBr(const CondMIPS32::Cond Cond, const Operand *OpRs, |
nop(); // delay slot |
} |
-void AssemblerMIPS32::b(Label *TargetLabel) { |
- static constexpr Operand *OpRsNone = nullptr; |
- static constexpr Operand *OpRtNone = nullptr; |
- if (TargetLabel->isBound()) { |
- const int32_t Dest = TargetLabel->getPosition() - Buffer.size(); |
- emitBr(CondMIPS32::AL, OpRsNone, OpRtNone, Dest); |
- return; |
- } |
- const IOffsetT Position = Buffer.size(); |
- emitBr(CondMIPS32::AL, OpRsNone, OpRtNone, TargetLabel->getEncodedPosition()); |
- TargetLabel->linkTo(*this, Position); |
-} |
- |
void AssemblerMIPS32::bcc(const CondMIPS32::Cond Cond, const Operand *OpRs, |
const Operand *OpRt, Label *TargetLabel) { |
if (TargetLabel->isBound()) { |