Commit 547bf682 authored by Ben.Lippmeier@anu.edu.au's avatar Ben.Lippmeier@anu.edu.au
Browse files

SPARC NCG: Reorganise Reg and RegInfo

parent 8b94848b
......@@ -479,10 +479,14 @@ Library
PPC.Cond
PPC.Ppr
PPC.CodeGen
SPARC.Base
SPARC.Regs
SPARC.RegInfo
SPARC.Instr
SPARC.Imm
SPARC.AddrMode
SPARC.Cond
SPARC.Instr
SPARC.Stack
SPARC.ShortcutJump
SPARC.Ppr
SPARC.CodeGen
RegAlloc.Liveness
......
......@@ -37,9 +37,9 @@ import X86.Ppr
#elif sparc_TARGET_ARCH
import SPARC.CodeGen
import SPARC.Regs
import SPARC.RegInfo
import SPARC.Instr
import SPARC.Ppr
import SPARC.ShortcutJump
#elif powerpc_TARGET_ARCH
import PPC.CodeGen
......
module SPARC.AddrMode (
AddrMode(..),
addrOffset
)
where
import SPARC.Imm
import SPARC.Base
import Reg
-- addressing modes ------------------------------------------------------------
-- | Represents a memory address in an instruction.
-- Being a RISC machine, the SPARC addressing modes are very regular.
--
data AddrMode
= AddrRegReg Reg Reg -- addr = r1 + r2
| AddrRegImm Reg Imm -- addr = r1 + imm
-- | Add an integer offset to the address in an AddrMode.
--
addrOffset :: AddrMode -> Int -> Maybe AddrMode
addrOffset addr off
= case addr of
AddrRegImm r (ImmInt n)
| fits13Bits n2 -> Just (AddrRegImm r (ImmInt n2))
| otherwise -> Nothing
where n2 = n + off
AddrRegImm r (ImmInteger n)
| fits13Bits n2 -> Just (AddrRegImm r (ImmInt (fromInteger n2)))
| otherwise -> Nothing
where n2 = n + toInteger off
AddrRegReg r (RealReg 0)
| fits13Bits off -> Just (AddrRegImm r (ImmInt off))
| otherwise -> Nothing
_ -> Nothing
-- | Bits and pieces on the bottom of the module dependency tree.
-- Also import the required constants, so we know what we're using.
--
-- In the interests of cross-compilation, we want to free ourselves
-- from the autoconf generated modules like main/Constants
--
module SPARC.Base (
wordLength,
wordLengthInBits,
spillAreaLength,
spillSlotSize,
fits13Bits,
largeOffsetError
)
where
import qualified Constants
import Panic
-- On 32 bit SPARC, pointers are 32 bits.
wordLength :: Int
wordLength = 4
wordLengthInBits :: Int
wordLengthInBits
= wordLength * 8
-- Size of the available spill area
spillAreaLength :: Int
spillAreaLength
= Constants.rESERVED_C_STACK_BYTES
-- | We need 8 bytes because our largest registers are 64 bit.
spillSlotSize :: Int
spillSlotSize = 8
{-# SPECIALIZE fits13Bits :: Int -> Bool, Integer -> Bool #-}
-- | Check whether an offset is representable with 13 bits.
fits13Bits :: Integral a => a -> Bool
fits13Bits x = x >= -4096 && x < 4096
-- | Sadness.
largeOffsetError :: Integral a => a -> b
largeOffsetError i
= panic ("ERROR: SPARC native-code generator cannot handle large offset ("
++ show i ++ ");\nprobably because of large constant data structures;" ++
"\nworkaround: use -fvia-C on this module.\n")
......@@ -20,9 +20,12 @@ where
-- NCG stuff:
import SPARC.Instr
import SPARC.Stack
import SPARC.Cond
import SPARC.Imm
import SPARC.AddrMode
import SPARC.Regs
import SPARC.RegInfo
import SPARC.Base
import Instruction
import Size
import Reg
......
module SPARC.Imm (
-- immediate values
Imm(..),
strImmLit,
litToImm
)
where
import Cmm
import CLabel
import BlockId
import Pretty
import Panic
-- | An immediate value.
-- Not all of these are directly representable by the machine.
-- Things like ImmLit are slurped out and put in a data segment instead.
--
data Imm
= ImmInt Int
-- Sigh.
| ImmInteger Integer
-- AbstractC Label (with baggage)
| ImmCLbl CLabel
-- Simple string
| ImmLit Doc
| ImmIndex CLabel Int
| ImmFloat Rational
| ImmDouble Rational
| ImmConstantSum Imm Imm
| ImmConstantDiff Imm Imm
| LO Imm
| HI Imm
-- | Create a ImmLit containing this string.
strImmLit :: String -> Imm
strImmLit s = ImmLit (text s)
-- | Convert a CmmLit to an Imm.
-- Narrow to the width: a CmmInt might be out of
-- range, but we assume that ImmInteger only contains
-- in-range values. A signed value should be fine here.
--
litToImm :: CmmLit -> Imm
litToImm lit
= case lit of
CmmInt i w -> ImmInteger (narrowS w i)
CmmFloat f W32 -> ImmFloat f
CmmFloat f W64 -> ImmDouble f
CmmLabel l -> ImmCLbl l
CmmLabelOff l off -> ImmIndex l off
CmmLabelDiffOff l1 l2 off
-> ImmConstantSum
(ImmConstantDiff (ImmCLbl l1) (ImmCLbl l2))
(ImmInt off)
CmmBlock id -> ImmCLbl (infoTblLbl id)
_ -> panic "SPARC.Regs.litToImm: no match"
......@@ -11,14 +11,23 @@
module SPARC.Instr (
RI(..),
riZero,
fpRelEA,
moveSp,
Instr(..),
maxSpillSlots
)
where
import SPARC.Regs
import SPARC.Stack
import SPARC.Imm
import SPARC.AddrMode
import SPARC.Cond
import SPARC.Regs
import SPARC.Base
import Instruction
import RegClass
import Reg
......@@ -26,8 +35,6 @@ import Size
import BlockId
import Cmm
import Outputable
import Constants (rESERVED_C_STACK_BYTES )
import FastString
import FastBool
......@@ -39,6 +46,29 @@ data RI
= RIReg Reg
| RIImm Imm
-- | Check if a RI represents a zero value.
-- - a literal zero
-- - register %g0, which is always zero.
--
riZero :: RI -> Bool
riZero (RIImm (ImmInt 0)) = True
riZero (RIImm (ImmInteger 0)) = True
riZero (RIReg (RealReg 0)) = True
riZero _ = False
-- | Calculate the effective address which would be used by the
-- corresponding fpRel sequence.
fpRelEA :: Int -> Reg -> Instr
fpRelEA n dst
= ADD False False fp (RIImm (ImmInt (n * wordLength))) dst
-- | Code to shift the stack pointer by n words.
moveSp :: Int -> Instr
moveSp n
= ADD False False sp (RIImm (ImmInt (n * wordLength))) sp
-- | instance for sparc instruction set
instance Instruction Instr where
......@@ -347,29 +377,6 @@ sparc_mkLoadInstr reg _ slot
in LD sz (fpRel (- off_w)) reg
-- | Convert a spill slot number to a *byte* offset, with no sign.
--
spillSlotToOffset :: Int -> Int
spillSlotToOffset slot
| slot >= 0 && slot < maxSpillSlots
= 64 + spillSlotSize * slot
| otherwise
= pprPanic "spillSlotToOffset:"
( text "invalid spill location: " <> int slot
$$ text "maxSpillSlots: " <> int maxSpillSlots)
-- | We need 8 bytes because our largest registers are 64 bit.
spillSlotSize :: Int
spillSlotSize = 8
-- | The maximum number of spill slots available on the C stack.
-- If we use up all of the slots, then we're screwed.
maxSpillSlots :: Int
maxSpillSlots = ((rESERVED_C_STACK_BYTES - 64) `div` spillSlotSize) - 1
--------------------------------------------------------------------------------
-- | See if this instruction is telling us the current C stack delta
......
......@@ -24,9 +24,11 @@ where
#include "nativeGen/NCG.h"
import SPARC.Regs
import SPARC.RegInfo
import SPARC.Instr
import SPARC.Cond
import SPARC.Imm
import SPARC.AddrMode
import SPARC.Base
import Instruction
import Reg
import Size
......
-----------------------------------------------------------------------------
--
-- Machine-specific parts of the register allocator
--
-- (c) The University of Glasgow 1996-2004
--
-----------------------------------------------------------------------------
module SPARC.RegInfo (
mkVReg,
riZero,
fpRelEA,
moveSp,
fPair,
shortcutStatic,
regDotColor,
JumpDest(..),
canShortcut,
shortcutJump,
)
where
import SPARC.Instr
import SPARC.Regs
import RegClass
import Reg
import Size
import Constants (wORD_SIZE)
import Cmm
import CLabel
import BlockId
import Outputable
import Unique
-- | Make a virtual reg with this size.
mkVReg :: Unique -> Size -> Reg
mkVReg u size
| not (isFloatSize size)
= VirtualRegI u
| otherwise
= case size of
FF32 -> VirtualRegF u
FF64 -> VirtualRegD u
_ -> panic "mkVReg"
-- | Check if a RI represents a zero value.
-- - a literal zero
-- - register %g0, which is always zero.
--
riZero :: RI -> Bool
riZero (RIImm (ImmInt 0)) = True
riZero (RIImm (ImmInteger 0)) = True
riZero (RIReg (RealReg 0)) = True
riZero _ = False
-- | Calculate the effective address which would be used by the
-- corresponding fpRel sequence. fpRel is in MachRegs.lhs,
-- alas -- can't have fpRelEA here because of module dependencies.
fpRelEA :: Int -> Reg -> Instr
fpRelEA n dst
= ADD False False fp (RIImm (ImmInt (n * wORD_SIZE))) dst
-- | Code to shift the stack pointer by n words.
moveSp :: Int -> Instr
moveSp n
= ADD False False sp (RIImm (ImmInt (n * wORD_SIZE))) sp
-- | Produce the second-half-of-a-double register given the first half.
fPair :: Reg -> Maybe Reg
fPair (RealReg n)
| n >= 32 && n `mod` 2 == 0 = Just (RealReg (n+1))
fPair (VirtualRegD u)
= Just (VirtualRegHi u)
fPair _
= trace ("MachInstrs.fPair: can't get high half of supposed double reg ")
Nothing
-- Here because it knows about JumpDest
shortcutStatic :: (BlockId -> Maybe JumpDest) -> CmmStatic -> CmmStatic
shortcutStatic fn (CmmStaticLit (CmmLabel lab))
| Just uq <- maybeAsmTemp lab
= CmmStaticLit (CmmLabel (shortBlockId fn (BlockId uq)))
shortcutStatic fn (CmmStaticLit (CmmLabelDiffOff lbl1 lbl2 off))
| Just uq <- maybeAsmTemp lbl1
= CmmStaticLit (CmmLabelDiffOff (shortBlockId fn (BlockId uq)) lbl2 off)
-- slightly dodgy, we're ignoring the second label, but this
-- works with the way we use CmmLabelDiffOff for jump tables now.
shortcutStatic _ other_static
= other_static
shortBlockId :: (BlockId -> Maybe JumpDest) -> BlockId -> CLabel
shortBlockId fn blockid@(BlockId uq) =
case fn blockid of
Nothing -> mkAsmTempLabel uq
Just (DestBlockId blockid') -> shortBlockId fn blockid'
Just (DestImm (ImmCLbl lbl)) -> lbl
_other -> panic "shortBlockId"
regDotColor :: Reg -> SDoc
regDotColor reg
= case regClass reg of
RcInteger -> text "blue"
RcFloat -> text "red"
RcDouble -> text "green"
data JumpDest = DestBlockId BlockId | DestImm Imm
canShortcut :: Instr -> Maybe JumpDest
canShortcut _ = Nothing
shortcutJump :: (BlockId -> Maybe JumpDest) -> Instr -> Instr
shortcutJump _ other = other
......@@ -5,38 +5,31 @@
-- -----------------------------------------------------------------------------
module SPARC.Regs (
-- immediate values
Imm(..),
strImmLit,
litToImm,
-- addressing modes
AddrMode(..),
addrOffset,
-- registers
spRel,
argRegs,
allArgRegs,
callClobberedRegs,
allMachRegNos,
regClass,
showReg,
regClass,
allMachRegNos,
-- machine specific info
fpRel,
fits13Bits,
largeOffsetError,
gReg, iReg, lReg, oReg, fReg,
fp, sp, g0, g1, g2, o0, o1, f0, f6, f8, f22, f26, f27,
nCG_FirstFloatReg,
fPair,
-- allocatable
freeReg,
allocatableRegs,
globalRegMaybe,
get_GlobalReg_reg_or_addr,
-- args
argRegs,
allArgRegs,
callClobberedRegs,
get_GlobalReg_reg_or_addr
--
mkVReg,
regDotColor
)
where
......@@ -44,164 +37,40 @@ where
import Reg
import RegClass
import Size
import Cmm
import CgUtils ( get_GlobalReg_addr )
import BlockId
import Cmm
import CLabel ( CLabel )
import Pretty
import Outputable ( panic )
import qualified Outputable
import CLabel
import Constants
import FastBool
-- immediates ------------------------------------------------------------------
-- | An immediate value.
-- Not all of these are directly representable by the machine.
-- Things like ImmLit are slurped out and put in a data segment instead.
--
data Imm
= ImmInt Int
-- Sigh.
| ImmInteger Integer
-- AbstractC Label (with baggage)
| ImmCLbl CLabel
-- Simple string
| ImmLit Doc
| ImmIndex CLabel Int
| ImmFloat Rational
| ImmDouble Rational
| ImmConstantSum Imm Imm
| ImmConstantDiff Imm Imm
| LO Imm
| HI Imm
-- | Create a ImmLit containing this string.
strImmLit :: String -> Imm
strImmLit s = ImmLit (text s)
-- | Convert a CmmLit to an Imm.
-- Narrow to the width: a CmmInt might be out of
-- range, but we assume that ImmInteger only contains
-- in-range values. A signed value should be fine here.
--
litToImm :: CmmLit -> Imm
litToImm lit
= case lit of
CmmInt i w -> ImmInteger (narrowS w i)
CmmFloat f W32 -> ImmFloat f
CmmFloat f W64 -> ImmDouble f
CmmLabel l -> ImmCLbl l
CmmLabelOff l off -> ImmIndex l off
CmmLabelDiffOff l1 l2 off
-> ImmConstantSum
(ImmConstantDiff (ImmCLbl l1) (ImmCLbl l2))
(ImmInt off)
CmmBlock id -> ImmCLbl (infoTblLbl id)
_ -> panic "SPARC.Regs.litToImm: no match"
-- addressing modes ------------------------------------------------------------
-- | Represents a memory address in an instruction.
-- Being a RISC machine, the SPARC addressing modes are very regular.
--
data AddrMode
= AddrRegReg Reg Reg -- addr = r1 + r2
| AddrRegImm Reg Imm -- addr = r1 + imm
-- | Add an integer offset to the address in an AddrMode.
--
addrOffset :: AddrMode -> Int -> Maybe AddrMode
addrOffset addr off
= case addr of
AddrRegImm r (ImmInt n)
| fits13Bits n2 -> Just (AddrRegImm r (ImmInt n2))
| otherwise -> Nothing
where n2 = n + off
AddrRegImm r (ImmInteger n)
| fits13Bits n2 -> Just (AddrRegImm r (ImmInt (fromInteger n2)))
| otherwise -> Nothing
where n2 = n + toInteger off
AddrRegReg r (RealReg 0)
| fits13Bits off -> Just (AddrRegImm r (ImmInt off))
| otherwise -> Nothing
_ -> Nothing
-- registers -------------------------------------------------------------------
-- | Get an AddrMode relative to the address in sp.
-- This gives us a stack relative addressing mode for volatile
-- temporaries and for excess call arguments.
--
spRel :: Int -- ^ stack offset in words, positive or negative
-> AddrMode
spRel n = AddrRegImm sp (ImmInt (n * wORD_SIZE))
-- | The registers to place arguments for function calls,
-- for some number of arguments.
--
argRegs :: RegNo -> [Reg]