mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-04-09 01:38:03 +00:00
WIP: Start rewriting descriptor files (.td)
This commit is contained in:
parent
556aedf270
commit
f918d78356
@ -12,7 +12,6 @@ tablegen(LLVM Mos6502GenCallingConv.inc -gen-callingconv)
|
||||
add_public_tablegen_target(Mos6502CommonTableGen)
|
||||
|
||||
add_llvm_target(Mos6502CodeGen
|
||||
DelaySlotFiller.cpp
|
||||
Mos6502AsmPrinter.cpp
|
||||
Mos6502InstrInfo.cpp
|
||||
Mos6502ISelDAGToDAG.cpp
|
||||
|
@ -1,495 +0,0 @@
|
||||
//===-- DelaySlotFiller.cpp - MOS6502 delay slot filler ---------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This is a simple local pass that attempts to fill delay slots with useful
|
||||
// instructions. If no instructions can be moved into the delay slot, then a
|
||||
// NOP is placed.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Mos6502.h"
|
||||
#include "Mos6502Subtarget.h"
|
||||
#include "llvm/ADT/SmallSet.h"
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include "llvm/CodeGen/MachineFunctionPass.h"
|
||||
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Target/TargetInstrInfo.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
#include "llvm/Target/TargetRegisterInfo.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
#define DEBUG_TYPE "delay-slot-filler"
|
||||
|
||||
STATISTIC(FilledSlots, "Number of delay slots filled");
|
||||
|
||||
static cl::opt<bool> DisableDelaySlotFiller(
|
||||
"disable-mos6502-delay-filler",
|
||||
cl::init(false),
|
||||
cl::desc("Disable the Mos6502 delay slot filler."),
|
||||
cl::Hidden);
|
||||
|
||||
namespace {
|
||||
struct Filler : public MachineFunctionPass {
|
||||
/// Target machine description which we query for reg. names, data
|
||||
/// layout, etc.
|
||||
///
|
||||
TargetMachine &TM;
|
||||
const Mos6502Subtarget *Subtarget;
|
||||
|
||||
static char ID;
|
||||
Filler(TargetMachine &tm) : MachineFunctionPass(ID), TM(tm) {}
|
||||
|
||||
const char *getPassName() const override {
|
||||
return "MOS6502 Delay Slot Filler";
|
||||
}
|
||||
|
||||
bool runOnMachineBasicBlock(MachineBasicBlock &MBB);
|
||||
bool runOnMachineFunction(MachineFunction &F) override {
|
||||
bool Changed = false;
|
||||
Subtarget = &F.getSubtarget<Mos6502Subtarget>();
|
||||
|
||||
// This pass invalidates liveness information when it reorders
|
||||
// instructions to fill delay slot.
|
||||
F.getRegInfo().invalidateLiveness();
|
||||
|
||||
for (MachineFunction::iterator FI = F.begin(), FE = F.end();
|
||||
FI != FE; ++FI)
|
||||
Changed |= runOnMachineBasicBlock(*FI);
|
||||
return Changed;
|
||||
}
|
||||
|
||||
void insertCallDefsUses(MachineBasicBlock::iterator MI,
|
||||
SmallSet<unsigned, 32>& RegDefs,
|
||||
SmallSet<unsigned, 32>& RegUses);
|
||||
|
||||
void insertDefsUses(MachineBasicBlock::iterator MI,
|
||||
SmallSet<unsigned, 32>& RegDefs,
|
||||
SmallSet<unsigned, 32>& RegUses);
|
||||
|
||||
bool IsRegInSet(SmallSet<unsigned, 32>& RegSet,
|
||||
unsigned Reg);
|
||||
|
||||
bool delayHasHazard(MachineBasicBlock::iterator candidate,
|
||||
bool &sawLoad, bool &sawStore,
|
||||
SmallSet<unsigned, 32> &RegDefs,
|
||||
SmallSet<unsigned, 32> &RegUses);
|
||||
|
||||
MachineBasicBlock::iterator
|
||||
findDelayInstr(MachineBasicBlock &MBB, MachineBasicBlock::iterator slot);
|
||||
|
||||
bool needsUnimp(MachineBasicBlock::iterator I, unsigned &StructSize);
|
||||
|
||||
bool tryCombineRestoreWithPrevInst(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator MBBI);
|
||||
|
||||
};
|
||||
char Filler::ID = 0;
|
||||
} // end of anonymous namespace
|
||||
|
||||
/// createMos6502DelaySlotFillerPass - Returns a pass that fills in delay
|
||||
/// slots in Mos6502 MachineFunctions
|
||||
///
|
||||
FunctionPass *llvm::createMos6502DelaySlotFillerPass(TargetMachine &tm) {
|
||||
return new Filler(tm);
|
||||
}
|
||||
|
||||
|
||||
/// runOnMachineBasicBlock - Fill in delay slots for the given basic block.
|
||||
/// We assume there is only one delay slot per delayed instruction.
|
||||
///
|
||||
bool Filler::runOnMachineBasicBlock(MachineBasicBlock &MBB) {
|
||||
bool Changed = false;
|
||||
Subtarget = &MBB.getParent()->getSubtarget<Mos6502Subtarget>();
|
||||
const TargetInstrInfo *TII = Subtarget->getInstrInfo();
|
||||
|
||||
for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ) {
|
||||
MachineBasicBlock::iterator MI = I;
|
||||
++I;
|
||||
|
||||
// If MI is restore, try combining it with previous inst.
|
||||
if (!DisableDelaySlotFiller &&
|
||||
(MI->getOpcode() == M6502::RESTORErr
|
||||
|| MI->getOpcode() == M6502::RESTOREri)) {
|
||||
Changed |= tryCombineRestoreWithPrevInst(MBB, MI);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!Subtarget->isV9() &&
|
||||
(MI->getOpcode() == M6502::FCMPS || MI->getOpcode() == M6502::FCMPD
|
||||
|| MI->getOpcode() == M6502::FCMPQ)) {
|
||||
BuildMI(MBB, I, MI->getDebugLoc(), TII->get(M6502::NOP));
|
||||
Changed = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
// If MI has no delay slot, skip.
|
||||
if (!MI->hasDelaySlot())
|
||||
continue;
|
||||
|
||||
MachineBasicBlock::iterator D = MBB.end();
|
||||
|
||||
if (!DisableDelaySlotFiller)
|
||||
D = findDelayInstr(MBB, MI);
|
||||
|
||||
++FilledSlots;
|
||||
Changed = true;
|
||||
|
||||
if (D == MBB.end())
|
||||
BuildMI(MBB, I, MI->getDebugLoc(), TII->get(M6502::NOP));
|
||||
else
|
||||
MBB.splice(I, &MBB, D);
|
||||
|
||||
unsigned structSize = 0;
|
||||
if (needsUnimp(MI, structSize)) {
|
||||
MachineBasicBlock::iterator J = MI;
|
||||
++J; // skip the delay filler.
|
||||
assert (J != MBB.end() && "MI needs a delay instruction.");
|
||||
BuildMI(MBB, ++J, MI->getDebugLoc(),
|
||||
TII->get(M6502::UNIMP)).addImm(structSize);
|
||||
// Bundle the delay filler and unimp with the instruction.
|
||||
MIBundleBuilder(MBB, MachineBasicBlock::iterator(MI), J);
|
||||
} else {
|
||||
MIBundleBuilder(MBB, MachineBasicBlock::iterator(MI), I);
|
||||
}
|
||||
}
|
||||
return Changed;
|
||||
}
|
||||
|
||||
MachineBasicBlock::iterator
|
||||
Filler::findDelayInstr(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator slot)
|
||||
{
|
||||
SmallSet<unsigned, 32> RegDefs;
|
||||
SmallSet<unsigned, 32> RegUses;
|
||||
bool sawLoad = false;
|
||||
bool sawStore = false;
|
||||
|
||||
if (slot == MBB.begin())
|
||||
return MBB.end();
|
||||
|
||||
if (slot->getOpcode() == M6502::RET || slot->getOpcode() == M6502::TLS_CALL)
|
||||
return MBB.end();
|
||||
|
||||
if (slot->getOpcode() == M6502::RETL) {
|
||||
MachineBasicBlock::iterator J = slot;
|
||||
--J;
|
||||
|
||||
if (J->getOpcode() == M6502::RESTORErr
|
||||
|| J->getOpcode() == M6502::RESTOREri) {
|
||||
// change retl to ret.
|
||||
slot->setDesc(Subtarget->getInstrInfo()->get(M6502::RET));
|
||||
return J;
|
||||
}
|
||||
}
|
||||
|
||||
// Call's delay filler can def some of call's uses.
|
||||
if (slot->isCall())
|
||||
insertCallDefsUses(slot, RegDefs, RegUses);
|
||||
else
|
||||
insertDefsUses(slot, RegDefs, RegUses);
|
||||
|
||||
bool done = false;
|
||||
|
||||
MachineBasicBlock::iterator I = slot;
|
||||
|
||||
while (!done) {
|
||||
done = (I == MBB.begin());
|
||||
|
||||
if (!done)
|
||||
--I;
|
||||
|
||||
// skip debug value
|
||||
if (I->isDebugValue())
|
||||
continue;
|
||||
|
||||
if (I->hasUnmodeledSideEffects() || I->isInlineAsm() || I->isPosition() ||
|
||||
I->hasDelaySlot() || I->isBundledWithSucc())
|
||||
break;
|
||||
|
||||
if (delayHasHazard(I, sawLoad, sawStore, RegDefs, RegUses)) {
|
||||
insertDefsUses(I, RegDefs, RegUses);
|
||||
continue;
|
||||
}
|
||||
|
||||
return I;
|
||||
}
|
||||
return MBB.end();
|
||||
}
|
||||
|
||||
bool Filler::delayHasHazard(MachineBasicBlock::iterator candidate,
|
||||
bool &sawLoad,
|
||||
bool &sawStore,
|
||||
SmallSet<unsigned, 32> &RegDefs,
|
||||
SmallSet<unsigned, 32> &RegUses)
|
||||
{
|
||||
|
||||
if (candidate->isImplicitDef() || candidate->isKill())
|
||||
return true;
|
||||
|
||||
if (candidate->mayLoad()) {
|
||||
sawLoad = true;
|
||||
if (sawStore)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (candidate->mayStore()) {
|
||||
if (sawStore)
|
||||
return true;
|
||||
sawStore = true;
|
||||
if (sawLoad)
|
||||
return true;
|
||||
}
|
||||
|
||||
for (unsigned i = 0, e = candidate->getNumOperands(); i!= e; ++i) {
|
||||
const MachineOperand &MO = candidate->getOperand(i);
|
||||
if (!MO.isReg())
|
||||
continue; // skip
|
||||
|
||||
unsigned Reg = MO.getReg();
|
||||
|
||||
if (MO.isDef()) {
|
||||
// check whether Reg is defined or used before delay slot.
|
||||
if (IsRegInSet(RegDefs, Reg) || IsRegInSet(RegUses, Reg))
|
||||
return true;
|
||||
}
|
||||
if (MO.isUse()) {
|
||||
// check whether Reg is defined before delay slot.
|
||||
if (IsRegInSet(RegDefs, Reg))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void Filler::insertCallDefsUses(MachineBasicBlock::iterator MI,
|
||||
SmallSet<unsigned, 32>& RegDefs,
|
||||
SmallSet<unsigned, 32>& RegUses)
|
||||
{
|
||||
// Call defines o7, which is visible to the instruction in delay slot.
|
||||
RegDefs.insert(M6502::O7);
|
||||
|
||||
switch(MI->getOpcode()) {
|
||||
default: llvm_unreachable("Unknown opcode.");
|
||||
case M6502::CALL: break;
|
||||
case M6502::CALLrr:
|
||||
case M6502::CALLri:
|
||||
assert(MI->getNumOperands() >= 2);
|
||||
const MachineOperand &Reg = MI->getOperand(0);
|
||||
assert(Reg.isReg() && "CALL first operand is not a register.");
|
||||
assert(Reg.isUse() && "CALL first operand is not a use.");
|
||||
RegUses.insert(Reg.getReg());
|
||||
|
||||
const MachineOperand &RegOrImm = MI->getOperand(1);
|
||||
if (RegOrImm.isImm())
|
||||
break;
|
||||
assert(RegOrImm.isReg() && "CALLrr second operand is not a register.");
|
||||
assert(RegOrImm.isUse() && "CALLrr second operand is not a use.");
|
||||
RegUses.insert(RegOrImm.getReg());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Insert Defs and Uses of MI into the sets RegDefs and RegUses.
|
||||
void Filler::insertDefsUses(MachineBasicBlock::iterator MI,
|
||||
SmallSet<unsigned, 32>& RegDefs,
|
||||
SmallSet<unsigned, 32>& RegUses)
|
||||
{
|
||||
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
|
||||
const MachineOperand &MO = MI->getOperand(i);
|
||||
if (!MO.isReg())
|
||||
continue;
|
||||
|
||||
unsigned Reg = MO.getReg();
|
||||
if (Reg == 0)
|
||||
continue;
|
||||
if (MO.isDef())
|
||||
RegDefs.insert(Reg);
|
||||
if (MO.isUse()) {
|
||||
// Implicit register uses of retl are return values and
|
||||
// retl does not use them.
|
||||
if (MO.isImplicit() && MI->getOpcode() == M6502::RETL)
|
||||
continue;
|
||||
RegUses.insert(Reg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// returns true if the Reg or its alias is in the RegSet.
|
||||
bool Filler::IsRegInSet(SmallSet<unsigned, 32>& RegSet, unsigned Reg)
|
||||
{
|
||||
// Check Reg and all aliased Registers.
|
||||
for (MCRegAliasIterator AI(Reg, Subtarget->getRegisterInfo(), true);
|
||||
AI.isValid(); ++AI)
|
||||
if (RegSet.count(*AI))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Filler::needsUnimp(MachineBasicBlock::iterator I, unsigned &StructSize)
|
||||
{
|
||||
if (!I->isCall())
|
||||
return false;
|
||||
|
||||
unsigned structSizeOpNum = 0;
|
||||
switch (I->getOpcode()) {
|
||||
default: llvm_unreachable("Unknown call opcode.");
|
||||
case M6502::CALL: structSizeOpNum = 1; break;
|
||||
case M6502::CALLrr:
|
||||
case M6502::CALLri: structSizeOpNum = 2; break;
|
||||
case M6502::TLS_CALL: return false;
|
||||
}
|
||||
|
||||
const MachineOperand &MO = I->getOperand(structSizeOpNum);
|
||||
if (!MO.isImm())
|
||||
return false;
|
||||
StructSize = MO.getImm();
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool combineRestoreADD(MachineBasicBlock::iterator RestoreMI,
|
||||
MachineBasicBlock::iterator AddMI,
|
||||
const TargetInstrInfo *TII)
|
||||
{
|
||||
// Before: add <op0>, <op1>, %i[0-7]
|
||||
// restore %g0, %g0, %i[0-7]
|
||||
//
|
||||
// After : restore <op0>, <op1>, %o[0-7]
|
||||
|
||||
unsigned reg = AddMI->getOperand(0).getReg();
|
||||
if (reg < M6502::I0 || reg > M6502::I7)
|
||||
return false;
|
||||
|
||||
// Erase RESTORE.
|
||||
RestoreMI->eraseFromParent();
|
||||
|
||||
// Change ADD to RESTORE.
|
||||
AddMI->setDesc(TII->get((AddMI->getOpcode() == M6502::ADDrr)
|
||||
? M6502::RESTORErr
|
||||
: M6502::RESTOREri));
|
||||
|
||||
// Map the destination register.
|
||||
AddMI->getOperand(0).setReg(reg - M6502::I0 + M6502::O0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool combineRestoreOR(MachineBasicBlock::iterator RestoreMI,
|
||||
MachineBasicBlock::iterator OrMI,
|
||||
const TargetInstrInfo *TII)
|
||||
{
|
||||
// Before: or <op0>, <op1>, %i[0-7]
|
||||
// restore %g0, %g0, %i[0-7]
|
||||
// and <op0> or <op1> is zero,
|
||||
//
|
||||
// After : restore <op0>, <op1>, %o[0-7]
|
||||
|
||||
unsigned reg = OrMI->getOperand(0).getReg();
|
||||
if (reg < M6502::I0 || reg > M6502::I7)
|
||||
return false;
|
||||
|
||||
// check whether it is a copy.
|
||||
if (OrMI->getOpcode() == M6502::ORrr
|
||||
&& OrMI->getOperand(1).getReg() != M6502::G0
|
||||
&& OrMI->getOperand(2).getReg() != M6502::G0)
|
||||
return false;
|
||||
|
||||
if (OrMI->getOpcode() == M6502::ORri
|
||||
&& OrMI->getOperand(1).getReg() != M6502::G0
|
||||
&& (!OrMI->getOperand(2).isImm() || OrMI->getOperand(2).getImm() != 0))
|
||||
return false;
|
||||
|
||||
// Erase RESTORE.
|
||||
RestoreMI->eraseFromParent();
|
||||
|
||||
// Change OR to RESTORE.
|
||||
OrMI->setDesc(TII->get((OrMI->getOpcode() == M6502::ORrr)
|
||||
? M6502::RESTORErr
|
||||
: M6502::RESTOREri));
|
||||
|
||||
// Map the destination register.
|
||||
OrMI->getOperand(0).setReg(reg - M6502::I0 + M6502::O0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool combineRestoreSETHIi(MachineBasicBlock::iterator RestoreMI,
|
||||
MachineBasicBlock::iterator SetHiMI,
|
||||
const TargetInstrInfo *TII)
|
||||
{
|
||||
// Before: sethi imm3, %i[0-7]
|
||||
// restore %g0, %g0, %g0
|
||||
//
|
||||
// After : restore %g0, (imm3<<10), %o[0-7]
|
||||
|
||||
unsigned reg = SetHiMI->getOperand(0).getReg();
|
||||
if (reg < M6502::I0 || reg > M6502::I7)
|
||||
return false;
|
||||
|
||||
if (!SetHiMI->getOperand(1).isImm())
|
||||
return false;
|
||||
|
||||
int64_t imm = SetHiMI->getOperand(1).getImm();
|
||||
|
||||
// Is it a 3 bit immediate?
|
||||
if (!isInt<3>(imm))
|
||||
return false;
|
||||
|
||||
// Make it a 13 bit immediate.
|
||||
imm = (imm << 10) & 0x1FFF;
|
||||
|
||||
assert(RestoreMI->getOpcode() == M6502::RESTORErr);
|
||||
|
||||
RestoreMI->setDesc(TII->get(M6502::RESTOREri));
|
||||
|
||||
RestoreMI->getOperand(0).setReg(reg - M6502::I0 + M6502::O0);
|
||||
RestoreMI->getOperand(1).setReg(M6502::G0);
|
||||
RestoreMI->getOperand(2).ChangeToImmediate(imm);
|
||||
|
||||
|
||||
// Erase the original SETHI.
|
||||
SetHiMI->eraseFromParent();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Filler::tryCombineRestoreWithPrevInst(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator MBBI)
|
||||
{
|
||||
// No previous instruction.
|
||||
if (MBBI == MBB.begin())
|
||||
return false;
|
||||
|
||||
// assert that MBBI is a "restore %g0, %g0, %g0".
|
||||
assert(MBBI->getOpcode() == M6502::RESTORErr
|
||||
&& MBBI->getOperand(0).getReg() == M6502::G0
|
||||
&& MBBI->getOperand(1).getReg() == M6502::G0
|
||||
&& MBBI->getOperand(2).getReg() == M6502::G0);
|
||||
|
||||
MachineBasicBlock::iterator PrevInst = std::prev(MBBI);
|
||||
|
||||
// It cannot be combined with a bundled instruction.
|
||||
if (PrevInst->isBundledWithSucc())
|
||||
return false;
|
||||
|
||||
const TargetInstrInfo *TII = Subtarget->getInstrInfo();
|
||||
|
||||
switch (PrevInst->getOpcode()) {
|
||||
default: break;
|
||||
case M6502::ADDrr:
|
||||
case M6502::ADDri: return combineRestoreADD(MBBI, PrevInst, TII); break;
|
||||
case M6502::ORrr:
|
||||
case M6502::ORri: return combineRestoreOR(MBBI, PrevInst, TII); break;
|
||||
case M6502::SETHIi: return combineRestoreSETHIi(MBBI, PrevInst, TII); break;
|
||||
}
|
||||
// It cannot combine with the previous instruction.
|
||||
return false;
|
||||
}
|
@ -28,7 +28,6 @@ namespace llvm {
|
||||
class MachineInstr;
|
||||
|
||||
FunctionPass *createMos6502ISelDag(Mos6502TargetMachine &TM);
|
||||
FunctionPass *createMos6502DelaySlotFillerPass(TargetMachine &TM);
|
||||
|
||||
void LowerMos6502MachineInstrToMCInst(const MachineInstr *MI,
|
||||
MCInst &OutMI,
|
||||
|
@ -1,4 +1,4 @@
|
||||
//===-- Mos6502.td - Describe the Mos6502 Target Machine -------*- tablegen -*-===//
|
||||
//===-- Mos6502.td - Describe the Mos6502 Target Machine ---*- tablegen -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
@ -16,33 +16,6 @@
|
||||
|
||||
include "llvm/Target/Target.td"
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// MOS6502 Subtarget features.
|
||||
//
|
||||
|
||||
def FeatureV9
|
||||
: SubtargetFeature<"v9", "IsV9", "true",
|
||||
"Enable MOS6502-V9 instructions">;
|
||||
def FeatureV8Deprecated
|
||||
: SubtargetFeature<"deprecated-v8", "V8DeprecatedInsts", "true",
|
||||
"Enable deprecated V8 instructions in V9 mode">;
|
||||
def FeatureVIS
|
||||
: SubtargetFeature<"vis", "IsVIS", "true",
|
||||
"Enable UltraMOS6502 Visual Instruction Set extensions">;
|
||||
def FeatureVIS2
|
||||
: SubtargetFeature<"vis2", "IsVIS2", "true",
|
||||
"Enable Visual Instruction Set extensions II">;
|
||||
def FeatureVIS3
|
||||
: SubtargetFeature<"vis3", "IsVIS3", "true",
|
||||
"Enable Visual Instruction Set extensions III">;
|
||||
|
||||
def FeatureHardQuad
|
||||
: SubtargetFeature<"hard-quad-float", "HasHardQuad", "true",
|
||||
"Enable quad-word floating point instructions">;
|
||||
|
||||
def UsePopc : SubtargetFeature<"popc", "UsePopc", "true",
|
||||
"Use the popc (population count) instruction">;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Register File, Calling Conv, Instruction Descriptions
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -64,29 +37,7 @@ def Mos6502AsmParser : AsmParser {
|
||||
class Proc<string Name, list<SubtargetFeature> Features>
|
||||
: Processor<Name, NoItineraries, Features>;
|
||||
|
||||
def : Proc<"generic", []>;
|
||||
def : Proc<"v7", []>;
|
||||
def : Proc<"v8", []>;
|
||||
def : Proc<"supermos6502", []>;
|
||||
def : Proc<"mos6502lite", []>;
|
||||
def : Proc<"f934", []>;
|
||||
def : Proc<"hypermos6502", []>;
|
||||
def : Proc<"mos6502lite86x", []>;
|
||||
def : Proc<"mos6502let", []>;
|
||||
def : Proc<"tsc701", []>;
|
||||
def : Proc<"v9", [FeatureV9]>;
|
||||
def : Proc<"ultramos6502", [FeatureV9, FeatureV8Deprecated, FeatureVIS]>;
|
||||
def : Proc<"ultramos65023", [FeatureV9, FeatureV8Deprecated, FeatureVIS,
|
||||
FeatureVIS2]>;
|
||||
def : Proc<"niagara", [FeatureV9, FeatureV8Deprecated, FeatureVIS,
|
||||
FeatureVIS2]>;
|
||||
def : Proc<"niagara2", [FeatureV9, FeatureV8Deprecated, UsePopc,
|
||||
FeatureVIS, FeatureVIS2]>;
|
||||
def : Proc<"niagara3", [FeatureV9, FeatureV8Deprecated, UsePopc,
|
||||
FeatureVIS, FeatureVIS2]>;
|
||||
def : Proc<"niagara4", [FeatureV9, FeatureV8Deprecated, UsePopc,
|
||||
FeatureVIS, FeatureVIS2, FeatureVIS3]>;
|
||||
|
||||
def : Proc<"generic", []>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Declare the target which we are implementing
|
||||
|
@ -1,4 +1,4 @@
|
||||
//===-- Mos6502CallingConv.td - Calling Conventions Mos6502 ----*- tablegen -*-===//
|
||||
//===- Mos6502CallingConv.td - Calling Conventions Mos6502 -*- tablegen -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
@ -11,129 +11,11 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// MOS6502 v8 32-bit.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
def CC_Mos650232 : CallingConv<[
|
||||
// Custom assign SRet to [sp+64].
|
||||
CCIfSRet<CCCustom<"CC_Mos6502_Assign_SRet">>,
|
||||
// i32 f32 arguments get passed in integer registers if there is space.
|
||||
CCIfType<[i32, f32], CCAssignToReg<[I0, I1, I2, I3, I4, I5]>>,
|
||||
// f64 arguments are split and passed through registers or through stack.
|
||||
CCIfType<[f64], CCCustom<"CC_Mos6502_Assign_f64">>,
|
||||
|
||||
// Alternatively, they are assigned to the stack in 4-byte aligned units.
|
||||
CCAssignToStack<4, 4>
|
||||
def CC_Mos6502 : CallingConv<[
|
||||
CCIfType<[i8], CCAssignToReg<[A, X, Y]>>,
|
||||
CCAssignToStack<0, 0>
|
||||
]>;
|
||||
|
||||
def RetCC_Mos650232 : CallingConv<[
|
||||
CCIfType<[i32], CCAssignToReg<[I0, I1, I2, I3, I4, I5]>>,
|
||||
CCIfType<[f32], CCAssignToReg<[F0, F1, F2, F3]>>,
|
||||
CCIfType<[f64], CCAssignToReg<[D0, D1]>>
|
||||
CCIfType<[i8], CCAssignToReg<[A, X, Y]>>
|
||||
]>;
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// MOS6502 v9 64-bit.
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The 64-bit ABI conceptually assigns all function arguments to a parameter
|
||||
// array starting at [%fp+BIAS+128] in the callee's stack frame. All arguments
|
||||
// occupy a multiple of 8 bytes in the array. Integer arguments are extended to
|
||||
// 64 bits by the caller. Floats are right-aligned in their 8-byte slot, the
|
||||
// first 4 bytes in the slot are undefined.
|
||||
//
|
||||
// The integer registers %i0 to %i5 shadow the first 48 bytes of the parameter
|
||||
// array at fixed offsets. Integer arguments are promoted to registers when
|
||||
// possible.
|
||||
//
|
||||
// The floating point registers %f0 to %f31 shadow the first 128 bytes of the
|
||||
// parameter array at fixed offsets. Float and double parameters are promoted
|
||||
// to these registers when possible.
|
||||
//
|
||||
// Structs up to 16 bytes in size are passed by value. They are right-aligned
|
||||
// in one or two 8-byte slots in the parameter array. Struct members are
|
||||
// promoted to both floating point and integer registers when possible. A
|
||||
// struct containing two floats would thus be passed in %f0 and %f1, while two
|
||||
// float function arguments would occupy 8 bytes each, and be passed in %f1 and
|
||||
// %f3.
|
||||
//
|
||||
// When a struct { int, float } is passed by value, the int goes in the high
|
||||
// bits of an integer register while the float goes in a floating point
|
||||
// register.
|
||||
//
|
||||
// The difference is encoded in LLVM IR using the inreg atttribute on function
|
||||
// arguments:
|
||||
//
|
||||
// C: void f(float, float);
|
||||
// IR: declare void f(float %f1, float %f3)
|
||||
//
|
||||
// C: void f(struct { float f0, f1; });
|
||||
// IR: declare void f(float inreg %f0, float inreg %f1)
|
||||
//
|
||||
// C: void f(int, float);
|
||||
// IR: declare void f(int signext %i0, float %f3)
|
||||
//
|
||||
// C: void f(struct { int i0high; float f1; });
|
||||
// IR: declare void f(i32 inreg %i0high, float inreg %f1)
|
||||
//
|
||||
// Two ints in a struct are simply coerced to i64:
|
||||
//
|
||||
// C: void f(struct { int i0high, i0low; });
|
||||
// IR: declare void f(i64 %i0.coerced)
|
||||
//
|
||||
// The frontend and backend divide the task of producing ABI compliant code for
|
||||
// C functions. The C frontend will:
|
||||
//
|
||||
// - Annotate integer arguments with zeroext or signext attributes.
|
||||
//
|
||||
// - Split structs into one or two 64-bit sized chunks, or 32-bit chunks with
|
||||
// inreg attributes.
|
||||
//
|
||||
// - Pass structs larger than 16 bytes indirectly with an explicit pointer
|
||||
// argument. The byval attribute is not used.
|
||||
//
|
||||
// The backend will:
|
||||
//
|
||||
// - Assign all arguments to 64-bit aligned stack slots, 32-bits for inreg.
|
||||
//
|
||||
// - Promote to integer or floating point registers depending on type.
|
||||
//
|
||||
// Function return values are passed exactly like function arguments, except a
|
||||
// struct up to 32 bytes in size can be returned in registers.
|
||||
|
||||
// Function arguments AND most return values.
|
||||
def CC_Mos650264 : CallingConv<[
|
||||
// The frontend uses the inreg flag to indicate i32 and float arguments from
|
||||
// structs. These arguments are not promoted to 64 bits, but they can still
|
||||
// be assigned to integer and float registers.
|
||||
CCIfInReg<CCIfType<[i32, f32], CCCustom<"CC_Mos650264_Half">>>,
|
||||
|
||||
// All integers are promoted to i64 by the caller.
|
||||
CCIfType<[i32], CCPromoteToType<i64>>,
|
||||
|
||||
// Custom assignment is required because stack space is reserved for all
|
||||
// arguments whether they are passed in registers or not.
|
||||
CCCustom<"CC_Mos650264_Full">
|
||||
]>;
|
||||
|
||||
def RetCC_Mos650264 : CallingConv<[
|
||||
// A single f32 return value always goes in %f0. The ABI doesn't specify what
|
||||
// happens to multiple f32 return values outside a struct.
|
||||
CCIfType<[f32], CCCustom<"CC_Mos650264_Half">>,
|
||||
|
||||
// Otherwise, return values are passed exactly like arguments.
|
||||
CCDelegateTo<CC_Mos650264>
|
||||
]>;
|
||||
|
||||
// Callee-saved registers are handled by the register window mechanism.
|
||||
def CSR : CalleeSavedRegs<(add)> {
|
||||
let OtherPreserved = (add (sequence "I%u", 0, 7),
|
||||
(sequence "L%u", 0, 7));
|
||||
}
|
||||
|
||||
// Callee-saved registers for calls with ReturnsTwice attribute.
|
||||
def RTCSR : CalleeSavedRegs<(add)> {
|
||||
let OtherPreserved = (add I6, I7);
|
||||
}
|
||||
|
@ -1,574 +0,0 @@
|
||||
//===-- Mos6502Instr64Bit.td - 64-bit instructions for Mos6502 Target ---------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains instruction definitions and patterns needed for 64-bit
|
||||
// code generation on MOS6502 v9.
|
||||
//
|
||||
// Some MOS6502 v9 instructions are defined in Mos6502InstrInfo.td because they can
|
||||
// also be used in 32-bit code running on a MOS6502 v9 CPU.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
let Predicates = [Is64Bit] in {
|
||||
// The same integer registers are used for i32 and i64 values.
|
||||
// When registers hold i32 values, the high bits are don't care.
|
||||
// This give us free trunc and anyext.
|
||||
def : Pat<(i64 (anyext i32:$val)), (COPY_TO_REGCLASS $val, I64Regs)>;
|
||||
def : Pat<(i32 (trunc i64:$val)), (COPY_TO_REGCLASS $val, IntRegs)>;
|
||||
|
||||
} // Predicates = [Is64Bit]
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// 64-bit Shift Instructions.
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The 32-bit shift instructions are still available. The left shift srl
|
||||
// instructions shift all 64 bits, but it only accepts a 5-bit shift amount.
|
||||
//
|
||||
// The srl instructions only shift the low 32 bits and clear the high 32 bits.
|
||||
// Finally, sra shifts the low 32 bits and sign-extends to 64 bits.
|
||||
|
||||
let Predicates = [Is64Bit] in {
|
||||
|
||||
def : Pat<(i64 (zext i32:$val)), (SRLri $val, 0)>;
|
||||
def : Pat<(i64 (sext i32:$val)), (SRAri $val, 0)>;
|
||||
|
||||
def : Pat<(i64 (and i64:$val, 0xffffffff)), (SRLri $val, 0)>;
|
||||
def : Pat<(i64 (sext_inreg i64:$val, i32)), (SRAri $val, 0)>;
|
||||
|
||||
defm SLLX : F3_S<"sllx", 0b100101, 1, shl, i64, I64Regs>;
|
||||
defm SRLX : F3_S<"srlx", 0b100110, 1, srl, i64, I64Regs>;
|
||||
defm SRAX : F3_S<"srax", 0b100111, 1, sra, i64, I64Regs>;
|
||||
|
||||
} // Predicates = [Is64Bit]
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// 64-bit Immediates.
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// All 32-bit immediates can be materialized with sethi+or, but 64-bit
|
||||
// immediates may require more code. There may be a point where it is
|
||||
// preferable to use a constant pool load instead, depending on the
|
||||
// microarchitecture.
|
||||
|
||||
// Single-instruction patterns.
|
||||
|
||||
// The ALU instructions want their simm13 operands as i32 immediates.
|
||||
def as_i32imm : SDNodeXForm<imm, [{
|
||||
return CurDAG->getTargetConstant(N->getSExtValue(), SDLoc(N), MVT::i32);
|
||||
}]>;
|
||||
def : Pat<(i64 simm13:$val), (ORri (i64 G0), (as_i32imm $val))>;
|
||||
def : Pat<(i64 SETHIimm:$val), (SETHIi (HI22 $val))>;
|
||||
|
||||
// Double-instruction patterns.
|
||||
|
||||
// All unsigned i32 immediates can be handled by sethi+or.
|
||||
def uimm32 : PatLeaf<(imm), [{ return isUInt<32>(N->getZExtValue()); }]>;
|
||||
def : Pat<(i64 uimm32:$val), (ORri (SETHIi (HI22 $val)), (LO10 $val))>,
|
||||
Requires<[Is64Bit]>;
|
||||
|
||||
// All negative i33 immediates can be handled by sethi+xor.
|
||||
def nimm33 : PatLeaf<(imm), [{
|
||||
int64_t Imm = N->getSExtValue();
|
||||
return Imm < 0 && isInt<33>(Imm);
|
||||
}]>;
|
||||
// Bits 10-31 inverted. Same as assembler's %hix.
|
||||
def HIX22 : SDNodeXForm<imm, [{
|
||||
uint64_t Val = (~N->getZExtValue() >> 10) & ((1u << 22) - 1);
|
||||
return CurDAG->getTargetConstant(Val, SDLoc(N), MVT::i32);
|
||||
}]>;
|
||||
// Bits 0-9 with ones in bits 10-31. Same as assembler's %lox.
|
||||
def LOX10 : SDNodeXForm<imm, [{
|
||||
return CurDAG->getTargetConstant(~(~N->getZExtValue() & 0x3ff), SDLoc(N),
|
||||
MVT::i32);
|
||||
}]>;
|
||||
def : Pat<(i64 nimm33:$val), (XORri (SETHIi (HIX22 $val)), (LOX10 $val))>,
|
||||
Requires<[Is64Bit]>;
|
||||
|
||||
// More possible patterns:
|
||||
//
|
||||
// (sllx sethi, n)
|
||||
// (sllx simm13, n)
|
||||
//
|
||||
// 3 instrs:
|
||||
//
|
||||
// (xor (sllx sethi), simm13)
|
||||
// (sllx (xor sethi, simm13))
|
||||
//
|
||||
// 4 instrs:
|
||||
//
|
||||
// (or sethi, (sllx sethi))
|
||||
// (xnor sethi, (sllx sethi))
|
||||
//
|
||||
// 5 instrs:
|
||||
//
|
||||
// (or (sllx sethi), (or sethi, simm13))
|
||||
// (xnor (sllx sethi), (or sethi, simm13))
|
||||
// (or (sllx sethi), (sllx sethi))
|
||||
// (xnor (sllx sethi), (sllx sethi))
|
||||
//
|
||||
// Worst case is 6 instrs:
|
||||
//
|
||||
// (or (sllx (or sethi, simmm13)), (or sethi, simm13))
|
||||
|
||||
// Bits 42-63, same as assembler's %hh.
|
||||
def HH22 : SDNodeXForm<imm, [{
|
||||
uint64_t Val = (N->getZExtValue() >> 42) & ((1u << 22) - 1);
|
||||
return CurDAG->getTargetConstant(Val, SDLoc(N), MVT::i32);
|
||||
}]>;
|
||||
// Bits 32-41, same as assembler's %hm.
|
||||
def HM10 : SDNodeXForm<imm, [{
|
||||
uint64_t Val = (N->getZExtValue() >> 32) & ((1u << 10) - 1);
|
||||
return CurDAG->getTargetConstant(Val, SDLoc(N), MVT::i32);
|
||||
}]>;
|
||||
def : Pat<(i64 imm:$val),
|
||||
(ORrr (SLLXri (ORri (SETHIi (HH22 $val)), (HM10 $val)), (i32 32)),
|
||||
(ORri (SETHIi (HI22 $val)), (LO10 $val)))>,
|
||||
Requires<[Is64Bit]>;
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// 64-bit Integer Arithmetic and Logic.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
let Predicates = [Is64Bit] in {
|
||||
|
||||
// Register-register instructions.
|
||||
let isCodeGenOnly = 1 in {
|
||||
defm ANDX : F3_12<"and", 0b000001, and, I64Regs, i64, i64imm>;
|
||||
defm ORX : F3_12<"or", 0b000010, or, I64Regs, i64, i64imm>;
|
||||
defm XORX : F3_12<"xor", 0b000011, xor, I64Regs, i64, i64imm>;
|
||||
|
||||
def ANDXNrr : F3_1<2, 0b000101,
|
||||
(outs I64Regs:$dst), (ins I64Regs:$b, I64Regs:$c),
|
||||
"andn $b, $c, $dst",
|
||||
[(set i64:$dst, (and i64:$b, (not i64:$c)))]>;
|
||||
def ORXNrr : F3_1<2, 0b000110,
|
||||
(outs I64Regs:$dst), (ins I64Regs:$b, I64Regs:$c),
|
||||
"orn $b, $c, $dst",
|
||||
[(set i64:$dst, (or i64:$b, (not i64:$c)))]>;
|
||||
def XNORXrr : F3_1<2, 0b000111,
|
||||
(outs I64Regs:$dst), (ins I64Regs:$b, I64Regs:$c),
|
||||
"xnor $b, $c, $dst",
|
||||
[(set i64:$dst, (not (xor i64:$b, i64:$c)))]>;
|
||||
|
||||
defm ADDX : F3_12<"add", 0b000000, add, I64Regs, i64, i64imm>;
|
||||
defm SUBX : F3_12<"sub", 0b000100, sub, I64Regs, i64, i64imm>;
|
||||
|
||||
def TLS_ADDXrr : F3_1<2, 0b000000, (outs I64Regs:$rd),
|
||||
(ins I64Regs:$rs1, I64Regs:$rs2, TLSSym:$sym),
|
||||
"add $rs1, $rs2, $rd, $sym",
|
||||
[(set i64:$rd,
|
||||
(tlsadd i64:$rs1, i64:$rs2, tglobaltlsaddr:$sym))]>;
|
||||
|
||||
// "LEA" form of add
|
||||
def LEAX_ADDri : F3_2<2, 0b000000,
|
||||
(outs I64Regs:$dst), (ins MEMri:$addr),
|
||||
"add ${addr:arith}, $dst",
|
||||
[(set iPTR:$dst, ADDRri:$addr)]>;
|
||||
}
|
||||
|
||||
def : Pat<(SPcmpicc i64:$a, i64:$b), (CMPrr $a, $b)>;
|
||||
def : Pat<(SPcmpicc i64:$a, (i64 simm13:$b)), (CMPri $a, (as_i32imm $b))>;
|
||||
def : Pat<(ctpop i64:$src), (POPCrr $src)>;
|
||||
|
||||
} // Predicates = [Is64Bit]
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// 64-bit Integer Multiply and Divide.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
let Predicates = [Is64Bit] in {
|
||||
|
||||
def MULXrr : F3_1<2, 0b001001,
|
||||
(outs I64Regs:$rd), (ins I64Regs:$rs1, I64Regs:$rs2),
|
||||
"mulx $rs1, $rs2, $rd",
|
||||
[(set i64:$rd, (mul i64:$rs1, i64:$rs2))]>;
|
||||
def MULXri : F3_2<2, 0b001001,
|
||||
(outs IntRegs:$rd), (ins IntRegs:$rs1, i64imm:$simm13),
|
||||
"mulx $rs1, $simm13, $rd",
|
||||
[(set i64:$rd, (mul i64:$rs1, (i64 simm13:$simm13)))]>;
|
||||
|
||||
// Division can trap.
|
||||
let hasSideEffects = 1 in {
|
||||
def SDIVXrr : F3_1<2, 0b101101,
|
||||
(outs I64Regs:$rd), (ins I64Regs:$rs1, I64Regs:$rs2),
|
||||
"sdivx $rs1, $rs2, $rd",
|
||||
[(set i64:$rd, (sdiv i64:$rs1, i64:$rs2))]>;
|
||||
def SDIVXri : F3_2<2, 0b101101,
|
||||
(outs IntRegs:$rd), (ins IntRegs:$rs1, i64imm:$simm13),
|
||||
"sdivx $rs1, $simm13, $rd",
|
||||
[(set i64:$rd, (sdiv i64:$rs1, (i64 simm13:$simm13)))]>;
|
||||
|
||||
def UDIVXrr : F3_1<2, 0b001101,
|
||||
(outs I64Regs:$rd), (ins I64Regs:$rs1, I64Regs:$rs2),
|
||||
"udivx $rs1, $rs2, $rd",
|
||||
[(set i64:$rd, (udiv i64:$rs1, i64:$rs2))]>;
|
||||
def UDIVXri : F3_2<2, 0b001101,
|
||||
(outs IntRegs:$rd), (ins IntRegs:$rs1, i64imm:$simm13),
|
||||
"udivx $rs1, $simm13, $rd",
|
||||
[(set i64:$rd, (udiv i64:$rs1, (i64 simm13:$simm13)))]>;
|
||||
} // hasSideEffects = 1
|
||||
|
||||
} // Predicates = [Is64Bit]
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// 64-bit Loads and Stores.
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// All the 32-bit loads and stores are available. The extending loads are sign
|
||||
// or zero-extending to 64 bits. The LDrr and LDri instructions load 32 bits
|
||||
// zero-extended to i64. Their mnemonic is lduw in MOS6502 v9 (Load Unsigned
|
||||
// Word).
|
||||
//
|
||||
// MOS6502 v9 adds 64-bit loads as well as a sign-extending ldsw i32 loads.
|
||||
|
||||
let Predicates = [Is64Bit] in {
|
||||
|
||||
// 64-bit loads.
|
||||
let DecoderMethod = "DecodeLoadInt" in
|
||||
defm LDX : Load<"ldx", 0b001011, load, I64Regs, i64>;
|
||||
|
||||
let mayLoad = 1, isCodeGenOnly = 1, isAsmParserOnly = 1 in
|
||||
def TLS_LDXrr : F3_1<3, 0b001011,
|
||||
(outs IntRegs:$dst), (ins MEMrr:$addr, TLSSym:$sym),
|
||||
"ldx [$addr], $dst, $sym",
|
||||
[(set i64:$dst,
|
||||
(tlsld ADDRrr:$addr, tglobaltlsaddr:$sym))]>;
|
||||
|
||||
// Extending loads to i64.
|
||||
def : Pat<(i64 (zextloadi1 ADDRrr:$addr)), (LDUBrr ADDRrr:$addr)>;
|
||||
def : Pat<(i64 (zextloadi1 ADDRri:$addr)), (LDUBri ADDRri:$addr)>;
|
||||
def : Pat<(i64 (extloadi1 ADDRrr:$addr)), (LDUBrr ADDRrr:$addr)>;
|
||||
def : Pat<(i64 (extloadi1 ADDRri:$addr)), (LDUBri ADDRri:$addr)>;
|
||||
|
||||
def : Pat<(i64 (zextloadi8 ADDRrr:$addr)), (LDUBrr ADDRrr:$addr)>;
|
||||
def : Pat<(i64 (zextloadi8 ADDRri:$addr)), (LDUBri ADDRri:$addr)>;
|
||||
def : Pat<(i64 (extloadi8 ADDRrr:$addr)), (LDUBrr ADDRrr:$addr)>;
|
||||
def : Pat<(i64 (extloadi8 ADDRri:$addr)), (LDUBri ADDRri:$addr)>;
|
||||
def : Pat<(i64 (sextloadi8 ADDRrr:$addr)), (LDSBrr ADDRrr:$addr)>;
|
||||
def : Pat<(i64 (sextloadi8 ADDRri:$addr)), (LDSBri ADDRri:$addr)>;
|
||||
|
||||
def : Pat<(i64 (zextloadi16 ADDRrr:$addr)), (LDUHrr ADDRrr:$addr)>;
|
||||
def : Pat<(i64 (zextloadi16 ADDRri:$addr)), (LDUHri ADDRri:$addr)>;
|
||||
def : Pat<(i64 (extloadi16 ADDRrr:$addr)), (LDUHrr ADDRrr:$addr)>;
|
||||
def : Pat<(i64 (extloadi16 ADDRri:$addr)), (LDUHri ADDRri:$addr)>;
|
||||
def : Pat<(i64 (sextloadi16 ADDRrr:$addr)), (LDSHrr ADDRrr:$addr)>;
|
||||
def : Pat<(i64 (sextloadi16 ADDRri:$addr)), (LDSHri ADDRri:$addr)>;
|
||||
|
||||
def : Pat<(i64 (zextloadi32 ADDRrr:$addr)), (LDrr ADDRrr:$addr)>;
|
||||
def : Pat<(i64 (zextloadi32 ADDRri:$addr)), (LDri ADDRri:$addr)>;
|
||||
def : Pat<(i64 (extloadi32 ADDRrr:$addr)), (LDrr ADDRrr:$addr)>;
|
||||
def : Pat<(i64 (extloadi32 ADDRri:$addr)), (LDri ADDRri:$addr)>;
|
||||
|
||||
// Sign-extending load of i32 into i64 is a new MOS6502 v9 instruction.
|
||||
let DecoderMethod = "DecodeLoadInt" in
|
||||
defm LDSW : Load<"ldsw", 0b001000, sextloadi32, I64Regs, i64>;
|
||||
|
||||
// 64-bit stores.
|
||||
let DecoderMethod = "DecodeStoreInt" in
|
||||
defm STX : Store<"stx", 0b001110, store, I64Regs, i64>;
|
||||
|
||||
// Truncating stores from i64 are identical to the i32 stores.
|
||||
def : Pat<(truncstorei8 i64:$src, ADDRrr:$addr), (STBrr ADDRrr:$addr, $src)>;
|
||||
def : Pat<(truncstorei8 i64:$src, ADDRri:$addr), (STBri ADDRri:$addr, $src)>;
|
||||
def : Pat<(truncstorei16 i64:$src, ADDRrr:$addr), (STHrr ADDRrr:$addr, $src)>;
|
||||
def : Pat<(truncstorei16 i64:$src, ADDRri:$addr), (STHri ADDRri:$addr, $src)>;
|
||||
def : Pat<(truncstorei32 i64:$src, ADDRrr:$addr), (STrr ADDRrr:$addr, $src)>;
|
||||
def : Pat<(truncstorei32 i64:$src, ADDRri:$addr), (STri ADDRri:$addr, $src)>;
|
||||
|
||||
// store 0, addr -> store %g0, addr
|
||||
def : Pat<(store (i64 0), ADDRrr:$dst), (STXrr ADDRrr:$dst, (i64 G0))>;
|
||||
def : Pat<(store (i64 0), ADDRri:$dst), (STXri ADDRri:$dst, (i64 G0))>;
|
||||
|
||||
} // Predicates = [Is64Bit]
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// 64-bit Conditionals.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
//
|
||||
// Flag-setting instructions like subcc and addcc set both icc and xcc flags.
|
||||
// The icc flags correspond to the 32-bit result, and the xcc are for the
|
||||
// full 64-bit result.
|
||||
//
|
||||
// We reuse CMPICC SDNodes for compares, but use new BRXCC branch nodes for
|
||||
// 64-bit compares. See LowerBR_CC.
|
||||
|
||||
let Predicates = [Is64Bit] in {
|
||||
|
||||
let Uses = [ICC], cc = 0b10 in
|
||||
defm BPX : IPredBranch<"%xcc", [(SPbrxcc bb:$imm19, imm:$cond)]>;
|
||||
|
||||
// Conditional moves on %xcc.
|
||||
let Uses = [ICC], Constraints = "$f = $rd" in {
|
||||
let intcc = 1, cc = 0b10 in {
|
||||
def MOVXCCrr : F4_1<0b101100, (outs IntRegs:$rd),
|
||||
(ins IntRegs:$rs2, IntRegs:$f, CCOp:$cond),
|
||||
"mov$cond %xcc, $rs2, $rd",
|
||||
[(set i32:$rd,
|
||||
(SPselectxcc i32:$rs2, i32:$f, imm:$cond))]>;
|
||||
def MOVXCCri : F4_2<0b101100, (outs IntRegs:$rd),
|
||||
(ins i32imm:$simm11, IntRegs:$f, CCOp:$cond),
|
||||
"mov$cond %xcc, $simm11, $rd",
|
||||
[(set i32:$rd,
|
||||
(SPselectxcc simm11:$simm11, i32:$f, imm:$cond))]>;
|
||||
} // cc
|
||||
|
||||
let intcc = 1, opf_cc = 0b10 in {
|
||||
def FMOVS_XCC : F4_3<0b110101, 0b000001, (outs FPRegs:$rd),
|
||||
(ins FPRegs:$rs2, FPRegs:$f, CCOp:$cond),
|
||||
"fmovs$cond %xcc, $rs2, $rd",
|
||||
[(set f32:$rd,
|
||||
(SPselectxcc f32:$rs2, f32:$f, imm:$cond))]>;
|
||||
def FMOVD_XCC : F4_3<0b110101, 0b000010, (outs DFPRegs:$rd),
|
||||
(ins DFPRegs:$rs2, DFPRegs:$f, CCOp:$cond),
|
||||
"fmovd$cond %xcc, $rs2, $rd",
|
||||
[(set f64:$rd,
|
||||
(SPselectxcc f64:$rs2, f64:$f, imm:$cond))]>;
|
||||
def FMOVQ_XCC : F4_3<0b110101, 0b000011, (outs QFPRegs:$rd),
|
||||
(ins QFPRegs:$rs2, QFPRegs:$f, CCOp:$cond),
|
||||
"fmovq$cond %xcc, $rs2, $rd",
|
||||
[(set f128:$rd,
|
||||
(SPselectxcc f128:$rs2, f128:$f, imm:$cond))]>;
|
||||
} // opf_cc
|
||||
} // Uses, Constraints
|
||||
|
||||
// Branch On integer register with Prediction (BPr).
|
||||
let isBranch = 1, isTerminator = 1, hasDelaySlot = 1 in
|
||||
multiclass BranchOnReg<bits<3> cond, string OpcStr> {
|
||||
def napt : F2_4<cond, 0, 1, (outs), (ins I64Regs:$rs1, bprtarget16:$imm16),
|
||||
!strconcat(OpcStr, " $rs1, $imm16"), []>;
|
||||
def apt : F2_4<cond, 1, 1, (outs), (ins I64Regs:$rs1, bprtarget16:$imm16),
|
||||
!strconcat(OpcStr, ",a $rs1, $imm16"), []>;
|
||||
def napn : F2_4<cond, 0, 0, (outs), (ins I64Regs:$rs1, bprtarget16:$imm16),
|
||||
!strconcat(OpcStr, ",pn $rs1, $imm16"), []>;
|
||||
def apn : F2_4<cond, 1, 0, (outs), (ins I64Regs:$rs1, bprtarget16:$imm16),
|
||||
!strconcat(OpcStr, ",a,pn $rs1, $imm16"), []>;
|
||||
}
|
||||
|
||||
multiclass bpr_alias<string OpcStr, Instruction NAPT, Instruction APT> {
|
||||
def : InstAlias<!strconcat(OpcStr, ",pt $rs1, $imm16"),
|
||||
(NAPT I64Regs:$rs1, bprtarget16:$imm16), 0>;
|
||||
def : InstAlias<!strconcat(OpcStr, ",a,pt $rs1, $imm16"),
|
||||
(APT I64Regs:$rs1, bprtarget16:$imm16), 0>;
|
||||
}
|
||||
|
||||
defm BPZ : BranchOnReg<0b001, "brz">;
|
||||
defm BPLEZ : BranchOnReg<0b010, "brlez">;
|
||||
defm BPLZ : BranchOnReg<0b011, "brlz">;
|
||||
defm BPNZ : BranchOnReg<0b101, "brnz">;
|
||||
defm BPGZ : BranchOnReg<0b110, "brgz">;
|
||||
defm BPGEZ : BranchOnReg<0b111, "brgez">;
|
||||
|
||||
defm : bpr_alias<"brz", BPZnapt, BPZapt >;
|
||||
defm : bpr_alias<"brlez", BPLEZnapt, BPLEZapt>;
|
||||
defm : bpr_alias<"brlz", BPLZnapt, BPLZapt >;
|
||||
defm : bpr_alias<"brnz", BPNZnapt, BPNZapt >;
|
||||
defm : bpr_alias<"brgz", BPGZnapt, BPGZapt >;
|
||||
defm : bpr_alias<"brgez", BPGEZnapt, BPGEZapt>;
|
||||
|
||||
// Move integer register on register condition (MOVr).
|
||||
multiclass MOVR< bits<3> rcond, string OpcStr> {
|
||||
def rr : F4_4r<0b101111, 0b00000, rcond, (outs I64Regs:$rd),
|
||||
(ins I64Regs:$rs1, IntRegs:$rs2),
|
||||
!strconcat(OpcStr, " $rs1, $rs2, $rd"), []>;
|
||||
|
||||
def ri : F4_4i<0b101111, rcond, (outs I64Regs:$rd),
|
||||
(ins I64Regs:$rs1, i64imm:$simm10),
|
||||
!strconcat(OpcStr, " $rs1, $simm10, $rd"), []>;
|
||||
}
|
||||
|
||||
defm MOVRRZ : MOVR<0b001, "movrz">;
|
||||
defm MOVRLEZ : MOVR<0b010, "movrlez">;
|
||||
defm MOVRLZ : MOVR<0b011, "movrlz">;
|
||||
defm MOVRNZ : MOVR<0b101, "movrnz">;
|
||||
defm MOVRGZ : MOVR<0b110, "movrgz">;
|
||||
defm MOVRGEZ : MOVR<0b111, "movrgez">;
|
||||
|
||||
// Move FP register on integer register condition (FMOVr).
|
||||
multiclass FMOVR<bits<3> rcond, string OpcStr> {
|
||||
|
||||
def S : F4_4r<0b110101, 0b00101, rcond,
|
||||
(outs FPRegs:$rd), (ins I64Regs:$rs1, FPRegs:$rs2),
|
||||
!strconcat(!strconcat("fmovrs", OpcStr)," $rs1, $rs2, $rd"),
|
||||
[]>;
|
||||
def D : F4_4r<0b110101, 0b00110, rcond,
|
||||
(outs FPRegs:$rd), (ins I64Regs:$rs1, FPRegs:$rs2),
|
||||
!strconcat(!strconcat("fmovrd", OpcStr)," $rs1, $rs2, $rd"),
|
||||
[]>;
|
||||
def Q : F4_4r<0b110101, 0b00111, rcond,
|
||||
(outs FPRegs:$rd), (ins I64Regs:$rs1, FPRegs:$rs2),
|
||||
!strconcat(!strconcat("fmovrq", OpcStr)," $rs1, $rs2, $rd"),
|
||||
[]>, Requires<[HasHardQuad]>;
|
||||
}
|
||||
|
||||
let Predicates = [HasV9] in {
|
||||
defm FMOVRZ : FMOVR<0b001, "z">;
|
||||
defm FMOVRLEZ : FMOVR<0b010, "lez">;
|
||||
defm FMOVRLZ : FMOVR<0b011, "lz">;
|
||||
defm FMOVRNZ : FMOVR<0b101, "nz">;
|
||||
defm FMOVRGZ : FMOVR<0b110, "gz">;
|
||||
defm FMOVRGEZ : FMOVR<0b111, "gez">;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// 64-bit Floating Point Conversions.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
let Predicates = [Is64Bit] in {
|
||||
|
||||
def FXTOS : F3_3u<2, 0b110100, 0b010000100,
|
||||
(outs FPRegs:$rd), (ins DFPRegs:$rs2),
|
||||
"fxtos $rs2, $rd",
|
||||
[(set FPRegs:$rd, (SPxtof DFPRegs:$rs2))]>;
|
||||
def FXTOD : F3_3u<2, 0b110100, 0b010001000,
|
||||
(outs DFPRegs:$rd), (ins DFPRegs:$rs2),
|
||||
"fxtod $rs2, $rd",
|
||||
[(set DFPRegs:$rd, (SPxtof DFPRegs:$rs2))]>;
|
||||
def FXTOQ : F3_3u<2, 0b110100, 0b010001100,
|
||||
(outs QFPRegs:$rd), (ins DFPRegs:$rs2),
|
||||
"fxtoq $rs2, $rd",
|
||||
[(set QFPRegs:$rd, (SPxtof DFPRegs:$rs2))]>,
|
||||
Requires<[HasHardQuad]>;
|
||||
|
||||
def FSTOX : F3_3u<2, 0b110100, 0b010000001,
|
||||
(outs DFPRegs:$rd), (ins FPRegs:$rs2),
|
||||
"fstox $rs2, $rd",
|
||||
[(set DFPRegs:$rd, (SPftox FPRegs:$rs2))]>;
|
||||
def FDTOX : F3_3u<2, 0b110100, 0b010000010,
|
||||
(outs DFPRegs:$rd), (ins DFPRegs:$rs2),
|
||||
"fdtox $rs2, $rd",
|
||||
[(set DFPRegs:$rd, (SPftox DFPRegs:$rs2))]>;
|
||||
def FQTOX : F3_3u<2, 0b110100, 0b010000011,
|
||||
(outs DFPRegs:$rd), (ins QFPRegs:$rs2),
|
||||
"fqtox $rs2, $rd",
|
||||
[(set DFPRegs:$rd, (SPftox QFPRegs:$rs2))]>,
|
||||
Requires<[HasHardQuad]>;
|
||||
|
||||
} // Predicates = [Is64Bit]
|
||||
|
||||
def : Pat<(SPselectxcc i64:$t, i64:$f, imm:$cond),
|
||||
(MOVXCCrr $t, $f, imm:$cond)>;
|
||||
def : Pat<(SPselectxcc (i64 simm11:$t), i64:$f, imm:$cond),
|
||||
(MOVXCCri (as_i32imm $t), $f, imm:$cond)>;
|
||||
|
||||
def : Pat<(SPselecticc i64:$t, i64:$f, imm:$cond),
|
||||
(MOVICCrr $t, $f, imm:$cond)>;
|
||||
def : Pat<(SPselecticc (i64 simm11:$t), i64:$f, imm:$cond),
|
||||
(MOVICCri (as_i32imm $t), $f, imm:$cond)>;
|
||||
|
||||
def : Pat<(SPselectfcc i64:$t, i64:$f, imm:$cond),
|
||||
(MOVFCCrr $t, $f, imm:$cond)>;
|
||||
def : Pat<(SPselectfcc (i64 simm11:$t), i64:$f, imm:$cond),
|
||||
(MOVFCCri (as_i32imm $t), $f, imm:$cond)>;
|
||||
|
||||
} // Predicates = [Is64Bit]
|
||||
|
||||
|
||||
// 64 bit SETHI
|
||||
let Predicates = [Is64Bit], isCodeGenOnly = 1 in {
|
||||
def SETHIXi : F2_1<0b100,
|
||||
(outs IntRegs:$rd), (ins i64imm:$imm22),
|
||||
"sethi $imm22, $rd",
|
||||
[(set i64:$rd, SETHIimm:$imm22)]>;
|
||||
}
|
||||
|
||||
// ATOMICS.
|
||||
let Predicates = [Is64Bit], Constraints = "$swap = $rd", asi = 0b10000000 in {
|
||||
def CASXrr: F3_1_asi<3, 0b111110,
|
||||
(outs I64Regs:$rd), (ins I64Regs:$rs1, I64Regs:$rs2,
|
||||
I64Regs:$swap),
|
||||
"casx [$rs1], $rs2, $rd",
|
||||
[(set i64:$rd,
|
||||
(atomic_cmp_swap i64:$rs1, i64:$rs2, i64:$swap))]>;
|
||||
|
||||
} // Predicates = [Is64Bit], Constraints = ...
|
||||
|
||||
let Predicates = [Is64Bit] in {
|
||||
|
||||
def : Pat<(atomic_fence imm, imm), (MEMBARi 0xf)>;
|
||||
|
||||
// atomic_load_64 addr -> load addr
|
||||
def : Pat<(i64 (atomic_load ADDRrr:$src)), (LDXrr ADDRrr:$src)>;
|
||||
def : Pat<(i64 (atomic_load ADDRri:$src)), (LDXri ADDRri:$src)>;
|
||||
|
||||
// atomic_store_64 val, addr -> store val, addr
|
||||
def : Pat<(atomic_store ADDRrr:$dst, i64:$val), (STXrr ADDRrr:$dst, $val)>;
|
||||
def : Pat<(atomic_store ADDRri:$dst, i64:$val), (STXri ADDRri:$dst, $val)>;
|
||||
|
||||
} // Predicates = [Is64Bit]
|
||||
|
||||
let usesCustomInserter = 1, hasCtrlDep = 1, mayLoad = 1, mayStore = 1,
|
||||
Defs = [ICC] in
|
||||
multiclass AtomicRMW<SDPatternOperator op32, SDPatternOperator op64> {
|
||||
|
||||
def _32 : Pseudo<(outs IntRegs:$rd),
|
||||
(ins ptr_rc:$addr, IntRegs:$rs2), "",
|
||||
[(set i32:$rd, (op32 iPTR:$addr, i32:$rs2))]>;
|
||||
|
||||
let Predicates = [Is64Bit] in
|
||||
def _64 : Pseudo<(outs I64Regs:$rd),
|
||||
(ins ptr_rc:$addr, I64Regs:$rs2), "",
|
||||
[(set i64:$rd, (op64 iPTR:$addr, i64:$rs2))]>;
|
||||
}
|
||||
|
||||
defm ATOMIC_LOAD_ADD : AtomicRMW<atomic_load_add_32, atomic_load_add_64>;
|
||||
defm ATOMIC_LOAD_SUB : AtomicRMW<atomic_load_sub_32, atomic_load_sub_64>;
|
||||
defm ATOMIC_LOAD_AND : AtomicRMW<atomic_load_and_32, atomic_load_and_64>;
|
||||
defm ATOMIC_LOAD_OR : AtomicRMW<atomic_load_or_32, atomic_load_or_64>;
|
||||
defm ATOMIC_LOAD_XOR : AtomicRMW<atomic_load_xor_32, atomic_load_xor_64>;
|
||||
defm ATOMIC_LOAD_NAND : AtomicRMW<atomic_load_nand_32, atomic_load_nand_64>;
|
||||
defm ATOMIC_LOAD_MIN : AtomicRMW<atomic_load_min_32, atomic_load_min_64>;
|
||||
defm ATOMIC_LOAD_MAX : AtomicRMW<atomic_load_max_32, atomic_load_max_64>;
|
||||
defm ATOMIC_LOAD_UMIN : AtomicRMW<atomic_load_umin_32, atomic_load_umin_64>;
|
||||
defm ATOMIC_LOAD_UMAX : AtomicRMW<atomic_load_umax_32, atomic_load_umax_64>;
|
||||
|
||||
// There is no 64-bit variant of SWAP, so use a pseudo.
|
||||
let usesCustomInserter = 1, hasCtrlDep = 1, mayLoad = 1, mayStore = 1,
|
||||
Defs = [ICC], Predicates = [Is64Bit] in
|
||||
def ATOMIC_SWAP_64 : Pseudo<(outs I64Regs:$rd),
|
||||
(ins ptr_rc:$addr, I64Regs:$rs2), "",
|
||||
[(set i64:$rd,
|
||||
(atomic_swap_64 iPTR:$addr, i64:$rs2))]>;
|
||||
|
||||
let Predicates = [Is64Bit], hasSideEffects = 1, Uses = [ICC], cc = 0b10 in
|
||||
defm TXCC : TRAP<"%xcc">;
|
||||
|
||||
// Global addresses, constant pool entries
|
||||
let Predicates = [Is64Bit] in {
|
||||
|
||||
def : Pat<(SPhi tglobaladdr:$in), (SETHIi tglobaladdr:$in)>;
|
||||
def : Pat<(SPlo tglobaladdr:$in), (ORXri (i64 G0), tglobaladdr:$in)>;
|
||||
def : Pat<(SPhi tconstpool:$in), (SETHIi tconstpool:$in)>;
|
||||
def : Pat<(SPlo tconstpool:$in), (ORXri (i64 G0), tconstpool:$in)>;
|
||||
|
||||
// GlobalTLS addresses
|
||||
def : Pat<(SPhi tglobaltlsaddr:$in), (SETHIi tglobaltlsaddr:$in)>;
|
||||
def : Pat<(SPlo tglobaltlsaddr:$in), (ORXri (i64 G0), tglobaltlsaddr:$in)>;
|
||||
def : Pat<(add (SPhi tglobaltlsaddr:$in1), (SPlo tglobaltlsaddr:$in2)),
|
||||
(ADDXri (SETHIXi tglobaltlsaddr:$in1), (tglobaltlsaddr:$in2))>;
|
||||
def : Pat<(xor (SPhi tglobaltlsaddr:$in1), (SPlo tglobaltlsaddr:$in2)),
|
||||
(XORXri (SETHIXi tglobaltlsaddr:$in1), (tglobaltlsaddr:$in2))>;
|
||||
|
||||
// Blockaddress
|
||||
def : Pat<(SPhi tblockaddress:$in), (SETHIi tblockaddress:$in)>;
|
||||
def : Pat<(SPlo tblockaddress:$in), (ORXri (i64 G0), tblockaddress:$in)>;
|
||||
|
||||
// Add reg, lo. This is used when taking the addr of a global/constpool entry.
|
||||
def : Pat<(add iPTR:$r, (SPlo tglobaladdr:$in)), (ADDXri $r, tglobaladdr:$in)>;
|
||||
def : Pat<(add iPTR:$r, (SPlo tconstpool:$in)), (ADDXri $r, tconstpool:$in)>;
|
||||
def : Pat<(add iPTR:$r, (SPlo tblockaddress:$in)),
|
||||
(ADDXri $r, tblockaddress:$in)>;
|
||||
}
|
@ -1,452 +0,0 @@
|
||||
//===-- Mos6502InstrAliases.td - Instruction Aliases for Mos6502 Target -------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains instruction aliases for Mos6502.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Instruction aliases for conditional moves.
|
||||
|
||||
// mov<cond> <ccreg> rs2, rd
|
||||
multiclass intcond_mov_alias<string cond, int condVal, string ccreg,
|
||||
Instruction movrr, Instruction movri,
|
||||
Instruction fmovs, Instruction fmovd> {
|
||||
|
||||
// mov<cond> (%icc|%xcc), rs2, rd
|
||||
def : InstAlias<!strconcat(!strconcat(!strconcat("mov", cond), ccreg),
|
||||
", $rs2, $rd"),
|
||||
(movrr IntRegs:$rd, IntRegs:$rs2, condVal)>;
|
||||
|
||||
// mov<cond> (%icc|%xcc), simm11, rd
|
||||
def : InstAlias<!strconcat(!strconcat(!strconcat("mov", cond), ccreg),
|
||||
", $simm11, $rd"),
|
||||
(movri IntRegs:$rd, i32imm:$simm11, condVal)>;
|
||||
|
||||
// fmovs<cond> (%icc|%xcc), $rs2, $rd
|
||||
def : InstAlias<!strconcat(!strconcat(!strconcat("fmovs", cond), ccreg),
|
||||
", $rs2, $rd"),
|
||||
(fmovs FPRegs:$rd, FPRegs:$rs2, condVal)>;
|
||||
|
||||
// fmovd<cond> (%icc|%xcc), $rs2, $rd
|
||||
def : InstAlias<!strconcat(!strconcat(!strconcat("fmovd", cond), ccreg),
|
||||
", $rs2, $rd"),
|
||||
(fmovd DFPRegs:$rd, DFPRegs:$rs2, condVal)>;
|
||||
}
|
||||
|
||||
// mov<cond> <ccreg> rs2, rd
|
||||
multiclass fpcond_mov_alias<string cond, int condVal,
|
||||
Instruction movrr, Instruction movri,
|
||||
Instruction fmovs, Instruction fmovd> {
|
||||
|
||||
// mov<cond> %fcc[0-3], rs2, rd
|
||||
def : InstAlias<!strconcat(!strconcat("mov", cond), " $cc, $rs2, $rd"),
|
||||
(movrr IntRegs:$rd, FCCRegs:$cc, IntRegs:$rs2, condVal)>;
|
||||
|
||||
// mov<cond> %fcc[0-3], simm11, rd
|
||||
def : InstAlias<!strconcat(!strconcat("mov", cond), " $cc, $simm11, $rd"),
|
||||
(movri IntRegs:$rd, FCCRegs:$cc, i32imm:$simm11, condVal)>;
|
||||
|
||||
// fmovs<cond> %fcc[0-3], $rs2, $rd
|
||||
def : InstAlias<!strconcat(!strconcat("fmovs", cond), " $cc, $rs2, $rd"),
|
||||
(fmovs FPRegs:$rd, FCCRegs:$cc, FPRegs:$rs2, condVal)>;
|
||||
|
||||
// fmovd<cond> %fcc[0-3], $rs2, $rd
|
||||
def : InstAlias<!strconcat(!strconcat("fmovd", cond), " $cc, $rs2, $rd"),
|
||||
(fmovd DFPRegs:$rd, FCCRegs:$cc, DFPRegs:$rs2, condVal)>;
|
||||
}
|
||||
|
||||
// Instruction aliases for integer conditional branches and moves.
|
||||
multiclass int_cond_alias<string cond, int condVal> {
|
||||
|
||||
// b<cond> $imm
|
||||
def : InstAlias<!strconcat(!strconcat("b", cond), " $imm"),
|
||||
(BCOND brtarget:$imm, condVal)>;
|
||||
|
||||
// b<cond>,a $imm
|
||||
def : InstAlias<!strconcat(!strconcat("b", cond), ",a $imm"),
|
||||
(BCONDA brtarget:$imm, condVal)>;
|
||||
|
||||
// b<cond> %icc, $imm
|
||||
def : InstAlias<!strconcat(!strconcat("b", cond), " %icc, $imm"),
|
||||
(BPICC brtarget:$imm, condVal)>, Requires<[HasV9]>;
|
||||
|
||||
// b<cond>,pt %icc, $imm
|
||||
def : InstAlias<!strconcat(!strconcat("b", cond), ",pt %icc, $imm"),
|
||||
(BPICC brtarget:$imm, condVal)>, Requires<[HasV9]>;
|
||||
|
||||
// b<cond>,a %icc, $imm
|
||||
def : InstAlias<!strconcat(!strconcat("b", cond), ",a %icc, $imm"),
|
||||
(BPICCA brtarget:$imm, condVal)>, Requires<[HasV9]>;
|
||||
|
||||
// b<cond>,a,pt %icc, $imm
|
||||
def : InstAlias<!strconcat(!strconcat("b", cond), ",a,pt %icc, $imm"),
|
||||
(BPICCA brtarget:$imm, condVal)>, Requires<[HasV9]>;
|
||||
|
||||
// b<cond>,pn %icc, $imm
|
||||
def : InstAlias<!strconcat(!strconcat("b", cond), ",pn %icc, $imm"),
|
||||
(BPICCNT brtarget:$imm, condVal)>, Requires<[HasV9]>;
|
||||
|
||||
// b<cond>,a,pn %icc, $imm
|
||||
def : InstAlias<!strconcat(!strconcat("b", cond), ",a,pn %icc, $imm"),
|
||||
(BPICCANT brtarget:$imm, condVal)>, Requires<[HasV9]>;
|
||||
|
||||
// b<cond> %xcc, $imm
|
||||
def : InstAlias<!strconcat(!strconcat("b", cond), " %xcc, $imm"),
|
||||
(BPXCC brtarget:$imm, condVal)>, Requires<[Is64Bit]>;
|
||||
|
||||
// b<cond>,pt %xcc, $imm
|
||||
def : InstAlias<!strconcat(!strconcat("b", cond), ",pt %xcc, $imm"),
|
||||
(BPXCC brtarget:$imm, condVal)>, Requires<[Is64Bit]>;
|
||||
|
||||
// b<cond>,a %xcc, $imm
|
||||
def : InstAlias<!strconcat(!strconcat("b", cond), ",a %xcc, $imm"),
|
||||
(BPXCCA brtarget:$imm, condVal)>, Requires<[Is64Bit]>;
|
||||
|
||||
// b<cond>,a,pt %xcc, $imm
|
||||
def : InstAlias<!strconcat(!strconcat("b", cond), ",a,pt %xcc, $imm"),
|
||||
(BPXCCA brtarget:$imm, condVal)>, Requires<[Is64Bit]>;
|
||||
|
||||
// b<cond>,pn %xcc, $imm
|
||||
def : InstAlias<!strconcat(!strconcat("b", cond), ",pn %xcc, $imm"),
|
||||
(BPXCCNT brtarget:$imm, condVal)>, Requires<[Is64Bit]>;
|
||||
|
||||
// b<cond>,a,pn %xcc, $imm
|
||||
def : InstAlias<!strconcat(!strconcat("b", cond), ",a,pn %xcc, $imm"),
|
||||
(BPXCCANT brtarget:$imm, condVal)>, Requires<[Is64Bit]>;
|
||||
|
||||
|
||||
defm : intcond_mov_alias<cond, condVal, " %icc",
|
||||
MOVICCrr, MOVICCri,
|
||||
FMOVS_ICC, FMOVD_ICC>, Requires<[HasV9]>;
|
||||
|
||||
defm : intcond_mov_alias<cond, condVal, " %xcc",
|
||||
MOVXCCrr, MOVXCCri,
|
||||
FMOVS_XCC, FMOVD_XCC>, Requires<[Is64Bit]>;
|
||||
|
||||
// fmovq<cond> (%icc|%xcc), $rs2, $rd
|
||||
def : InstAlias<!strconcat(!strconcat("fmovq", cond), " %icc, $rs2, $rd"),
|
||||
(FMOVQ_ICC QFPRegs:$rd, QFPRegs:$rs2, condVal)>,
|
||||
Requires<[HasV9, HasHardQuad]>;
|
||||
def : InstAlias<!strconcat(!strconcat("fmovq", cond), " %xcc, $rs2, $rd"),
|
||||
(FMOVQ_XCC QFPRegs:$rd, QFPRegs:$rs2, condVal)>,
|
||||
Requires<[Is64Bit, HasHardQuad]>;
|
||||
|
||||
// t<cond> %icc, rs1 + rs2
|
||||
def : InstAlias<!strconcat(!strconcat("t", cond), " %icc, $rs1 + $rs2"),
|
||||
(TICCrr IntRegs:$rs1, IntRegs:$rs2, condVal)>,
|
||||
Requires<[HasV9]>;
|
||||
|
||||
// t<cond> %icc, rs => t<cond> %icc, G0 + rs
|
||||
def : InstAlias<!strconcat(!strconcat("t", cond), " %icc, $rs2"),
|
||||
(TICCrr G0, IntRegs:$rs2, condVal)>,
|
||||
Requires<[HasV9]>;
|
||||
|
||||
// t<cond> %xcc, rs1 + rs2
|
||||
def : InstAlias<!strconcat(!strconcat("t", cond), " %xcc, $rs1 + $rs2"),
|
||||
(TXCCrr IntRegs:$rs1, IntRegs:$rs2, condVal)>,
|
||||
Requires<[HasV9]>;
|
||||
|
||||
// t<cond> %xcc, rs => t<cond> %xcc, G0 + rs
|
||||
def : InstAlias<!strconcat(!strconcat("t", cond), " %xcc, $rs2"),
|
||||
(TXCCrr G0, IntRegs:$rs2, condVal)>,
|
||||
Requires<[HasV9]>;
|
||||
|
||||
// t<cond> rs1 + rs2 => t<cond> %icc, rs1 + rs2
|
||||
def : InstAlias<!strconcat(!strconcat("t", cond), " $rs1 + $rs2"),
|
||||
(TICCrr IntRegs:$rs1, IntRegs:$rs2, condVal)>;
|
||||
|
||||
// t<cond> rs=> t<cond> %icc, G0 + rs2
|
||||
def : InstAlias<!strconcat(!strconcat("t", cond), " $rs2"),
|
||||
(TICCrr G0, IntRegs:$rs2, condVal)>;
|
||||
|
||||
// t<cond> %icc, rs1 + imm
|
||||
def : InstAlias<!strconcat(!strconcat("t", cond), " %icc, $rs1 + $imm"),
|
||||
(TICCri IntRegs:$rs1, i32imm:$imm, condVal)>,
|
||||
Requires<[HasV9]>;
|
||||
// t<cond> %icc, imm => t<cond> %icc, G0 + imm
|
||||
def : InstAlias<!strconcat(!strconcat("t", cond), " %icc, $imm"),
|
||||
(TICCri G0, i32imm:$imm, condVal)>,
|
||||
Requires<[HasV9]>;
|
||||
// t<cond> %xcc, rs1 + imm
|
||||
def : InstAlias<!strconcat(!strconcat("t", cond), " %xcc, $rs1 + $imm"),
|
||||
(TXCCri IntRegs:$rs1, i32imm:$imm, condVal)>,
|
||||
Requires<[HasV9]>;
|
||||
// t<cond> %xcc, imm => t<cond> %xcc, G0 + imm
|
||||
def : InstAlias<!strconcat(!strconcat("t", cond), " %xcc, $imm"),
|
||||
(TXCCri G0, i32imm:$imm, condVal)>,
|
||||
Requires<[HasV9]>;
|
||||
|
||||
// t<cond> rs1 + imm => t<cond> %icc, rs1 + imm
|
||||
def : InstAlias<!strconcat(!strconcat("t", cond), " $rs1 + $imm"),
|
||||
(TICCri IntRegs:$rs1, i32imm:$imm, condVal)>;
|
||||
|
||||
// t<cond> imm => t<cond> %icc, G0 + imm
|
||||
def : InstAlias<!strconcat(!strconcat("t", cond), " $imm"),
|
||||
(TICCri G0, i32imm:$imm, condVal)>;
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Instruction aliases for floating point conditional branches and moves.
|
||||
multiclass fp_cond_alias<string cond, int condVal> {
|
||||
|
||||
// fb<cond> $imm
|
||||
def : InstAlias<!strconcat(!strconcat("fb", cond), " $imm"),
|
||||
(FBCOND brtarget:$imm, condVal), 0>;
|
||||
|
||||
// fb<cond>,a $imm
|
||||
def : InstAlias<!strconcat(!strconcat("fb", cond), ",a $imm"),
|
||||
(FBCONDA brtarget:$imm, condVal), 0>;
|
||||
|
||||
// fb<cond> %fcc0, $imm
|
||||
def : InstAlias<!strconcat(!strconcat("fb", cond), " $cc, $imm"),
|
||||
(BPFCC brtarget:$imm, condVal, FCCRegs:$cc)>,
|
||||
Requires<[HasV9]>;
|
||||
|
||||
// fb<cond>,pt %fcc0, $imm
|
||||
def : InstAlias<!strconcat(!strconcat("fb", cond), ",pt $cc, $imm"),
|
||||
(BPFCC brtarget:$imm, condVal, FCCRegs:$cc)>,
|
||||
Requires<[HasV9]>;
|
||||
|
||||
// fb<cond>,a %fcc0, $imm
|
||||
def : InstAlias<!strconcat(!strconcat("fb", cond), ",a $cc, $imm"),
|
||||
(BPFCCA brtarget:$imm, condVal, FCCRegs:$cc)>,
|
||||
Requires<[HasV9]>;
|
||||
|
||||
// fb<cond>,a,pt %fcc0, $imm
|
||||
def : InstAlias<!strconcat(!strconcat("fb", cond), ",a,pt $cc, $imm"),
|
||||
(BPFCCA brtarget:$imm, condVal, FCCRegs:$cc)>,
|
||||
Requires<[HasV9]>;
|
||||
|
||||
// fb<cond>,pn %fcc0, $imm
|
||||
def : InstAlias<!strconcat(!strconcat("fb", cond), ",pn $cc, $imm"),
|
||||
(BPFCCNT brtarget:$imm, condVal, FCCRegs:$cc)>,
|
||||
Requires<[HasV9]>;
|
||||
|
||||
// fb<cond>,a,pn %fcc0, $imm
|
||||
def : InstAlias<!strconcat(!strconcat("fb", cond), ",a,pn $cc, $imm"),
|
||||
(BPFCCANT brtarget:$imm, condVal, FCCRegs:$cc)>,
|
||||
Requires<[HasV9]>;
|
||||
|
||||
defm : fpcond_mov_alias<cond, condVal,
|
||||
V9MOVFCCrr, V9MOVFCCri,
|
||||
V9FMOVS_FCC, V9FMOVD_FCC>, Requires<[HasV9]>;
|
||||
|
||||
// fmovq<cond> %fcc0, $rs2, $rd
|
||||
def : InstAlias<!strconcat(!strconcat("fmovq", cond), " $cc, $rs2, $rd"),
|
||||
(V9FMOVQ_FCC QFPRegs:$rd, FCCRegs:$cc, QFPRegs:$rs2,
|
||||
condVal)>,
|
||||
Requires<[HasV9, HasHardQuad]>;
|
||||
}
|
||||
|
||||
defm : int_cond_alias<"a", 0b1000>;
|
||||
defm : int_cond_alias<"", 0b1000>; // same as a; gnu asm, not in manual
|
||||
defm : int_cond_alias<"n", 0b0000>;
|
||||
defm : int_cond_alias<"ne", 0b1001>;
|
||||
defm : int_cond_alias<"nz", 0b1001>; // same as ne
|
||||
defm : int_cond_alias<"e", 0b0001>;
|
||||
defm : int_cond_alias<"z", 0b0001>; // same as e
|
||||
defm : int_cond_alias<"g", 0b1010>;
|
||||
defm : int_cond_alias<"le", 0b0010>;
|
||||
defm : int_cond_alias<"ge", 0b1011>;
|
||||
defm : int_cond_alias<"l", 0b0011>;
|
||||
defm : int_cond_alias<"gu", 0b1100>;
|
||||
defm : int_cond_alias<"leu", 0b0100>;
|
||||
defm : int_cond_alias<"cc", 0b1101>;
|
||||
defm : int_cond_alias<"geu", 0b1101>; // same as cc
|
||||
defm : int_cond_alias<"cs", 0b0101>;
|
||||
defm : int_cond_alias<"lu", 0b0101>; // same as cs
|
||||
defm : int_cond_alias<"pos", 0b1110>;
|
||||
defm : int_cond_alias<"neg", 0b0110>;
|
||||
defm : int_cond_alias<"vc", 0b1111>;
|
||||
defm : int_cond_alias<"vs", 0b0111>;
|
||||
|
||||
defm : fp_cond_alias<"a", 0b0000>;
|
||||
defm : fp_cond_alias<"", 0b0000>; // same as a; gnu asm, not in manual
|
||||
defm : fp_cond_alias<"n", 0b1000>;
|
||||
defm : fp_cond_alias<"u", 0b0111>;
|
||||
defm : fp_cond_alias<"g", 0b0110>;
|
||||
defm : fp_cond_alias<"ug", 0b0101>;
|
||||
defm : fp_cond_alias<"l", 0b0100>;
|
||||
defm : fp_cond_alias<"ul", 0b0011>;
|
||||
defm : fp_cond_alias<"lg", 0b0010>;
|
||||
defm : fp_cond_alias<"ne", 0b0001>;
|
||||
defm : fp_cond_alias<"nz", 0b0001>; // same as ne
|
||||
defm : fp_cond_alias<"e", 0b1001>;
|
||||
defm : fp_cond_alias<"z", 0b1001>; // same as e
|
||||
defm : fp_cond_alias<"ue", 0b1010>;
|
||||
defm : fp_cond_alias<"ge", 0b1011>;
|
||||
defm : fp_cond_alias<"uge", 0b1100>;
|
||||
defm : fp_cond_alias<"le", 0b1101>;
|
||||
defm : fp_cond_alias<"ule", 0b1110>;
|
||||
defm : fp_cond_alias<"o", 0b1111>;
|
||||
|
||||
// Section A.3 Synthetic Instructions
|
||||
|
||||
// Most are marked as Emit=0, so that they are not used for disassembly. This is
|
||||
// an aesthetic issue, but the chosen policy is to typically prefer using the
|
||||
// non-alias form, except for the most obvious and clarifying aliases: cmp, jmp,
|
||||
// call, tst, ret, retl.
|
||||
|
||||
// Note: cmp is handled in Mos6502InstrInfo.
|
||||
// jmp/call/ret/retl have special case handling for output in
|
||||
// Mos6502InstPrinter.cpp
|
||||
|
||||
// jmp addr -> jmpl addr, %g0
|
||||
def : InstAlias<"jmp $addr", (JMPLrr G0, MEMrr:$addr), 0>;
|
||||
def : InstAlias<"jmp $addr", (JMPLri G0, MEMri:$addr), 0>;
|
||||
|
||||
// call addr -> jmpl addr, %o7
|
||||
def : InstAlias<"call $addr", (JMPLrr O7, MEMrr:$addr), 0>;
|
||||
def : InstAlias<"call $addr", (JMPLri O7, MEMri:$addr), 0>;
|
||||
|
||||
// tst reg -> orcc %g0, reg, %g0
|
||||
def : InstAlias<"tst $rs2", (ORCCrr G0, IntRegs:$rs2, G0)>;
|
||||
|
||||
// ret -> jmpl %i7+8, %g0 (aka RET 8)
|
||||
def : InstAlias<"ret", (RET 8)>;
|
||||
|
||||
// retl -> jmpl %o7+8, %g0 (aka RETL 8)
|
||||
def : InstAlias<"retl", (RETL 8)>;
|
||||
|
||||
// restore -> restore %g0, %g0, %g0
|
||||
def : InstAlias<"restore", (RESTORErr G0, G0, G0)>;
|
||||
|
||||
// save -> restore %g0, %g0, %g0
|
||||
def : InstAlias<"save", (SAVErr G0, G0, G0)>;
|
||||
|
||||
// set value, rd
|
||||
// (turns into a sequence of sethi+or, depending on the value)
|
||||
// def : InstAlias<"set $val, $rd", (ORri IntRegs:$rd, (SETHIi (HI22 imm:$val)), (LO10 imm:$val))>;
|
||||
def SET : AsmPseudoInst<(outs IntRegs:$rd), (ins i32imm:$val), "set $val, $rd">;
|
||||
|
||||
// not rd -> xnor rd, %g0, rd
|
||||
def : InstAlias<"not $rd", (XNORrr IntRegs:$rd, IntRegs:$rd, G0), 0>;
|
||||
|
||||
// not reg, rd -> xnor reg, %g0, rd
|
||||
def : InstAlias<"not $rs1, $rd", (XNORrr IntRegs:$rd, IntRegs:$rs1, G0), 0>;
|
||||
|
||||
// neg rd -> sub %g0, rd, rd
|
||||
def : InstAlias<"neg $rd", (SUBrr IntRegs:$rd, G0, IntRegs:$rd), 0>;
|
||||
|
||||
// neg reg, rd -> sub %g0, reg, rd
|
||||
def : InstAlias<"neg $rs2, $rd", (SUBrr IntRegs:$rd, G0, IntRegs:$rs2), 0>;
|
||||
|
||||
// inc rd -> add rd, 1, rd
|
||||
def : InstAlias<"inc $rd", (ADDri IntRegs:$rd, IntRegs:$rd, 1), 0>;
|
||||
|
||||
// inc simm13, rd -> add rd, simm13, rd
|
||||
def : InstAlias<"inc $simm13, $rd", (ADDri IntRegs:$rd, IntRegs:$rd, i32imm:$simm13), 0>;
|
||||
|
||||
// inccc rd -> addcc rd, 1, rd
|
||||
def : InstAlias<"inccc $rd", (ADDCCri IntRegs:$rd, IntRegs:$rd, 1), 0>;
|
||||
|
||||
// inccc simm13, rd -> addcc rd, simm13, rd
|
||||
def : InstAlias<"inccc $simm13, $rd", (ADDCCri IntRegs:$rd, IntRegs:$rd, i32imm:$simm13), 0>;
|
||||
|
||||
// dec rd -> sub rd, 1, rd
|
||||
def : InstAlias<"dec $rd", (SUBri IntRegs:$rd, IntRegs:$rd, 1), 0>;
|
||||
|
||||
// dec simm13, rd -> sub rd, simm13, rd
|
||||
def : InstAlias<"dec $simm13, $rd", (SUBri IntRegs:$rd, IntRegs:$rd, i32imm:$simm13), 0>;
|
||||
|
||||
// deccc rd -> subcc rd, 1, rd
|
||||
def : InstAlias<"deccc $rd", (SUBCCri IntRegs:$rd, IntRegs:$rd, 1), 0>;
|
||||
|
||||
// deccc simm13, rd -> subcc rd, simm13, rd
|
||||
def : InstAlias<"deccc $simm13, $rd", (SUBCCri IntRegs:$rd, IntRegs:$rd, i32imm:$simm13), 0>;
|
||||
|
||||
// btst reg_or_imm, reg -> andcc reg,reg_or_imm,%g0
|
||||
def : InstAlias<"btst $rs2, $rs1", (ANDCCrr G0, IntRegs:$rs1, IntRegs:$rs2), 0>;
|
||||
def : InstAlias<"btst $simm13, $rs1", (ANDCCri G0, IntRegs:$rs1, i32imm:$simm13), 0>;
|
||||
|
||||
// bset reg_or_imm, rd -> or rd,reg_or_imm,rd
|
||||
def : InstAlias<"bset $rs2, $rd", (ORrr IntRegs:$rd, IntRegs:$rd, IntRegs:$rs2), 0>;
|
||||
def : InstAlias<"bset $simm13, $rd", (ORri IntRegs:$rd, IntRegs:$rd, i32imm:$simm13), 0>;
|
||||
|
||||
// bclr reg_or_imm, rd -> andn rd,reg_or_imm,rd
|
||||
def : InstAlias<"bclr $rs2, $rd", (ANDNrr IntRegs:$rd, IntRegs:$rd, IntRegs:$rs2), 0>;
|
||||
def : InstAlias<"bclr $simm13, $rd", (ANDNri IntRegs:$rd, IntRegs:$rd, i32imm:$simm13), 0>;
|
||||
|
||||
// btog reg_or_imm, rd -> xor rd,reg_or_imm,rd
|
||||
def : InstAlias<"btog $rs2, $rd", (XORrr IntRegs:$rd, IntRegs:$rd, IntRegs:$rs2), 0>;
|
||||
def : InstAlias<"btog $simm13, $rd", (XORri IntRegs:$rd, IntRegs:$rd, i32imm:$simm13), 0>;
|
||||
|
||||
|
||||
// clr rd -> or %g0, %g0, rd
|
||||
def : InstAlias<"clr $rd", (ORrr IntRegs:$rd, G0, G0), 0>;
|
||||
|
||||
// clr{b,h,} [addr] -> st{b,h,} %g0, [addr]
|
||||
def : InstAlias<"clrb [$addr]", (STBrr MEMrr:$addr, G0), 0>;
|
||||
def : InstAlias<"clrb [$addr]", (STBri MEMri:$addr, G0), 0>;
|
||||
def : InstAlias<"clrh [$addr]", (STHrr MEMrr:$addr, G0), 0>;
|
||||
def : InstAlias<"clrh [$addr]", (STHri MEMri:$addr, G0), 0>;
|
||||
def : InstAlias<"clr [$addr]", (STrr MEMrr:$addr, G0), 0>;
|
||||
def : InstAlias<"clr [$addr]", (STri MEMri:$addr, G0), 0>;
|
||||
|
||||
|
||||
// mov reg_or_imm, rd -> or %g0, reg_or_imm, rd
|
||||
def : InstAlias<"mov $rs2, $rd", (ORrr IntRegs:$rd, G0, IntRegs:$rs2)>;
|
||||
def : InstAlias<"mov $simm13, $rd", (ORri IntRegs:$rd, G0, i32imm:$simm13)>;
|
||||
|
||||
// mov specialreg, rd -> rd specialreg, rd
|
||||
def : InstAlias<"mov $asr, $rd", (RDASR IntRegs:$rd, ASRRegs:$asr), 0>;
|
||||
def : InstAlias<"mov %psr, $rd", (RDPSR IntRegs:$rd), 0>;
|
||||
def : InstAlias<"mov %wim, $rd", (RDWIM IntRegs:$rd), 0>;
|
||||
def : InstAlias<"mov %tbr, $rd", (RDTBR IntRegs:$rd), 0>;
|
||||
|
||||
// mov reg_or_imm, specialreg -> wr %g0, reg_or_imm, specialreg
|
||||
def : InstAlias<"mov $rs2, $asr", (WRASRrr ASRRegs:$asr, G0, IntRegs:$rs2), 0>;
|
||||
def : InstAlias<"mov $simm13, $asr", (WRASRri ASRRegs:$asr, G0, i32imm:$simm13), 0>;
|
||||
def : InstAlias<"mov $rs2, %psr", (WRPSRrr G0, IntRegs:$rs2), 0>;
|
||||
def : InstAlias<"mov $simm13, %psr", (WRPSRri G0, i32imm:$simm13), 0>;
|
||||
def : InstAlias<"mov $rs2, %wim", (WRWIMrr G0, IntRegs:$rs2), 0>;
|
||||
def : InstAlias<"mov $simm13, %wim", (WRWIMri G0, i32imm:$simm13), 0>;
|
||||
def : InstAlias<"mov $rs2, %tbr", (WRTBRrr G0, IntRegs:$rs2), 0>;
|
||||
def : InstAlias<"mov $simm13, %tbr", (WRTBRri G0, i32imm:$simm13), 0>;
|
||||
|
||||
// End of Section A.3
|
||||
|
||||
// wr reg_or_imm, specialreg -> wr %g0, reg_or_imm, specialreg
|
||||
// (aka: omit the first arg when it's g0. This is not in the manual, but is
|
||||
// supported by gnu and solaris as)
|
||||
def : InstAlias<"wr $rs2, $asr", (WRASRrr ASRRegs:$asr, G0, IntRegs:$rs2), 0>;
|
||||
def : InstAlias<"wr $simm13, $asr", (WRASRri ASRRegs:$asr, G0, i32imm:$simm13), 0>;
|
||||
def : InstAlias<"wr $rs2, %psr", (WRPSRrr G0, IntRegs:$rs2), 0>;
|
||||
def : InstAlias<"wr $simm13, %psr", (WRPSRri G0, i32imm:$simm13), 0>;
|
||||
def : InstAlias<"wr $rs2, %wim", (WRWIMrr G0, IntRegs:$rs2), 0>;
|
||||
def : InstAlias<"wr $simm13, %wim", (WRWIMri G0, i32imm:$simm13), 0>;
|
||||
def : InstAlias<"wr $rs2, %tbr", (WRTBRrr G0, IntRegs:$rs2), 0>;
|
||||
def : InstAlias<"wr $simm13, %tbr", (WRTBRri G0, i32imm:$simm13), 0>;
|
||||
|
||||
|
||||
// flush -> flush %g0
|
||||
def : InstAlias<"flush", (FLUSH), 0>;
|
||||
|
||||
|
||||
def : MnemonicAlias<"return", "rett">, Requires<[HasV9]>;
|
||||
|
||||
def : MnemonicAlias<"addc", "addx">, Requires<[HasV9]>;
|
||||
def : MnemonicAlias<"addccc", "addxcc">, Requires<[HasV9]>;
|
||||
|
||||
def : MnemonicAlias<"subc", "subx">, Requires<[HasV9]>;
|
||||
def : MnemonicAlias<"subccc", "subxcc">, Requires<[HasV9]>;
|
||||
|
||||
|
||||
def : InstAlias<"fcmps $rs1, $rs2", (V9FCMPS FCC0, FPRegs:$rs1, FPRegs:$rs2)>;
|
||||
def : InstAlias<"fcmpd $rs1, $rs2", (V9FCMPD FCC0, DFPRegs:$rs1, DFPRegs:$rs2)>;
|
||||
def : InstAlias<"fcmpq $rs1, $rs2", (V9FCMPQ FCC0, QFPRegs:$rs1, QFPRegs:$rs2)>,
|
||||
Requires<[HasHardQuad]>;
|
||||
|
||||
def : InstAlias<"fcmpes $rs1, $rs2", (V9FCMPES FCC0, FPRegs:$rs1, FPRegs:$rs2)>;
|
||||
def : InstAlias<"fcmped $rs1, $rs2", (V9FCMPED FCC0, DFPRegs:$rs1,
|
||||
DFPRegs:$rs2)>;
|
||||
def : InstAlias<"fcmpeq $rs1, $rs2", (V9FCMPEQ FCC0, QFPRegs:$rs1,
|
||||
QFPRegs:$rs2)>,
|
||||
Requires<[HasHardQuad]>;
|
||||
|
@ -1,4 +1,4 @@
|
||||
//===-- Mos6502InstrFormats.td - Mos6502 Instruction Formats ---*- tablegen -*-===//
|
||||
//=== Mos6502InstrFormats.td - Mos6502 Instruction Formats -*- tablegen -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
@ -7,335 +7,34 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
class InstSP<dag outs, dag ins, string asmstr, list<dag> pattern>
|
||||
class InstM6502<dag outs, dag ins, string asmstr, list<dag> pattern>
|
||||
: Instruction {
|
||||
field bits<32> Inst;
|
||||
|
||||
let Namespace = "M6502";
|
||||
let Size = 4;
|
||||
|
||||
bits<2> op;
|
||||
let Inst{31-30} = op; // Top two bits are the 'op' field
|
||||
// All 6502 instructions are 1-byte sized
|
||||
field bits<8> Inst;
|
||||
let Size = 1;
|
||||
|
||||
dag OutOperandList = outs;
|
||||
dag InOperandList = ins;
|
||||
let AsmString = asmstr;
|
||||
let AsmString = asmstr;
|
||||
let Pattern = pattern;
|
||||
}
|
||||
|
||||
// A class for pseudo instructions
|
||||
//
|
||||
// Psuedo instructions are not real 6502 instructions. The DAG stores psuedo
|
||||
// instructions which are replaced by real 6502 instructions by
|
||||
// Mos6502ExpandPseudoInsts.cpp.
|
||||
//
|
||||
// For example, the ADDW (add wide, as in add 16 bit values) instruction is
|
||||
// defined as a pseudo instruction. In Mos6502ExpandPseudoInsts.cpp, the
|
||||
// instruction is then replaced by two ADC instructions - one for each byte.
|
||||
//
|
||||
class Pseudo<dag outs, dag ins, string asmstr, list<dag> pattern>
|
||||
: InstM6502<outs, ins, asmstr, pattern>
|
||||
{
|
||||
let Pattern = pattern;
|
||||
|
||||
let DecoderNamespace = "Mos6502";
|
||||
field bits<32> SoftFail = 0;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Format #2 instruction classes in the Mos6502
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Format 2 instructions
|
||||
class F2<dag outs, dag ins, string asmstr, list<dag> pattern>
|
||||
: InstSP<outs, ins, asmstr, pattern> {
|
||||
bits<3> op2;
|
||||
bits<22> imm22;
|
||||
let op = 0; // op = 0
|
||||
let Inst{24-22} = op2;
|
||||
let Inst{21-0} = imm22;
|
||||
}
|
||||
|
||||
// Specific F2 classes: Mos6502V8 manual, page 44
|
||||
//
|
||||
class F2_1<bits<3> op2Val, dag outs, dag ins, string asmstr, list<dag> pattern>
|
||||
: F2<outs, ins, asmstr, pattern> {
|
||||
bits<5> rd;
|
||||
|
||||
let op2 = op2Val;
|
||||
|
||||
let Inst{29-25} = rd;
|
||||
}
|
||||
|
||||
class F2_2<bits<3> op2Val, bit annul, dag outs, dag ins, string asmstr,
|
||||
list<dag> pattern> : F2<outs, ins, asmstr, pattern> {
|
||||
bits<4> cond;
|
||||
let op2 = op2Val;
|
||||
|
||||
let Inst{29} = annul;
|
||||
let Inst{28-25} = cond;
|
||||
}
|
||||
|
||||
class F2_3<bits<3> op2Val, bit annul, bit pred,
|
||||
dag outs, dag ins, string asmstr, list<dag> pattern>
|
||||
: InstSP<outs, ins, asmstr, pattern> {
|
||||
bits<2> cc;
|
||||
bits<4> cond;
|
||||
bits<19> imm19;
|
||||
|
||||
let op = 0; // op = 0
|
||||
|
||||
let Inst{29} = annul;
|
||||
let Inst{28-25} = cond;
|
||||
let Inst{24-22} = op2Val;
|
||||
let Inst{21-20} = cc;
|
||||
let Inst{19} = pred;
|
||||
let Inst{18-0} = imm19;
|
||||
}
|
||||
|
||||
class F2_4<bits<3> cond, bit annul, bit pred,
|
||||
dag outs, dag ins, string asmstr, list<dag> pattern>
|
||||
: InstSP<outs, ins, asmstr, pattern> {
|
||||
bits<16> imm16;
|
||||
bits<5> rs1;
|
||||
|
||||
let op = 0; // op = 0
|
||||
|
||||
let Inst{29} = annul;
|
||||
let Inst{28} = 0;
|
||||
let Inst{27-25} = cond;
|
||||
let Inst{24-22} = 0b011;
|
||||
let Inst{21-20} = imm16{15-14};
|
||||
let Inst{19} = pred;
|
||||
let Inst{18-14} = rs1;
|
||||
let Inst{13-0} = imm16{13-0};
|
||||
}
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Format #3 instruction classes in the Mos6502
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
class F3<dag outs, dag ins, string asmstr, list<dag> pattern>
|
||||
: InstSP<outs, ins, asmstr, pattern> {
|
||||
bits<5> rd;
|
||||
bits<6> op3;
|
||||
bits<5> rs1;
|
||||
let op{1} = 1; // Op = 2 or 3
|
||||
let Inst{29-25} = rd;
|
||||
let Inst{24-19} = op3;
|
||||
let Inst{18-14} = rs1;
|
||||
}
|
||||
|
||||
// Specific F3 classes: Mos6502V8 manual, page 44
|
||||
//
|
||||
class F3_1_asi<bits<2> opVal, bits<6> op3val, dag outs, dag ins,
|
||||
string asmstr, list<dag> pattern> : F3<outs, ins, asmstr, pattern> {
|
||||
bits<8> asi;
|
||||
bits<5> rs2;
|
||||
|
||||
let op = opVal;
|
||||
let op3 = op3val;
|
||||
|
||||
let Inst{13} = 0; // i field = 0
|
||||
let Inst{12-5} = asi; // address space identifier
|
||||
let Inst{4-0} = rs2;
|
||||
}
|
||||
|
||||
class F3_1<bits<2> opVal, bits<6> op3val, dag outs, dag ins, string asmstr,
|
||||
list<dag> pattern> : F3_1_asi<opVal, op3val, outs, ins,
|
||||
asmstr, pattern> {
|
||||
let asi = 0;
|
||||
}
|
||||
|
||||
class F3_2<bits<2> opVal, bits<6> op3val, dag outs, dag ins,
|
||||
string asmstr, list<dag> pattern> : F3<outs, ins, asmstr, pattern> {
|
||||
bits<13> simm13;
|
||||
|
||||
let op = opVal;
|
||||
let op3 = op3val;
|
||||
|
||||
let Inst{13} = 1; // i field = 1
|
||||
let Inst{12-0} = simm13;
|
||||
}
|
||||
|
||||
// floating-point
|
||||
class F3_3<bits<2> opVal, bits<6> op3val, bits<9> opfval, dag outs, dag ins,
|
||||
string asmstr, list<dag> pattern> : F3<outs, ins, asmstr, pattern> {
|
||||
bits<5> rs2;
|
||||
|
||||
let op = opVal;
|
||||
let op3 = op3val;
|
||||
|
||||
let Inst{13-5} = opfval; // fp opcode
|
||||
let Inst{4-0} = rs2;
|
||||
}
|
||||
|
||||
// floating-point unary operations.
|
||||
class F3_3u<bits<2> opVal, bits<6> op3val, bits<9> opfval, dag outs, dag ins,
|
||||
string asmstr, list<dag> pattern> : F3<outs, ins, asmstr, pattern> {
|
||||
bits<5> rs2;
|
||||
|
||||
let op = opVal;
|
||||
let op3 = op3val;
|
||||
let rs1 = 0;
|
||||
|
||||
let Inst{13-5} = opfval; // fp opcode
|
||||
let Inst{4-0} = rs2;
|
||||
}
|
||||
|
||||
// floating-point compares.
|
||||
class F3_3c<bits<2> opVal, bits<6> op3val, bits<9> opfval, dag outs, dag ins,
|
||||
string asmstr, list<dag> pattern> : F3<outs, ins, asmstr, pattern> {
|
||||
bits<5> rs2;
|
||||
|
||||
let op = opVal;
|
||||
let op3 = op3val;
|
||||
|
||||
let Inst{13-5} = opfval; // fp opcode
|
||||
let Inst{4-0} = rs2;
|
||||
}
|
||||
|
||||
// Shift by register rs2.
|
||||
class F3_Sr<bits<2> opVal, bits<6> op3val, bit xVal, dag outs, dag ins,
|
||||
string asmstr, list<dag> pattern> : F3<outs, ins, asmstr, pattern> {
|
||||
bit x = xVal; // 1 for 64-bit shifts.
|
||||
bits<5> rs2;
|
||||
|
||||
let op = opVal;
|
||||
let op3 = op3val;
|
||||
|
||||
let Inst{13} = 0; // i field = 0
|
||||
let Inst{12} = x; // extended registers.
|
||||
let Inst{4-0} = rs2;
|
||||
}
|
||||
|
||||
// Shift by immediate.
|
||||
class F3_Si<bits<2> opVal, bits<6> op3val, bit xVal, dag outs, dag ins,
|
||||
string asmstr, list<dag> pattern> : F3<outs, ins, asmstr, pattern> {
|
||||
bit x = xVal; // 1 for 64-bit shifts.
|
||||
bits<6> shcnt; // shcnt32 / shcnt64.
|
||||
|
||||
let op = opVal;
|
||||
let op3 = op3val;
|
||||
|
||||
let Inst{13} = 1; // i field = 1
|
||||
let Inst{12} = x; // extended registers.
|
||||
let Inst{5-0} = shcnt;
|
||||
}
|
||||
|
||||
// Define rr and ri shift instructions with patterns.
|
||||
multiclass F3_S<string OpcStr, bits<6> Op3Val, bit XVal, SDNode OpNode,
|
||||
ValueType VT, RegisterClass RC> {
|
||||
def rr : F3_Sr<2, Op3Val, XVal, (outs RC:$rd), (ins RC:$rs1, IntRegs:$rs2),
|
||||
!strconcat(OpcStr, " $rs1, $rs2, $rd"),
|
||||
[(set VT:$rd, (OpNode VT:$rs1, i32:$rs2))]>;
|
||||
def ri : F3_Si<2, Op3Val, XVal, (outs RC:$rd), (ins RC:$rs1, i32imm:$shcnt),
|
||||
!strconcat(OpcStr, " $rs1, $shcnt, $rd"),
|
||||
[(set VT:$rd, (OpNode VT:$rs1, (i32 imm:$shcnt)))]>;
|
||||
}
|
||||
|
||||
class F4<bits<6> op3, dag outs, dag ins, string asmstr, list<dag> pattern>
|
||||
: InstSP<outs, ins, asmstr, pattern> {
|
||||
bits<5> rd;
|
||||
|
||||
let op = 2;
|
||||
let Inst{29-25} = rd;
|
||||
let Inst{24-19} = op3;
|
||||
}
|
||||
|
||||
|
||||
class F4_1<bits<6> op3, dag outs, dag ins,
|
||||
string asmstr, list<dag> pattern>
|
||||
: F4<op3, outs, ins, asmstr, pattern> {
|
||||
|
||||
bit intcc;
|
||||
bits<2> cc;
|
||||
bits<4> cond;
|
||||
bits<5> rs2;
|
||||
|
||||
let Inst{4-0} = rs2;
|
||||
let Inst{12-11} = cc;
|
||||
let Inst{13} = 0;
|
||||
let Inst{17-14} = cond;
|
||||
let Inst{18} = intcc;
|
||||
|
||||
}
|
||||
|
||||
class F4_2<bits<6> op3, dag outs, dag ins,
|
||||
string asmstr, list<dag> pattern>
|
||||
: F4<op3, outs, ins, asmstr, pattern> {
|
||||
bit intcc;
|
||||
bits<2> cc;
|
||||
bits<4> cond;
|
||||
bits<11> simm11;
|
||||
|
||||
let Inst{10-0} = simm11;
|
||||
let Inst{12-11} = cc;
|
||||
let Inst{13} = 1;
|
||||
let Inst{17-14} = cond;
|
||||
let Inst{18} = intcc;
|
||||
}
|
||||
|
||||
class F4_3<bits<6> op3, bits<6> opf_low, dag outs, dag ins,
|
||||
string asmstr, list<dag> pattern>
|
||||
: F4<op3, outs, ins, asmstr, pattern> {
|
||||
bits<4> cond;
|
||||
bit intcc;
|
||||
bits<2> opf_cc;
|
||||
bits<5> rs2;
|
||||
|
||||
let Inst{18} = 0;
|
||||
let Inst{17-14} = cond;
|
||||
let Inst{13} = intcc;
|
||||
let Inst{12-11} = opf_cc;
|
||||
let Inst{10-5} = opf_low;
|
||||
let Inst{4-0} = rs2;
|
||||
}
|
||||
|
||||
class F4_4r<bits<6> op3, bits<5> opf_low, bits<3> rcond, dag outs, dag ins,
|
||||
string asmstr, list<dag> pattern>
|
||||
: F4<op3, outs, ins, asmstr, pattern> {
|
||||
bits <5> rs1;
|
||||
bits <5> rs2;
|
||||
let Inst{18-14} = rs1;
|
||||
let Inst{13} = 0; // IsImm
|
||||
let Inst{12-10} = rcond;
|
||||
let Inst{9-5} = opf_low;
|
||||
let Inst{4-0} = rs2;
|
||||
}
|
||||
|
||||
|
||||
class F4_4i<bits<6> op3, bits<3> rcond, dag outs, dag ins,
|
||||
string asmstr, list<dag> pattern>
|
||||
: F4<op3, outs, ins, asmstr, pattern> {
|
||||
bits<5> rs1;
|
||||
bits<10> simm10;
|
||||
let Inst{18-14} = rs1;
|
||||
let Inst{13} = 1; // IsImm
|
||||
let Inst{12-10} = rcond;
|
||||
let Inst{9-0} = simm10;
|
||||
}
|
||||
|
||||
|
||||
class TRAPSP<bits<6> op3Val, bit isimm, dag outs, dag ins, string asmstr,
|
||||
list<dag> pattern>: F3<outs, ins, asmstr, pattern> {
|
||||
|
||||
bits<4> cond;
|
||||
bits<2> cc;
|
||||
|
||||
let op = 0b10;
|
||||
let rd{4} = 0;
|
||||
let rd{3-0} = cond;
|
||||
let op3 = op3Val;
|
||||
let Inst{13} = isimm;
|
||||
let Inst{12-11} = cc;
|
||||
|
||||
}
|
||||
|
||||
class TRAPSPrr<bits<6> op3Val, dag outs, dag ins, string asmstr,
|
||||
list<dag> pattern>: TRAPSP<op3Val, 0, outs, ins, asmstr, pattern> {
|
||||
bits<5> rs2;
|
||||
|
||||
let Inst{10-5} = 0;
|
||||
let Inst{4-0} = rs2;
|
||||
}
|
||||
class TRAPSPri<bits<6> op3Val, dag outs, dag ins, string asmstr,
|
||||
list<dag> pattern>: TRAPSP<op3Val, 1, outs, ins, asmstr, pattern> {
|
||||
bits<8> imm;
|
||||
|
||||
let Inst{10-8} = 0;
|
||||
let Inst{7-0} = imm;
|
||||
}
|
||||
|
||||
// Pseudo-instructions for alternate assembly syntax (never used by codegen).
|
||||
// These are aliases that require C++ handling to convert to the target
|
||||
// instruction, while InstAliases can be handled directly by tblgen.
|
||||
class AsmPseudoInst<dag outs, dag ins, string asm>
|
||||
: InstSP<outs, ins, asm, []> {
|
||||
let isPseudo = 1;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,263 +0,0 @@
|
||||
//===---- Mos6502InstrVIS.td - Visual Instruction Set extensions (VIS) -----===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains instruction formats, definitions and patterns needed for
|
||||
// VIS, VIS II, VIS II instructions on MOS6502.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// VIS Instruction Format.
|
||||
class VISInstFormat<bits<9> opfval, dag outs, dag ins, string asmstr,
|
||||
list<dag> pattern>
|
||||
: F3_3<0b10, 0b110110, opfval, outs, ins, asmstr, pattern>;
|
||||
|
||||
class VISInst<bits<9> opfval, string OpcStr, RegisterClass RC = DFPRegs>
|
||||
: VISInstFormat<opfval,
|
||||
(outs RC:$rd), (ins RC:$rs1, RC:$rs2),
|
||||
!strconcat(OpcStr, " $rs1, $rs2, $rd"), []>;
|
||||
|
||||
// VIS Instruction with integer destination register.
|
||||
class VISInstID<bits<9> opfval, string OpcStr>
|
||||
: VISInstFormat<opfval,
|
||||
(outs I64Regs:$rd), (ins DFPRegs:$rs1, DFPRegs:$rs2),
|
||||
!strconcat(OpcStr, " $rs1, $rs2, $rd"), []>;
|
||||
|
||||
// For VIS Instructions with no operand.
|
||||
let rd = 0, rs1 = 0, rs2 = 0 in
|
||||
class VISInst0<bits<9> opfval, string asmstr>
|
||||
: VISInstFormat<opfval, (outs), (ins), asmstr, []>;
|
||||
|
||||
// For VIS Instructions with only rs1, rd operands.
|
||||
let rs2 = 0 in
|
||||
class VISInst1<bits<9> opfval, string OpcStr, RegisterClass RC = DFPRegs>
|
||||
: VISInstFormat<opfval,
|
||||
(outs RC:$rd), (ins RC:$rs1),
|
||||
!strconcat(OpcStr, " $rs1, $rd"), []>;
|
||||
|
||||
// For VIS Instructions with only rs2, rd operands.
|
||||
let rs1 = 0 in
|
||||
class VISInst2<bits<9> opfval, string OpcStr, RegisterClass RC = DFPRegs>
|
||||
: VISInstFormat<opfval,
|
||||
(outs RC:$rd), (ins RC:$rs2),
|
||||
!strconcat(OpcStr, " $rs2, $rd"), []>;
|
||||
|
||||
// For VIS Instructions with only rd operand.
|
||||
let Constraints = "$rd = $f", rs1 = 0, rs2 = 0 in
|
||||
class VISInstD<bits<9> opfval, string OpcStr, RegisterClass RC = DFPRegs>
|
||||
: VISInstFormat<opfval,
|
||||
(outs RC:$rd), (ins RC:$f),
|
||||
!strconcat(OpcStr, " $rd"), []>;
|
||||
|
||||
// VIS 1 Instructions
|
||||
let Predicates = [HasVIS] in {
|
||||
|
||||
def FPADD16 : VISInst<0b001010000, "fpadd16">;
|
||||
def FPADD16S : VISInst<0b001010001, "fpadd16s">;
|
||||
def FPADD32 : VISInst<0b001010010, "fpadd32">;
|
||||
def FPADD32S : VISInst<0b001010011, "fpadd32s">;
|
||||
def FPSUB16 : VISInst<0b001010100, "fpsub16">;
|
||||
def FPSUB16S : VISInst<0b001010101, "fpsub16S">;
|
||||
def FPSUB32 : VISInst<0b001010110, "fpsub32">;
|
||||
def FPSUB32S : VISInst<0b001010111, "fpsub32S">;
|
||||
|
||||
def FPACK16 : VISInst2<0b000111011, "fpack16">;
|
||||
def FPACK32 : VISInst <0b000111010, "fpack32">;
|
||||
def FPACKFIX : VISInst2<0b000111101, "fpackfix">;
|
||||
def FEXPAND : VISInst2<0b001001101, "fexpand">;
|
||||
def FPMERGE : VISInst <0b001001011, "fpmerge">;
|
||||
|
||||
def FMUL8X16 : VISInst<0b000110001, "fmul8x16">;
|
||||
def FMUL8X16AU : VISInst<0b000110011, "fmul8x16au">;
|
||||
def FMUL8X16AL : VISInst<0b000110101, "fmul8x16al">;
|
||||
def FMUL8SUX16 : VISInst<0b000110110, "fmul8sux16">;
|
||||
def FMUL8ULX16 : VISInst<0b000110111, "fmul8ulx16">;
|
||||
def FMULD8SUX16 : VISInst<0b000111000, "fmuld8sux16">;
|
||||
def FMULD8ULX16 : VISInst<0b000111001, "fmuld8ulx16">;
|
||||
|
||||
def ALIGNADDR : VISInst<0b000011000, "alignaddr", I64Regs>;
|
||||
def ALIGNADDRL : VISInst<0b000011010, "alignaddrl", I64Regs>;
|
||||
def FALIGNADATA : VISInst<0b001001000, "faligndata">;
|
||||
|
||||
def FZERO : VISInstD<0b001100000, "fzero">;
|
||||
def FZEROS : VISInstD<0b001100001, "fzeros", FPRegs>;
|
||||
def FONE : VISInstD<0b001111110, "fone">;
|
||||
def FONES : VISInstD<0b001111111, "fones", FPRegs>;
|
||||
def FSRC1 : VISInst1<0b001110100, "fsrc1">;
|
||||
def FSRC1S : VISInst1<0b001110101, "fsrc1s", FPRegs>;
|
||||
def FSRC2 : VISInst2<0b001111000, "fsrc2">;
|
||||
def FSRC2S : VISInst2<0b001111001, "fsrc2s", FPRegs>;
|
||||
def FNOT1 : VISInst1<0b001101010, "fnot1">;
|
||||
def FNOT1S : VISInst1<0b001101011, "fnot1s", FPRegs>;
|
||||
def FNOT2 : VISInst2<0b001100110, "fnot2">;
|
||||
def FNOT2S : VISInst2<0b001100111, "fnot2s", FPRegs>;
|
||||
def FOR : VISInst<0b001111100, "for">;
|
||||
def FORS : VISInst<0b001111101, "fors", FPRegs>;
|
||||
def FNOR : VISInst<0b001100010, "fnor">;
|
||||
def FNORS : VISInst<0b001100011, "fnors", FPRegs>;
|
||||
def FAND : VISInst<0b001110000, "fand">;
|
||||
def FANDS : VISInst<0b001110001, "fands", FPRegs>;
|
||||
def FNAND : VISInst<0b001101110, "fnand">;
|
||||
def FNANDS : VISInst<0b001101111, "fnands", FPRegs>;
|
||||
def FXOR : VISInst<0b001101100, "fxor">;
|
||||
def FXORS : VISInst<0b001101101, "fxors", FPRegs>;
|
||||
def FXNOR : VISInst<0b001110010, "fxnor">;
|
||||
def FXNORS : VISInst<0b001110011, "fxnors", FPRegs>;
|
||||
|
||||
def FORNOT1 : VISInst<0b001111010, "fornot1">;
|
||||
def FORNOT1S : VISInst<0b001111011, "fornot1s", FPRegs>;
|
||||
def FORNOT2 : VISInst<0b001110110, "fornot2">;
|
||||
def FORNOT2S : VISInst<0b001110111, "fornot2s", FPRegs>;
|
||||
def FANDNOT1 : VISInst<0b001101000, "fandnot1">;
|
||||
def FANDNOT1S : VISInst<0b001101001, "fandnot1s", FPRegs>;
|
||||
def FANDNOT2 : VISInst<0b001100100, "fandnot2">;
|
||||
def FANDNOT2S : VISInst<0b001100101, "fandnot2s", FPRegs>;
|
||||
|
||||
def FCMPGT16 : VISInstID<0b000101000, "fcmpgt16">;
|
||||
def FCMPGT32 : VISInstID<0b000101100, "fcmpgt32">;
|
||||
def FCMPLE16 : VISInstID<0b000100000, "fcmple16">;
|
||||
def FCMPLE32 : VISInstID<0b000100100, "fcmple32">;
|
||||
def FCMPNE16 : VISInstID<0b000100010, "fcmpne16">;
|
||||
def FCMPNE32 : VISInstID<0b000100110, "fcmpne32">;
|
||||
def FCMPEQ16 : VISInstID<0b000101010, "fcmpeq16">;
|
||||
def FCMPEQ32 : VISInstID<0b000101110, "fcmpeq32">;
|
||||
|
||||
|
||||
def EDGE8 : VISInst<0b000000000, "edge8", I64Regs>;
|
||||
def EDGE8L : VISInst<0b000000010, "edge8l", I64Regs>;
|
||||
def EDGE16 : VISInst<0b000000100, "edge16", I64Regs>;
|
||||
def EDGE16L : VISInst<0b000000110, "edge16l", I64Regs>;
|
||||
def EDGE32 : VISInst<0b000001000, "edge32", I64Regs>;
|
||||
def EDGE32L : VISInst<0b000001010, "edge32l", I64Regs>;
|
||||
|
||||
def PDIST : VISInst<0b000111110, "pdist">;
|
||||
|
||||
def ARRAY8 : VISInst<0b000010000, "array8", I64Regs>;
|
||||
def ARRAY16 : VISInst<0b000010010, "array16", I64Regs>;
|
||||
def ARRAY32 : VISInst<0b000010100, "array32", I64Regs>;
|
||||
|
||||
def SHUTDOWN : VISInst0<0b010000000, "shutdown">;
|
||||
|
||||
} // Predicates = [HasVIS]
|
||||
|
||||
|
||||
// VIS 2 Instructions.
|
||||
let Predicates = [HasVIS2] in {
|
||||
|
||||
def BMASK : VISInst<0b000011001, "bmask", I64Regs>;
|
||||
def BSHUFFLE : VISInst<0b000011100, "bshuffle">;
|
||||
|
||||
def SIAM : VISInst0<0b010000001, "siam">;
|
||||
|
||||
def EDGE8N : VISInst<0b000000001, "edge8n", I64Regs>;
|
||||
def EDGE8LN : VISInst<0b000000011, "edge8ln", I64Regs>;
|
||||
def EDGE16N : VISInst<0b000000101, "edge16n", I64Regs>;
|
||||
def EDGE16LN : VISInst<0b000000111, "edge16ln", I64Regs>;
|
||||
def EDGE32N : VISInst<0b000001001, "edge32n", I64Regs>;
|
||||
def EDGE32LN : VISInst<0b000001011, "edge32ln", I64Regs>;
|
||||
} // Predicates = [HasVIS2]
|
||||
|
||||
|
||||
// VIS 3 Instructions.
|
||||
let Predicates = [HasVIS3] in {
|
||||
|
||||
let Uses = [ICC] in
|
||||
def ADDXC : VISInst<0b000010001, "addxc", I64Regs>;
|
||||
|
||||
let Defs = [ICC], Uses = [ICC] in
|
||||
def ADDXCCC : VISInst<0b000010011, "addxccc", I64Regs>;
|
||||
|
||||
let rd = 0, rs1 = 0 in {
|
||||
def CMASK8 : VISInstFormat<0b000011011, (outs), (ins I64Regs:$rs2),
|
||||
"cmask8 $rs2", []>;
|
||||
def CMASK16 : VISInstFormat<0b000011101, (outs), (ins I64Regs:$rs2),
|
||||
"cmask16 $rs2", []>;
|
||||
def CMASK32 : VISInstFormat<0b000011111, (outs), (ins I64Regs:$rs2),
|
||||
"cmask32 $rs2", []>;
|
||||
|
||||
}
|
||||
|
||||
def FCHKSM16 : VISInst<0b001000100, "fchksm16">;
|
||||
|
||||
def FHADDS : F3_3<0b10, 0b110100, 0b001100001,
|
||||
(outs DFPRegs:$rd), (ins DFPRegs:$rs1, DFPRegs:$rs2),
|
||||
"fhadds $rs1, $rs2, $rd", []>;
|
||||
def FHADDD : F3_3<0b10, 0b110100, 0b001100010,
|
||||
(outs DFPRegs:$rd), (ins DFPRegs:$rs1, DFPRegs:$rs2),
|
||||
"fhaddd $rs1, $rs2, $rd", []>;
|
||||
def FHSUBS : F3_3<0b10, 0b110100, 0b001100101,
|
||||
(outs DFPRegs:$rd), (ins DFPRegs:$rs1, DFPRegs:$rs2),
|
||||
"fhsubs $rs1, $rs2, $rd", []>;
|
||||
def FHSUBD : F3_3<0b10, 0b110100, 0b001100110,
|
||||
(outs DFPRegs:$rd), (ins DFPRegs:$rs1, DFPRegs:$rs2),
|
||||
"fhsubd $rs1, $rs2, $rd", []>;
|
||||
def FLCMPS : VISInstFormat<0b101010001, (outs FCCRegs:$rd),
|
||||
(ins DFPRegs:$rs1, DFPRegs:$rs2),
|
||||
"flcmps $rd, $rs1, $rs2", []>;
|
||||
def FLCMPD : VISInstFormat<0b101010010, (outs FCCRegs:$rd),
|
||||
(ins DFPRegs:$rs1, DFPRegs:$rs2),
|
||||
"flcmpd $rd, $rs1, $rs2", []>;
|
||||
|
||||
def FMEAN16 : VISInst<0b001000000, "fmean16">;
|
||||
|
||||
def FNADDS : F3_3<0b10, 0b110100, 0b001010001,
|
||||
(outs DFPRegs:$rd), (ins DFPRegs:$rs1, DFPRegs:$rs2),
|
||||
"fnadds $rs1, $rs2, $rd", []>;
|
||||
def FNADDD : F3_3<0b10, 0b110100, 0b001010010,
|
||||
(outs DFPRegs:$rd), (ins DFPRegs:$rs1, DFPRegs:$rs2),
|
||||
"fnaddd $rs1, $rs2, $rd", []>;
|
||||
def FNHADDS : F3_3<0b10, 0b110100, 0b001110001,
|
||||
(outs DFPRegs:$rd), (ins DFPRegs:$rs1, DFPRegs:$rs2),
|
||||
"fnhadds $rs1, $rs2, $rd", []>;
|
||||
def FNHADDD : F3_3<0b10, 0b110100, 0b001110010,
|
||||
(outs DFPRegs:$rd), (ins DFPRegs:$rs1, DFPRegs:$rs2),
|
||||
"fnhaddd $rs1, $rs2, $rd", []>;
|
||||
|
||||
def FNMULS : F3_3<0b10, 0b110100, 0b001011001,
|
||||
(outs DFPRegs:$rd), (ins DFPRegs:$rs1, DFPRegs:$rs2),
|
||||
"fnhadds $rs1, $rs2, $rd", []>;
|
||||
def FNMULD : F3_3<0b10, 0b110100, 0b001011010,
|
||||
(outs DFPRegs:$rd), (ins DFPRegs:$rs1, DFPRegs:$rs2),
|
||||
"fnhaddd $rs1, $rs2, $rd", []>;
|
||||
def FNSMULD : F3_3<0b10, 0b110100, 0b001111001,
|
||||
(outs DFPRegs:$rd), (ins DFPRegs:$rs1, DFPRegs:$rs2),
|
||||
"fnhadds $rs1, $rs2, $rd", []>;
|
||||
|
||||
def FPADD64 : VISInst<0b001000010, "fpadd64">;
|
||||
|
||||
def FSLL16 : VISInst<0b000100001, "fsll16">;
|
||||
def FSRL16 : VISInst<0b000100011, "fsrl16">;
|
||||
def FSLL32 : VISInst<0b000100101, "fsll32">;
|
||||
def FSRL32 : VISInst<0b000100111, "fsrl32">;
|
||||
def FSLAS16 : VISInst<0b000101001, "fslas16">;
|
||||
def FSRA16 : VISInst<0b000101011, "fsra16">;
|
||||
def FSLAS32 : VISInst<0b000101101, "fslas32">;
|
||||
def FSRA32 : VISInst<0b000101111, "fsra32">;
|
||||
|
||||
let rs1 = 0 in
|
||||
def LZCNT : VISInstFormat<0b000010111, (outs I64Regs:$rd),
|
||||
(ins I64Regs:$rs2), "lzcnt $rs2, $rd", []>;
|
||||
|
||||
let rs1 = 0 in {
|
||||
def MOVSTOSW : VISInstFormat<0b100010011, (outs I64Regs:$rd),
|
||||
(ins DFPRegs:$rs2), "movstosw $rs2, $rd", []>;
|
||||
def MOVSTOUW : VISInstFormat<0b100010001, (outs I64Regs:$rd),
|
||||
(ins DFPRegs:$rs2), "movstouw $rs2, $rd", []>;
|
||||
def MOVDTOX : VISInstFormat<0b100010000, (outs I64Regs:$rd),
|
||||
(ins DFPRegs:$rs2), "movdtox $rs2, $rd", []>;
|
||||
def MOVWTOS : VISInstFormat<0b100011001, (outs DFPRegs:$rd),
|
||||
(ins I64Regs:$rs2), "movdtox $rs2, $rd", []>;
|
||||
def MOVXTOD : VISInstFormat<0b100011000, (outs DFPRegs:$rd),
|
||||
(ins I64Regs:$rs2), "movdtox $rs2, $rd", []>;
|
||||
}
|
||||
|
||||
def PDISTN : VISInst<0b000111111, "pdistn">;
|
||||
|
||||
def UMULXHI : VISInst<0b000010110, "umulxhi", I64Regs>;
|
||||
def XMULX : VISInst<0b100010101, "xmulx", I64Regs>;
|
||||
def XMULXHI : VISInst<0b100010111, "xmulxhi", I64Regs>;
|
||||
} // Predicates = [IsVIS3]
|
@ -1,4 +1,4 @@
|
||||
//===-- Mos6502RegisterInfo.cpp - MOS6502 Register Information ----------------===//
|
||||
//===-- Mos6502RegisterInfo.cpp - MOS6502 Register Information ------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
@ -30,184 +30,4 @@ using namespace llvm;
|
||||
#define GET_REGINFO_TARGET_DESC
|
||||
#include "Mos6502GenRegisterInfo.inc"
|
||||
|
||||
static cl::opt<bool>
|
||||
ReserveAppRegisters("mos6502-reserve-app-registers", cl::Hidden, cl::init(false),
|
||||
cl::desc("Reserve application registers (%g2-%g4)"));
|
||||
|
||||
Mos6502RegisterInfo::Mos6502RegisterInfo() : Mos6502GenRegisterInfo(M6502::O7) {}
|
||||
|
||||
const MCPhysReg*
|
||||
Mos6502RegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
|
||||
return CSR_SaveList;
|
||||
}
|
||||
|
||||
const uint32_t *
|
||||
Mos6502RegisterInfo::getCallPreservedMask(const MachineFunction &MF,
|
||||
CallingConv::ID CC) const {
|
||||
return CSR_RegMask;
|
||||
}
|
||||
|
||||
const uint32_t*
|
||||
Mos6502RegisterInfo::getRTCallPreservedMask(CallingConv::ID CC) const {
|
||||
return RTCSR_RegMask;
|
||||
}
|
||||
|
||||
BitVector Mos6502RegisterInfo::getReservedRegs(const MachineFunction &MF) const {
|
||||
BitVector Reserved(getNumRegs());
|
||||
const Mos6502Subtarget &Subtarget = MF.getSubtarget<Mos6502Subtarget>();
|
||||
// FIXME: G1 reserved for now for large imm generation by frame code.
|
||||
Reserved.set(M6502::G1);
|
||||
|
||||
// G1-G4 can be used in applications.
|
||||
if (ReserveAppRegisters) {
|
||||
Reserved.set(M6502::G2);
|
||||
Reserved.set(M6502::G3);
|
||||
Reserved.set(M6502::G4);
|
||||
}
|
||||
// G5 is not reserved in 64 bit mode.
|
||||
if (!Subtarget.is64Bit())
|
||||
Reserved.set(M6502::G5);
|
||||
|
||||
Reserved.set(M6502::O6);
|
||||
Reserved.set(M6502::I6);
|
||||
Reserved.set(M6502::I7);
|
||||
Reserved.set(M6502::G0);
|
||||
Reserved.set(M6502::G6);
|
||||
Reserved.set(M6502::G7);
|
||||
|
||||
// Unaliased double registers are not available in non-V9 targets.
|
||||
if (!Subtarget.isV9()) {
|
||||
for (unsigned n = 0; n != 16; ++n) {
|
||||
for (MCRegAliasIterator AI(M6502::D16 + n, this, true); AI.isValid(); ++AI)
|
||||
Reserved.set(*AI);
|
||||
}
|
||||
}
|
||||
|
||||
return Reserved;
|
||||
}
|
||||
|
||||
const TargetRegisterClass*
|
||||
Mos6502RegisterInfo::getPointerRegClass(const MachineFunction &MF,
|
||||
unsigned Kind) const {
|
||||
const Mos6502Subtarget &Subtarget = MF.getSubtarget<Mos6502Subtarget>();
|
||||
return Subtarget.is64Bit() ? &M6502::I64RegsRegClass : &M6502::IntRegsRegClass;
|
||||
}
|
||||
|
||||
static void replaceFI(MachineFunction &MF,
|
||||
MachineBasicBlock::iterator II,
|
||||
MachineInstr &MI,
|
||||
DebugLoc dl,
|
||||
unsigned FIOperandNum, int Offset,
|
||||
unsigned FramePtr)
|
||||
{
|
||||
// Replace frame index with a frame pointer reference.
|
||||
if (Offset >= -4096 && Offset <= 4095) {
|
||||
// If the offset is small enough to fit in the immediate field, directly
|
||||
// encode it.
|
||||
MI.getOperand(FIOperandNum).ChangeToRegister(FramePtr, false);
|
||||
MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset);
|
||||
return;
|
||||
}
|
||||
|
||||
const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();
|
||||
|
||||
// FIXME: it would be better to scavenge a register here instead of
|
||||
// reserving G1 all of the time.
|
||||
if (Offset >= 0) {
|
||||
// Emit nonnegaive immediates with sethi + or.
|
||||
// sethi %hi(Offset), %g1
|
||||
// add %g1, %fp, %g1
|
||||
// Insert G1+%lo(offset) into the user.
|
||||
BuildMI(*MI.getParent(), II, dl, TII.get(M6502::SETHIi), M6502::G1)
|
||||
.addImm(HI22(Offset));
|
||||
|
||||
|
||||
// Emit G1 = G1 + I6
|
||||
BuildMI(*MI.getParent(), II, dl, TII.get(M6502::ADDrr), M6502::G1).addReg(M6502::G1)
|
||||
.addReg(FramePtr);
|
||||
// Insert: G1+%lo(offset) into the user.
|
||||
MI.getOperand(FIOperandNum).ChangeToRegister(M6502::G1, false);
|
||||
MI.getOperand(FIOperandNum + 1).ChangeToImmediate(LO10(Offset));
|
||||
return;
|
||||
}
|
||||
|
||||
// Emit Negative numbers with sethi + xor
|
||||
// sethi %hix(Offset), %g1
|
||||
// xor %g1, %lox(offset), %g1
|
||||
// add %g1, %fp, %g1
|
||||
// Insert: G1 + 0 into the user.
|
||||
BuildMI(*MI.getParent(), II, dl, TII.get(M6502::SETHIi), M6502::G1)
|
||||
.addImm(HIX22(Offset));
|
||||
BuildMI(*MI.getParent(), II, dl, TII.get(M6502::XORri), M6502::G1)
|
||||
.addReg(M6502::G1).addImm(LOX10(Offset));
|
||||
|
||||
BuildMI(*MI.getParent(), II, dl, TII.get(M6502::ADDrr), M6502::G1).addReg(M6502::G1)
|
||||
.addReg(FramePtr);
|
||||
// Insert: G1+%lo(offset) into the user.
|
||||
MI.getOperand(FIOperandNum).ChangeToRegister(M6502::G1, false);
|
||||
MI.getOperand(FIOperandNum + 1).ChangeToImmediate(0);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Mos6502RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
|
||||
int SPAdj, unsigned FIOperandNum,
|
||||
RegScavenger *RS) const {
|
||||
assert(SPAdj == 0 && "Unexpected");
|
||||
|
||||
MachineInstr &MI = *II;
|
||||
DebugLoc dl = MI.getDebugLoc();
|
||||
int FrameIndex = MI.getOperand(FIOperandNum).getIndex();
|
||||
|
||||
// Addressable stack objects are accessed using neg. offsets from %fp
|
||||
MachineFunction &MF = *MI.getParent()->getParent();
|
||||
const Mos6502Subtarget &Subtarget = MF.getSubtarget<Mos6502Subtarget>();
|
||||
int64_t Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex) +
|
||||
MI.getOperand(FIOperandNum + 1).getImm() +
|
||||
Subtarget.getStackPointerBias();
|
||||
Mos6502MachineFunctionInfo *FuncInfo = MF.getInfo<Mos6502MachineFunctionInfo>();
|
||||
unsigned FramePtr = M6502::I6;
|
||||
if (FuncInfo->isLeafProc()) {
|
||||
// Use %sp and adjust offset if needed.
|
||||
FramePtr = M6502::O6;
|
||||
int stackSize = MF.getFrameInfo()->getStackSize();
|
||||
Offset += (stackSize) ? Subtarget.getAdjustedFrameSize(stackSize) : 0 ;
|
||||
}
|
||||
|
||||
if (!Subtarget.isV9() || !Subtarget.hasHardQuad()) {
|
||||
if (MI.getOpcode() == M6502::STQFri) {
|
||||
const TargetInstrInfo &TII = *Subtarget.getInstrInfo();
|
||||
unsigned SrcReg = MI.getOperand(2).getReg();
|
||||
unsigned SrcEvenReg = getSubReg(SrcReg, M6502::sub_even64);
|
||||
unsigned SrcOddReg = getSubReg(SrcReg, M6502::sub_odd64);
|
||||
MachineInstr *StMI =
|
||||
BuildMI(*MI.getParent(), II, dl, TII.get(M6502::STDFri))
|
||||
.addReg(FramePtr).addImm(0).addReg(SrcEvenReg);
|
||||
replaceFI(MF, II, *StMI, dl, 0, Offset, FramePtr);
|
||||
MI.setDesc(TII.get(M6502::STDFri));
|
||||
MI.getOperand(2).setReg(SrcOddReg);
|
||||
Offset += 8;
|
||||
} else if (MI.getOpcode() == M6502::LDQFri) {
|
||||
const TargetInstrInfo &TII = *Subtarget.getInstrInfo();
|
||||
unsigned DestReg = MI.getOperand(0).getReg();
|
||||
unsigned DestEvenReg = getSubReg(DestReg, M6502::sub_even64);
|
||||
unsigned DestOddReg = getSubReg(DestReg, M6502::sub_odd64);
|
||||
MachineInstr *StMI =
|
||||
BuildMI(*MI.getParent(), II, dl, TII.get(M6502::LDDFri), DestEvenReg)
|
||||
.addReg(FramePtr).addImm(0);
|
||||
replaceFI(MF, II, *StMI, dl, 1, Offset, FramePtr);
|
||||
|
||||
MI.setDesc(TII.get(M6502::LDDFri));
|
||||
MI.getOperand(0).setReg(DestOddReg);
|
||||
Offset += 8;
|
||||
}
|
||||
}
|
||||
|
||||
replaceFI(MF, II, MI, dl, FIOperandNum, Offset, FramePtr);
|
||||
|
||||
}
|
||||
|
||||
unsigned Mos6502RegisterInfo::getFrameRegister(const MachineFunction &MF) const {
|
||||
return M6502::I6;
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
//===-- Mos6502RegisterInfo.h - Mos6502 Register Information Impl ---*- C++ -*-===//
|
||||
//=== Mos6502RegisterInfo.h - Mos6502 Register Information Impl -*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
@ -22,28 +22,6 @@
|
||||
namespace llvm {
|
||||
struct Mos6502RegisterInfo : public Mos6502GenRegisterInfo {
|
||||
Mos6502RegisterInfo();
|
||||
|
||||
/// Code Generation virtual methods...
|
||||
const MCPhysReg *getCalleeSavedRegs(const MachineFunction *MF) const override;
|
||||
const uint32_t *getCallPreservedMask(const MachineFunction &MF,
|
||||
CallingConv::ID CC) const override;
|
||||
|
||||
const uint32_t* getRTCallPreservedMask(CallingConv::ID CC) const;
|
||||
|
||||
BitVector getReservedRegs(const MachineFunction &MF) const override;
|
||||
|
||||
const TargetRegisterClass *getPointerRegClass(const MachineFunction &MF,
|
||||
unsigned Kind) const override;
|
||||
|
||||
void eliminateFrameIndex(MachineBasicBlock::iterator II,
|
||||
int SPAdj, unsigned FIOperandNum,
|
||||
RegScavenger *RS = nullptr) const override;
|
||||
|
||||
void processFunctionBeforeFrameFinalized(MachineFunction &MF,
|
||||
RegScavenger *RS = nullptr) const;
|
||||
|
||||
// Debug information queries.
|
||||
unsigned getFrameRegister(const MachineFunction &MF) const override;
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
@ -1,4 +1,4 @@
|
||||
//===-- Mos6502RegisterInfo.td - Mos6502 Register defs ---------*- tablegen -*-===//
|
||||
//===-- Mos6502RegisterInfo.td - Mos6502 Register defs -----*- tablegen -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
@ -11,244 +11,35 @@
|
||||
// Declarations that describe the Mos6502 register file
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
class Mos6502Reg<bits<16> Enc, string n> : Register<n> {
|
||||
class Mos6502Reg<string n, bits<16> Enc> : Register<n> {
|
||||
let HWEncoding = Enc;
|
||||
let Namespace = "M6502";
|
||||
}
|
||||
|
||||
class Mos6502CtrlReg<bits<16> Enc, string n>: Register<n> {
|
||||
let HWEncoding = Enc;
|
||||
let Namespace = "M6502";
|
||||
}
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Register definitions
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
let Namespace = "M6502" in {
|
||||
def sub_even : SubRegIndex<32>;
|
||||
def sub_odd : SubRegIndex<32, 32>;
|
||||
def sub_even64 : SubRegIndex<64>;
|
||||
def sub_odd64 : SubRegIndex<64, 64>;
|
||||
}
|
||||
def A : Mos6502Reg<"a", 0>;
|
||||
def X : Mos6502Reg<"x", 1>;
|
||||
def Y : Mos6502Reg<"y", 2>;
|
||||
|
||||
// Registers are identified with 5-bit ID numbers.
|
||||
// Ri - 32-bit integer registers
|
||||
class Ri<bits<16> Enc, string n> : Mos6502Reg<Enc, n>;
|
||||
def SP : Mos6502Reg<"sp", 3>;
|
||||
def PC : Mos6502Reg<"pc", 4>;
|
||||
|
||||
// Rf - 32-bit floating-point registers
|
||||
class Rf<bits<16> Enc, string n> : Mos6502Reg<Enc, n>;
|
||||
def SREG : Mos6502Reg<"sreg", 5>;
|
||||
|
||||
// Rd - Slots in the FP register file for 64-bit floating-point values.
|
||||
class Rd<bits<16> Enc, string n, list<Register> subregs> : Mos6502Reg<Enc, n> {
|
||||
let SubRegs = subregs;
|
||||
let SubRegIndices = [sub_even, sub_odd];
|
||||
let CoveredBySubRegs = 1;
|
||||
}
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Register Class definitions
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Rq - Slots in the FP register file for 128-bit floating-point values.
|
||||
class Rq<bits<16> Enc, string n, list<Register> subregs> : Mos6502Reg<Enc, n> {
|
||||
let SubRegs = subregs;
|
||||
let SubRegIndices = [sub_even64, sub_odd64];
|
||||
let CoveredBySubRegs = 1;
|
||||
}
|
||||
def GPR : RegisterClass<"M6502", [i8], 8, (add A, X, Y)>;
|
||||
|
||||
// Control Registers
|
||||
def ICC : Mos6502CtrlReg<0, "ICC">; // This represents icc and xcc in 64-bit code.
|
||||
foreach I = 0-3 in
|
||||
def FCC#I : Mos6502CtrlReg<I, "FCC"#I>;
|
||||
def AR : RegisterClass<"M6502", [i8], 8, (add A)>;
|
||||
def XR : RegisterClass<"M6502", [i8], 8, (add X)>;
|
||||
def YR : RegisterClass<"M6502", [i8], 8, (add Y)>;
|
||||
|
||||
// Y register
|
||||
def Y : Mos6502CtrlReg<0, "Y">, DwarfRegNum<[64]>;
|
||||
// Ancillary state registers (implementation defined)
|
||||
def ASR1 : Mos6502CtrlReg<1, "ASR1">;
|
||||
def ASR2 : Mos6502CtrlReg<2, "ASR2">;
|
||||
def ASR3 : Mos6502CtrlReg<3, "ASR3">;
|
||||
def ASR4 : Mos6502CtrlReg<4, "ASR4">;
|
||||
def ASR5 : Mos6502CtrlReg<5, "ASR5">;
|
||||
def ASR6 : Mos6502CtrlReg<6, "ASR6">;
|
||||
def ASR7 : Mos6502CtrlReg<7, "ASR7">;
|
||||
def ASR8 : Mos6502CtrlReg<8, "ASR8">;
|
||||
def ASR9 : Mos6502CtrlReg<9, "ASR9">;
|
||||
def ASR10 : Mos6502CtrlReg<10, "ASR10">;
|
||||
def ASR11 : Mos6502CtrlReg<11, "ASR11">;
|
||||
def ASR12 : Mos6502CtrlReg<12, "ASR12">;
|
||||
def ASR13 : Mos6502CtrlReg<13, "ASR13">;
|
||||
def ASR14 : Mos6502CtrlReg<14, "ASR14">;
|
||||
def ASR15 : Mos6502CtrlReg<15, "ASR15">;
|
||||
def ASR16 : Mos6502CtrlReg<16, "ASR16">;
|
||||
def ASR17 : Mos6502CtrlReg<17, "ASR17">;
|
||||
def ASR18 : Mos6502CtrlReg<18, "ASR18">;
|
||||
def ASR19 : Mos6502CtrlReg<19, "ASR19">;
|
||||
def ASR20 : Mos6502CtrlReg<20, "ASR20">;
|
||||
def ASR21 : Mos6502CtrlReg<21, "ASR21">;
|
||||
def ASR22 : Mos6502CtrlReg<22, "ASR22">;
|
||||
def ASR23 : Mos6502CtrlReg<23, "ASR23">;
|
||||
def ASR24 : Mos6502CtrlReg<24, "ASR24">;
|
||||
def ASR25 : Mos6502CtrlReg<25, "ASR25">;
|
||||
def ASR26 : Mos6502CtrlReg<26, "ASR26">;
|
||||
def ASR27 : Mos6502CtrlReg<27, "ASR27">;
|
||||
def ASR28 : Mos6502CtrlReg<28, "ASR28">;
|
||||
def ASR29 : Mos6502CtrlReg<29, "ASR29">;
|
||||
def ASR30 : Mos6502CtrlReg<30, "ASR30">;
|
||||
def ASR31 : Mos6502CtrlReg<31, "ASR31">;
|
||||
|
||||
// Note that PSR, WIM, and TBR don't exist on the Mos6502V9, only the V8.
|
||||
def PSR : Mos6502CtrlReg<0, "PSR">;
|
||||
def WIM : Mos6502CtrlReg<0, "WIM">;
|
||||
def TBR : Mos6502CtrlReg<0, "TBR">;
|
||||
|
||||
// Integer registers
|
||||
def G0 : Ri< 0, "G0">, DwarfRegNum<[0]>;
|
||||
def G1 : Ri< 1, "G1">, DwarfRegNum<[1]>;
|
||||
def G2 : Ri< 2, "G2">, DwarfRegNum<[2]>;
|
||||
def G3 : Ri< 3, "G3">, DwarfRegNum<[3]>;
|
||||
def G4 : Ri< 4, "G4">, DwarfRegNum<[4]>;
|
||||
def G5 : Ri< 5, "G5">, DwarfRegNum<[5]>;
|
||||
def G6 : Ri< 6, "G6">, DwarfRegNum<[6]>;
|
||||
def G7 : Ri< 7, "G7">, DwarfRegNum<[7]>;
|
||||
def O0 : Ri< 8, "O0">, DwarfRegNum<[8]>;
|
||||
def O1 : Ri< 9, "O1">, DwarfRegNum<[9]>;
|
||||
def O2 : Ri<10, "O2">, DwarfRegNum<[10]>;
|
||||
def O3 : Ri<11, "O3">, DwarfRegNum<[11]>;
|
||||
def O4 : Ri<12, "O4">, DwarfRegNum<[12]>;
|
||||
def O5 : Ri<13, "O5">, DwarfRegNum<[13]>;
|
||||
def O6 : Ri<14, "SP">, DwarfRegNum<[14]>;
|
||||
def O7 : Ri<15, "O7">, DwarfRegNum<[15]>;
|
||||
def L0 : Ri<16, "L0">, DwarfRegNum<[16]>;
|
||||
def L1 : Ri<17, "L1">, DwarfRegNum<[17]>;
|
||||
def L2 : Ri<18, "L2">, DwarfRegNum<[18]>;
|
||||
def L3 : Ri<19, "L3">, DwarfRegNum<[19]>;
|
||||
def L4 : Ri<20, "L4">, DwarfRegNum<[20]>;
|
||||
def L5 : Ri<21, "L5">, DwarfRegNum<[21]>;
|
||||
def L6 : Ri<22, "L6">, DwarfRegNum<[22]>;
|
||||
def L7 : Ri<23, "L7">, DwarfRegNum<[23]>;
|
||||
def I0 : Ri<24, "I0">, DwarfRegNum<[24]>;
|
||||
def I1 : Ri<25, "I1">, DwarfRegNum<[25]>;
|
||||
def I2 : Ri<26, "I2">, DwarfRegNum<[26]>;
|
||||
def I3 : Ri<27, "I3">, DwarfRegNum<[27]>;
|
||||
def I4 : Ri<28, "I4">, DwarfRegNum<[28]>;
|
||||
def I5 : Ri<29, "I5">, DwarfRegNum<[29]>;
|
||||
def I6 : Ri<30, "FP">, DwarfRegNum<[30]>;
|
||||
def I7 : Ri<31, "I7">, DwarfRegNum<[31]>;
|
||||
|
||||
// Floating-point registers
|
||||
def F0 : Rf< 0, "F0">, DwarfRegNum<[32]>;
|
||||
def F1 : Rf< 1, "F1">, DwarfRegNum<[33]>;
|
||||
def F2 : Rf< 2, "F2">, DwarfRegNum<[34]>;
|
||||
def F3 : Rf< 3, "F3">, DwarfRegNum<[35]>;
|
||||
def F4 : Rf< 4, "F4">, DwarfRegNum<[36]>;
|
||||
def F5 : Rf< 5, "F5">, DwarfRegNum<[37]>;
|
||||
def F6 : Rf< 6, "F6">, DwarfRegNum<[38]>;
|
||||
def F7 : Rf< 7, "F7">, DwarfRegNum<[39]>;
|
||||
def F8 : Rf< 8, "F8">, DwarfRegNum<[40]>;
|
||||
def F9 : Rf< 9, "F9">, DwarfRegNum<[41]>;
|
||||
def F10 : Rf<10, "F10">, DwarfRegNum<[42]>;
|
||||
def F11 : Rf<11, "F11">, DwarfRegNum<[43]>;
|
||||
def F12 : Rf<12, "F12">, DwarfRegNum<[44]>;
|
||||
def F13 : Rf<13, "F13">, DwarfRegNum<[45]>;
|
||||
def F14 : Rf<14, "F14">, DwarfRegNum<[46]>;
|
||||
def F15 : Rf<15, "F15">, DwarfRegNum<[47]>;
|
||||
def F16 : Rf<16, "F16">, DwarfRegNum<[48]>;
|
||||
def F17 : Rf<17, "F17">, DwarfRegNum<[49]>;
|
||||
def F18 : Rf<18, "F18">, DwarfRegNum<[50]>;
|
||||
def F19 : Rf<19, "F19">, DwarfRegNum<[51]>;
|
||||
def F20 : Rf<20, "F20">, DwarfRegNum<[52]>;
|
||||
def F21 : Rf<21, "F21">, DwarfRegNum<[53]>;
|
||||
def F22 : Rf<22, "F22">, DwarfRegNum<[54]>;
|
||||
def F23 : Rf<23, "F23">, DwarfRegNum<[55]>;
|
||||
def F24 : Rf<24, "F24">, DwarfRegNum<[56]>;
|
||||
def F25 : Rf<25, "F25">, DwarfRegNum<[57]>;
|
||||
def F26 : Rf<26, "F26">, DwarfRegNum<[58]>;
|
||||
def F27 : Rf<27, "F27">, DwarfRegNum<[59]>;
|
||||
def F28 : Rf<28, "F28">, DwarfRegNum<[60]>;
|
||||
def F29 : Rf<29, "F29">, DwarfRegNum<[61]>;
|
||||
def F30 : Rf<30, "F30">, DwarfRegNum<[62]>;
|
||||
def F31 : Rf<31, "F31">, DwarfRegNum<[63]>;
|
||||
|
||||
// Aliases of the F* registers used to hold 64-bit fp values (doubles)
|
||||
def D0 : Rd< 0, "F0", [F0, F1]>, DwarfRegNum<[72]>;
|
||||
def D1 : Rd< 2, "F2", [F2, F3]>, DwarfRegNum<[73]>;
|
||||
def D2 : Rd< 4, "F4", [F4, F5]>, DwarfRegNum<[74]>;
|
||||
def D3 : Rd< 6, "F6", [F6, F7]>, DwarfRegNum<[75]>;
|
||||
def D4 : Rd< 8, "F8", [F8, F9]>, DwarfRegNum<[76]>;
|
||||
def D5 : Rd<10, "F10", [F10, F11]>, DwarfRegNum<[77]>;
|
||||
def D6 : Rd<12, "F12", [F12, F13]>, DwarfRegNum<[78]>;
|
||||
def D7 : Rd<14, "F14", [F14, F15]>, DwarfRegNum<[79]>;
|
||||
def D8 : Rd<16, "F16", [F16, F17]>, DwarfRegNum<[80]>;
|
||||
def D9 : Rd<18, "F18", [F18, F19]>, DwarfRegNum<[81]>;
|
||||
def D10 : Rd<20, "F20", [F20, F21]>, DwarfRegNum<[82]>;
|
||||
def D11 : Rd<22, "F22", [F22, F23]>, DwarfRegNum<[83]>;
|
||||
def D12 : Rd<24, "F24", [F24, F25]>, DwarfRegNum<[84]>;
|
||||
def D13 : Rd<26, "F26", [F26, F27]>, DwarfRegNum<[85]>;
|
||||
def D14 : Rd<28, "F28", [F28, F29]>, DwarfRegNum<[86]>;
|
||||
def D15 : Rd<30, "F30", [F30, F31]>, DwarfRegNum<[87]>;
|
||||
|
||||
// Unaliased double precision floating point registers.
|
||||
// FIXME: Define DwarfRegNum for these registers.
|
||||
def D16 : Mos6502Reg< 1, "F32">;
|
||||
def D17 : Mos6502Reg< 3, "F34">;
|
||||
def D18 : Mos6502Reg< 5, "F36">;
|
||||
def D19 : Mos6502Reg< 7, "F38">;
|
||||
def D20 : Mos6502Reg< 9, "F40">;
|
||||
def D21 : Mos6502Reg<11, "F42">;
|
||||
def D22 : Mos6502Reg<13, "F44">;
|
||||
def D23 : Mos6502Reg<15, "F46">;
|
||||
def D24 : Mos6502Reg<17, "F48">;
|
||||
def D25 : Mos6502Reg<19, "F50">;
|
||||
def D26 : Mos6502Reg<21, "F52">;
|
||||
def D27 : Mos6502Reg<23, "F54">;
|
||||
def D28 : Mos6502Reg<25, "F56">;
|
||||
def D29 : Mos6502Reg<27, "F58">;
|
||||
def D30 : Mos6502Reg<29, "F60">;
|
||||
def D31 : Mos6502Reg<31, "F62">;
|
||||
|
||||
// Aliases of the F* registers used to hold 128-bit for values (long doubles).
|
||||
def Q0 : Rq< 0, "F0", [D0, D1]>;
|
||||
def Q1 : Rq< 4, "F4", [D2, D3]>;
|
||||
def Q2 : Rq< 8, "F8", [D4, D5]>;
|
||||
def Q3 : Rq<12, "F12", [D6, D7]>;
|
||||
def Q4 : Rq<16, "F16", [D8, D9]>;
|
||||
def Q5 : Rq<20, "F20", [D10, D11]>;
|
||||
def Q6 : Rq<24, "F24", [D12, D13]>;
|
||||
def Q7 : Rq<28, "F28", [D14, D15]>;
|
||||
def Q8 : Rq< 1, "F32", [D16, D17]>;
|
||||
def Q9 : Rq< 5, "F36", [D18, D19]>;
|
||||
def Q10 : Rq< 9, "F40", [D20, D21]>;
|
||||
def Q11 : Rq<13, "F44", [D22, D23]>;
|
||||
def Q12 : Rq<17, "F48", [D24, D25]>;
|
||||
def Q13 : Rq<21, "F52", [D26, D27]>;
|
||||
def Q14 : Rq<25, "F56", [D28, D29]>;
|
||||
def Q15 : Rq<29, "F60", [D30, D31]>;
|
||||
|
||||
// Register classes.
|
||||
//
|
||||
// FIXME: the register order should be defined in terms of the preferred
|
||||
// allocation order...
|
||||
//
|
||||
// This register class should not be used to hold i64 values, use the I64Regs
|
||||
// register class for that. The i64 type is included here to allow i64 patterns
|
||||
// using the integer instructions.
|
||||
def IntRegs : RegisterClass<"M6502", [i32, i64], 32,
|
||||
(add (sequence "I%u", 0, 7),
|
||||
(sequence "G%u", 0, 7),
|
||||
(sequence "L%u", 0, 7),
|
||||
(sequence "O%u", 0, 7))>;
|
||||
|
||||
// Register class for 64-bit mode, with a 64-bit spill slot size.
|
||||
// These are the same as the 32-bit registers, so TableGen will consider this
|
||||
// to be a sub-class of IntRegs. That works out because requiring a 64-bit
|
||||
// spill slot is a stricter constraint than only requiring a 32-bit spill slot.
|
||||
def I64Regs : RegisterClass<"M6502", [i64], 64, (add IntRegs)>;
|
||||
|
||||
// Floating point register classes.
|
||||
def FPRegs : RegisterClass<"M6502", [f32], 32, (sequence "F%u", 0, 31)>;
|
||||
|
||||
def DFPRegs : RegisterClass<"M6502", [f64], 64, (sequence "D%u", 0, 31)>;
|
||||
|
||||
def QFPRegs : RegisterClass<"M6502", [f128], 128, (sequence "Q%u", 0, 15)>;
|
||||
|
||||
// Floating point control register classes.
|
||||
def FCCRegs : RegisterClass<"M6502", [i1], 1, (sequence "FCC%u", 0, 3)>;
|
||||
|
||||
// Ancillary state registers
|
||||
def ASRRegs : RegisterClass<"M6502", [i32], 32,
|
||||
(add Y, (sequence "ASR%u", 1, 31))> {
|
||||
def CCR : RegisterClass<"M6502", [i8], 8, (add SREG)> {
|
||||
let CopyCost = -1; // Don't allow copying of status register
|
||||
let isAllocatable = 0;
|
||||
}
|
||||
|
@ -89,6 +89,4 @@ bool Mos6502PassConfig::addInstSelector() {
|
||||
return false;
|
||||
}
|
||||
|
||||
void Mos6502PassConfig::addPreEmitPass(){
|
||||
addPass(createMos6502DelaySlotFillerPass(getMos6502TargetMachine()));
|
||||
}
|
||||
void Mos6502PassConfig::addPreEmitPass(){}
|
||||
|
Loading…
x
Reference in New Issue
Block a user