//===-- W65816RegisterInfo.td - W65816 Register defs -------*- tablegen -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===// // Declarations that describe the W65816 register file //===----------------------------------------------------------------------===// class W65816Reg num, string n> : Register { field bits<8> Num = num; let Namespace = "W65816"; let HWEncoding{7-0} = num; let DwarfNumbers = [num]; } //===----------------------------------------------------------------------===// // Registers //===----------------------------------------------------------------------===// // // The 65816 registers are variable-width: A, X and Y are each 8 or 16 bits // wide depending on the M and X bits in the processor status register. For // the skeleton we model each physical register once and create parallel 8-bit // and 16-bit register classes that share the same physical register. A later // pass is responsible for managing REP/SEP transitions and verifying that the // selected width matches the current processor mode. // def A : W65816Reg<0, "a">, DwarfRegNum<[0]>; def X : W65816Reg<1, "x">, DwarfRegNum<[1]>; def Y : W65816Reg<2, "y">, DwarfRegNum<[2]>; def SP : W65816Reg<3, "sp">, DwarfRegNum<[3]>; def DP : W65816Reg<4, "dp">, DwarfRegNum<[4]>; def DBR : W65816Reg<5, "dbr">, DwarfRegNum<[5]>; def PBR : W65816Reg<6, "pbr">, DwarfRegNum<[6]>; def PC : W65816Reg<7, "pc">, DwarfRegNum<[7]>; def P : W65816Reg<8, "p">, DwarfRegNum<[8]>; // Imaginary 16-bit registers backed by direct-page slots $D0..$DE. // The regalloc treats them as physical registers with cheap LDA/STA dp // inter-register moves. This relieves pressure on the single Acc16 // register (A) so greedy regalloc can succeed on functions with // multiple simultaneously-live i16 vregs. Caller-save: callees may // freely overwrite them, so regalloc spills around any call that // might touch them. Their HWEncoding is never emitted (asmprinter // translates IMGn references into LDA/STA dp with the right address). def IMG0 : W65816Reg<16, "img0">, DwarfRegNum<[16]>; def IMG1 : W65816Reg<17, "img1">, DwarfRegNum<[17]>; def IMG2 : W65816Reg<18, "img2">, DwarfRegNum<[18]>; def IMG3 : W65816Reg<19, "img3">, DwarfRegNum<[19]>; def IMG4 : W65816Reg<20, "img4">, DwarfRegNum<[20]>; def IMG5 : W65816Reg<21, "img5">, DwarfRegNum<[21]>; def IMG6 : W65816Reg<22, "img6">, DwarfRegNum<[22]>; def IMG7 : W65816Reg<23, "img7">, DwarfRegNum<[23]>; // DPF0 — pseudo-physreg modeling the i16 storage at DP $F0..$F1. // Used as the carrier for the highest 16 bits of an i64/double // return. JSLpseudo Defs DPF0 so the SDAG combiner / scheduler // can't merge or reorder reads of it across calls; we plumb the // 4th return half via CopyFromReg(DPF0) in LowerCall, which lowers // to `LDA $F0` via copyPhysReg. Never allocated to a vreg — // always a transient bridge from DP[$F0] to A. def DPF0 : W65816Reg<24, "dpf0">, DwarfRegNum<[24]>; //===----------------------------------------------------------------------===// // Register Classes //===----------------------------------------------------------------------===// // // Acc8/Acc16 hold the accumulator A in 8-bit and 16-bit mode respectively. // Idx8/Idx16 hold the index registers X and Y in 8-bit and 16-bit mode. // PtrRegs holds the stack pointer for framing and pointer arithmetic; DP is // reserved and not allocatable. def Acc8 : RegisterClass<"W65816", [i8], 8, (add A)>; def Acc16 : RegisterClass<"W65816", [i16], 16, (add A)>; def Idx8 : RegisterClass<"W65816", [i8], 8, (add X, Y)>; def Idx16 : RegisterClass<"W65816", [i16], 16, (add X, Y)>; // Imaginary i16 registers backed by DP slots $D0..$DE. Vregs in this // class lower to LDA/STA dp on cross-class moves to A (4 cyc each // way). Used by ABridgeViaX (and future regalloc-pressure passes) as // an alternative parking spot to stack spills. Caller-save: a callee // may freely overwrite $D0..$DF, so the allocator must spill IMGn // vregs around any call. def Img16 : RegisterClass<"W65816", [i16], 16, (add IMG0, IMG1, IMG2, IMG3, IMG4, IMG5, IMG6, IMG7)>; // Acc-or-IMG combined class. Vregs that are not constrained to A // (i.e., not the source of an arithmetic op) get widened to this // class pre-RA so greedy regalloc can pick A or any IMGn. Listing // A first so the allocator's default order prefers A; cross-class // moves to/from A are LDA/STA dp via copyPhysReg. def Wide16 : RegisterClass<"W65816", [i16], 16, (add A, IMG0, IMG1, IMG2, IMG3, IMG4, IMG5, IMG6, IMG7)>; def PtrRegs : RegisterClass<"W65816", [i16], 16, (add SP)>; // Single-register class for DPF0, the i64-return high-half carrier. // Not allocatable — only used as a CopyFromReg source in LowerCall; // copyPhysReg lowers DPF0 → A by emitting `LDA $F0`. def DPF0Reg : RegisterClass<"W65816", [i16], 16, (add DPF0)> { let isAllocatable = 0; } // Single-register class for the processor status register, used for condition // code modeling. Not currently allocatable. def StatusReg : RegisterClass<"W65816", [i8], 8, (add P)> { let isAllocatable = 0; }