Added support for bkrep in assembler, replace addv by modr if possible by extra pass

This commit is contained in:
Gericom 2020-08-08 13:48:31 +02:00
parent 3da44a85b7
commit 4bd5cbf0f7
9 changed files with 196 additions and 4 deletions

View File

@ -69,6 +69,16 @@ void Teak::relocateOne(uint8_t *loc, RelType type, uint64_t val) const
case R_TEAK_PTR_IMM16:
write16le(loc + 2, (val >> 1) & 0xFFFF);
break;
case R_TEAK_BKREP_REG:
val -= 2;
write16le(loc, (read16le(loc) & ~0x60) | (((val >> 17) & 3) << 5));
write16le(loc + 2, (val >> 1) & 0xFFFF);
break;
case R_TEAK_BKREP_R6:
val -= 2;
write16le(loc, (read16le(loc) & ~3) | ((val >> 17) & 3));
write16le(loc + 2, (val >> 1) & 0xFFFF);
break;
default:
error(getErrorLocation(loc) + "unrecognized relocation " + toString(type));
}
@ -82,6 +92,10 @@ int64_t Teak::getImplicitAddend(const uint8_t* buf, RelType type) const
return (((read16le(buf) >> 4) & 3) << 17) | (read16le(buf + 2) << 1);
case R_TEAK_PTR_IMM16:
return read16le(buf + 2) << 1;
case R_TEAK_BKREP_REG:
return (((read16le(buf) >> 5) & 3) << 17) | (read16le(buf + 2) << 1) + 2;
case R_TEAK_BKREP_R6:
return ((read16le(buf) & 3) << 17) | (read16le(buf + 2) << 1) + 2;
default:
error("unrecognized relocation " + toString(type));
}

View File

@ -7,3 +7,5 @@ ELF_RELOC(R_TEAK_16, 1)
ELF_RELOC(R_TEAK_CALL_IMM18, 2)
ELF_RELOC(R_TEAK_PTR_IMM16, 3)
ELF_RELOC(R_TEAK_REL7, 4)
ELF_RELOC(R_TEAK_BKREP_REG, 5)
ELF_RELOC(R_TEAK_BKREP_R6, 6)

View File

@ -314,6 +314,18 @@ bool TeakAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, Opera
Out.EmitInstruction(Inst, getSTI());
return false;
}
else if(((TeakOperand&)*Operands[0]).getToken() == "callr")
{
std::string cc = ((TeakOperand&)*Operands[2]).getToken();
TeakCC::CondCodes condition;
if(!ParseConditionOp(cc, condition))
return Error(IDLoc, "Invalid condition code!");
Inst.setOpcode(Teak::CALLR_rel7);
Inst.addOperand(MCOperand::createExpr(MCSymbolRefExpr::create(((TeakOperand&)*Operands[1]).getToken(), MCSymbolRefExpr::VK_None, getContext())));
Inst.addOperand(MCOperand::createImm((int)condition));
Out.EmitInstruction(Inst, getSTI());
return false;
}
else if(((TeakOperand&)*Operands[0]).getToken() == "br")
{
std::string cc = ((TeakOperand&)*Operands[2]).getToken();
@ -326,6 +338,72 @@ bool TeakAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, Opera
Out.EmitInstruction(Inst, getSTI());
return false;
}
else if(((TeakOperand&)*Operands[0]).getToken() == "brr")
{
std::string cc = ((TeakOperand&)*Operands[2]).getToken();
TeakCC::CondCodes condition;
if(!ParseConditionOp(cc, condition))
return Error(IDLoc, "Invalid condition code!");
Inst.setOpcode(Teak::BRRCond_rel7);
Inst.addOperand(MCOperand::createExpr(MCSymbolRefExpr::create(((TeakOperand&)*Operands[1]).getToken(), MCSymbolRefExpr::VK_None, getContext())));
Inst.addOperand(MCOperand::createImm((int)condition));
Out.EmitInstruction(Inst, getSTI());
return false;
}
else if(((TeakOperand&)*Operands[0]).getToken() == "bkrep")
{
std::string regString = ((TeakOperand&)*Operands[1]).getToken();
Inst.setOpcode(Teak::BKREP_reg16);
int reg = -1;
if (regString == "a0l")
reg = Teak::A0L;
else if (regString == "a1l")
reg = Teak::A1L;
else if (regString == "b0l")
reg = Teak::B0L;
else if (regString == "b1l")
reg = Teak::B1L;
else if (regString == "a0h")
reg = Teak::A0H;
else if (regString == "a1h")
reg = Teak::A1H;
else if (regString == "b0h")
reg = Teak::B0H;
else if (regString == "b1h")
reg = Teak::B1H;
else if (regString == "r0")
reg = Teak::R0;
else if (regString == "r1")
reg = Teak::R1;
else if (regString == "r2")
reg = Teak::R2;
else if (regString == "r3")
reg = Teak::R3;
else if (regString == "r4")
reg = Teak::R4;
else if (regString == "r5")
reg = Teak::R5;
else if (regString == "r6")
reg = Teak::R6;
else if (regString == "r7")
reg = Teak::R7;
else if (regString == "y0")
reg = Teak::Y0;
else if (regString == "sv")
reg = Teak::SV;
else if (regString == "lc")
reg = Teak::LC;
if (reg == -1)
return Error(IDLoc, "Invalid register for bkrep");
Inst.addOperand(MCOperand::createReg(reg));
Inst.addOperand(MCOperand::createExpr(MCSymbolRefExpr::create(((TeakOperand&)*Operands[2]).getToken(), MCSymbolRefExpr::VK_None, getContext())));
Out.EmitInstruction(Inst, getSTI());
return false;
}
for (auto &op : Operands)
{
TeakOperand& teakOp = static_cast<TeakOperand&>(*op);
@ -510,6 +588,19 @@ bool TeakAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
else
Operands.push_back(TeakOperand::createToken(op + formatString("0x%04x", val), loc, true, hasSign, false, val * mul));
}
else if (Tok.is(AsmToken::Identifier))
{
std::string reg = Tok.getString();
getParser().Lex();
const AsmToken &Tok2 = getParser().getTok();
if (reg == "p" && Tok2.is(AsmToken::Star))
{
Operands.push_back(TeakOperand::createToken("p*", loc));
getParser().Lex();
}
else
Operands.push_back(TeakOperand::createToken(reg, loc));
}
else
{
Operands.push_back(TeakOperand::createToken(Name2, Tok.getLoc()));

View File

@ -59,6 +59,8 @@ public:
{ "fixup_teak_call_imm18", 0, 18, 0 },
{ "fixup_teak_rel7", 0, 7, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_teak_ptr_imm16", 0, 16, 0 },
{ "fixup_teak_bkrep_reg", 0, 18, 0 },
{ "fixup_teak_bkrep_r6", 0, 18, 0 },
};
if (Kind < FirstTargetFixupKind)
@ -132,6 +134,16 @@ void TeakAsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
case Teak::fixup_teak_ptr_imm16:
write16le(&Data[Offset + 2], Value);
break;
case Teak::fixup_teak_bkrep_reg:
Value--; //bkrep wants as address the last instruction word
write16le(&Data[Offset], (read16le(&Data[Offset]) & ~0x60) | (((Value >> 16) & 3) << 5));
write16le(&Data[Offset + 2], Value & 0xFFFF);
break;
case Teak::fixup_teak_bkrep_r6:
Value--; //bkrep wants as address the last instruction word
write16le(&Data[Offset], (read16le(&Data[Offset]) & ~3) | ((Value >> 16) & 3));
write16le(&Data[Offset + 2], Value & 0xFFFF);
break;
}
// unsigned NumBytes = 4;
// Value = adjustFixupValue(Fixup, Value);

View File

@ -56,6 +56,12 @@ unsigned TeakELFObjectWriter::getRelocType(MCContext &Ctx,
case Teak::fixup_teak_ptr_imm16:
Type = ELF::R_TEAK_PTR_IMM16;
break;
case Teak::fixup_teak_bkrep_reg:
Type = ELF::R_TEAK_BKREP_REG;
break;
case Teak::fixup_teak_bkrep_r6:
Type = ELF::R_TEAK_BKREP_R6;
break;
}
return Type;
}

View File

@ -18,6 +18,8 @@ enum Fixups {
fixup_teak_call_imm18 = FirstTargetFixupKind,
fixup_teak_rel7,
fixup_teak_ptr_imm16,
fixup_teak_bkrep_reg,
fixup_teak_bkrep_r6,
// Marker
LastTargetFixupKind,

View File

@ -495,6 +495,23 @@ void TeakMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
case Teak::AND_memrn_a:
EmitConstant(0x8280 | encodeRnOp(MI.getOperand(1).getReg()) | (encodeAxOp(MI.getOperand(0).getReg()) << 8), 2, OS);
break;
case Teak::BKREP_reg16:
{
unsigned lcReg = MI.getOperand(0).getReg();
if (lcReg == Teak::R6)
{
EmitConstant(0x8FDC, 2, OS);
EmitConstant(0, 2, OS);
Fixups.push_back(MCFixup::create(0, MI.getOperand(1).getExpr(), MCFixupKind(Teak::fixup_teak_bkrep_r6)));
}
else
{
EmitConstant(0x5D00 | encodeRegisterOp(lcReg), 2, OS);
EmitConstant(0, 2, OS);
Fixups.push_back(MCFixup::create(0, MI.getOperand(1).getExpr(), MCFixupKind(Teak::fixup_teak_bkrep_reg)));
}
break;
}
case Teak::BRR_rel7:
case Teak::BRRCond_rel7:
EmitConstant(0x5000 | (MI.getOpcode() == Teak::BRR_rel7 ? 0 : MI.getOperand(1).getImm()), 2, OS);

View File

@ -237,10 +237,10 @@ let Defs = [ICC] in
let Constraints = "$dst = $a" in
{
def MODR_inc1 : InstTeak<(outs GRRegs:$dst), (ins GRRegs:$a), "modr [${a}++]", [(set GRRegs:$dst, (add GRRegs:$a, 1))]>;
def MODR_dec1 : InstTeak<(outs GRRegs:$dst), (ins GRRegs:$a), "modr [${a}--]", [(set GRRegs:$dst, (add GRRegs:$a, -1))]>;
def MODR_inc2 : InstTeak<(outs GRRegs:$dst), (ins GRRegs:$a), "modr ${a}, +2", [(set GRRegs:$dst, (add GRRegs:$a, 2))]>;
def MODR_dec2 : InstTeak<(outs GRRegs:$dst), (ins GRRegs:$a), "modr ${a}, -2", [(set GRRegs:$dst, (add GRRegs:$a, -2))]>;
def MODR_inc1 : InstTeak<(outs GRRegs:$dst), (ins GRRegs:$a), "modr [${a}++]", []>;//(set GRRegs:$dst, (add GRRegs:$a, 1))]>;
def MODR_dec1 : InstTeak<(outs GRRegs:$dst), (ins GRRegs:$a), "modr [${a}--]", []>;//(set GRRegs:$dst, (add GRRegs:$a, -1))]>;
def MODR_inc2 : InstTeak<(outs GRRegs:$dst), (ins GRRegs:$a), "modr ${a}, +2", []>;//(set GRRegs:$dst, (add GRRegs:$a, 2))]>;
def MODR_dec2 : InstTeak<(outs GRRegs:$dst), (ins GRRegs:$a), "modr ${a}, -2", []>;//(set GRRegs:$dst, (add GRRegs:$a, -2))]>;
}
let Constraints = "$dst = $a" in
@ -624,6 +624,9 @@ def BRR_rel7 : InstTeak<(outs), (ins Operand<OtherVT>:$addr), "brr $addr, always
let isBranch = 1, isTerminator = 1 in
def BR_imm18 : InstTeakImm16<(outs), (ins Operand<OtherVT>:$addr, pred:$p), "br $addr, $p", []>;
let Defs = [LC] in
def BKREP_reg16 : InstTeakImm16<(outs), (ins RegNoBRegs16:$it, Operand<OtherVT>:$addr), "bkre $it, $addr", []>;
let isCall = 1, Uses = [SP] in
def CALLR_rel7 : InstTeak<(outs), (ins Operand<i40>:$addr, pred:$p), "callr $addr, $p", []>;

View File

@ -35,6 +35,7 @@ bool TeakOptimizeMovImmPass::runOnMachineFunction(MachineFunction& mf)
const TargetInstrInfo* tii = mf.getSubtarget().getInstrInfo();
std::vector<MachineInstr*> movImms;
std::vector<MachineInstr*> addvSubvReg;
for (auto& mbb : mf)
{
@ -46,6 +47,8 @@ bool TeakOptimizeMovImmPass::runOnMachineFunction(MachineFunction& mf)
{
movImms.push_back(&mi);
}
else if (mi.getOpcode() == Teak::ADDV_imm16_RegNoBRegs16 || mi.getOpcode() == Teak::SUBV_imm16_RegNoBRegs16)
addvSubvReg.push_back(&mi);
}
}
@ -84,6 +87,48 @@ bool TeakOptimizeMovImmPass::runOnMachineFunction(MachineFunction& mf)
}
}
for (auto mi : addvSubvReg)
{
if (!mi->getOperand(1).isImm())
continue;
unsigned dstReg = mi->getOperand(0).getReg();
if (!TeakMCRegisterClasses[Teak::GRRegsRegClassID].contains(dstReg))
continue;
int16_t imm = (int16_t)mi->getOperand(1).getImm();
if (mi->getOpcode() == Teak::SUBV_imm16_RegNoBRegs16)
imm = -imm;
if (imm == 1)
{
BuildMI(*mi->getParent(), *mi, mi->getDebugLoc(), tii->get(Teak::MODR_inc1), dstReg)
.addReg(dstReg);
mi->eraseFromParent();
changed = true;
}
else if (imm == -1)
{
BuildMI(*mi->getParent(), *mi, mi->getDebugLoc(), tii->get(Teak::MODR_dec1), dstReg)
.addReg(dstReg);
mi->eraseFromParent();
changed = true;
}
else if (imm == 2)
{
BuildMI(*mi->getParent(), *mi, mi->getDebugLoc(), tii->get(Teak::MODR_inc2), dstReg)
.addReg(dstReg);
mi->eraseFromParent();
changed = true;
}
else if (imm == -2)
{
BuildMI(*mi->getParent(), *mi, mi->getDebugLoc(), tii->get(Teak::MODR_dec2), dstReg)
.addReg(dstReg);
mi->eraseFromParent();
changed = true;
}
}
return changed;
}