template <> const char *InstMIPS32Mov_d::Opcode = "mov.d";
template <> const char *InstMIPS32Mov_s::Opcode = "mov.s";
template <> const char *InstMIPS32Movf::Opcode = "movf";
+template <> const char *InstMIPS32Movn::Opcode = "movn";
+template <> const char *InstMIPS32Movn_d::Opcode = "movn.d";
+template <> const char *InstMIPS32Movn_s::Opcode = "movn.s";
template <> const char *InstMIPS32Movt::Opcode = "movt";
+template <> const char *InstMIPS32Movz::Opcode = "movz";
+template <> const char *InstMIPS32Movz_d::Opcode = "movz.d";
+template <> const char *InstMIPS32Movz_s::Opcode = "movz.s";
template <> const char *InstMIPS32Mtc1::Opcode = "mtc1";
template <> const char *InstMIPS32Mthi::Opcode = "mthi";
template <> const char *InstMIPS32Mtlo::Opcode = "mtlo";
const Type SrcType = Src->getType();
// move GP to/from FP
- if (DstType != SrcType) {
+ if ((isScalarIntegerType(DstType) && isScalarFloatingType(SrcType)) ||
+ (isScalarFloatingType(DstType) && isScalarIntegerType(SrcType))) {
if (isScalarFloatingType(DstType)) {
Str << "\t"
"mtc1"
Mov_d,
Mov_s,
Movf,
+ Movn,
+ Movn_d,
+ Movn_s,
Movt,
+ Movz,
+ Movz_d,
+ Movz_s,
Mtc1,
Mthi,
Mtlo,
using InstMIPS32Mov_d = InstMIPS32TwoAddrFPR<InstMIPS32::Mov_d>;
using InstMIPS32Mov_s = InstMIPS32TwoAddrFPR<InstMIPS32::Mov_s>;
using InstMIPS32Movf = InstMIPS32MovConditional<InstMIPS32::Movf>;
+using InstMIPS32Movn = InstMIPS32ThreeAddrGPR<InstMIPS32::Movn>;
+using InstMIPS32Movn_d = InstMIPS32ThreeAddrGPR<InstMIPS32::Movn_d>;
+using InstMIPS32Movn_s = InstMIPS32ThreeAddrGPR<InstMIPS32::Movn_s>;
using InstMIPS32Movt = InstMIPS32MovConditional<InstMIPS32::Movt>;
+using InstMIPS32Movz = InstMIPS32ThreeAddrGPR<InstMIPS32::Movz>;
+using InstMIPS32Movz_d = InstMIPS32ThreeAddrGPR<InstMIPS32::Movz_d>;
+using InstMIPS32Movz_s = InstMIPS32ThreeAddrGPR<InstMIPS32::Movz_s>;
using InstMIPS32Mtc1 = InstMIPS32TwoAddrGPR<InstMIPS32::Mtc1>;
using InstMIPS32Mthi = InstMIPS32UnaryopGPR<InstMIPS32::Mthi>;
using InstMIPS32Mtlo = InstMIPS32UnaryopGPR<InstMIPS32::Mtlo>;
if (Instr->hasRetValue()) {
Operand *Src0 = Instr->getRetValue();
switch (Src0->getType()) {
+ case IceType_f32: {
+ Operand *Src0F = legalizeToReg(Src0);
+ Reg = makeReg(Src0F->getType(), RegMIPS32::Reg_F0);
+ _mov(Reg, Src0F);
+ break;
+ }
+ case IceType_f64: {
+ Operand *Src0F = legalizeToReg(Src0);
+ Reg = makeReg(Src0F->getType(), RegMIPS32::Reg_F0F1);
+ _mov(Reg, Src0F);
+ break;
+ }
case IceType_i1:
case IceType_i8:
case IceType_i16:
case IceType_i32: {
- // Reg = legalizeToReg(Src0, RegMIPS32::Reg_V0);
- Operand *Src0F = legalize(Src0, Legal_Reg);
+ Operand *Src0F = legalizeToReg(Src0);
Reg = makeReg(Src0F->getType(), RegMIPS32::Reg_V0);
_mov(Reg, Src0F);
break;
}
void TargetMIPS32::lowerSelect(const InstSelect *Instr) {
- UnimplementedLoweringError(this, Instr);
+ Variable *Dest = Instr->getDest();
+ const Type DestTy = Dest->getType();
+
+ if (DestTy == IceType_i64 || isVectorType(DestTy)) {
+ UnimplementedLoweringError(this, Instr);
+ return;
+ }
+
+ Variable *DestR = legalizeToReg(Dest);
+ Variable *SrcTR = legalizeToReg(Instr->getTrueOperand());
+ Variable *SrcFR = legalizeToReg(Instr->getFalseOperand());
+
+ Variable *ConditionR = legalizeToReg(Instr->getCondition());
+
+ assert(Instr->getCondition()->getType() == IceType_i1);
+
+ switch (DestTy) {
+ case IceType_i1:
+ case IceType_i8:
+ case IceType_i16:
+ case IceType_i32:
+ _movn(SrcFR, SrcTR, ConditionR);
+ _mov(DestR, SrcFR);
+ _mov(Dest, DestR);
+ break;
+ case IceType_f32:
+ _movn_s(SrcFR, SrcTR, ConditionR);
+ _mov(DestR, SrcFR);
+ _mov(Dest, DestR);
+ break;
+ case IceType_f64:
+ _movn_d(SrcFR, SrcTR, ConditionR);
+ _mov(DestR, SrcFR);
+ _mov(Dest, DestR);
+ break;
+ default:
+ UnimplementedLoweringError(this, Instr);
+ }
}
void TargetMIPS32::lowerShuffleVector(const InstShuffleVector *Instr) {
Context.insert<InstMIPS32Lui>(Dest, Src, Reloc);
}
+ void _mfc1(Variable *Dest, Variable *Src) {
+ Context.insert<InstMIPS32Mfc1>(Dest, Src);
+ }
+
+ void _mfhi(Variable *Dest, Operand *Src) {
+ Context.insert<InstMIPS32Mfhi>(Dest, Src);
+ }
+
+ void _mflo(Variable *Dest, Operand *Src) {
+ Context.insert<InstMIPS32Mflo>(Dest, Src);
+ }
+
void _mov(Variable *Dest, Operand *Src0) {
assert(Dest != nullptr);
// Variable* Src0_ = llvm::dyn_cast<Variable>(Src0);
Context.insert<InstMIPS32Movf>(Src0, Src1, FCC);
}
+ void _movn(Variable *Dest, Variable *Src0, Variable *Src1) {
+ Context.insert<InstMIPS32Movn>(Dest, Src0, Src1);
+ }
+
+ void _movn_d(Variable *Dest, Variable *Src0, Variable *Src1) {
+ Context.insert<InstMIPS32Movn_d>(Dest, Src0, Src1);
+ }
+
+ void _movn_s(Variable *Dest, Variable *Src0, Variable *Src1) {
+ Context.insert<InstMIPS32Movn_s>(Dest, Src0, Src1);
+ }
+
void _movt(Variable *Src0, Variable *Src1, Operand *FCC) {
Context.insert<InstMIPS32Movt>(Src0, Src1, FCC);
}
- void _mfc1(Variable *Dest, Variable *Src) {
- Context.insert<InstMIPS32Mfc1>(Dest, Src);
+ void _movz(Variable *Dest, Variable *Src0, Variable *Src1) {
+ Context.insert<InstMIPS32Movz>(Dest, Src0, Src1);
}
- void _mfhi(Variable *Dest, Operand *Src) {
- Context.insert<InstMIPS32Mfhi>(Dest, Src);
+ void _movz_d(Variable *Dest, Variable *Src0, Variable *Src1) {
+ Context.insert<InstMIPS32Movz_d>(Dest, Src0, Src1);
}
- void _mflo(Variable *Dest, Operand *Src) {
- Context.insert<InstMIPS32Mflo>(Dest, Src);
+ void _movz_s(Variable *Dest, Variable *Src0, Variable *Src1) {
+ Context.insert<InstMIPS32Movz_s>(Dest, Src0, Src1);
}
void _mtc1(Variable *Dest, Variable *Src) {
; ARM32-OM1: vmovne.f32 s{{[0-9]+}}
; ARM32-O2: vmovmi.f32 s{{[0-9]+}}
; ARM32: bx
+; MIPS32-LABEL: selectFloatVarVar
+; MIPS32: movn.s {{.*}}
+; MIPS32: mov.s {{.*}}
define internal double @selectDoubleVarVar(double %a, double %b) {
entry:
; ARM32-OM1: vmovne.f64 d{{[0-9]+}}
; ARM32-O2: vmovmi.f64 d{{[0-9]+}}
; ARM32: bx
+; MIPS32-LABEL: selectDoubleVarVar
+; MIPS32: movn.d {{.*}}
+; MIPS32: mov.d {{.*}}
; RUN: | %if --need=target_ARM32 --need=allow_dump \
; RUN: --command FileCheck --check-prefix ARM32 --check-prefix ARM32-OM1 %s
+; RUN: %if --need=target_MIPS32 --need=allow_dump \
+; RUN: --command %p2i --filetype=asm --assemble \
+; RUN: --disassemble --target mips32 -i %s --args -Om1 \
+; RUN: -allow-externally-defined-symbols -skip-unimplemented \
+; RUN: | %if --need=target_MIPS32 --need=allow_dump \
+; RUN: --command FileCheck --check-prefix MIPS32 %s
+
+; RUN: %if --need=target_MIPS32 --need=allow_dump \
+; RUN: --command %p2i --filetype=asm --assemble \
+; RUN: --disassemble --target mips32 -i %s --args -O2 \
+; RUN: -allow-externally-defined-symbols -skip-unimplemented \
+; RUN: | %if --need=target_MIPS32 --need=allow_dump \
+; RUN: --command FileCheck --check-prefix MIPS32 %s
+
define internal void @testSelect(i32 %a, i32 %b) {
entry:
%cmp = icmp slt i32 %a, %b
; ARM32: bl {{.*}} useInt
; ARM32: bl {{.*}} useInt
; ARM32: bx lr
+; MIPS32-LABEL: testSelect
+; MIPS32: slt {{.*}}
+; MIPS32: movn {{.*}}
+; MIPS32: move {{.*}}
; Check for valid addressing mode in the cmp instruction when the
; operand is an immediate.
; CHECK-NOT: cmp 0x{{[0-9a-f]+}},
; ARM32-LABEL: testSelectImm32
; ARM32-NOT: cmp #{{.*}},
+; MIPS32-LABEL: testSelectImm32
+; MIPS32: movn {{.*}}
+; MIPS32: move {{.*}}
; Check for valid addressing mode in the cmp instruction when the
; operand is an immediate. There is a different x86-32 lowering
; CHECK-NOT: cmp 0x{{[0-9a-f]+}},
; ARM32-LABEL: testSelectImm64
; ARM32-NOT: cmp #{{.*}},
+; MIPS32-LABEL: testSelectImm64