#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCInstBuilder.h"
#include "llvm/MC/MCParser/MCAsmLexer.h"
#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
#include "llvm/MC/MCStreamer.h"
bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
SmallVectorImpl<MCInst> &Instructions) {
const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
+
Inst.setLoc(IDLoc);
if (MCID.isBranch() || MCID.isCall()) {
case Mips::LoadImm32Reg:
case Mips::LoadAddr32Imm:
case Mips::LoadAddr32Reg:
+ case Mips::SUBi:
+ case Mips::SUBiu:
+ case Mips::DSUBi:
+ case Mips::DSUBiu:
return true;
default:
return false;
return expandLoadAddressImm(Inst, IDLoc, Instructions);
case Mips::LoadAddr32Reg:
return expandLoadAddressReg(Inst, IDLoc, Instructions);
+ case Mips::SUBi:
+ Instructions.push_back(MCInstBuilder(Mips::ADDi)
+ .addReg(Inst.getOperand(0).getReg())
+ .addReg(Inst.getOperand(1).getReg())
+ .addImm(-Inst.getOperand(2).getImm()));
+ return;
+ case Mips::SUBiu:
+ Instructions.push_back(MCInstBuilder(Mips::ADDiu)
+ .addReg(Inst.getOperand(0).getReg())
+ .addReg(Inst.getOperand(1).getReg())
+ .addImm(-Inst.getOperand(2).getImm()));
+ return;
+ case Mips::DSUBi:
+ Instructions.push_back(MCInstBuilder(Mips::DADDi)
+ .addReg(Inst.getOperand(0).getReg())
+ .addReg(Inst.getOperand(1).getReg())
+ .addImm(-Inst.getOperand(2).getImm()));
+ return;
+ case Mips::DSUBiu:
+ Instructions.push_back(MCInstBuilder(Mips::DADDiu)
+ .addReg(Inst.getOperand(0).getReg())
+ .addReg(Inst.getOperand(1).getReg())
+ .addImm(-Inst.getOperand(2).getImm()));
+ return;
}
}
}
/// Arithmetic Instructions (3-Operand, R-Type)
-def DADD : ArithLogicR<"dadd", GPR64Opnd>, ADD_FM<0, 0x2c>;
+def DADD : ArithLogicR<"dadd", GPR64Opnd, 1, II_DADD>, ADD_FM<0, 0x2c>;
def DADDu : ArithLogicR<"daddu", GPR64Opnd, 1, II_DADDU, add>,
ADD_FM<0, 0x2d>;
def DSUBu : ArithLogicR<"dsubu", GPR64Opnd, 0, II_DSUBU, sub>,
ADD_FM<0, 0x2f>;
+def DSUB : ArithLogicR<"dsub", GPR64Opnd, 0, II_DSUB, sub>, ADD_FM<0, 0x2e>;
let isCodeGenOnly = 1 in {
def SLT64 : SetCC_R<"slt", setlt, GPR64Opnd>, ADD_FM<0, 0x2a>;
def : InstAlias<"dadd $rs, $rt, $imm",
(DADDi GPR64Opnd:$rs, GPR64Opnd:$rt, simm16_64:$imm),
0>;
+def : InstAlias<"daddu $rs, $imm",
+ (DADDiu GPR64Opnd:$rs, GPR64Opnd:$rs, simm16_64:$imm),
+ 0>;
+def : InstAlias<"dadd $rs, $imm",
+ (DADDi GPR64Opnd:$rs, GPR64Opnd:$rs, simm16_64:$imm),
+ 0>;
+def : InstAlias<"dadd $rs, $rt",
+ (DADD GPR64Opnd:$rs, GPR64Opnd:$rs, GPR64Opnd:$rt),
+ 0>;
+def : InstAlias<"daddu $rs, $rt",
+ (DADDu GPR64Opnd:$rs, GPR64Opnd:$rs, GPR64Opnd:$rt),
+ 0>;
+def : InstAlias<"dsub $rs, $rt",
+ (DSUB GPR64Opnd:$rs, GPR64Opnd:$rs, GPR64Opnd:$rt),
+ 0>;
+def : InstAlias<"dsubu $rs, $rt",
+ (DSUBu GPR64Opnd:$rs, GPR64Opnd:$rs, GPR64Opnd:$rt),
+ 0>;
+def : InstAlias<"add $rs, $imm",
+ (ADDi GPR32Opnd:$rs, GPR32Opnd:$rs, simm16:$imm),
+ 0>;
+def : InstAlias<"addu $rs, $imm",
+ (ADDiu GPR32Opnd:$rs, GPR32Opnd:$rs, simm16:$imm),
+ 0>;
+def : InstAlias<"add $rs, $rt",
+ (ADD GPR32Opnd:$rs, GPR32Opnd:$rs, GPR32Opnd:$rt),
+ 0>;
+def : InstAlias<"addu $rs, $rt",
+ (ADDu GPR32Opnd:$rs, GPR32Opnd:$rs, GPR32Opnd:$rt),
+ 0>;
+def : InstAlias<"sub $rs, $rt",
+ (SUB GPR32Opnd:$rs, GPR32Opnd:$rs, GPR32Opnd:$rt),
+ 0>;
+def : InstAlias<"subu $rs, $rt",
+ (SUBu GPR32Opnd:$rs, GPR32Opnd:$rs, GPR32Opnd:$rt),
+ 0>;
+let isPseudo=1, usesCustomInserter=1, isCodeGenOnly=1 in {
+def SUBi : MipsInst<(outs GPR32Opnd: $rt), (ins GPR32Opnd: $rs, simm16: $imm),
+ "sub\t$rt, $rs, $imm", [], II_DSUB, Pseudo>;
+def SUBiu : MipsInst<(outs GPR32Opnd: $rt), (ins GPR32Opnd: $rs, simm16: $imm),
+ "subu\t$rt, $rs, $imm", [], II_DSUB, Pseudo>;
+def DSUBi : MipsInst<(outs GPR64Opnd: $rt), (ins GPR64Opnd: $rs, simm16_64: $imm),
+ "ssub\t$rt, $rs, $imm", [], II_DSUB, Pseudo>;
+def DSUBiu : MipsInst<(outs GPR64Opnd: $rt), (ins GPR64Opnd: $rs, simm16_64: $imm),
+ "ssubu\t$rt, $rs, $imm", [], II_DSUB, Pseudo>;
+}
+def : InstAlias<"sub $rs, $imm",
+ (SUBi GPR32Opnd:$rs, GPR32Opnd:$rs, simm16:$imm),
+ 0>;
+def : InstAlias<"subu $rs, $imm",
+ (SUBiu GPR32Opnd:$rs, GPR32Opnd:$rs, simm16:$imm),
+ 0>;
+def : InstAlias<"dsub $rs, $imm",
+ (DSUBi GPR64Opnd:$rs, GPR64Opnd:$rs, simm16_64:$imm),
+ 0>;
+def : InstAlias<"dsubu $rs, $imm",
+ (DSUBiu GPR64Opnd:$rs, GPR64Opnd:$rs, simm16_64:$imm),
+ 0>;
/// Move between CPU and coprocessor registers
let DecoderNamespace = "Mips64", Predicates = [HasMips64] in {
def II_C_CC_S : InstrItinClass; // Any c.<cc>.s instruction
def II_DADDIU : InstrItinClass;
def II_DADDU : InstrItinClass;
+def II_DADD : InstrItinClass;
def II_DDIV : InstrItinClass;
def II_DDIVU : InstrItinClass;
def II_DIV : InstrItinClass;
def II_DSRL32 : InstrItinClass;
def II_DSRLV : InstrItinClass;
def II_DSUBU : InstrItinClass;
+def II_DSUB : InstrItinClass;
def II_FLOOR : InstrItinClass;
def II_LB : InstrItinClass;
def II_LBU : InstrItinClass;
InstrItinData<II_CLZ , [InstrStage<1, [ALU]>]>,
InstrItinData<II_DADDIU , [InstrStage<1, [ALU]>]>,
InstrItinData<II_DADDU , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_DADD , [InstrStage<1, [ALU]>]>,
InstrItinData<II_DSLL , [InstrStage<1, [ALU]>]>,
InstrItinData<II_DSRL , [InstrStage<1, [ALU]>]>,
InstrItinData<II_DSRA , [InstrStage<1, [ALU]>]>,
InstrItinData<II_DSRLV , [InstrStage<1, [ALU]>]>,
InstrItinData<II_DSRAV , [InstrStage<1, [ALU]>]>,
InstrItinData<II_DSUBU , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_DSUB , [InstrStage<1, [ALU]>]>,
InstrItinData<II_DROTR , [InstrStage<1, [ALU]>]>,
InstrItinData<II_DROTRV , [InstrStage<1, [ALU]>]>,
InstrItinData<II_LUI , [InstrStage<1, [ALU]>]>,
negu $6,$7
move $7,$8
rdhwr $5, $29
+
+#------------------------------------------------------------------------------
+# Shortcuts for arithmetic instructions
+#------------------------------------------------------------------------------
+
+# CHECK: add $9, $9, $3 # encoding: [0x20,0x48,0x23,0x01]
+# CHECK: addu $9, $9, $3 # encoding: [0x21,0x48,0x23,0x01]
+# CHECK: addi $9, $9, 10 # encoding: [0x0a,0x00,0x29,0x21]
+# CHECK: addiu $9, $9, 10 # encoding: [0x0a,0x00,0x29,0x25]
+# CHECK: sub $9, $9, $3 # encoding: [0x22,0x48,0x23,0x01]
+# CHECK: subu $9, $9, $3 # encoding: [0x23,0x48,0x23,0x01]
+# CHECK: addi $9, $9, -10 # encoding: [0xf6,0xff,0x29,0x21]
+# CHECK: addiu $9, $9, -10 # encoding: [0xf6,0xff,0x29,0x25]
+ add $9, $3
+ addu $9, $3
+ add $9, 10
+ addu $9, 10
+ sub $9, $3
+ subu $9, $3
+ sub $9, 10
+ subu $9, 10
# CHECK: msubu $6, $7 # encoding: [0x05,0x00,0xc7,0x70]
# CHECK: mult $3, $5 # encoding: [0x18,0x00,0x65,0x00]
# CHECK: multu $3, $5 # encoding: [0x19,0x00,0x65,0x00]
+# CHECK: dsub $9, $6, $7 # encoding: [0x2e,0x48,0xc7,0x00]
# CHECK: dsubu $4, $3, $5 # encoding: [0x2f,0x20,0x65,0x00]
# CHECK: move $7, $8 # encoding: [0x2d,0x38,0x00,0x01]
# CHECK: .set push
msubu $6,$7
mult $3,$5
multu $3,$5
+ dsub $9,$6,$7
dsubu $4,$3,$5
move $7,$8
rdhwr $5, $29
+
+#------------------------------------------------------------------------------
+# Shortcuts for arithmetic instructions
+#------------------------------------------------------------------------------
+
+# CHECK: dadd $9, $9, $3 # encoding: [0x2c,0x48,0x23,0x01]
+# CHECK: daddu $9, $9, $3 # encoding: [0x2d,0x48,0x23,0x01]
+# CHECK: daddi $9, $9, 10 # encoding: [0x0a,0x00,0x29,0x61]
+# CHECK: daddiu $9, $9, 10 # encoding: [0x0a,0x00,0x29,0x65]
+# CHECK: dsub $9, $9, $3 # encoding: [0x2e,0x48,0x23,0x01]
+# CHECK: dsubu $9, $9, $3 # encoding: [0x2f,0x48,0x23,0x01]
+# CHECK: daddi $9, $9, -10 # encoding: [0xf6,0xff,0x29,0x61]
+# CHECK: daddiu $9, $9, -10 # encoding: [0xf6,0xff,0x29,0x65]
+ dadd $9, $3
+ daddu $9, $3
+ dadd $9, 10
+ daddu $9, 10
+ dsub $9, $3
+ dsubu $9, $3
+ dsub $9, 10
+ dsubu $9, 10