mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 20:51:52 +01:00
Initial assembler implementation of Mips load address macro
This patch provides initial implementation of load address macro instruction for Mips. We have implemented two kinds of expansions with their variations depending on the size of immediate operand: 1) load address with immediate value directly: * la d,j => addiu d,$zero,j (for -32768 <= j <= 65535) * la d,j => lui d,hi16(j) ori d,d,lo16(j) (for any other 32 bit value of j) 2) load load address with register offset value * la d,j(s) => addiu d,s,j (for -32768 <= j <= 65535) * la d,j(s) => lui d,hi16(j) (for any other 32 bit value of j) ori d,d,lo16(j) addu d,d,s This patch does not cover the case when the address is loaded from the value of the label or function. Contributer: Vladimir Medic llvm-svn: 165561
This commit is contained in:
parent
ecabb8b6ff
commit
f403d95eb4
@ -98,6 +98,10 @@ class MipsAsmParser : public MCTargetAsmParser {
|
||||
SmallVectorImpl<MCInst> &Instructions);
|
||||
void expandLoadImm(MCInst &Inst, SMLoc IDLoc,
|
||||
SmallVectorImpl<MCInst> &Instructions);
|
||||
void expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
|
||||
SmallVectorImpl<MCInst> &Instructions);
|
||||
void expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
|
||||
SmallVectorImpl<MCInst> &Instructions);
|
||||
bool reportParseError(StringRef ErrorMsg);
|
||||
|
||||
bool parseMemOffset(const MCExpr *&Res);
|
||||
@ -305,6 +309,8 @@ bool MipsAsmParser::needsExpansion(MCInst &Inst) {
|
||||
|
||||
switch(Inst.getOpcode()) {
|
||||
case Mips::LoadImm32Reg:
|
||||
case Mips::LoadAddr32Imm:
|
||||
case Mips::LoadAddr32Reg:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
@ -316,14 +322,18 @@ void MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
|
||||
switch(Inst.getOpcode()) {
|
||||
case Mips::LoadImm32Reg:
|
||||
return expandLoadImm(Inst, IDLoc, Instructions);
|
||||
case Mips::LoadAddr32Imm:
|
||||
return expandLoadAddressImm(Inst,IDLoc,Instructions);
|
||||
case Mips::LoadAddr32Reg:
|
||||
return expandLoadAddressReg(Inst,IDLoc,Instructions);
|
||||
}
|
||||
}
|
||||
|
||||
void MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
|
||||
SmallVectorImpl<MCInst> &Instructions){
|
||||
SmallVectorImpl<MCInst> &Instructions){
|
||||
MCInst tmpInst;
|
||||
const MCOperand &ImmOp = Inst.getOperand(1);
|
||||
assert(ImmOp.isImm() && "expected imediate operand kind");
|
||||
assert(ImmOp.isImm() && "expected immediate operand kind");
|
||||
const MCOperand &RegOp = Inst.getOperand(0);
|
||||
assert(RegOp.isReg() && "expected register operand kind");
|
||||
|
||||
@ -350,7 +360,7 @@ void MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
|
||||
} else {
|
||||
// for any other value of j that is representable as a 32-bit integer.
|
||||
// li d,j => lui d,hi16(j)
|
||||
// ori d,d,lo16(j)
|
||||
// ori d,d,lo16(j)
|
||||
tmpInst.setOpcode(isMips64() ? Mips::LUi64 : Mips::LUi);
|
||||
tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
|
||||
tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
|
||||
@ -365,6 +375,82 @@ void MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
|
||||
}
|
||||
}
|
||||
|
||||
void MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
|
||||
SmallVectorImpl<MCInst> &Instructions){
|
||||
MCInst tmpInst;
|
||||
const MCOperand &ImmOp = Inst.getOperand(2);
|
||||
assert(ImmOp.isImm() && "expected immediate operand kind");
|
||||
const MCOperand &SrcRegOp = Inst.getOperand(1);
|
||||
assert(SrcRegOp.isReg() && "expected register operand kind");
|
||||
const MCOperand &DstRegOp = Inst.getOperand(0);
|
||||
assert(DstRegOp.isReg() && "expected register operand kind");
|
||||
int ImmValue = ImmOp.getImm();
|
||||
if ( -32768 <= ImmValue && ImmValue <= 65535) {
|
||||
//for -32768 <= j <= 65535.
|
||||
//la d,j(s) => addiu d,s,j
|
||||
tmpInst.setOpcode(Mips::ADDiu); //TODO:no ADDiu64 in td files?
|
||||
tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
|
||||
tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
|
||||
tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
|
||||
Instructions.push_back(tmpInst);
|
||||
} else {
|
||||
//for any other value of j that is representable as a 32-bit integer.
|
||||
//la d,j(s) => lui d,hi16(j)
|
||||
// ori d,d,lo16(j)
|
||||
// addu d,d,s
|
||||
tmpInst.setOpcode(isMips64()?Mips::LUi64:Mips::LUi);
|
||||
tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
|
||||
tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
|
||||
Instructions.push_back(tmpInst);
|
||||
tmpInst.clear();
|
||||
tmpInst.setOpcode(isMips64()?Mips::ORi64:Mips::ORi);
|
||||
tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
|
||||
tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
|
||||
tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
|
||||
Instructions.push_back(tmpInst);
|
||||
tmpInst.clear();
|
||||
tmpInst.setOpcode(Mips::ADDu);
|
||||
tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
|
||||
tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
|
||||
tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
|
||||
Instructions.push_back(tmpInst);
|
||||
}
|
||||
}
|
||||
|
||||
void MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
|
||||
SmallVectorImpl<MCInst> &Instructions){
|
||||
MCInst tmpInst;
|
||||
const MCOperand &ImmOp = Inst.getOperand(1);
|
||||
assert(ImmOp.isImm() && "expected immediate operand kind");
|
||||
const MCOperand &RegOp = Inst.getOperand(0);
|
||||
assert(RegOp.isReg() && "expected register operand kind");
|
||||
int ImmValue = ImmOp.getImm();
|
||||
if ( -32768 <= ImmValue && ImmValue <= 65535) {
|
||||
//for -32768 <= j <= 65535.
|
||||
//la d,j => addiu d,$zero,j
|
||||
tmpInst.setOpcode(Mips::ADDiu);
|
||||
tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
|
||||
tmpInst.addOperand(
|
||||
MCOperand::CreateReg(isMips64()?Mips::ZERO_64:Mips::ZERO));
|
||||
tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
|
||||
Instructions.push_back(tmpInst);
|
||||
} else {
|
||||
//for any other value of j that is representable as a 32-bit integer.
|
||||
//la d,j => lui d,hi16(j)
|
||||
// ori d,d,lo16(j)
|
||||
tmpInst.setOpcode(isMips64()?Mips::LUi64:Mips::LUi);
|
||||
tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
|
||||
tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
|
||||
Instructions.push_back(tmpInst);
|
||||
tmpInst.clear();
|
||||
tmpInst.setOpcode(isMips64()?Mips::ORi64:Mips::ORi);
|
||||
tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
|
||||
tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
|
||||
tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
|
||||
Instructions.push_back(tmpInst);
|
||||
}
|
||||
}
|
||||
|
||||
bool MipsAsmParser::
|
||||
MatchAndEmitInstruction(SMLoc IDLoc,
|
||||
SmallVectorImpl<MCParsedAsmOperand*> &Operands,
|
||||
@ -820,13 +906,19 @@ MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
|
||||
|
||||
const AsmToken &Tok = Parser.getTok(); // get next token
|
||||
if (Tok.isNot(AsmToken::LParen)) {
|
||||
MipsOperand *Mnemonic = static_cast<MipsOperand*>(Operands[0]);
|
||||
if (Mnemonic->getToken() == "la") {
|
||||
SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer()-1);
|
||||
Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
|
||||
return MatchOperand_Success;
|
||||
}
|
||||
Error(Parser.getTok().getLoc(), "'(' expected");
|
||||
return MatchOperand_ParseFail;
|
||||
}
|
||||
|
||||
Parser.Lex(); // Eat '(' token.
|
||||
|
||||
const AsmToken &Tok1 = Parser.getTok(); //get next token
|
||||
const AsmToken &Tok1 = Parser.getTok(); // get next token
|
||||
if (Tok1.is(AsmToken::Dollar)) {
|
||||
Parser.Lex(); // Eat '$' token.
|
||||
if (tryParseRegisterOperand(Operands,"")) {
|
||||
|
@ -883,8 +883,19 @@ let usesCustomInserter = 1 in {
|
||||
|
||||
class LoadImm32< string instr_asm, Operand Od, RegisterClass RC> :
|
||||
MipsAsmPseudoInst<(outs RC:$rt), (ins Od:$imm32),
|
||||
!strconcat(instr_asm, "\t$rt, $imm32")> ;
|
||||
def LoadImm32Reg : LoadImm32<"li",shamt,CPURegs>;
|
||||
!strconcat(instr_asm, "\t$rt, $imm32")> ;
|
||||
def LoadImm32Reg : LoadImm32<"li", shamt,CPURegs>;
|
||||
|
||||
class LoadAddress<string instr_asm, Operand MemOpnd, RegisterClass RC> :
|
||||
MipsAsmPseudoInst<(outs RC:$rt), (ins MemOpnd:$addr),
|
||||
!strconcat(instr_asm, "\t$rt, $addr")> ;
|
||||
def LoadAddr32Reg : LoadAddress<"la", mem, CPURegs>;
|
||||
|
||||
class LoadAddressImm<string instr_asm, Operand Od, RegisterClass RC> :
|
||||
MipsAsmPseudoInst<(outs RC:$rt), (ins Od:$imm32),
|
||||
!strconcat(instr_asm, "\t$rt, $imm32")> ;
|
||||
def LoadAddr32Imm : LoadAddressImm<"la", shamt,CPURegs>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// MipsI Instructions
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -9,6 +9,19 @@
|
||||
# CHECK: addiu $6, $zero, -2345 # encoding: [0xd7,0xf6,0x06,0x24]
|
||||
# CHECK: lui $7, 1 # encoding: [0x01,0x00,0x07,0x3c]
|
||||
# CHECK: ori $7, $7, 2 # encoding: [0x02,0x00,0xe7,0x34]
|
||||
# CHECK: addiu $4, $zero, 20 # encoding: [0x14,0x00,0x04,0x24]
|
||||
# CHECK: lui $7, 1 # encoding: [0x01,0x00,0x07,0x3c]
|
||||
# CHECK: ori $7, $7, 2 # encoding: [0x02,0x00,0xe7,0x34]
|
||||
# CHECK: addiu $4, $5, 20 # encoding: [0x14,0x00,0xa4,0x24]
|
||||
# CHECK: lui $7, 1 # encoding: [0x01,0x00,0x07,0x3c]
|
||||
# CHECK: ori $7, $7, 2 # encoding: [0x02,0x00,0xe7,0x34]
|
||||
# CHECK: addu $7, $7, $8 # encoding: [0x21,0x38,0xe8,0x00]
|
||||
|
||||
li $5,123
|
||||
li $6,-2345
|
||||
li $7,65538
|
||||
|
||||
la $a0, 20
|
||||
la $7,65538
|
||||
la $a0, 20($a1)
|
||||
la $7,65538($8)
|
||||
|
Loading…
x
Reference in New Issue
Block a user