ghc-9.6.4: The GHC API
Safe HaskellSafe-Inferred
LanguageHaskell2010

GHC.CmmToAsm.RV64.Instr

Synopsis

Documentation

stackFrameHeaderSize :: Int Source #

Stack frame header size in bytes.

The stack frame header is made of the values that are always saved (regardless of the context.) It consists of the saved return address and a pointer to the previous frame. Thus, its size is two stack frame slots which equals two addresses/words (2 * 8 byte).

spillSlotSize :: Int Source #

All registers are 8 byte wide.

stackAlign :: Int Source #

The number of bytes that the stack pointer should be aligned to.

maxSpillSlots :: NCGConfig -> Int Source #

The number of spill slots available without allocating more.

spillSlotToOffset :: Int -> Int Source #

Convert a spill slot number to a *byte* offset, with no sign.

callerSavedRegisters :: [Reg] Source #

0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 42 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | |== General Purpose registers ==================================================================================================================================| | ZR | RA | SP | GP | TP | tmp r. - | FP | | <---- argument passing ------------- | -- callee saved ------------------------------> | tmp regs -- | | -- | -- | -- | -- | -- | free r. | -- | BR | free registers --------------- | SP | HP | R1 | R2 | R3 | R4 | R5 | R6 | R7 | SL | free regs -- | |== SIMD/FP Registers ==========================================================================================================================================| | temporary registers ----------- | | <---- argument passing ------------- | -- callee saved ------------------------------> | tmp regs -- | | free registers --------- | F1 | F2 | free registers --------------- | F3 | F4 | F5 | F6 | D1 | D2 | D3 | D4 | D5 | D6 | -- | -- | -- | -- | '---------------------------------------------------------------------------------------------------------------------------------------------------------------' ZR: Zero, RA: Return Address, SP: Stack Pointer, GP: Global Pointer, TP: Thread Pointer, FP: Frame Pointer BR: Base, SL: SpLim

patchRegsOfInstr :: Instr -> (Reg -> Reg) -> Instr Source #

Apply a given mapping to all the register references in this instruction.

isJumpishInstr :: Instr -> Bool Source #

Checks whether this instruction is a jump/branch instruction.

One that can change the flow of control in a way that the register allocator needs to worry about.

jumpDestsOfInstr :: Instr -> [BlockId] Source #

Get the BlockIds of the jump destinations (if any)

patchJumpInstr :: Instr -> (BlockId -> BlockId) -> Instr Source #

Change the destination of this (potential) jump instruction.

Used in the linear allocator when adding fixup blocks for join points.

mkSpillInstr Source #

Arguments

:: HasCallStack 
=> NCGConfig 
-> Reg

register to spill

-> Int

current stack delta

-> Int

spill slot to use

-> [Instr] 

An instruction to spill a register into a spill slot.

mkLoadInstr Source #

Arguments

:: NCGConfig 
-> Reg

register to load

-> Int

current stack delta

-> Int

spill slot to use

-> [Instr] 

takeDeltaInstr :: Instr -> Maybe Int Source #

See if this instruction is telling us the current C stack delta

isMetaInstr :: Instr -> Bool Source #

Not real instructions. Just meta data

mkRegRegMoveInstr :: Reg -> Reg -> Instr Source #

Copy the value in a register to another one.

Must work for all register classes.

takeRegRegMoveInstr :: Instr -> Maybe (Reg, Reg) Source #

Take the source and destination from this (potential) reg -> reg move instruction

We have to be a bit careful here: A MOV can also mean an implicit conversion. This case is filtered out.

mkJumpInstr :: BlockId -> [Instr] Source #

Make an unconditional jump instruction.

mkStackAllocInstr :: Platform -> Int -> [Instr] Source #

Decrement sp to allocate stack space.

The stack grows downwards, so we decrement the stack pointer by n (bytes). This is dual to mkStackDeallocInstr. sp is the RISCV stack pointer, not to be confused with the STG stack pointer.

mkStackDeallocInstr :: Platform -> Int -> [Instr] Source #

Increment SP to deallocate stack space.

The stack grows downwards, so we increment the stack pointer by n (bytes). This is dual to mkStackAllocInstr. sp is the RISCV stack pointer, not to be confused with the STG stack pointer.

data Instr Source #

Constructors

COMMENT SDoc 
MULTILINE_COMMENT SDoc 
ANN SDoc Instr 
LOCATION Int Int Int String 
LDATA Section RawCmmStatics 
NEWBLOCK BlockId 
DELTA Int 
PUSH_STACK_FRAME

SXTW Operand Operand | SXTX Operand Operand

POP_STACK_FRAME 
ADD Operand Operand Operand 
SUB Operand Operand Operand 
AND Operand Operand Operand 
OR Operand Operand Operand 
LSL Operand Operand Operand

XOR Operand Operand Operand -- rd = rs1 ^ rs2

LSR Operand Operand Operand 
ASR Operand Operand Operand

ASL {- SLA -} Operand Operand Operand -- rd = rs1 << rs2 (sign ext)

STR Format Operand Operand

SLT Operand Operand Operand -- rd = rs1 < rs2 ? 1 : 0 (signed) | SLTU Operand Operand Operand -- rd = rs1 < rs2 ? 1 : 0 (unsigned)

LDR Format Operand Operand 
LDRU Format Operand Operand 
MUL Operand Operand Operand

CMN Operand Operand -- rd + op2 | CMP Operand Operand -- rd - op2

NEG Operand Operand 
DIV Operand Operand Operand 
REM Operand Operand Operand 
REMU Operand Operand Operand 
SMULH Operand Operand Operand 
DIVU Operand Operand Operand 
SBFM Operand Operand Operand Operand 
UBFM Operand Operand Operand Operand 
UBFX Operand Operand Operand Operand 
BIC Operand Operand Operand

AND Operand Operand Operand -- rd = rn & op2 | ANDS Operand Operand Operand -- rd = rn & op2 | ASR Operand Operand Operand -- rd = rn ≫ rm or rd = rn ≫ #i, i is 6 bits TODO: unused

BICS Operand Operand Operand 
XOR Operand Operand Operand 
MOV Operand Operand

LSL Operand Operand Operand -- rd = rn ≪ rm or rd = rn ≪ #i, i is 6 bits | LSR Operand Operand Operand -- rd = rn ≫ rm or rd = rn ≫ #i, i is 6 bits

ORI Operand Operand Operand 
XORI Operand Operand Operand 
CSET Operand Operand Operand Cond

STR Format Operand Operand -- str Xn, address-mode // Xn -> *addr | STLR Format Operand Operand -- stlr Xn, address-mode // Xn -> *addr | LDR Format Operand Operand -- ldr Xn, address-mode // Xn <- *addr | LDAR Format Operand Operand -- ldar Xn, address-mode // Xn <- *addr | STP Format Operand Operand Operand -- stp Xn, Xm, address-mode // Xn -> *addr, Xm -> *(addr + 8) | LDP Format Operand Operand Operand -- stp Xn, Xm, address-mode // Xn <- *addr, Xm <- *(addr + 8)

J Target 
B Target 
B_FAR BlockId

pseudo-op for far branch targets

BL Target [Reg] [Reg] 
BCOND Cond Operand Operand Target 
BCOND_FAR Cond Operand Operand Target Target

pseudo-op for far branch targets

DMBSY DmbType DmbType 
FCVT Operand Operand 
SCVTF Operand Operand 
FCVTZS Operand Operand 
FABS Operand Operand 

data Operand Source #

Instances

Instances details
Show Operand Source # 
Instance details

Defined in GHC.CmmToAsm.RV64.Instr

Eq Operand Source # 
Instance details

Defined in GHC.CmmToAsm.RV64.Instr

Methods

(==) :: Operand -> Operand -> Bool #

(/=) :: Operand -> Operand -> Bool #

fitsIn12bitImm :: (Num a, Ord a) => a -> Bool Source #

fitsIn32bits :: (Num a, Ord a, Bits a) => a -> Bool Source #

Orphan instances

Outputable RegUsage Source #

Get the registers that are being used by this instruction. regUsage doesn't need to do any trickery for jumps and such. Just state precisely the regs read and written by that insn. The consequences of control flow transfers, as far as register allocation goes, are taken care of by the register allocator.

RegUsage = RU [regs] [regs]

Instance details

Methods

ppr :: RegUsage -> SDoc Source #