1 Pull in r198533 from upstream llvm trunk (by Venkatraman Govindaraju):
3 [Sparc] Add initial implementation of MC Code emitter for sparc.
5 Introduced here: http://svn.freebsd.org/changeset/base/262261
7 Index: lib/Target/Sparc/SparcInstrInfo.td
8 ===================================================================
9 --- lib/Target/Sparc/SparcInstrInfo.td
10 +++ lib/Target/Sparc/SparcInstrInfo.td
11 @@ -100,9 +100,14 @@ def MEMri : Operand<iPTR> {
12 def TLSSym : Operand<iPTR>;
14 // Branch targets have OtherVT type.
15 -def brtarget : Operand<OtherVT>;
16 -def calltarget : Operand<i32>;
17 +def brtarget : Operand<OtherVT> {
18 + let EncoderMethod = "getBranchTargetOpValue";
21 +def calltarget : Operand<i32> {
22 + let EncoderMethod = "getCallTargetOpValue";
25 // Operand for printing out a condition code.
26 let PrintMethod = "printCCOperand" in
27 def CCOp : Operand<i32>;
28 Index: lib/Target/Sparc/MCTargetDesc/CMakeLists.txt
29 ===================================================================
30 --- lib/Target/Sparc/MCTargetDesc/CMakeLists.txt
31 +++ lib/Target/Sparc/MCTargetDesc/CMakeLists.txt
33 add_llvm_library(LLVMSparcDesc
36 + SparcMCCodeEmitter.cpp
40 SparcTargetStreamer.cpp
42 Index: lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp
43 ===================================================================
44 --- lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp
45 +++ lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp
47 +//===-- SparcMCCodeEmitter.cpp - Convert Sparc code to machine code -------===//
49 +// The LLVM Compiler Infrastructure
51 +// This file is distributed under the University of Illinois Open Source
52 +// License. See LICENSE.TXT for details.
54 +//===----------------------------------------------------------------------===//
56 +// This file implements the SparcMCCodeEmitter class.
58 +//===----------------------------------------------------------------------===//
60 +#define DEBUG_TYPE "mccodeemitter"
61 +#include "SparcMCTargetDesc.h"
62 +#include "MCTargetDesc/SparcFixupKinds.h"
63 +#include "llvm/MC/MCCodeEmitter.h"
64 +#include "llvm/MC/MCContext.h"
65 +#include "llvm/MC/MCExpr.h"
66 +#include "llvm/MC/MCInst.h"
67 +#include "llvm/MC/MCRegisterInfo.h"
68 +#include "llvm/ADT/Statistic.h"
69 +#include "llvm/Support/raw_ostream.h"
71 +using namespace llvm;
73 +STATISTIC(MCNumEmitted, "Number of MC instructions emitted");
76 +class SparcMCCodeEmitter : public MCCodeEmitter {
77 + SparcMCCodeEmitter(const SparcMCCodeEmitter &) LLVM_DELETED_FUNCTION;
78 + void operator=(const SparcMCCodeEmitter &) LLVM_DELETED_FUNCTION;
82 + SparcMCCodeEmitter(MCContext &ctx): Ctx(ctx) {}
84 + ~SparcMCCodeEmitter() {}
86 + void EncodeInstruction(const MCInst &MI, raw_ostream &OS,
87 + SmallVectorImpl<MCFixup> &Fixups) const;
89 + // getBinaryCodeForInstr - TableGen'erated function for getting the
90 + // binary encoding for an instruction.
91 + uint64_t getBinaryCodeForInstr(const MCInst &MI,
92 + SmallVectorImpl<MCFixup> &Fixups) const;
94 + /// getMachineOpValue - Return binary encoding of operand. If the machine
95 + /// operand requires relocation, record the relocation and return zero.
96 + unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO,
97 + SmallVectorImpl<MCFixup> &Fixups) const;
99 + unsigned getCallTargetOpValue(const MCInst &MI, unsigned OpNo,
100 + SmallVectorImpl<MCFixup> &Fixups) const;
101 + unsigned getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
102 + SmallVectorImpl<MCFixup> &Fixups) const;
105 +} // end anonymous namespace
107 +MCCodeEmitter *llvm::createSparcMCCodeEmitter(const MCInstrInfo &MCII,
108 + const MCRegisterInfo &MRI,
109 + const MCSubtargetInfo &STI,
111 + return new SparcMCCodeEmitter(Ctx);
114 +void SparcMCCodeEmitter::
115 +EncodeInstruction(const MCInst &MI, raw_ostream &OS,
116 + SmallVectorImpl<MCFixup> &Fixups) const {
117 + unsigned Bits = getBinaryCodeForInstr(MI, Fixups);
119 + // Output the constant in big endian byte order.
120 + for (unsigned i = 0; i != 4; ++i) {
121 + OS << (char)(Bits >> 24);
125 + ++MCNumEmitted; // Keep track of the # of mi's emitted.
129 +unsigned SparcMCCodeEmitter::
130 +getMachineOpValue(const MCInst &MI, const MCOperand &MO,
131 + SmallVectorImpl<MCFixup> &Fixups) const {
134 + return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
137 + return MO.getImm();
139 + assert(MO.isExpr());
140 + const MCExpr *Expr = MO.getExpr();
142 + if (Expr->EvaluateAsAbsolute(Res))
145 + assert(0 && "Unhandled expression!");
149 +unsigned SparcMCCodeEmitter::
150 +getCallTargetOpValue(const MCInst &MI, unsigned OpNo,
151 + SmallVectorImpl<MCFixup> &Fixups) const {
152 + const MCOperand &MO = MI.getOperand(OpNo);
153 + if (MO.isReg() || MO.isImm())
154 + return getMachineOpValue(MI, MO, Fixups);
156 + Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
157 + (MCFixupKind)Sparc::fixup_sparc_call30));
161 +unsigned SparcMCCodeEmitter::
162 +getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
163 + SmallVectorImpl<MCFixup> &Fixups) const {
164 + const MCOperand &MO = MI.getOperand(OpNo);
165 + if (MO.isReg() || MO.isImm())
166 + return getMachineOpValue(MI, MO, Fixups);
168 + Sparc::Fixups fixup = Sparc::fixup_sparc_br22;
169 + if (MI.getOpcode() == SP::BPXCC)
170 + fixup = Sparc::fixup_sparc_br19;
172 + Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
173 + (MCFixupKind)fixup));
177 +#include "SparcGenMCCodeEmitter.inc"
178 Index: lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp
179 ===================================================================
180 --- lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp
181 +++ lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp
182 @@ -136,6 +136,18 @@ extern "C" void LLVMInitializeSparcTargetMC() {
183 TargetRegistry::RegisterMCSubtargetInfo(TheSparcV9Target,
184 createSparcMCSubtargetInfo);
186 + // Register the MC Code Emitter.
187 + TargetRegistry::RegisterMCCodeEmitter(TheSparcTarget,
188 + createSparcMCCodeEmitter);
189 + TargetRegistry::RegisterMCCodeEmitter(TheSparcV9Target,
190 + createSparcMCCodeEmitter);
192 + //Register the asm backend.
193 + TargetRegistry::RegisterMCAsmBackend(TheSparcTarget,
194 + createSparcAsmBackend);
195 + TargetRegistry::RegisterMCAsmBackend(TheSparcV9Target,
196 + createSparcAsmBackend);
198 TargetRegistry::RegisterAsmStreamer(TheSparcTarget,
199 createMCAsmStreamer);
200 TargetRegistry::RegisterAsmStreamer(TheSparcV9Target,
201 Index: lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp
202 ===================================================================
203 --- lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp
204 +++ lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp
206 +//===-- SparcAsmBackend.cpp - Sparc Assembler Backend ---------------------===//
208 +// The LLVM Compiler Infrastructure
210 +// This file is distributed under the University of Illinois Open Source
211 +// License. See LICENSE.TXT for details.
213 +//===----------------------------------------------------------------------===//
215 +#include "llvm/MC/MCAsmBackend.h"
216 +#include "MCTargetDesc/SparcMCTargetDesc.h"
217 +#include "MCTargetDesc/SparcFixupKinds.h"
218 +#include "llvm/MC/MCFixupKindInfo.h"
219 +#include "llvm/MC/MCObjectWriter.h"
220 +#include "llvm/Support/TargetRegistry.h"
222 +using namespace llvm;
225 + class SparcAsmBackend : public MCAsmBackend {
228 + SparcAsmBackend(const Target &T) : MCAsmBackend() {}
230 + unsigned getNumFixupKinds() const {
231 + return Sparc::NumTargetFixupKinds;
234 + const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const {
235 + const static MCFixupKindInfo Infos[Sparc::NumTargetFixupKinds] = {
236 + // name offset bits flags
237 + { "fixup_sparc_call30", 0, 30, MCFixupKindInfo::FKF_IsPCRel },
238 + { "fixup_sparc_br22", 0, 22, MCFixupKindInfo::FKF_IsPCRel },
239 + { "fixup_sparc_br19", 0, 19, MCFixupKindInfo::FKF_IsPCRel }
242 + if (Kind < FirstTargetFixupKind)
243 + return MCAsmBackend::getFixupKindInfo(Kind);
245 + assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&
247 + return Infos[Kind - FirstTargetFixupKind];
250 + bool mayNeedRelaxation(const MCInst &Inst) const {
255 + /// fixupNeedsRelaxation - Target specific predicate for whether a given
256 + /// fixup requires the associated instruction to be relaxed.
257 + bool fixupNeedsRelaxation(const MCFixup &Fixup,
259 + const MCRelaxableFragment *DF,
260 + const MCAsmLayout &Layout) const {
262 + assert(0 && "fixupNeedsRelaxation() unimplemented");
265 + void relaxInstruction(const MCInst &Inst, MCInst &Res) const {
267 + assert(0 && "relaxInstruction() unimplemented");
270 + bool writeNopData(uint64_t Count, MCObjectWriter *OW) const {
271 + // FIXME: Zero fill for now.
272 + for (uint64_t i = 0; i != Count; ++i)
278 + class ELFSparcAsmBackend : public SparcAsmBackend {
280 + ELFSparcAsmBackend(const Target &T, Triple::OSType OSType) :
281 + SparcAsmBackend(T) { }
283 + void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize,
284 + uint64_t Value) const {
285 + assert(0 && "applyFixup not implemented yet");
288 + MCObjectWriter *createObjectWriter(raw_ostream &OS) const {
289 + assert(0 && "Object Writer not implemented yet");
293 + virtual bool doesSectionRequireSymbols(const MCSection &Section) const {
298 +} // end anonymous namespace
301 +MCAsmBackend *llvm::createSparcAsmBackend(const Target &T,
302 + const MCRegisterInfo &MRI,
305 + return new ELFSparcAsmBackend(T, Triple(TT).getOS());
307 Index: lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h
308 ===================================================================
309 --- lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h
310 +++ lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h
312 +//===-- SparcFixupKinds.h - Sparc Specific Fixup Entries --------*- C++ -*-===//
314 +// The LLVM Compiler Infrastructure
316 +// This file is distributed under the University of Illinois Open Source
317 +// License. See LICENSE.TXT for details.
319 +//===----------------------------------------------------------------------===//
321 +#ifndef LLVM_SPARC_FIXUPKINDS_H
322 +#define LLVM_SPARC_FIXUPKINDS_H
324 +#include "llvm/MC/MCFixup.h"
329 + // fixup_sparc_call30 - 30-bit PC relative relocation for call
330 + fixup_sparc_call30 = FirstTargetFixupKind,
332 + /// fixup_sparc_br22 - 22-bit PC relative relocation for
336 + /// fixup_sparc_br22 - 22-bit PC relative relocation for
337 + /// branches on icc/xcc
341 + LastTargetFixupKind,
342 + NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind
348 Index: lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.h
349 ===================================================================
350 --- lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.h
351 +++ lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.h
353 #define SPARCMCTARGETDESC_H
357 +class MCCodeEmitter;
360 +class MCRegisterInfo;
361 +class MCSubtargetInfo;
365 extern Target TheSparcTarget;
366 extern Target TheSparcV9Target;
368 +MCCodeEmitter *createSparcMCCodeEmitter(const MCInstrInfo &MCII,
369 + const MCRegisterInfo &MRI,
370 + const MCSubtargetInfo &STI,
372 +MCAsmBackend *createSparcAsmBackend(const Target &T,
373 + const MCRegisterInfo &MRI,
377 } // End llvm namespace
379 // Defines symbolic names for Sparc registers. This defines a mapping from
380 Index: lib/Target/Sparc/Makefile
381 ===================================================================
382 --- lib/Target/Sparc/Makefile
383 +++ lib/Target/Sparc/Makefile
384 @@ -16,7 +16,7 @@ BUILT_SOURCES = SparcGenRegisterInfo.inc SparcGenI
385 SparcGenAsmWriter.inc SparcGenAsmMatcher.inc \
386 SparcGenDAGISel.inc \
387 SparcGenSubtargetInfo.inc SparcGenCallingConv.inc \
388 - SparcGenCodeEmitter.inc
389 + SparcGenCodeEmitter.inc SparcGenMCCodeEmitter.inc
391 DIRS = InstPrinter AsmParser TargetInfo MCTargetDesc
393 Index: lib/Target/Sparc/CMakeLists.txt
394 ===================================================================
395 --- lib/Target/Sparc/CMakeLists.txt
396 +++ lib/Target/Sparc/CMakeLists.txt
397 @@ -3,6 +3,7 @@ set(LLVM_TARGET_DEFINITIONS Sparc.td)
398 tablegen(LLVM SparcGenRegisterInfo.inc -gen-register-info)
399 tablegen(LLVM SparcGenInstrInfo.inc -gen-instr-info)
400 tablegen(LLVM SparcGenCodeEmitter.inc -gen-emitter)
401 +tablegen(LLVM SparcGenMCCodeEmitter.inc -gen-emitter -mc-emitter)
402 tablegen(LLVM SparcGenAsmWriter.inc -gen-asm-writer)
403 tablegen(LLVM SparcGenAsmMatcher.inc -gen-asm-matcher)
404 tablegen(LLVM SparcGenDAGISel.inc -gen-dag-isel)
405 Index: lib/Target/Sparc/SparcCodeEmitter.cpp
406 ===================================================================
407 --- lib/Target/Sparc/SparcCodeEmitter.cpp
408 +++ lib/Target/Sparc/SparcCodeEmitter.cpp
409 @@ -72,6 +72,11 @@ class SparcCodeEmitter : public MachineFunctionPas
410 unsigned getMachineOpValue(const MachineInstr &MI,
411 const MachineOperand &MO) const;
413 + unsigned getCallTargetOpValue(const MachineInstr &MI,
415 + unsigned getBranchTargetOpValue(const MachineInstr &MI,
418 void emitWord(unsigned Word);
420 unsigned getRelocation(const MachineInstr &MI,
421 @@ -181,6 +186,18 @@ unsigned SparcCodeEmitter::getMachineOpValue(const
422 llvm_unreachable("Unable to encode MachineOperand!");
425 +unsigned SparcCodeEmitter::getCallTargetOpValue(const MachineInstr &MI,
426 + unsigned opIdx) const {
427 + const MachineOperand MO = MI.getOperand(opIdx);
428 + return getMachineOpValue(MI, MO);
431 +unsigned SparcCodeEmitter::getBranchTargetOpValue(const MachineInstr &MI,
432 + unsigned opIdx) const {
433 + const MachineOperand MO = MI.getOperand(opIdx);
434 + return getMachineOpValue(MI, MO);
437 unsigned SparcCodeEmitter::getRelocation(const MachineInstr &MI,
438 const MachineOperand &MO) const {
440 Index: test/MC/Sparc/sparc-alu-instructions.s
441 ===================================================================
442 --- test/MC/Sparc/sparc-alu-instructions.s
443 +++ test/MC/Sparc/sparc-alu-instructions.s
445 +! RUN: llvm-mc %s -arch=sparc -show-encoding | FileCheck %s
446 +! RUN: llvm-mc %s -arch=sparcv9 -show-encoding | FileCheck %s
448 + ! CHECK: add %g0, %g0, %g0 ! encoding: [0x80,0x00,0x00,0x00]
450 + ! CHECK: add %g1, %g2, %g3 ! encoding: [0x86,0x00,0x40,0x02]
452 + ! CHECK: add %o0, %o1, %l0 ! encoding: [0xa0,0x02,0x00,0x09]
454 + ! CHECK: add %o0, 10, %l0 ! encoding: [0xa0,0x02,0x20,0x0a]
457 + ! CHECK: addcc %g1, %g2, %g3 ! encoding: [0x86,0x80,0x40,0x02]
458 + addcc %g1, %g2, %g3
460 + ! CHECK: addxcc %g1, %g2, %g3 ! encoding: [0x86,0xc0,0x40,0x02]
461 + addxcc %g1, %g2, %g3
463 + ! CHECK: udiv %g1, %g2, %g3 ! encoding: [0x86,0x70,0x40,0x02]
466 + ! CHECK: sdiv %g1, %g2, %g3 ! encoding: [0x86,0x78,0x40,0x02]
469 + ! CHECK: and %g1, %g2, %g3 ! encoding: [0x86,0x08,0x40,0x02]
471 + ! CHECK: andn %g1, %g2, %g3 ! encoding: [0x86,0x28,0x40,0x02]
473 + ! CHECK: or %g1, %g2, %g3 ! encoding: [0x86,0x10,0x40,0x02]
475 + ! CHECK: orn %g1, %g2, %g3 ! encoding: [0x86,0x30,0x40,0x02]
477 + ! CHECK: xor %g1, %g2, %g3 ! encoding: [0x86,0x18,0x40,0x02]
479 + ! CHECK: xnor %g1, %g2, %g3 ! encoding: [0x86,0x38,0x40,0x02]
482 + ! CHECK: umul %g1, %g2, %g3 ! encoding: [0x86,0x50,0x40,0x02]
485 + ! CHECK: smul %g1, %g2, %g3 ! encoding: [0x86,0x58,0x40,0x02]
488 + ! CHECK: nop ! encoding: [0x01,0x00,0x00,0x00]
491 + ! CHECK: sethi 10, %l0 ! encoding: [0x21,0x00,0x00,0x0a]
494 + ! CHECK: sll %g1, %g2, %g3 ! encoding: [0x87,0x28,0x40,0x02]
496 + ! CHECK: sll %g1, 31, %g3 ! encoding: [0x87,0x28,0x60,0x1f]
499 + ! CHECK: srl %g1, %g2, %g3 ! encoding: [0x87,0x30,0x40,0x02]
501 + ! CHECK: srl %g1, 31, %g3 ! encoding: [0x87,0x30,0x60,0x1f]
504 + ! CHECK: sra %g1, %g2, %g3 ! encoding: [0x87,0x38,0x40,0x02]
506 + ! CHECK: sra %g1, 31, %g3 ! encoding: [0x87,0x38,0x60,0x1f]
509 + ! CHECK: sub %g1, %g2, %g3 ! encoding: [0x86,0x20,0x40,0x02]
511 + ! CHECK: subcc %g1, %g2, %g3 ! encoding: [0x86,0xa0,0x40,0x02]
512 + subcc %g1, %g2, %g3
514 + ! CHECK: subxcc %g1, %g2, %g3 ! encoding: [0x86,0xe0,0x40,0x02]
515 + subxcc %g1, %g2, %g3