diff options
Diffstat (limited to 'llvm/lib/Target/AVR')
18 files changed, 131 insertions, 34 deletions
diff --git a/llvm/lib/Target/AVR/AVRAsmPrinter.cpp b/llvm/lib/Target/AVR/AVRAsmPrinter.cpp index 1db6b2236b4f..9b09c7456543 100644 --- a/llvm/lib/Target/AVR/AVRAsmPrinter.cpp +++ b/llvm/lib/Target/AVR/AVRAsmPrinter.cpp @@ -178,7 +178,7 @@ void AVRAsmPrinter::EmitInstruction(const MachineInstr *MI) { } // end of namespace llvm -extern "C" void LLVMInitializeAVRAsmPrinter() { +extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeAVRAsmPrinter() { llvm::RegisterAsmPrinter<llvm::AVRAsmPrinter> X(llvm::getTheAVRTarget()); } diff --git a/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp b/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp index 83d0f6845332..f466c5c053ad 100644 --- a/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp +++ b/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp @@ -52,6 +52,8 @@ private: /// The register to be used for temporary storage. const unsigned SCRATCH_REGISTER = AVR::R0; + /// The register that will always contain zero. + const unsigned ZERO_REGISTER = AVR::R1; /// The IO address of the status register. const unsigned SREG_ADDR = 0x3f; @@ -1243,6 +1245,93 @@ bool AVRExpandPseudo::expand<AVR::POPWRd>(Block &MBB, BlockIt MBBI) { } template <> +bool AVRExpandPseudo::expand<AVR::ROLBRd>(Block &MBB, BlockIt MBBI) { + // In AVR, the rotate instructions behave quite unintuitively. They rotate + // bits through the carry bit in SREG, effectively rotating over 9 bits, + // instead of 8. This is useful when we are dealing with numbers over + // multiple registers, but when we actually need to rotate stuff, we have + // to explicitly add the carry bit. + + MachineInstr &MI = *MBBI; + unsigned OpShift, OpCarry; + unsigned DstReg = MI.getOperand(0).getReg(); + bool DstIsDead = MI.getOperand(0).isDead(); + OpShift = AVR::ADDRdRr; + OpCarry = AVR::ADCRdRr; + + // add r16, r16 + // adc r16, r1 + + // Shift part + buildMI(MBB, MBBI, OpShift) + .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead)) + .addReg(DstReg) + .addReg(DstReg); + + // Add the carry bit + auto MIB = buildMI(MBB, MBBI, OpCarry) + .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead)) + .addReg(DstReg) + .addReg(ZERO_REGISTER); + + // SREG is always implicitly killed + MIB->getOperand(2).setIsKill(); + + MI.eraseFromParent(); + return true; +} + +template <> +bool AVRExpandPseudo::expand<AVR::RORBRd>(Block &MBB, BlockIt MBBI) { + // In AVR, the rotate instructions behave quite unintuitively. They rotate + // bits through the carry bit in SREG, effectively rotating over 9 bits, + // instead of 8. This is useful when we are dealing with numbers over + // multiple registers, but when we actually need to rotate stuff, we have + // to explicitly add the carry bit. + + MachineInstr &MI = *MBBI; + unsigned OpShiftOut, OpLoad, OpShiftIn, OpAdd; + unsigned DstReg = MI.getOperand(0).getReg(); + bool DstIsDead = MI.getOperand(0).isDead(); + OpShiftOut = AVR::LSRRd; + OpLoad = AVR::LDIRdK; + OpShiftIn = AVR::RORRd; + OpAdd = AVR::ORRdRr; + + // lsr r16 + // ldi r0, 0 + // ror r0 + // or r16, r17 + + // Shift out + buildMI(MBB, MBBI, OpShiftOut) + .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead)) + .addReg(DstReg); + + // Put 0 in temporary register + buildMI(MBB, MBBI, OpLoad) + .addReg(SCRATCH_REGISTER, RegState::Define | getDeadRegState(true)) + .addImm(0x00); + + // Shift in + buildMI(MBB, MBBI, OpShiftIn) + .addReg(SCRATCH_REGISTER, RegState::Define | getDeadRegState(true)) + .addReg(SCRATCH_REGISTER); + + // Add the results together using an or-instruction + auto MIB = buildMI(MBB, MBBI, OpAdd) + .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead)) + .addReg(DstReg) + .addReg(SCRATCH_REGISTER); + + // SREG is always implicitly killed + MIB->getOperand(2).setIsKill(); + + MI.eraseFromParent(); + return true; +} + +template <> bool AVRExpandPseudo::expand<AVR::LSLWRd>(Block &MBB, BlockIt MBBI) { MachineInstr &MI = *MBBI; unsigned OpLo, OpHi, DstLoReg, DstHiReg; @@ -1562,6 +1651,8 @@ bool AVRExpandPseudo::expandMI(Block &MBB, BlockIt MBBI) { EXPAND(AVR::OUTWARr); EXPAND(AVR::PUSHWRr); EXPAND(AVR::POPWRd); + EXPAND(AVR::ROLBRd); + EXPAND(AVR::RORBRd); EXPAND(AVR::LSLWRd); EXPAND(AVR::LSRWRd); EXPAND(AVR::RORWRd); diff --git a/llvm/lib/Target/AVR/AVRISelLowering.cpp b/llvm/lib/Target/AVR/AVRISelLowering.cpp index f12c59b7d8c3..880688807702 100644 --- a/llvm/lib/Target/AVR/AVRISelLowering.cpp +++ b/llvm/lib/Target/AVR/AVRISelLowering.cpp @@ -1472,16 +1472,15 @@ MachineBasicBlock *AVRTargetLowering::insertShift(MachineInstr &MI, RC = &AVR::DREGSRegClass; break; case AVR::Rol8: - Opc = AVR::ADCRdRr; // ROL is an alias of ADC Rd, Rd + Opc = AVR::ROLBRd; RC = &AVR::GPR8RegClass; - HasRepeatedOperand = true; break; case AVR::Rol16: Opc = AVR::ROLWRd; RC = &AVR::DREGSRegClass; break; case AVR::Ror8: - Opc = AVR::RORRd; + Opc = AVR::RORBRd; RC = &AVR::GPR8RegClass; break; case AVR::Ror16: @@ -2006,11 +2005,11 @@ void AVRTargetLowering::LowerAsmOperandForConstraint(SDValue Op, return TargetLowering::LowerAsmOperandForConstraint(Op, Constraint, Ops, DAG); } -Register AVRTargetLowering::getRegisterByName(const char *RegName, EVT VT, +Register AVRTargetLowering::getRegisterByName(const char *RegName, LLT VT, const MachineFunction &MF) const { Register Reg; - if (VT == MVT::i8) { + if (VT == LLT::scalar(8)) { Reg = StringSwitch<unsigned>(RegName) .Case("r0", AVR::R0).Case("r1", AVR::R1).Case("r2", AVR::R2) .Case("r3", AVR::R3).Case("r4", AVR::R4).Case("r5", AVR::R5) diff --git a/llvm/lib/Target/AVR/AVRISelLowering.h b/llvm/lib/Target/AVR/AVRISelLowering.h index 6c722fa5414b..aca1ea1d50e5 100644 --- a/llvm/lib/Target/AVR/AVRISelLowering.h +++ b/llvm/lib/Target/AVR/AVRISelLowering.h @@ -125,7 +125,7 @@ public: std::vector<SDValue> &Ops, SelectionDAG &DAG) const override; - Register getRegisterByName(const char* RegName, EVT VT, + Register getRegisterByName(const char* RegName, LLT VT, const MachineFunction &MF) const override; bool shouldSplitFunctionArgumentsAsLittleEndian(const DataLayout &DL) diff --git a/llvm/lib/Target/AVR/AVRInstrFormats.td b/llvm/lib/Target/AVR/AVRInstrFormats.td index 347e683cd47f..ef596f5cebd5 100644 --- a/llvm/lib/Target/AVR/AVRInstrFormats.td +++ b/llvm/lib/Target/AVR/AVRInstrFormats.td @@ -42,8 +42,8 @@ class AVRInst32<dag outs, dag ins, string asmstr, list<dag> pattern> } // A class for pseudo instructions. -// Psuedo instructions are not real AVR instructions. The DAG stores -// psuedo instructions which are replaced by real AVR instructions by +// Pseudo instructions are not real AVR instructions. The DAG stores +// pseudo instructions which are replaced by real AVR instructions by // AVRExpandPseudoInsts.cpp. // // For example, the ADDW (add wide, as in add 16 bit values) instruction diff --git a/llvm/lib/Target/AVR/AVRInstrInfo.cpp b/llvm/lib/Target/AVR/AVRInstrInfo.cpp index ba7a95e92c5c..a6832f282b31 100644 --- a/llvm/lib/Target/AVR/AVRInstrInfo.cpp +++ b/llvm/lib/Target/AVR/AVRInstrInfo.cpp @@ -40,8 +40,8 @@ AVRInstrInfo::AVRInstrInfo() void AVRInstrInfo::copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, - const DebugLoc &DL, unsigned DestReg, - unsigned SrcReg, bool KillSrc) const { + const DebugLoc &DL, MCRegister DestReg, + MCRegister SrcReg, bool KillSrc) const { const AVRSubtarget &STI = MBB.getParent()->getSubtarget<AVRSubtarget>(); const AVRRegisterInfo &TRI = *STI.getRegisterInfo(); unsigned Opc; diff --git a/llvm/lib/Target/AVR/AVRInstrInfo.h b/llvm/lib/Target/AVR/AVRInstrInfo.h index ba74af325474..bb00ca8c724a 100644 --- a/llvm/lib/Target/AVR/AVRInstrInfo.h +++ b/llvm/lib/Target/AVR/AVRInstrInfo.h @@ -72,7 +72,7 @@ public: unsigned getInstSizeInBytes(const MachineInstr &MI) const override; void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, - const DebugLoc &DL, unsigned DestReg, unsigned SrcReg, + const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg, bool KillSrc) const override; void storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, unsigned SrcReg, diff --git a/llvm/lib/Target/AVR/AVRInstrInfo.td b/llvm/lib/Target/AVR/AVRInstrInfo.td index caca9b617609..acf991dcfbb1 100644 --- a/llvm/lib/Target/AVR/AVRInstrInfo.td +++ b/llvm/lib/Target/AVR/AVRInstrInfo.td @@ -1310,7 +1310,7 @@ def AtomicLoadOr16 : AtomicLoadOp16<atomic_load_or_16>; def AtomicLoadXor8 : AtomicLoadOp8<atomic_load_xor_8>; def AtomicLoadXor16 : AtomicLoadOp16<atomic_load_xor_16>; def AtomicFence : Pseudo<(outs), (ins), "atomic_fence", - [(atomic_fence imm, imm)]>; + [(atomic_fence timm, timm)]>; // Indirect store from register to data space. def STSKRr : F32DM<0b1, @@ -1676,6 +1676,16 @@ Defs = [SREG] in { // 8-bit ROL is an alias of ADC Rd, Rd + def ROLBRd : Pseudo<(outs GPR8:$rd), + (ins GPR8:$src), + "rolb\t$rd", + [(set i8:$rd, (AVRrol i8:$src)), (implicit SREG)]>; + + def RORBRd : Pseudo<(outs GPR8:$rd), + (ins GPR8:$src), + "rorb\t$rd", + [(set i8:$rd, (AVRror i8:$src)), (implicit SREG)]>; + def ROLWRd : Pseudo<(outs DREGS:$rd), (ins DREGS:$src), "rolw\t$rd", @@ -1686,7 +1696,7 @@ Defs = [SREG] in (outs GPR8:$rd), (ins GPR8:$src), "ror\t$rd", - [(set i8:$rd, (AVRror i8:$src)), (implicit SREG)]>; + []>; def RORWRd : Pseudo<(outs DREGS:$rd), (ins DREGS:$src), diff --git a/llvm/lib/Target/AVR/AVRTargetMachine.cpp b/llvm/lib/Target/AVR/AVRTargetMachine.cpp index 25304280d002..b33284b73d63 100644 --- a/llvm/lib/Target/AVR/AVRTargetMachine.cpp +++ b/llvm/lib/Target/AVR/AVRTargetMachine.cpp @@ -76,7 +76,7 @@ TargetPassConfig *AVRTargetMachine::createPassConfig(PassManagerBase &PM) { return new AVRPassConfig(*this, PM); } -extern "C" void LLVMInitializeAVRTarget() { +extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeAVRTarget() { // Register the target. RegisterTargetMachine<AVRTargetMachine> X(getTheAVRTarget()); diff --git a/llvm/lib/Target/AVR/AsmParser/AVRAsmParser.cpp b/llvm/lib/Target/AVR/AsmParser/AVRAsmParser.cpp index af60bc4fdc90..fc34583ae573 100644 --- a/llvm/lib/Target/AVR/AsmParser/AVRAsmParser.cpp +++ b/llvm/lib/Target/AVR/AsmParser/AVRAsmParser.cpp @@ -682,7 +682,7 @@ bool AVRAsmParser::parseLiteralValues(unsigned SizeInBytes, SMLoc L) { return (parseMany(parseOne)); } -extern "C" void LLVMInitializeAVRAsmParser() { +extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeAVRAsmParser() { RegisterMCAsmParser<AVRAsmParser> X(getTheAVRTarget()); } diff --git a/llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp b/llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp index e203a5069c85..694aee818f7c 100644 --- a/llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp +++ b/llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp @@ -40,7 +40,6 @@ public: DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size, ArrayRef<uint8_t> Bytes, uint64_t Address, - raw_ostream &VStream, raw_ostream &CStream) const override; }; } @@ -52,7 +51,7 @@ static MCDisassembler *createAVRDisassembler(const Target &T, } -extern "C" void LLVMInitializeAVRDisassembler() { +extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeAVRDisassembler() { // Register the disassembler. TargetRegistry::RegisterMCDisassembler(getTheAVRTarget(), createAVRDisassembler); @@ -114,7 +113,6 @@ static const uint8_t *getDecoderTable(uint64_t Size) { DecodeStatus AVRDisassembler::getInstruction(MCInst &Instr, uint64_t &Size, ArrayRef<uint8_t> Bytes, uint64_t Address, - raw_ostream &VStream, raw_ostream &CStream) const { uint32_t Insn; diff --git a/llvm/lib/Target/AVR/MCTargetDesc/AVRInstPrinter.cpp b/llvm/lib/Target/AVR/MCTargetDesc/AVRInstPrinter.cpp index 88ce9a25680e..832112406155 100644 --- a/llvm/lib/Target/AVR/MCTargetDesc/AVRInstPrinter.cpp +++ b/llvm/lib/Target/AVR/MCTargetDesc/AVRInstPrinter.cpp @@ -32,8 +32,9 @@ namespace llvm { #define PRINT_ALIAS_INSTR #include "AVRGenAsmWriter.inc" -void AVRInstPrinter::printInst(const MCInst *MI, raw_ostream &O, - StringRef Annot, const MCSubtargetInfo &STI) { +void AVRInstPrinter::printInst(const MCInst *MI, uint64_t Address, + StringRef Annot, const MCSubtargetInfo &STI, + raw_ostream &O) { unsigned Opcode = MI->getOpcode(); // First handle load and store instructions with postinc or predec @@ -78,7 +79,7 @@ void AVRInstPrinter::printInst(const MCInst *MI, raw_ostream &O, break; default: if (!printAliasInstr(MI, O)) - printInstruction(MI, O); + printInstruction(MI, Address, O); printAnnotation(O, Annot); break; diff --git a/llvm/lib/Target/AVR/MCTargetDesc/AVRInstPrinter.h b/llvm/lib/Target/AVR/MCTargetDesc/AVRInstPrinter.h index 5b758a7503c9..247e9fc83989 100644 --- a/llvm/lib/Target/AVR/MCTargetDesc/AVRInstPrinter.h +++ b/llvm/lib/Target/AVR/MCTargetDesc/AVRInstPrinter.h @@ -29,8 +29,8 @@ public: static const char *getPrettyRegisterName(unsigned RegNo, MCRegisterInfo const &MRI); - void printInst(const MCInst *MI, raw_ostream &O, StringRef Annot, - const MCSubtargetInfo &STI) override; + void printInst(const MCInst *MI, uint64_t Address, StringRef Annot, + const MCSubtargetInfo &STI, raw_ostream &O) override; private: static const char *getRegisterName(unsigned RegNo, @@ -41,7 +41,7 @@ private: void printMemri(const MCInst *MI, unsigned OpNo, raw_ostream &O); // Autogenerated by TableGen. - void printInstruction(const MCInst *MI, raw_ostream &O); + void printInstruction(const MCInst *MI, uint64_t Address, raw_ostream &O); bool printAliasInstr(const MCInst *MI, raw_ostream &O); void printCustomAliasOperand(const MCInst *MI, unsigned OpIdx, unsigned PrintMethodIdx, raw_ostream &O); diff --git a/llvm/lib/Target/AVR/MCTargetDesc/AVRMCAsmInfo.cpp b/llvm/lib/Target/AVR/MCTargetDesc/AVRMCAsmInfo.cpp index 99b2172c562f..c25a2b232013 100644 --- a/llvm/lib/Target/AVR/MCTargetDesc/AVRMCAsmInfo.cpp +++ b/llvm/lib/Target/AVR/MCTargetDesc/AVRMCAsmInfo.cpp @@ -16,7 +16,7 @@ namespace llvm { -AVRMCAsmInfo::AVRMCAsmInfo(const Triple &TT) { +AVRMCAsmInfo::AVRMCAsmInfo(const Triple &TT, const MCTargetOptions &Options) { CodePointerSize = 2; CalleeSaveStackSlotSize = 2; CommentString = ";"; diff --git a/llvm/lib/Target/AVR/MCTargetDesc/AVRMCAsmInfo.h b/llvm/lib/Target/AVR/MCTargetDesc/AVRMCAsmInfo.h index b2fa18777bc0..17dd77f6266a 100644 --- a/llvm/lib/Target/AVR/MCTargetDesc/AVRMCAsmInfo.h +++ b/llvm/lib/Target/AVR/MCTargetDesc/AVRMCAsmInfo.h @@ -22,7 +22,7 @@ class Triple; /// Specifies the format of AVR assembly files. class AVRMCAsmInfo : public MCAsmInfo { public: - explicit AVRMCAsmInfo(const Triple &TT); + explicit AVRMCAsmInfo(const Triple &TT, const MCTargetOptions &Options); }; } // end namespace llvm diff --git a/llvm/lib/Target/AVR/MCTargetDesc/AVRMCCodeEmitter.cpp b/llvm/lib/Target/AVR/MCTargetDesc/AVRMCCodeEmitter.cpp index bc0488778685..db995e247562 100644 --- a/llvm/lib/Target/AVR/MCTargetDesc/AVRMCCodeEmitter.cpp +++ b/llvm/lib/Target/AVR/MCTargetDesc/AVRMCCodeEmitter.cpp @@ -25,6 +25,7 @@ #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/Support/Casting.h" +#include "llvm/Support/EndianStream.h" #include "llvm/Support/raw_ostream.h" #define DEBUG_TYPE "mccodeemitter" @@ -268,14 +269,11 @@ unsigned AVRMCCodeEmitter::getMachineOpValue(const MCInst &MI, void AVRMCCodeEmitter::emitInstruction(uint64_t Val, unsigned Size, const MCSubtargetInfo &STI, raw_ostream &OS) const { - const uint16_t *Words = reinterpret_cast<uint16_t const *>(&Val); size_t WordCount = Size / 2; for (int64_t i = WordCount - 1; i >= 0; --i) { - uint16_t Word = Words[i]; - - OS << (uint8_t) ((Word & 0x00ff) >> 0); - OS << (uint8_t) ((Word & 0xff00) >> 8); + uint16_t Word = (Val >> (i * 16)) & 0xFFFF; + support::endian::write(OS, Word, support::endianness::little); } } diff --git a/llvm/lib/Target/AVR/MCTargetDesc/AVRMCTargetDesc.cpp b/llvm/lib/Target/AVR/MCTargetDesc/AVRMCTargetDesc.cpp index f6607b26a065..bfc274d9cdcc 100644 --- a/llvm/lib/Target/AVR/MCTargetDesc/AVRMCTargetDesc.cpp +++ b/llvm/lib/Target/AVR/MCTargetDesc/AVRMCTargetDesc.cpp @@ -89,7 +89,7 @@ static MCTargetStreamer *createMCAsmTargetStreamer(MCStreamer &S, return new AVRTargetAsmStreamer(S); } -extern "C" void LLVMInitializeAVRTargetMC() { +extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeAVRTargetMC() { // Register the MC asm info. RegisterMCAsmInfo<AVRMCAsmInfo> X(getTheAVRTarget()); diff --git a/llvm/lib/Target/AVR/TargetInfo/AVRTargetInfo.cpp b/llvm/lib/Target/AVR/TargetInfo/AVRTargetInfo.cpp index c62d5cb85bc4..69b509b33e88 100644 --- a/llvm/lib/Target/AVR/TargetInfo/AVRTargetInfo.cpp +++ b/llvm/lib/Target/AVR/TargetInfo/AVRTargetInfo.cpp @@ -15,7 +15,7 @@ Target &getTheAVRTarget() { } } -extern "C" void LLVMInitializeAVRTargetInfo() { +extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeAVRTargetInfo() { llvm::RegisterTarget<llvm::Triple::avr> X(llvm::getTheAVRTarget(), "avr", "Atmel AVR Microcontroller", "AVR"); } |