1 //===-- MBlazeAsmBackend.cpp - MBlaze Assembler Backend -------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "llvm/Target/TargetAsmBackend.h"
12 #include "MBlazeELFWriterInfo.h"
13 #include "llvm/ADT/Twine.h"
14 #include "llvm/MC/MCAssembler.h"
15 #include "llvm/MC/MCAsmLayout.h"
16 #include "llvm/MC/MCELFObjectWriter.h"
17 #include "llvm/MC/MCELFSymbolFlags.h"
18 #include "llvm/MC/MCExpr.h"
19 #include "llvm/MC/MCObjectWriter.h"
20 #include "llvm/MC/MCSectionELF.h"
21 #include "llvm/MC/MCSectionMachO.h"
22 #include "llvm/MC/MCValue.h"
23 #include "llvm/Support/ELF.h"
24 #include "llvm/Support/ErrorHandling.h"
25 #include "llvm/Support/raw_ostream.h"
26 #include "llvm/Target/TargetRegistry.h"
27 #include "llvm/Target/TargetAsmBackend.h"
30 static unsigned getFixupKindSize(unsigned Kind
) {
32 default: assert(0 && "invalid fixup kind!");
33 case FK_Data_1
: return 1;
35 case FK_Data_2
: return 2;
37 case FK_Data_4
: return 4;
38 case FK_Data_8
: return 8;
44 class MBlazeELFObjectWriter
: public MCELFObjectTargetWriter
{
46 MBlazeELFObjectWriter(Triple::OSType OSType
)
47 : MCELFObjectTargetWriter(/*is64Bit*/ false, OSType
, ELF::EM_MBLAZE
,
48 /*HasRelocationAddend*/ true) {}
51 class MBlazeAsmBackend
: public TargetAsmBackend
{
53 MBlazeAsmBackend(const Target
&T
)
54 : TargetAsmBackend() {
57 unsigned getNumFixupKinds() const {
61 bool MayNeedRelaxation(const MCInst
&Inst
) const;
63 void RelaxInstruction(const MCInst
&Inst
, MCInst
&Res
) const;
65 bool WriteNopData(uint64_t Count
, MCObjectWriter
*OW
) const;
67 unsigned getPointerSize() const {
72 static unsigned getRelaxedOpcode(unsigned Op
) {
75 case MBlaze::ADDIK
: return MBlaze::ADDIK32
;
76 case MBlaze::ORI
: return MBlaze::ORI32
;
77 case MBlaze::BRLID
: return MBlaze::BRLID32
;
81 bool MBlazeAsmBackend::MayNeedRelaxation(const MCInst
&Inst
) const {
82 if (getRelaxedOpcode(Inst
.getOpcode()) == Inst
.getOpcode())
85 bool hasExprOrImm
= false;
86 for (unsigned i
= 0; i
< Inst
.getNumOperands(); ++i
)
87 hasExprOrImm
|= Inst
.getOperand(i
).isExpr();
92 void MBlazeAsmBackend::RelaxInstruction(const MCInst
&Inst
, MCInst
&Res
) const {
94 Res
.setOpcode(getRelaxedOpcode(Inst
.getOpcode()));
97 bool MBlazeAsmBackend::WriteNopData(uint64_t Count
, MCObjectWriter
*OW
) const {
101 for (uint64_t i
= 0; i
< Count
; i
+= 4)
102 OW
->Write32(0x00000000);
106 } // end anonymous namespace
109 class ELFMBlazeAsmBackend
: public MBlazeAsmBackend
{
111 Triple::OSType OSType
;
112 ELFMBlazeAsmBackend(const Target
&T
, Triple::OSType _OSType
)
113 : MBlazeAsmBackend(T
), OSType(_OSType
) { }
115 void ApplyFixup(const MCFixup
&Fixup
, char *Data
, unsigned DataSize
,
116 uint64_t Value
) const;
118 MCObjectWriter
*createObjectWriter(raw_ostream
&OS
) const {
119 return createELFObjectWriter(new MBlazeELFObjectWriter(OSType
), OS
,
120 /*IsLittleEndian*/ false);
124 void ELFMBlazeAsmBackend::ApplyFixup(const MCFixup
&Fixup
, char *Data
,
125 unsigned DataSize
, uint64_t Value
) const {
126 unsigned Size
= getFixupKindSize(Fixup
.getKind());
128 assert(Fixup
.getOffset() + Size
<= DataSize
&&
129 "Invalid fixup offset!");
131 char *data
= Data
+ Fixup
.getOffset();
133 default: llvm_unreachable("Cannot fixup unknown value.");
134 case 1: llvm_unreachable("Cannot fixup 1 byte value.");
135 case 8: llvm_unreachable("Cannot fixup 8 byte value.");
138 *(data
+7) = uint8_t(Value
);
139 *(data
+6) = uint8_t(Value
>> 8);
140 *(data
+3) = uint8_t(Value
>> 16);
141 *(data
+2) = uint8_t(Value
>> 24);
145 *(data
+3) = uint8_t(Value
>> 0);
146 *(data
+2) = uint8_t(Value
>> 8);
149 } // end anonymous namespace
151 TargetAsmBackend
*llvm::createMBlazeAsmBackend(const Target
&T
,
152 const std::string
&TT
) {
153 Triple
TheTriple(TT
);
155 if (TheTriple
.isOSDarwin())
156 assert(0 && "Mac not supported on MBlaze");
158 if (TheTriple
.isOSWindows())
159 assert(0 && "Windows not supported on MBlaze");
161 return new ELFMBlazeAsmBackend(T
, TheTriple
.getOS());