mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-11-01 15:11:24 +00:00
[mips][msa] Direct Object Emission of INSERT.{B,H,W} instruction.
INSERT is the first type of MSA instruction that requires a change to the way MSA registers are parsed. This happens because MSA registers may be suffixed by an index in the form of an immediate or a general purpose register. The changes to parseMSARegs reflect that requirement. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@192447 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
71e7893757
commit
6f36ea5c47
@ -236,6 +236,12 @@ class MipsAsmParser : public MCTargetAsmParser {
|
||||
|
||||
bool processInstruction(MCInst &Inst, SMLoc IDLoc,
|
||||
SmallVectorImpl<MCInst> &Instructions);
|
||||
|
||||
// Helper function that checks if the value of a vector index is within the
|
||||
// boundaries of accepted values for each RegisterKind
|
||||
// Example: INSERT.B $w0[n], $1 => 16 > n >= 0
|
||||
bool validateMSAIndex(int Val, int RegKind);
|
||||
|
||||
public:
|
||||
MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
|
||||
const MCInstrInfo &MII)
|
||||
@ -1547,6 +1553,26 @@ MipsAsmParser::parseRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
|
||||
return MatchOperand_NoMatch;
|
||||
}
|
||||
|
||||
bool MipsAsmParser::validateMSAIndex(int Val, int RegKind) {
|
||||
MipsOperand::RegisterKind Kind = (MipsOperand::RegisterKind)RegKind;
|
||||
|
||||
if (Val < 0)
|
||||
return false;
|
||||
|
||||
switch (Kind) {
|
||||
default:
|
||||
return false;
|
||||
case MipsOperand::Kind_MSA128BRegs:
|
||||
return Val < 16;
|
||||
case MipsOperand::Kind_MSA128HRegs:
|
||||
return Val < 8;
|
||||
case MipsOperand::Kind_MSA128WRegs:
|
||||
return Val < 4;
|
||||
case MipsOperand::Kind_MSA128DRegs:
|
||||
return Val < 2;
|
||||
}
|
||||
}
|
||||
|
||||
MipsAsmParser::OperandMatchResultTy
|
||||
MipsAsmParser::parseMSARegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
|
||||
int RegKind) {
|
||||
@ -1589,6 +1615,101 @@ MipsAsmParser::parseMSARegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
|
||||
|
||||
Parser.Lex(); // Eat the register identifier.
|
||||
|
||||
// MSA registers may be suffixed with an index in the form of:
|
||||
// 1) Immediate expression.
|
||||
// 2) General Purpose Register.
|
||||
// Examples:
|
||||
// 1) copy_s.b $29,$w0[0]
|
||||
// 2) sld.b $w0,$w1[$1]
|
||||
|
||||
if (Parser.getTok().isNot(AsmToken::LBrac))
|
||||
return MatchOperand_Success;
|
||||
|
||||
MipsOperand *Mnemonic = static_cast<MipsOperand *>(Operands[0]);
|
||||
|
||||
Operands.push_back(MipsOperand::CreateToken("[", Parser.getTok().getLoc()));
|
||||
Parser.Lex(); // Parse the '[' token.
|
||||
|
||||
if (Parser.getTok().is(AsmToken::Dollar)) {
|
||||
// This must be a GPR.
|
||||
MipsOperand *RegOp;
|
||||
SMLoc VIdx = Parser.getTok().getLoc();
|
||||
Parser.Lex(); // Parse the '$' token.
|
||||
|
||||
// GPR have aliases and we must account for that. Example: $30 == $fp
|
||||
if (getLexer().getKind() == AsmToken::Integer) {
|
||||
unsigned RegNum = Parser.getTok().getIntVal();
|
||||
int Reg = matchRegisterByNumber(
|
||||
RegNum, regKindToRegClass(MipsOperand::Kind_GPR32));
|
||||
if (Reg == -1) {
|
||||
Error(VIdx, "invalid general purpose register");
|
||||
return MatchOperand_ParseFail;
|
||||
}
|
||||
|
||||
RegOp = MipsOperand::CreateReg(Reg, VIdx, Parser.getTok().getLoc());
|
||||
} else if (getLexer().getKind() == AsmToken::Identifier) {
|
||||
int RegNum = -1;
|
||||
std::string RegName = Parser.getTok().getString().lower();
|
||||
|
||||
RegNum = matchCPURegisterName(RegName);
|
||||
if (RegNum == -1) {
|
||||
Error(VIdx, "general purpose register expected");
|
||||
return MatchOperand_ParseFail;
|
||||
}
|
||||
RegNum = getReg(regKindToRegClass(MipsOperand::Kind_GPR32), RegNum);
|
||||
RegOp = MipsOperand::CreateReg(RegNum, VIdx, Parser.getTok().getLoc());
|
||||
}
|
||||
|
||||
RegOp->setRegKind(MipsOperand::Kind_GPR32);
|
||||
Operands.push_back(RegOp);
|
||||
Parser.Lex(); // Eat the register identifier.
|
||||
|
||||
if (Parser.getTok().isNot(AsmToken::RBrac))
|
||||
return MatchOperand_ParseFail;
|
||||
|
||||
Operands.push_back(MipsOperand::CreateToken("]", Parser.getTok().getLoc()));
|
||||
Parser.Lex(); // Parse the ']' token.
|
||||
|
||||
return MatchOperand_Success;
|
||||
}
|
||||
|
||||
// The index must be a constant expression then.
|
||||
SMLoc VIdx = Parser.getTok().getLoc();
|
||||
const MCExpr *ImmVal;
|
||||
|
||||
if (getParser().parseExpression(ImmVal))
|
||||
return MatchOperand_ParseFail;
|
||||
|
||||
const MCConstantExpr *expr = dyn_cast<MCConstantExpr>(ImmVal);
|
||||
if (!expr || !validateMSAIndex((int)expr->getValue(), Kind)) {
|
||||
Error(VIdx, "invalid immediate value");
|
||||
return MatchOperand_ParseFail;
|
||||
}
|
||||
|
||||
SMLoc E = Parser.getTok().getEndLoc();
|
||||
|
||||
if (Parser.getTok().isNot(AsmToken::RBrac))
|
||||
return MatchOperand_ParseFail;
|
||||
|
||||
bool insve = Mnemonic->getToken() == "insve.b" ||
|
||||
Mnemonic->getToken() == "insve.h" ||
|
||||
Mnemonic->getToken() == "insve.w" ||
|
||||
Mnemonic->getToken() == "insve.d";
|
||||
|
||||
// The second vector index of insve instructions is always 0.
|
||||
if (insve && Operands.size() > 6) {
|
||||
if (expr->getValue() != 0) {
|
||||
Error(VIdx, "immediate value must be 0");
|
||||
return MatchOperand_ParseFail;
|
||||
}
|
||||
Operands.push_back(MipsOperand::CreateToken("0", VIdx));
|
||||
} else
|
||||
Operands.push_back(MipsOperand::CreateImm(expr, VIdx, E));
|
||||
|
||||
Operands.push_back(MipsOperand::CreateToken("]", Parser.getTok().getLoc()));
|
||||
|
||||
Parser.Lex(); // Parse the ']' token.
|
||||
|
||||
return MatchOperand_Success;
|
||||
}
|
||||
|
||||
|
@ -133,6 +133,45 @@ class MSA_ELM_D_FMT<bits<4> major, bits<6> minor>: MSAInst {
|
||||
let Inst{5-0} = minor;
|
||||
}
|
||||
|
||||
class MSA_ELM_INSERT_B_FMT<bits<4> major, bits<6> minor>: MSAInst {
|
||||
bits<6> n;
|
||||
bits<5> rs;
|
||||
bits<5> wd;
|
||||
|
||||
let Inst{25-22} = major;
|
||||
let Inst{21-20} = 0b00;
|
||||
let Inst{19-16} = n{3-0};
|
||||
let Inst{15-11} = rs;
|
||||
let Inst{10-6} = wd;
|
||||
let Inst{5-0} = minor;
|
||||
}
|
||||
|
||||
class MSA_ELM_INSERT_H_FMT<bits<4> major, bits<6> minor>: MSAInst {
|
||||
bits<6> n;
|
||||
bits<5> rs;
|
||||
bits<5> wd;
|
||||
|
||||
let Inst{25-22} = major;
|
||||
let Inst{21-19} = 0b100;
|
||||
let Inst{18-16} = n{2-0};
|
||||
let Inst{15-11} = rs;
|
||||
let Inst{10-6} = wd;
|
||||
let Inst{5-0} = minor;
|
||||
}
|
||||
|
||||
class MSA_ELM_INSERT_W_FMT<bits<4> major, bits<6> minor>: MSAInst {
|
||||
bits<6> n;
|
||||
bits<5> rs;
|
||||
bits<5> wd;
|
||||
|
||||
let Inst{25-22} = major;
|
||||
let Inst{21-18} = 0b1100;
|
||||
let Inst{17-16} = n{1-0};
|
||||
let Inst{15-11} = rs;
|
||||
let Inst{10-6} = wd;
|
||||
let Inst{5-0} = minor;
|
||||
}
|
||||
|
||||
class MSA_I5_FMT<bits<3> major, bits<2> df, bits<6> minor>: MSAInst {
|
||||
bits<5> imm;
|
||||
bits<5> ws;
|
||||
|
@ -738,9 +738,9 @@ class ILVR_H_ENC : MSA_3R_FMT<0b101, 0b01, 0b010100>;
|
||||
class ILVR_W_ENC : MSA_3R_FMT<0b101, 0b10, 0b010100>;
|
||||
class ILVR_D_ENC : MSA_3R_FMT<0b101, 0b11, 0b010100>;
|
||||
|
||||
class INSERT_B_ENC : MSA_ELM_B_FMT<0b0100, 0b011001>;
|
||||
class INSERT_H_ENC : MSA_ELM_H_FMT<0b0100, 0b011001>;
|
||||
class INSERT_W_ENC : MSA_ELM_W_FMT<0b0100, 0b011001>;
|
||||
class INSERT_B_ENC : MSA_ELM_INSERT_B_FMT<0b0100, 0b011001>;
|
||||
class INSERT_H_ENC : MSA_ELM_INSERT_H_FMT<0b0100, 0b011001>;
|
||||
class INSERT_W_ENC : MSA_ELM_INSERT_W_FMT<0b0100, 0b011001>;
|
||||
|
||||
class INSVE_B_ENC : MSA_ELM_B_FMT<0b0101, 0b011001>;
|
||||
class INSVE_H_ENC : MSA_ELM_H_FMT<0b0101, 0b011001>;
|
||||
@ -1239,13 +1239,13 @@ class MSA_CBRANCH_DESC_BASE<string instr_asm, RegisterClass RCWD> {
|
||||
}
|
||||
|
||||
class MSA_INSERT_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
|
||||
RegisterClass RCWD, RegisterClass RCS,
|
||||
RegisterOperand ROWD, RegisterOperand ROS,
|
||||
InstrItinClass itin = NoItinerary> {
|
||||
dag OutOperandList = (outs RCWD:$wd);
|
||||
dag InOperandList = (ins RCWD:$wd_in, RCS:$rs, uimm6:$n);
|
||||
dag OutOperandList = (outs ROWD:$wd);
|
||||
dag InOperandList = (ins ROWD:$wd_in, ROS:$rs, uimm6:$n);
|
||||
string AsmString = !strconcat(instr_asm, "\t$wd[$n], $rs");
|
||||
list<dag> Pattern = [(set RCWD:$wd, (OpNode RCWD:$wd_in,
|
||||
RCS:$rs,
|
||||
list<dag> Pattern = [(set ROWD:$wd, (OpNode ROWD:$wd_in,
|
||||
ROS:$rs,
|
||||
immZExt6:$n))];
|
||||
InstrItinClass Itinerary = itin;
|
||||
string Constraints = "$wd = $wd_in";
|
||||
@ -1964,12 +1964,12 @@ class ILVR_H_DESC : MSA_3R_DESC_BASE<"ilvr.h", MipsILVR, MSA128HOpnd>;
|
||||
class ILVR_W_DESC : MSA_3R_DESC_BASE<"ilvr.w", MipsILVR, MSA128WOpnd>;
|
||||
class ILVR_D_DESC : MSA_3R_DESC_BASE<"ilvr.d", MipsILVR, MSA128DOpnd>;
|
||||
|
||||
class INSERT_B_DESC : MSA_INSERT_DESC_BASE<"insert.b", vinsert_v16i8, MSA128B,
|
||||
GPR32>;
|
||||
class INSERT_H_DESC : MSA_INSERT_DESC_BASE<"insert.h", vinsert_v8i16, MSA128H,
|
||||
GPR32>;
|
||||
class INSERT_W_DESC : MSA_INSERT_DESC_BASE<"insert.w", vinsert_v4i32, MSA128W,
|
||||
GPR32>;
|
||||
class INSERT_B_DESC : MSA_INSERT_DESC_BASE<"insert.b", vinsert_v16i8,
|
||||
MSA128BOpnd, GPR32Opnd>;
|
||||
class INSERT_H_DESC : MSA_INSERT_DESC_BASE<"insert.h", vinsert_v8i16,
|
||||
MSA128HOpnd, GPR32Opnd>;
|
||||
class INSERT_W_DESC : MSA_INSERT_DESC_BASE<"insert.w", vinsert_v4i32,
|
||||
MSA128WOpnd, GPR32Opnd>;
|
||||
|
||||
class INSERT_FW_PSEUDO_DESC : MSA_INSERT_PSEUDO_BASE<vector_insert, v4f32,
|
||||
MSA128W, FGR32>;
|
||||
|
15
test/MC/Mips/msa/test_elm_insert.s
Normal file
15
test/MC/Mips/msa/test_elm_insert.s
Normal file
@ -0,0 +1,15 @@
|
||||
# RUN: llvm-mc %s -triple=mipsel-unknown-linux -show-encoding -mcpu=mips32r2 -mattr=+msa -arch=mips | FileCheck %s
|
||||
#
|
||||
# RUN: llvm-mc %s -triple=mipsel-unknown-linux -mcpu=mips32r2 -mattr=+msa -arch=mips -filetype=obj -o - | llvm-objdump -d -triple=mipsel-unknown-linux -mattr=+msa -arch=mips - | FileCheck %s -check-prefix=CHECKOBJDUMP
|
||||
#
|
||||
# CHECK: insert.b $w23[3], $sp # encoding: [0x79,0x03,0xed,0xd9]
|
||||
# CHECK: insert.h $w20[2], $5 # encoding: [0x79,0x22,0x2d,0x19]
|
||||
# CHECK: insert.w $w8[2], $15 # encoding: [0x79,0x32,0x7a,0x19]
|
||||
|
||||
# CHECKOBJDUMP: insert.b $w23[3], $sp
|
||||
# CHECKOBJDUMP: insert.h $w20[2], $5
|
||||
# CHECKOBJDUMP: insert.w $w8[2], $15
|
||||
|
||||
insert.b $w23[3], $sp
|
||||
insert.h $w20[2], $5
|
||||
insert.w $w8[2], $15
|
Loading…
Reference in New Issue
Block a user