{-# LANGUAGE CPP #-}
module GHC.CmmToAsm.X86.Regs (
        
        virtualRegSqueeze,
        realRegSqueeze,
        
        Imm(..),
        strImmLit,
        litToImm,
        
        AddrMode(..),
        addrOffset,
        
        spRel,
        argRegs,
        allArgRegs,
        allIntArgRegs,
        callClobberedRegs,
        instrClobberedRegs,
        allMachRegNos,
        classOfRealReg,
        showReg,
        
        EABase(..), EAIndex(..), addrModeRegs,
        eax, ebx, ecx, edx, esi, edi, ebp, esp,
        rax, rbx, rcx, rdx, rsi, rdi, rbp, rsp,
        r8,  r9,  r10, r11, r12, r13, r14, r15,
        lastint,
        xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7,
        xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15,
        xmm,
        firstxmm, lastxmm,
        ripRel,
        allFPArgRegs,
        allocatableRegs
)
where
#include "HsVersions.h"
import GHC.Prelude
import GHC.Platform.Regs
import GHC.Platform.Reg
import GHC.Platform.Reg.Class
import GHC.Cmm
import GHC.Cmm.CLabel           ( CLabel )
import GHC.Utils.Outputable
import GHC.Utils.Panic
import GHC.Platform
import qualified Data.Array as A
{-# INLINE virtualRegSqueeze #-}
virtualRegSqueeze :: RegClass -> VirtualReg -> Int
virtualRegSqueeze :: RegClass -> VirtualReg -> Int
virtualRegSqueeze RegClass
cls VirtualReg
vr
 = case RegClass
cls of
        RegClass
RcInteger
         -> case VirtualReg
vr of
                VirtualRegI{}           -> Int
1
                VirtualRegHi{}          -> Int
1
                VirtualReg
_other                  -> Int
0
        RegClass
RcDouble
         -> case VirtualReg
vr of
                VirtualRegD{}           -> Int
1
                VirtualRegF{}           -> Int
0
                VirtualReg
_other                  -> Int
0
        RegClass
_other -> Int
0
{-# INLINE realRegSqueeze #-}
realRegSqueeze :: RegClass -> RealReg -> Int
realRegSqueeze :: RegClass -> RealReg -> Int
realRegSqueeze RegClass
cls RealReg
rr
 = case RegClass
cls of
        RegClass
RcInteger
         -> case RealReg
rr of
                RealRegSingle Int
regNo
                        | Int
regNo Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
firstxmm -> Int
1
                        | Bool
otherwise     -> Int
0
                RealRegPair{}           -> Int
0
        RegClass
RcDouble
         -> case RealReg
rr of
                RealRegSingle Int
regNo
                        | Int
regNo Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
firstxmm  -> Int
1
                        | Bool
otherwise     -> Int
0
                RealRegPair{}           -> Int
0
        RegClass
_other -> Int
0
data Imm
  = ImmInt      Int
  | ImmInteger  Integer     
  | ImmCLbl     CLabel      
  | ImmLit      SDoc        
  | ImmIndex    CLabel Int
  | ImmFloat    Rational
  | ImmDouble   Rational
  | ImmConstantSum Imm Imm
  | ImmConstantDiff Imm Imm
strImmLit :: String -> Imm
strImmLit :: String -> Imm
strImmLit String
s = SDoc -> Imm
ImmLit (String -> SDoc
text String
s)
litToImm :: CmmLit -> Imm
litToImm :: CmmLit -> Imm
litToImm (CmmInt Integer
i Width
w)        = Integer -> Imm
ImmInteger (Width -> Integer -> Integer
narrowS Width
w Integer
i)
                
                
                
litToImm (CmmFloat Rational
f Width
W32)    = Rational -> Imm
ImmFloat Rational
f
litToImm (CmmFloat Rational
f Width
W64)    = Rational -> Imm
ImmDouble Rational
f
litToImm (CmmLabel CLabel
l)        = CLabel -> Imm
ImmCLbl CLabel
l
litToImm (CmmLabelOff CLabel
l Int
off) = CLabel -> Int -> Imm
ImmIndex CLabel
l Int
off
litToImm (CmmLabelDiffOff CLabel
l1 CLabel
l2 Int
off Width
_)
                             = Imm -> Imm -> Imm
ImmConstantSum
                               (Imm -> Imm -> Imm
ImmConstantDiff (CLabel -> Imm
ImmCLbl CLabel
l1) (CLabel -> Imm
ImmCLbl CLabel
l2))
                               (Int -> Imm
ImmInt Int
off)
litToImm CmmLit
_                   = String -> Imm
forall a. String -> a
panic String
"X86.Regs.litToImm: no match"
data AddrMode
        = AddrBaseIndex EABase EAIndex Displacement
        | ImmAddr Imm Int
data EABase       = EABaseNone  | EABaseReg Reg | EABaseRip
data EAIndex      = EAIndexNone | EAIndex Reg Int
type Displacement = Imm
addrOffset :: AddrMode -> Int -> Maybe AddrMode
addrOffset :: AddrMode -> Int -> Maybe AddrMode
addrOffset AddrMode
addr Int
off
  = case AddrMode
addr of
      ImmAddr Imm
i Int
off0      -> AddrMode -> Maybe AddrMode
forall a. a -> Maybe a
Just (Imm -> Int -> AddrMode
ImmAddr Imm
i (Int
off0 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
off))
      AddrBaseIndex EABase
r EAIndex
i (ImmInt Int
n) -> AddrMode -> Maybe AddrMode
forall a. a -> Maybe a
Just (EABase -> EAIndex -> Imm -> AddrMode
AddrBaseIndex EABase
r EAIndex
i (Int -> Imm
ImmInt (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
off)))
      AddrBaseIndex EABase
r EAIndex
i (ImmInteger Integer
n)
        -> AddrMode -> Maybe AddrMode
forall a. a -> Maybe a
Just (EABase -> EAIndex -> Imm -> AddrMode
AddrBaseIndex EABase
r EAIndex
i (Int -> Imm
ImmInt (Integer -> Int
forall a. Num a => Integer -> a
fromInteger (Integer
n Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Int -> Integer
forall a. Integral a => a -> Integer
toInteger Int
off))))
      AddrBaseIndex EABase
r EAIndex
i (ImmCLbl CLabel
lbl)
        -> AddrMode -> Maybe AddrMode
forall a. a -> Maybe a
Just (EABase -> EAIndex -> Imm -> AddrMode
AddrBaseIndex EABase
r EAIndex
i (CLabel -> Int -> Imm
ImmIndex CLabel
lbl Int
off))
      AddrBaseIndex EABase
r EAIndex
i (ImmIndex CLabel
lbl Int
ix)
        -> AddrMode -> Maybe AddrMode
forall a. a -> Maybe a
Just (EABase -> EAIndex -> Imm -> AddrMode
AddrBaseIndex EABase
r EAIndex
i (CLabel -> Int -> Imm
ImmIndex CLabel
lbl (Int
ixInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
off)))
      AddrMode
_ -> Maybe AddrMode
forall a. Maybe a
Nothing  
addrModeRegs :: AddrMode -> [Reg]
addrModeRegs :: AddrMode -> [Reg]
addrModeRegs (AddrBaseIndex EABase
b EAIndex
i Imm
_) =  [Reg]
b_regs [Reg] -> [Reg] -> [Reg]
forall a. [a] -> [a] -> [a]
++ [Reg]
i_regs
  where
   b_regs :: [Reg]
b_regs = case EABase
b of { EABaseReg Reg
r -> [Reg
r]; EABase
_ -> [] }
   i_regs :: [Reg]
i_regs = case EAIndex
i of { EAIndex Reg
r Int
_ -> [Reg
r]; EAIndex
_ -> [] }
addrModeRegs AddrMode
_ = []
spRel :: Platform
      -> Int 
      -> AddrMode
spRel :: Platform -> Int -> AddrMode
spRel Platform
platform Int
n
 | Platform -> Bool
target32Bit Platform
platform
    = EABase -> EAIndex -> Imm -> AddrMode
AddrBaseIndex (Reg -> EABase
EABaseReg Reg
esp) EAIndex
EAIndexNone (Int -> Imm
ImmInt Int
n)
 | Bool
otherwise
    = EABase -> EAIndex -> Imm -> AddrMode
AddrBaseIndex (Reg -> EABase
EABaseReg Reg
rsp) EAIndex
EAIndexNone (Int -> Imm
ImmInt Int
n)
firstxmm :: RegNo
firstxmm :: Int
firstxmm  = Int
16
lastxmm :: Platform -> RegNo
lastxmm :: Platform -> Int
lastxmm Platform
platform
 | Platform -> Bool
target32Bit Platform
platform = Int
firstxmm Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
7  
 | Bool
otherwise            = Int
firstxmm Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
15 
lastint :: Platform -> RegNo
lastint :: Platform -> Int
lastint Platform
platform
 | Platform -> Bool
target32Bit Platform
platform = Int
7 
 | Bool
otherwise            = Int
15
intregnos :: Platform -> [RegNo]
intregnos :: Platform -> [Int]
intregnos Platform
platform = [Int
0 .. Platform -> Int
lastint Platform
platform]
xmmregnos :: Platform -> [RegNo]
xmmregnos :: Platform -> [Int]
xmmregnos Platform
platform = [Int
firstxmm  .. Platform -> Int
lastxmm Platform
platform]
floatregnos :: Platform -> [RegNo]
floatregnos :: Platform -> [Int]
floatregnos Platform
platform = Platform -> [Int]
xmmregnos Platform
platform
argRegs :: RegNo -> [Reg]
argRegs :: Int -> [Reg]
argRegs Int
_       = String -> [Reg]
forall a. String -> a
panic String
"MachRegs.argRegs(x86): should not be used!"
allMachRegNos :: Platform -> [RegNo]
allMachRegNos :: Platform -> [Int]
allMachRegNos Platform
platform = Platform -> [Int]
intregnos Platform
platform [Int] -> [Int] -> [Int]
forall a. [a] -> [a] -> [a]
++ Platform -> [Int]
floatregnos Platform
platform
{-# INLINE classOfRealReg #-}
classOfRealReg :: Platform -> RealReg -> RegClass
classOfRealReg :: Platform -> RealReg -> RegClass
classOfRealReg Platform
platform RealReg
reg
    = case RealReg
reg of
        RealRegSingle Int
i
            | Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Platform -> Int
lastint Platform
platform -> RegClass
RcInteger
            | Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Platform -> Int
lastxmm Platform
platform -> RegClass
RcDouble
            | Bool
otherwise             -> String -> RegClass
forall a. String -> a
panic String
"X86.Reg.classOfRealReg registerSingle too high"
        RealReg
_   -> String -> RegClass
forall a. String -> a
panic String
"X86.Regs.classOfRealReg: RegPairs on this arch"
showReg :: Platform -> RegNo -> String
showReg :: Platform -> Int -> String
showReg Platform
platform Int
n
        | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
firstxmm Bool -> Bool -> Bool
&& Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Platform -> Int
lastxmm  Platform
platform = String
"%xmm" String -> String -> String
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
firstxmm)
        | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
8   Bool -> Bool -> Bool
&& Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
firstxmm      = String
"%r" String -> String -> String
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
n
        | Bool
otherwise      = Platform -> Array Int String
regNames Platform
platform Array Int String -> Int -> String
forall i e. Ix i => Array i e -> i -> e
A.! Int
n
regNames :: Platform -> A.Array Int String
regNames :: Platform -> Array Int String
regNames Platform
platform
    = if Platform -> Bool
target32Bit Platform
platform
      then (Int, Int) -> [String] -> Array Int String
forall i e. Ix i => (i, i) -> [e] -> Array i e
A.listArray (Int
0,Int
8) [String
"%eax", String
"%ebx", String
"%ecx", String
"%edx", String
"%esi", String
"%edi", String
"%ebp", String
"%esp"]
      else (Int, Int) -> [String] -> Array Int String
forall i e. Ix i => (i, i) -> [e] -> Array i e
A.listArray (Int
0,Int
8) [String
"%rax", String
"%rbx", String
"%rcx", String
"%rdx", String
"%rsi", String
"%rdi", String
"%rbp", String
"%rsp"]
eax, ebx, ecx, edx, esp, ebp, esi, edi :: Reg
eax :: Reg
eax   = Int -> Reg
regSingle Int
0
ebx :: Reg
ebx   = Int -> Reg
regSingle Int
1
ecx :: Reg
ecx   = Int -> Reg
regSingle Int
2
edx :: Reg
edx   = Int -> Reg
regSingle Int
3
esi :: Reg
esi   = Int -> Reg
regSingle Int
4
edi :: Reg
edi   = Int -> Reg
regSingle Int
5
ebp :: Reg
ebp   = Int -> Reg
regSingle Int
6
esp :: Reg
esp   = Int -> Reg
regSingle Int
7
rax, rbx, rcx, rdx, rsp, rbp, rsi, rdi,
  r8, r9, r10, r11, r12, r13, r14, r15,
  xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7,
  xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15 :: Reg
rax :: Reg
rax   = Int -> Reg
regSingle Int
0
rbx :: Reg
rbx   = Int -> Reg
regSingle Int
1
rcx :: Reg
rcx   = Int -> Reg
regSingle Int
2
rdx :: Reg
rdx   = Int -> Reg
regSingle Int
3
rsi :: Reg
rsi   = Int -> Reg
regSingle Int
4
rdi :: Reg
rdi   = Int -> Reg
regSingle Int
5
rbp :: Reg
rbp   = Int -> Reg
regSingle Int
6
rsp :: Reg
rsp   = Int -> Reg
regSingle Int
7
r8 :: Reg
r8    = Int -> Reg
regSingle Int
8
r9 :: Reg
r9    = Int -> Reg
regSingle Int
9
r10 :: Reg
r10   = Int -> Reg
regSingle Int
10
r11 :: Reg
r11   = Int -> Reg
regSingle Int
11
r12 :: Reg
r12   = Int -> Reg
regSingle Int
12
r13 :: Reg
r13   = Int -> Reg
regSingle Int
13
r14 :: Reg
r14   = Int -> Reg
regSingle Int
14
r15 :: Reg
r15   = Int -> Reg
regSingle Int
15
xmm0 :: Reg
xmm0  = Int -> Reg
regSingle Int
16
xmm1 :: Reg
xmm1  = Int -> Reg
regSingle Int
17
xmm2 :: Reg
xmm2  = Int -> Reg
regSingle Int
18
xmm3 :: Reg
xmm3  = Int -> Reg
regSingle Int
19
xmm4 :: Reg
xmm4  = Int -> Reg
regSingle Int
20
xmm5 :: Reg
xmm5  = Int -> Reg
regSingle Int
21
xmm6 :: Reg
xmm6  = Int -> Reg
regSingle Int
22
xmm7 :: Reg
xmm7  = Int -> Reg
regSingle Int
23
xmm8 :: Reg
xmm8  = Int -> Reg
regSingle Int
24
xmm9 :: Reg
xmm9  = Int -> Reg
regSingle Int
25
xmm10 :: Reg
xmm10 = Int -> Reg
regSingle Int
26
xmm11 :: Reg
xmm11 = Int -> Reg
regSingle Int
27
xmm12 :: Reg
xmm12 = Int -> Reg
regSingle Int
28
xmm13 :: Reg
xmm13 = Int -> Reg
regSingle Int
29
xmm14 :: Reg
xmm14 = Int -> Reg
regSingle Int
30
xmm15 :: Reg
xmm15 = Int -> Reg
regSingle Int
31
ripRel :: Displacement -> AddrMode
ripRel :: Imm -> AddrMode
ripRel Imm
imm      = EABase -> EAIndex -> Imm -> AddrMode
AddrBaseIndex EABase
EABaseRip EAIndex
EAIndexNone Imm
imm
 
xmm :: RegNo -> Reg
xmm :: Int -> Reg
xmm Int
n = Int -> Reg
regSingle (Int
firstxmmInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
n)
callClobberedRegs       :: Platform -> [Reg]
callClobberedRegs :: Platform -> [Reg]
callClobberedRegs Platform
platform
 | Platform -> Bool
target32Bit Platform
platform = [Reg
eax,Reg
ecx,Reg
edx] [Reg] -> [Reg] -> [Reg]
forall a. [a] -> [a] -> [a]
++ (Int -> Reg) -> [Int] -> [Reg]
forall a b. (a -> b) -> [a] -> [b]
map Int -> Reg
regSingle (Platform -> [Int]
floatregnos Platform
platform)
 | Platform -> OS
platformOS Platform
platform OS -> OS -> Bool
forall a. Eq a => a -> a -> Bool
== OS
OSMinGW32
   = [Reg
rax,Reg
rcx,Reg
rdx,Reg
r8,Reg
r9,Reg
r10,Reg
r11]
   
   
   
   [Reg] -> [Reg] -> [Reg]
forall a. [a] -> [a] -> [a]
++ (Int -> Reg) -> [Int] -> [Reg]
forall a b. (a -> b) -> [a] -> [b]
map Int -> Reg
xmm [Int
0  .. Int
5]
 | Bool
otherwise
    
    
    = [Reg
rax,Reg
rcx,Reg
rdx,Reg
rsi,Reg
rdi,Reg
r8,Reg
r9,Reg
r10,Reg
r11]
   [Reg] -> [Reg] -> [Reg]
forall a. [a] -> [a] -> [a]
++ (Int -> Reg) -> [Int] -> [Reg]
forall a b. (a -> b) -> [a] -> [b]
map Int -> Reg
regSingle (Platform -> [Int]
floatregnos Platform
platform)
allArgRegs :: Platform -> [(Reg, Reg)]
allArgRegs :: Platform -> [(Reg, Reg)]
allArgRegs Platform
platform
 | Platform -> OS
platformOS Platform
platform OS -> OS -> Bool
forall a. Eq a => a -> a -> Bool
== OS
OSMinGW32 = [Reg] -> [Reg] -> [(Reg, Reg)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Reg
rcx,Reg
rdx,Reg
r8,Reg
r9]
                                          ((Int -> Reg) -> [Int] -> [Reg]
forall a b. (a -> b) -> [a] -> [b]
map Int -> Reg
regSingle [Int
firstxmm ..])
 | Bool
otherwise = String -> [(Reg, Reg)]
forall a. String -> a
panic String
"X86.Regs.allArgRegs: not defined for this arch"
allIntArgRegs :: Platform -> [Reg]
allIntArgRegs :: Platform -> [Reg]
allIntArgRegs Platform
platform
 | (Platform -> OS
platformOS Platform
platform OS -> OS -> Bool
forall a. Eq a => a -> a -> Bool
== OS
OSMinGW32) Bool -> Bool -> Bool
|| Platform -> Bool
target32Bit Platform
platform
    = String -> [Reg]
forall a. String -> a
panic String
"X86.Regs.allIntArgRegs: not defined for this platform"
 | Bool
otherwise = [Reg
rdi,Reg
rsi,Reg
rdx,Reg
rcx,Reg
r8,Reg
r9]
allFPArgRegs :: Platform -> [Reg]
allFPArgRegs :: Platform -> [Reg]
allFPArgRegs Platform
platform
 | Platform -> OS
platformOS Platform
platform OS -> OS -> Bool
forall a. Eq a => a -> a -> Bool
== OS
OSMinGW32
    = String -> [Reg]
forall a. String -> a
panic String
"X86.Regs.allFPArgRegs: not defined for this platform"
 | Bool
otherwise = (Int -> Reg) -> [Int] -> [Reg]
forall a b. (a -> b) -> [a] -> [b]
map Int -> Reg
regSingle [Int
firstxmm .. Int
firstxmm Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
7 ]
instrClobberedRegs :: Platform -> [Reg]
instrClobberedRegs :: Platform -> [Reg]
instrClobberedRegs Platform
platform
 | Platform -> Bool
target32Bit Platform
platform = [ Reg
eax, Reg
ecx, Reg
edx ]
 | Bool
otherwise            = [ Reg
rax, Reg
rcx, Reg
rdx ]
allocatableRegs :: Platform -> [RealReg]
allocatableRegs :: Platform -> [RealReg]
allocatableRegs Platform
platform
   = let isFree :: Int -> Bool
isFree Int
i = Platform -> Int -> Bool
freeReg Platform
platform Int
i
     in  (Int -> RealReg) -> [Int] -> [RealReg]
forall a b. (a -> b) -> [a] -> [b]
map Int -> RealReg
RealRegSingle ([Int] -> [RealReg]) -> [Int] -> [RealReg]
forall a b. (a -> b) -> a -> b
$ (Int -> Bool) -> [Int] -> [Int]
forall a. (a -> Bool) -> [a] -> [a]
filter Int -> Bool
isFree (Platform -> [Int]
allMachRegNos Platform
platform)