diff options
Diffstat (limited to 'compiler/nativeGen/PPC')
-rw-r--r-- | compiler/nativeGen/PPC/Instr.hs | 39 | ||||
-rw-r--r-- | compiler/nativeGen/PPC/Ppr.hs | 68 | ||||
-rw-r--r-- | compiler/nativeGen/PPC/Regs.hs | 14 |
3 files changed, 95 insertions, 26 deletions
diff --git a/compiler/nativeGen/PPC/Instr.hs b/compiler/nativeGen/PPC/Instr.hs index 975527817d..b5c26ed906 100644 --- a/compiler/nativeGen/PPC/Instr.hs +++ b/compiler/nativeGen/PPC/Instr.hs @@ -74,19 +74,19 @@ instance Instruction Instr where ppc_mkStackAllocInstr :: Platform -> Int -> Instr ppc_mkStackAllocInstr platform amount - = case platformArch platform of - ArchPPC -> -- SUB II32 (OpImm (ImmInt amount)) (OpReg esp) - ADD sp sp (RIImm (ImmInt (-amount))) - ArchPPC_64 _ -> STU II64 sp (AddrRegImm sp (ImmInt (-amount))) - arch -> panic $ "ppc_mkStackAllocInstr " ++ show arch + = ppc_mkStackAllocInstr' platform (-amount) ppc_mkStackDeallocInstr :: Platform -> Int -> Instr ppc_mkStackDeallocInstr platform amount + = ppc_mkStackAllocInstr' platform amount + +ppc_mkStackAllocInstr' :: Platform -> Int -> Instr +ppc_mkStackAllocInstr' platform amount = case platformArch platform of - ArchPPC -> -- ADD II32 (OpImm (ImmInt amount)) (OpReg esp) - ADD sp sp (RIImm (ImmInt amount)) - ArchPPC_64 _ -> ADD sp sp (RIImm (ImmInt amount)) - arch -> panic $ "ppc_mkStackDeallocInstr " ++ show arch + ArchPPC -> UPDATE_SP II32 (ImmInt amount) + ArchPPC_64 _ -> UPDATE_SP II64 (ImmInt amount) + _ -> panic $ "ppc_mkStackAllocInstr' " + ++ show (platformArch platform) -- -- See note [extra spill slots] in X86/Instr.hs @@ -186,8 +186,10 @@ data Instr -- Loads and stores. | LD Format Reg AddrMode -- Load format, dst, src + | LDFAR Format Reg AddrMode -- Load format, dst, src 32 bit offset | LA Format Reg AddrMode -- Load arithmetic format, dst, src | ST Format Reg AddrMode -- Store format, src, dst + | STFAR Format Reg AddrMode -- Store format, src, dst 32 bit offset | STU Format Reg AddrMode -- Store with Update format, src, dst | LIS Reg Imm -- Load Immediate Shifted dst, src | LI Reg Imm -- Load Immediate dst, src @@ -277,6 +279,8 @@ data Instr | NOP -- no operation, PowerPC 64 bit -- needs this as place holder to -- reload TOC pointer + | UPDATE_SP Format Imm -- expand/shrink spill area on C stack + -- pseudo-instruction -- | Get the registers that are being used by this instruction. -- regUsage doesn't need to do any trickery for jumps and such. @@ -288,8 +292,10 @@ ppc_regUsageOfInstr :: Platform -> Instr -> RegUsage ppc_regUsageOfInstr platform instr = case instr of LD _ reg addr -> usage (regAddr addr, [reg]) + LDFAR _ reg addr -> usage (regAddr addr, [reg]) LA _ reg addr -> usage (regAddr addr, [reg]) ST _ reg addr -> usage (reg : regAddr addr, []) + STFAR _ reg addr -> usage (reg : regAddr addr, []) STU _ reg addr -> usage (reg : regAddr addr, []) LIS reg _ -> usage ([], [reg]) LI reg _ -> usage ([], [reg]) @@ -349,6 +355,7 @@ ppc_regUsageOfInstr platform instr MFLR reg -> usage ([], [reg]) FETCHPC reg -> usage ([], [reg]) FETCHTOC reg _ -> usage ([], [reg]) + UPDATE_SP _ _ -> usage ([], [sp]) _ -> noUsage where usage (src, dst) = RU (filter (interesting platform) src) @@ -373,8 +380,10 @@ ppc_patchRegsOfInstr :: Instr -> (Reg -> Reg) -> Instr ppc_patchRegsOfInstr instr env = case instr of LD fmt reg addr -> LD fmt (env reg) (fixAddr addr) + LDFAR fmt reg addr -> LDFAR fmt (env reg) (fixAddr addr) LA fmt reg addr -> LA fmt (env reg) (fixAddr addr) ST fmt reg addr -> ST fmt (env reg) (fixAddr addr) + STFAR fmt reg addr -> STFAR fmt (env reg) (fixAddr addr) STU fmt reg addr -> STU fmt (env reg) (fixAddr addr) LIS reg imm -> LIS (env reg) imm LI reg imm -> LI (env reg) imm @@ -505,7 +514,11 @@ ppc_mkSpillInstr dflags reg delta slot _ -> II64 RcDouble -> FF64 _ -> panic "PPC.Instr.mkSpillInstr: no match" - in ST fmt reg (AddrRegImm sp (ImmInt (off-delta))) + instr = case makeImmediate W32 True (off-delta) of + Just _ -> ST + Nothing -> STFAR -- pseudo instruction: 32 bit offsets + + in instr fmt reg (AddrRegImm sp (ImmInt (off-delta))) ppc_mkLoadInstr @@ -526,7 +539,11 @@ ppc_mkLoadInstr dflags reg delta slot _ -> II64 RcDouble -> FF64 _ -> panic "PPC.Instr.mkLoadInstr: no match" - in LD fmt reg (AddrRegImm sp (ImmInt (off-delta))) + instr = case makeImmediate W32 True (off-delta) of + Just _ -> LD + Nothing -> LDFAR -- pseudo instruction: 32 bit offsets + + in instr fmt reg (AddrRegImm sp (ImmInt (off-delta))) -- | The maximum number of bytes required to spill a register. PPC32 diff --git a/compiler/nativeGen/PPC/Ppr.hs b/compiler/nativeGen/PPC/Ppr.hs index 6b9150a2d1..e5147794ce 100644 --- a/compiler/nativeGen/PPC/Ppr.hs +++ b/compiler/nativeGen/PPC/Ppr.hs @@ -246,10 +246,10 @@ pprFormat x FF32 -> sLit "fs" FF64 -> sLit "fd" _ -> panic "PPC.Ppr.pprFormat: no match") - - + + pprCond :: Cond -> SDoc -pprCond c +pprCond c = ptext (case c of { ALWAYS -> sLit ""; EQQ -> sLit "eq"; NE -> sLit "ne"; @@ -373,7 +373,7 @@ pprDataItem lit ppr_item II64 (CmmInt x _) dflags | not(archPPC_64 dflags) = [ptext (sLit "\t.long\t") - <> int (fromIntegral + <> int (fromIntegral (fromIntegral (x `shiftR` 32) :: Word32)), ptext (sLit "\t.long\t") <> int (fromIntegral (fromIntegral x :: Word32))] @@ -437,6 +437,15 @@ pprInstr (LD fmt reg addr) = hcat [ ptext (sLit ", "), pprAddr addr ] +pprInstr (LDFAR fmt reg (AddrRegImm source off)) = + sdocWithPlatform $ \platform -> vcat [ + pprInstr (ADDIS (tmpReg platform) source (HA off)), + pprInstr (LD fmt reg (AddrRegImm (tmpReg platform) (LO off))) + ] + +pprInstr (LDFAR _ _ _) = + panic "PPC.Ppr.pprInstr LDFAR: no match" + pprInstr (LA fmt reg addr) = hcat [ char '\t', ptext (sLit "l"), @@ -467,6 +476,14 @@ pprInstr (ST fmt reg addr) = hcat [ ptext (sLit ", "), pprAddr addr ] +pprInstr (STFAR fmt reg (AddrRegImm source off)) = + sdocWithPlatform $ \platform -> vcat [ + pprInstr (ADDIS (tmpReg platform) source (HA off)), + pprInstr (ST fmt reg (AddrRegImm (tmpReg platform) (LO off))) + ] + +pprInstr (STFAR _ _ _) = + panic "PPC.Ppr.pprInstr STFAR: no match" pprInstr (STU fmt reg addr) = hcat [ char '\t', ptext (sLit "st"), @@ -494,7 +511,7 @@ pprInstr (LI reg imm) = hcat [ ptext (sLit ", "), pprImm imm ] -pprInstr (MR reg1 reg2) +pprInstr (MR reg1 reg2) | reg1 == reg2 = empty | otherwise = hcat [ char '\t', @@ -693,6 +710,21 @@ pprInstr (EXTS fmt reg1 reg2) = hcat [ pprInstr (NEG reg1 reg2) = pprUnary (sLit "neg") reg1 reg2 pprInstr (NOT reg1 reg2) = pprUnary (sLit "not") reg1 reg2 +pprInstr (SR II32 reg1 reg2 (RIImm (ImmInt i))) | i < 0 || i > 31 = + -- Handle the case where we are asked to shift a 32 bit register by + -- less than zero or more than 31 bits. We convert this into a clear + -- of the destination register. + -- Fixes ticket http://ghc.haskell.org/trac/ghc/ticket/5900 + pprInstr (XOR reg1 reg2 (RIReg reg2)) + +pprInstr (SL II32 reg1 reg2 (RIImm (ImmInt i))) | i < 0 || i > 31 = + -- As aboce for SR, but for left shifts. + -- Fixes ticket http://ghc.haskell.org/trac/ghc/ticket/10870 + pprInstr (XOR reg1 reg2 (RIReg reg2)) + +pprInstr (SRA II32 reg1 reg2 (RIImm (ImmInt i))) | i < 0 || i > 31 = + pprInstr (XOR reg1 reg2 (RIReg reg2)) + pprInstr (SL fmt reg1 reg2 ri) = let op = case fmt of II32 -> "slw" @@ -700,12 +732,6 @@ pprInstr (SL fmt reg1 reg2 ri) = _ -> panic "PPC.Ppr.pprInstr: shift illegal size" in pprLogic (sLit op) reg1 reg2 (limitShiftRI fmt ri) -pprInstr (SR II32 reg1 reg2 (RIImm (ImmInt i))) | i > 31 || i < 0 = - -- Handle the case where we are asked to shift a 32 bit register by - -- less than zero or more than 31 bits. We convert this into a clear - -- of the destination register. - -- Fixes ticket http://ghc.haskell.org/trac/ghc/ticket/5900 - pprInstr (XOR reg1 reg2 (RIReg reg2)) pprInstr (SR fmt reg1 reg2 ri) = let op = case fmt of II32 -> "srw" @@ -732,7 +758,7 @@ pprInstr (RLWINM reg1 reg2 sh mb me) = hcat [ ptext (sLit ", "), int me ] - + pprInstr (FADD fmt reg1 reg2 reg3) = pprBinaryF (sLit "fadd") fmt reg1 reg2 reg3 pprInstr (FSUB fmt reg1 reg2 reg3) = pprBinaryF (sLit "fsub") fmt reg1 reg2 reg3 pprInstr (FMUL fmt reg1 reg2 reg3) = pprBinaryF (sLit "fmul") fmt reg1 reg2 reg3 @@ -799,6 +825,22 @@ pprInstr LWSYNC = ptext (sLit "\tlwsync") pprInstr NOP = ptext (sLit "\tnop") +pprInstr (UPDATE_SP fmt amount@(ImmInt offset)) + | fits16Bits offset = vcat [ + pprInstr (LD fmt r0 (AddrRegImm sp (ImmInt 0))), + pprInstr (STU fmt r0 (AddrRegImm sp amount)) + ] + +pprInstr (UPDATE_SP fmt amount) + = sdocWithPlatform $ \platform -> + let tmp = tmpReg platform in + vcat [ + pprInstr (LD fmt r0 (AddrRegImm sp (ImmInt 0))), + pprInstr (ADDIS tmp sp (HA amount)), + pprInstr (ADD tmp tmp (RIImm (LO amount))), + pprInstr (STU fmt r0 (AddrRegReg sp tmp)) + ] + -- pprInstr _ = panic "pprInstr (ppc)" @@ -841,7 +883,7 @@ pprBinaryF op fmt reg1 reg2 reg3 = hcat [ ptext (sLit ", "), pprReg reg3 ] - + pprRI :: RI -> SDoc pprRI (RIReg r) = pprReg r pprRI (RIImm r) = pprImm r diff --git a/compiler/nativeGen/PPC/Regs.hs b/compiler/nativeGen/PPC/Regs.hs index 05efaeb1f4..14bdab734b 100644 --- a/compiler/nativeGen/PPC/Regs.hs +++ b/compiler/nativeGen/PPC/Regs.hs @@ -37,7 +37,8 @@ module PPC.Regs ( fits16Bits, makeImmediate, fReg, - sp, toc, r3, r4, r11, r12, r27, r28, r30, + r0, sp, toc, r3, r4, r11, r12, r27, r28, r30, + tmpReg, f1, f20, f21, allocatableRegs @@ -304,7 +305,8 @@ point registers. fReg :: Int -> RegNo fReg x = (32 + x) -sp, toc, r3, r4, r11, r12, r27, r28, r30, f1, f20, f21 :: Reg +r0, sp, toc, r3, r4, r11, r12, r27, r28, r30, f1, f20, f21 :: Reg +r0 = regSingle 0 sp = regSingle 1 toc = regSingle 2 r3 = regSingle 3 @@ -325,3 +327,11 @@ allocatableRegs :: Platform -> [RealReg] allocatableRegs platform = let isFree i = freeReg platform i in map RealRegSingle $ filter isFree allMachRegNos + +-- temporary register for compiler use +tmpReg :: Platform -> Reg +tmpReg platform = + case platformArch platform of + ArchPPC -> regSingle 13 + ArchPPC_64 _ -> regSingle 30 + _ -> panic "PPC.Regs.tmpReg: unknowm arch" |