diff --git a/lld/ELF/Arch/Teak.cpp b/lld/ELF/Arch/Teak.cpp index 2ad6d9e0a3f..10c58f6259c 100644 --- a/lld/ELF/Arch/Teak.cpp +++ b/lld/ELF/Arch/Teak.cpp @@ -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)); } diff --git a/llvm/include/llvm/BinaryFormat/ELFRelocs/Teak.def b/llvm/include/llvm/BinaryFormat/ELFRelocs/Teak.def index e1fa7a5fe0f..1c9c684446f 100644 --- a/llvm/include/llvm/BinaryFormat/ELFRelocs/Teak.def +++ b/llvm/include/llvm/BinaryFormat/ELFRelocs/Teak.def @@ -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) \ No newline at end of file diff --git a/llvm/lib/Target/Teak/AsmParser/TeakAsmParser.cpp b/llvm/lib/Target/Teak/AsmParser/TeakAsmParser.cpp index e87616f15b0..a5d53230077 100644 --- a/llvm/lib/Target/Teak/AsmParser/TeakAsmParser.cpp +++ b/llvm/lib/Target/Teak/AsmParser/TeakAsmParser.cpp @@ -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(*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())); diff --git a/llvm/lib/Target/Teak/MCTargetDesc/TeakAsmBackend.cpp b/llvm/lib/Target/Teak/MCTargetDesc/TeakAsmBackend.cpp index 8735efb55a0..dca4d2d4fbe 100644 --- a/llvm/lib/Target/Teak/MCTargetDesc/TeakAsmBackend.cpp +++ b/llvm/lib/Target/Teak/MCTargetDesc/TeakAsmBackend.cpp @@ -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); diff --git a/llvm/lib/Target/Teak/MCTargetDesc/TeakELFObjectWriter.cpp b/llvm/lib/Target/Teak/MCTargetDesc/TeakELFObjectWriter.cpp index 4ae53dcda9c..878ba242703 100644 --- a/llvm/lib/Target/Teak/MCTargetDesc/TeakELFObjectWriter.cpp +++ b/llvm/lib/Target/Teak/MCTargetDesc/TeakELFObjectWriter.cpp @@ -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; } diff --git a/llvm/lib/Target/Teak/MCTargetDesc/TeakFixupKinds.h b/llvm/lib/Target/Teak/MCTargetDesc/TeakFixupKinds.h index 110de1e7a1d..a4a9060283a 100644 --- a/llvm/lib/Target/Teak/MCTargetDesc/TeakFixupKinds.h +++ b/llvm/lib/Target/Teak/MCTargetDesc/TeakFixupKinds.h @@ -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, diff --git a/llvm/lib/Target/Teak/MCTargetDesc/TeakMCCodeEmitter.cpp b/llvm/lib/Target/Teak/MCTargetDesc/TeakMCCodeEmitter.cpp index ec98a2feb8e..2d1da7a0f6d 100644 --- a/llvm/lib/Target/Teak/MCTargetDesc/TeakMCCodeEmitter.cpp +++ b/llvm/lib/Target/Teak/MCTargetDesc/TeakMCCodeEmitter.cpp @@ -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); diff --git a/llvm/lib/Target/Teak/TeakInstrInfo.td b/llvm/lib/Target/Teak/TeakInstrInfo.td index 3606bacf45c..6923a443456 100644 --- a/llvm/lib/Target/Teak/TeakInstrInfo.td +++ b/llvm/lib/Target/Teak/TeakInstrInfo.td @@ -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:$addr), "brr $addr, always let isBranch = 1, isTerminator = 1 in def BR_imm18 : InstTeakImm16<(outs), (ins Operand:$addr, pred:$p), "br $addr, $p", []>; +let Defs = [LC] in +def BKREP_reg16 : InstTeakImm16<(outs), (ins RegNoBRegs16:$it, Operand:$addr), "bkre $it, $addr", []>; + let isCall = 1, Uses = [SP] in def CALLR_rel7 : InstTeak<(outs), (ins Operand:$addr, pred:$p), "callr $addr, $p", []>; diff --git a/llvm/lib/Target/Teak/TeakOptimizeMovImmPass.cpp b/llvm/lib/Target/Teak/TeakOptimizeMovImmPass.cpp index 8fcb739a4e0..ae6c8ebca7a 100644 --- a/llvm/lib/Target/Teak/TeakOptimizeMovImmPass.cpp +++ b/llvm/lib/Target/Teak/TeakOptimizeMovImmPass.cpp @@ -35,6 +35,7 @@ bool TeakOptimizeMovImmPass::runOnMachineFunction(MachineFunction& mf) const TargetInstrInfo* tii = mf.getSubtarget().getInstrInfo(); std::vector movImms; + std::vector 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; }