Commit 132ea7a5 by Srdjan Obucina Committed by Jim Stichnoth

Subzero, MIPS32: Floating point support in ELF output

Patch implements improvements and instruction encodings for many COP1 instructions for handling floating point values. Patch covers load, store, basic arithmetic, data movement for FPR<->FPR, GPR<->FPR, FPR<->GPR, and format conversion instructinos. Added instruction encodings: Load: lb, lh, lwc1, ldc1 Store: sb, sh, swc1, sdc1 FP arith: abs_d, abs_s, add_d, add_s, div_d, div_s, mul_d, mul_s, sqrt_d, sqrt_s, sub_d, sub_s FP movs: mfc1, mov_d, mov_s, movn_d, movn_s, movz_d, movz_s, mtc1 Conversion: cvt_d_l, cvt_d_s, cvt_d_w, cvt_s_d, cvt_s_l, cvt_s_w, trunc_l_d, trunc_l_s, trunc_w_d, trunc_w_s R=stichnot@chromium.org Review URL: https://codereview.chromium.org/2341713003 . Patch from Srdjan Obucina <Srdjan.Obucina@imgtec.com>.
parent 40fc8193
...@@ -27,6 +27,13 @@ namespace MIPS32 { ...@@ -27,6 +27,13 @@ namespace MIPS32 {
using IValueT = uint32_t; using IValueT = uint32_t;
using IOffsetT = int32_t; using IOffsetT = int32_t;
enum FPInstDataFormat {
SinglePrecision = 16,
DoublePrecision = 17,
Word = 20,
Long = 21
};
class AssemblerMIPS32 : public Assembler { class AssemblerMIPS32 : public Assembler {
AssemblerMIPS32(const AssemblerMIPS32 &) = delete; AssemblerMIPS32(const AssemblerMIPS32 &) = delete;
AssemblerMIPS32 &operator=(const AssemblerMIPS32 &) = delete; AssemblerMIPS32 &operator=(const AssemblerMIPS32 &) = delete;
...@@ -54,56 +61,134 @@ public: ...@@ -54,56 +61,134 @@ public:
void nop(); void nop();
void emitRtRsImm16(IValueT Opcode, const Operand *OpRt, const Operand *OpRs, void emitRtRsImm16(IValueT Opcode, const Operand *OpRt, const Operand *OpRs,
const uint32_t Imm, const char *InsnName); uint32_t Imm, const char *InsnName);
void emitFtRsImm16(IValueT Opcode, const Operand *OpFt, const Operand *OpRs,
uint32_t Imm, const char *InsnName);
void emitRdRtSa(IValueT Opcode, const Operand *OpRd, const Operand *OpRt, void emitRdRtSa(IValueT Opcode, const Operand *OpRd, const Operand *OpRt,
const uint32_t Sa, const char *InsnName); uint32_t Sa, const char *InsnName);
void emitRdRsRt(IValueT Opcode, const Operand *OpRd, const Operand *OpRs, void emitRdRsRt(IValueT Opcode, const Operand *OpRd, const Operand *OpRs,
const Operand *OpRt, const char *InsnName); const Operand *OpRt, const char *InsnName);
void emitCOP1FmtFsFd(IValueT Opcode, FPInstDataFormat Format,
const Operand *OpFd, const Operand *OpFs,
const char *InsnName);
void emitCOP1FmtFtFsFd(IValueT Opcode, FPInstDataFormat Format,
const Operand *OpFd, const Operand *OpFs,
const Operand *OpFt, const char *InsnName);
void emitCOP1FmtRtFsFd(IValueT Opcode, FPInstDataFormat Format,
const Operand *OpFd, const Operand *OpFs,
const Operand *OpRt, const char *InsnName);
void emitCOP1MovRtFs(IValueT Opcode, const Operand *OpRt, const Operand *OpFs,
const char *InsnName);
void emitBr(const CondMIPS32::Cond Cond, const Operand *OpRs, void emitBr(const CondMIPS32::Cond Cond, const Operand *OpRs,
const Operand *OpRt, IOffsetT Offset); const Operand *OpRt, IOffsetT Offset);
void addiu(const Operand *OpRt, const Operand *OpRs, const uint32_t Imm); void abs_d(const Operand *OpFd, const Operand *OpFs);
void slti(const Operand *OpRt, const Operand *OpRs, const uint32_t Imm); void abs_s(const Operand *OpFd, const Operand *OpFs);
void sltiu(const Operand *OpRt, const Operand *OpRs, const uint32_t Imm); void add_d(const Operand *OpFd, const Operand *OpFs, const Operand *OpFt);
void add_s(const Operand *OpFd, const Operand *OpFs, const Operand *OpFt);
void addu(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt);
void addiu(const Operand *OpRt, const Operand *OpRs, const uint32_t Imm);
void and_(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt); void and_(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt);
void andi(const Operand *OpRt, const Operand *OpRs, const uint32_t Imm); void andi(const Operand *OpRt, const Operand *OpRs, const uint32_t Imm);
void or_(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt); void b(Label *TargetLabel);
void ori(const Operand *OpRt, const Operand *OpRs, const uint32_t Imm); void cvt_d_l(const Operand *OpFd, const Operand *OpFs);
void xor_(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt); void cvt_d_s(const Operand *OpFd, const Operand *OpFs);
void xori(const Operand *OpRt, const Operand *OpRs, const uint32_t Imm); void cvt_d_w(const Operand *OpFd, const Operand *OpFs);
void sll(const Operand *OpRd, const Operand *OpRt, const uint32_t Sa); void cvt_s_d(const Operand *OpFd, const Operand *OpFs);
void srl(const Operand *OpRd, const Operand *OpRt, const uint32_t Sa); void cvt_s_l(const Operand *OpFd, const Operand *OpFs);
void sra(const Operand *OpRd, const Operand *OpRt, const uint32_t Sa); void cvt_s_w(const Operand *OpFd, const Operand *OpFs);
void div_d(const Operand *OpFd, const Operand *OpFs, const Operand *OpFt);
void div_s(const Operand *OpFd, const Operand *OpFs, const Operand *OpFt);
void lw(const Operand *OpRt, const Operand *OpBase, const uint32_t Offset);
void mfc1(const Operand *OpRt, const Operand *OpFs);
void mov_d(const Operand *OpFd, const Operand *OpFs);
void mov_s(const Operand *OpFd, const Operand *OpFs);
void move(const Operand *OpRd, const Operand *OpRs); void move(const Operand *OpRd, const Operand *OpRs);
void addu(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt); void movn_d(const Operand *OpFd, const Operand *OpFs, const Operand *OpFt);
void movn_s(const Operand *OpFd, const Operand *OpFs, const Operand *OpFt);
void movz_d(const Operand *OpFd, const Operand *OpFs, const Operand *OpFt);
void movz_s(const Operand *OpFd, const Operand *OpFs, const Operand *OpFt);
void mtc1(const Operand *OpRt, const Operand *OpFs);
void mul_d(const Operand *OpFd, const Operand *OpFs, const Operand *OpFt);
void mul_s(const Operand *OpFd, const Operand *OpFs, const Operand *OpFt);
void or_(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt);
void ori(const Operand *OpRt, const Operand *OpRs, const uint32_t Imm);
void ret(void);
void sll(const Operand *OpRd, const Operand *OpRt, const uint32_t Sa);
void slt(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt); void slt(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt);
void slti(const Operand *OpRt, const Operand *OpRs, const uint32_t Imm);
void sltiu(const Operand *OpRt, const Operand *OpRs, const uint32_t Imm);
void sltu(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt); void sltu(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt);
void sqrt_d(const Operand *OpFd, const Operand *OpFs);
void sqrt_s(const Operand *OpFd, const Operand *OpFs);
void sra(const Operand *OpRd, const Operand *OpRt, const uint32_t Sa);
void srl(const Operand *OpRd, const Operand *OpRt, const uint32_t Sa);
void sub_d(const Operand *OpFd, const Operand *OpFs, const Operand *OpFt);
void sub_s(const Operand *OpFd, const Operand *OpFs, const Operand *OpFt);
void sw(const Operand *OpRt, const Operand *OpBase, const uint32_t Offset); void sw(const Operand *OpRt, const Operand *OpBase, const uint32_t Offset);
void lw(const Operand *OpRt, const Operand *OpBase, const uint32_t Offset); void trunc_l_d(const Operand *OpFd, const Operand *OpFs);
void ret(void); void trunc_l_s(const Operand *OpFd, const Operand *OpFs);
void b(Label *TargetLabel); void trunc_w_d(const Operand *OpFd, const Operand *OpFs);
void trunc_w_s(const Operand *OpFd, const Operand *OpFs);
void xor_(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt);
void xori(const Operand *OpRt, const Operand *OpRs, const uint32_t Imm);
void bcc(const CondMIPS32::Cond Cond, const Operand *OpRs, void bcc(const CondMIPS32::Cond Cond, const Operand *OpRs,
const Operand *OpRt, Label *TargetLabel); const Operand *OpRt, Label *TargetLabel);
......
...@@ -1171,31 +1171,60 @@ private: ...@@ -1171,31 +1171,60 @@ private:
// default implementations. Without this, there is the possibility of ODR // default implementations. Without this, there is the possibility of ODR
// violations and link errors. // violations and link errors.
template <> void InstMIPS32Abs_d::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Abs_s::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Add_d::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Add_s::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Addiu::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Addu::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32And::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Andi::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Cvt_d_l::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Cvt_d_s::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Cvt_d_w::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Cvt_s_d::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Cvt_s_l::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Cvt_s_w::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Div_d::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Div_s::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Lui::emit(const Cfg *Func) const;
template <> void InstMIPS32Lw::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Mfc1::emit(const Cfg *Func) const;
template <> void InstMIPS32Mflo::emit(const Cfg *Func) const; template <> void InstMIPS32Mflo::emit(const Cfg *Func) const;
template <> void InstMIPS32Mfhi::emit(const Cfg *Func) const; template <> void InstMIPS32Mfhi::emit(const Cfg *Func) const;
template <> void InstMIPS32Mov_d::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Mov_s::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Movn_d::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Movn_s::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Movz_d::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Movz_s::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Mtc1::emit(const Cfg *Func) const;
template <> void InstMIPS32Mtlo::emit(const Cfg *Func) const; template <> void InstMIPS32Mtlo::emit(const Cfg *Func) const;
template <> void InstMIPS32Mthi::emit(const Cfg *Func) const; template <> void InstMIPS32Mthi::emit(const Cfg *Func) const;
template <> void InstMIPS32Mul_d::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Mul_s::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Mult::emit(const Cfg *Func) const; template <> void InstMIPS32Mult::emit(const Cfg *Func) const;
template <> void InstMIPS32Multu::emit(const Cfg *Func) const; template <> void InstMIPS32Multu::emit(const Cfg *Func) const;
template <> void InstMIPS32Lui::emit(const Cfg *Func) const;
template <> void InstMIPS32Addiu::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Slti::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Sltiu::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32And::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Andi::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Or::emitIAS(const Cfg *Func) const; template <> void InstMIPS32Or::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Ori::emitIAS(const Cfg *Func) const; template <> void InstMIPS32Ori::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Xor::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Xori::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Sll::emitIAS(const Cfg *Func) const; template <> void InstMIPS32Sll::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Srl::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Sra::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Addu::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Slt::emitIAS(const Cfg *Func) const; template <> void InstMIPS32Slt::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Slti::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Sltiu::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Sltu::emitIAS(const Cfg *Func) const; template <> void InstMIPS32Sltu::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Sqrt_d::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Sqrt_s::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Sw::emitIAS(const Cfg *Func) const; template <> void InstMIPS32Sw::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Lw::emitIAS(const Cfg *Func) const; template <> void InstMIPS32Sra::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Srl::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Sub_d::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Sub_s::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Trunc_l_d::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Trunc_l_s::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Trunc_w_d::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Trunc_w_s::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Xor::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Xori::emitIAS(const Cfg *Func) const;
} // end of namespace MIPS32 } // end of namespace MIPS32
} // end of namespace Ice } // end of namespace Ice
......
...@@ -86,8 +86,19 @@ static inline FPRRegister getEncodedFPR(RegNumT RegNum) { ...@@ -86,8 +86,19 @@ static inline FPRRegister getEncodedFPR(RegNumT RegNum) {
} }
static inline bool isFPRReg(RegNumT RegNum) { static inline bool isFPRReg(RegNumT RegNum) {
return (int(Reg_FPR_First) <= int(RegNum)) && return ((int(Reg_FPR_First) <= int(RegNum)) &&
(unsigned(RegNum) <= Reg_FPR_Last); (unsigned(RegNum) <= Reg_FPR_Last));
}
static inline FPRRegister getEncodedFPR64(RegNumT RegNum) {
assert(int(Reg_F64PAIR_First) <= int(RegNum));
assert(unsigned(RegNum) <= Reg_F64PAIR_Last);
return FPRRegister((RegNum - Reg_F64PAIR_First) * 2);
}
static inline bool isFPR64Reg(RegNumT RegNum) {
return (int(Reg_F64PAIR_First) <= int(RegNum)) &&
(unsigned(RegNum) <= Reg_F64PAIR_Last);
} }
const char *getRegName(RegNumT RegNum); const char *getRegName(RegNumT RegNum);
......
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