Let us add some local variables:
int foo() {
int retval = 0x0AB;
int dummy = 0;
return retval;
}
This requires adding some information about accessing memory. I will just postulate that I have memory available from address 1 growing upwards. As anyone that really knows the HP-41 understands, this is a very bad idea. However we are still just showing some basic LLVM principles, not producing actually useful Nut code. I am however excluding the possibility of generating READ 0, as that instruction does not even exist.
Some code snippets:
// Addressing modes.
def ADDR : ComplexPattern<iPTR, 2, "SelectADDR",
[frameindex], []>;
// Address operands
def MEM : Operand {
let MIOperandInfo = (ops RC, i16imm);
let PrintMethod = "printMemOperand";
let DecoderMethod = "decodeMemOperand";
}
...
let mayLoad=1 in {
def READ : HP41MCODEInst<0x078, (outs RC:$r),
(ins MEM:$addr), "READ $addr",
[(set RC:$r, (load ADDR:$addr))]>;
}
let mayStore=1 in {
def WRIT : HP41MCODEInst<0x068, (outs), (ins MEM:$addr,
RC:$r), "WRIT $addr", [(store RC:$r, ADDR:$addr)]>;
}
...
bool
HP41MCODERegisterInfo::eliminateFrameIndex(
MachineBasicBlock::iterator II,
int SPAdj, unsigned FIOperandNum,
RegScavenger *RS) const {
MachineInstr &MI = *II;
int FrameIndex = MI.getOperand(FIOperandNum).getIndex();
MachineFunction &MF = *MI.getParent()->getParent();
const HP41MCODEFrameLowering *TFI = getFrameLowering(MF);
llvm::Register FrameReg;
int Offset;
Offset = TFI->getFrameIndexReference(MF, FrameIndex,
FrameReg).getFixed()/4+1;
MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg,
false);
MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset);
return false;
}
...
void HP41MCODEInstPrinter::printMemOperand(const MCInst *MI,
int opNum,
const MCSubtargetInfo &STI,
raw_ostream &O, const char *Modifier) {
const MCOperand &MO = MI->getOperand(opNum+1);
if (MO.isImm()) {
O << format_decimal((int)MO.getImm(), 1); return; }
assert(MO.isExpr() &&
"Unknown operand kind in printMemOperand");
MO.getExpr()->print(O, &MAI);
}
...
bool HP41MCODEDAGToDAGISel::SelectADDR(SDValue Addr,
SDValue &Base, SDValue &Offset) {
if (FrameIndexSDNode *FIN = dyn_cast(Addr)) {
Base = CurDAG->getTargetFrameIndex(
FIN->getIndex(), TLI->getPointerTy(
CurDAG->getDataLayout()));
Offset = CurDAG->getTargetConstant(0, SDLoc(Addr),
MVT::i32);
return true;
}
return false;
}
Then we end up with:
.file "hello.c"
.text
.globl foo ! -- Begin function foo
.type foo,@function
foo: ! @foo
! %bb.0: ! %entry
LDI S&X HEX: 0AB
WRIT 2
C=0 ALL
WRIT 1
READ 2
RTN
.Lfunc_end0:
.size foo, .Lfunc_end0-foo
! -- End function
.ident "clang version 20.0.0git (https://github.com/llvm/llvm-project.git ea1dfd50bfdfbd75969fd7653bc71c81f2a2350f)"
.section ".note.GNU-stack"
.addrsig