/* -----------------------------------------------------------------------------
- * $Id: MachRegs.h,v 1.14 2003/08/29 16:00:26 simonmar Exp $
*
* (c) The GHC Team, 1998-1999
*
* only in here please.
*/
-/* define NO_REGS to omit register declarations - used in RTS C code
- * that needs all the STG definitions but not the global register
- * settings.
+/*
+ * Defining NO_REGS causes no global registers to be used. NO_REGS is
+ * typically defined by GHC, via a command-line option passed to gcc,
+ * when the -funregisterised flag is given.
+ *
+ * NB. When NO_REGS is on, calling & return conventions may be
+ * different. For example, all function arguments will be passed on
+ * the stack, and components of an unboxed tuple will be returned on
+ * the stack rather than in registers.
*/
#ifndef NO_REGS
+/* NOTE: when testing the platform in this file we must test either
+ * *_HOST_ARCH and *_TARGET_ARCH, depending on whether COMPILING_GHC
+ * is set. This is because when we're compiling the RTS and HC code,
+ * the platform we're running on is the HOST, but when compiling GHC
+ * we want to know about the register mapping on the TARGET platform.
+ */
+#ifdef COMPILING_GHC
+#define alpha_REGS alpha_TARGET_ARCH
+#define hppa1_1_REGS hppa1_1_TARGET_ARCH
+#define i386_REGS i386_TARGET_ARCH
+#define x86_64_REGS x86_64_TARGET_ARCH
+#define m68k_REGS m68k_TARGET_ARCH
+#define mips_REGS (mipsel_TARGET_ARCH || mipseb_TARGET_ARCH)
+#define powerpc_REGS (powerpc_TARGET_ARCH || powerpc64_TARGET_ARCH || rs6000_TARGET_ARCH)
+#define ia64_REGS ia64_TARGET_ARCH
+#define sparc_REGS sparc_TARGET_ARCH
+#define darwin_REGS darwin_TARGET_OS
+#else
+#define alpha_REGS alpha_HOST_ARCH
+#define hppa1_1_REGS hppa1_1_HOST_ARCH
+#define i386_REGS i386_HOST_ARCH
+#define x86_64_REGS x86_64_HOST_ARCH
+#define m68k_REGS m68k_HOST_ARCH
+#define mips_REGS (mipsel_HOST_ARCH || mipseb_HOST_ARCH)
+#define powerpc_REGS (powerpc_HOST_ARCH || powerpc64_HOST_ARCH || rs6000_HOST_ARCH)
+#define ia64_REGS ia64_HOST_ARCH
+#define sparc_REGS sparc_HOST_ARCH
+#define darwin_REGS darwin_HOST_OS
+#endif
+
/* ----------------------------------------------------------------------------
Caller saves and callee-saves regs.
Caller-saves regs have to be saved around C-calls made from STG
land, so this file defines CALLER_SAVES_<reg> for each <reg> that
is designated caller-saves in that machine's C calling convention.
-
- Additionally, the following macros should be defined when
-
- CALLER_SAVES_USER one or more of R<n>, F, D
- are caller-saves.
-
- CALLER_SAVES_SYSTEM one or more of Sp, SpLim, Hp, HpLim
- are caller-saves.
-
- This is so that the callWrapper mechanism knows which kind of
- wrapper to generate for certain types of C call.
-------------------------------------------------------------------------- */
/* -----------------------------------------------------------------------------
t12 $27 NCG_reserved
-------------------------------------------------------------------------- */
-#if defined(alpha_TARGET_ARCH)
+#if alpha_REGS
# define REG(x) __asm__("$" #x)
# define CALLER_SAVES_R2
# define NCG_Reserved_F1 f29
# define NCG_Reserved_F2 f30
-#endif /* alpha_TARGET_ARCH */
+#endif /* alpha_REGS */
/* -----------------------------------------------------------------------------
The HP-PA register mapping
\tr{%fr8}--\tr{%fr11} are some available caller-save fl-pt registers.
-------------------------------------------------------------------------- */
-#if hppa1_1_TARGET_ARCH
+#if hppa1_1_REGS
#define REG(x) __asm__("%" #x)
-------------------------------------------------------------------------- */
-#if i386_TARGET_ARCH
+#if i386_REGS
#define REG(x) __asm__("%" #x)
#endif
#define REG_Sp ebp
+#ifndef STOLEN_X86_REGS
+#define STOLEN_X86_REGS 4
+#endif
+
#if STOLEN_X86_REGS >= 3
# define REG_R1 esi
#endif
/* -----------------------------------------------------------------------------
The x86-64 register mapping
- callee-saves
- %rax
+ %rax caller-saves, don't steal this one
%rbx YES
- %rcx
- %rdx (seem to be used as arg regs on x86-64)
- %rsi (seem to be used as arg regs on x86-64)
- %rdi (seem to be used as arg regs on x86-64)
- %rbp YES
+ %rcx arg reg, caller-saves
+ %rdx arg reg, caller-saves
+ %rsi arg reg, caller-saves
+ %rdi arg reg, caller-saves
+ %rbp YES (our *prime* register)
%rsp (unavailable - stack pointer)
- %r8
- %r9
- %r10
- %r11
+ %r8 arg reg, caller-saves
+ %r9 arg reg, caller-saves
+ %r10 caller-saves
+ %r11 caller-saves
%r12 YES
%r13 YES
%r14 YES
%r15 YES
+
+ %xmm0-7 arg regs, caller-saves
+ %xmm8-15 caller-saves
+
+ Use the caller-saves regs for Rn, because we don't always have to
+ save those (as opposed to Sp/Hp/SpLim etc. which always have to be
+ saved).
+
--------------------------------------------------------------------------- */
-#if x86_64_TARGET_ARCH
+#if x86_64_REGS
#define REG(x) __asm__("%" #x)
-#define REG_Base rbx
+#define REG_Base r13
#define REG_Sp rbp
#define REG_Hp r12
-#define REG_R1 r13
+#define REG_R1 rbx
+#define REG_R2 rsi
+#define REG_R3 rdi
+#define REG_R4 r8
+#define REG_R5 r9
#define REG_SpLim r14
#define REG_HpLim r15
-/* ToDo: try R2/R3 instead of SpLim/HpLim? */
-#define MAX_REAL_VANILLA_REG 1
-#define MAX_REAL_FLOAT_REG 0
-#define MAX_REAL_DOUBLE_REG 0
+#define REG_F1 xmm1
+#define REG_F2 xmm2
+#define REG_F3 xmm3
+#define REG_F4 xmm4
+
+#define REG_D1 xmm5
+#define REG_D2 xmm6
+
+#define CALLER_SAVES_R2
+#define CALLER_SAVES_R3
+#define CALLER_SAVES_R4
+#define CALLER_SAVES_R5
+
+#define CALLER_SAVES_F1
+#define CALLER_SAVES_F2
+#define CALLER_SAVES_F3
+#define CALLER_SAVES_F4
+
+#define CALLER_SAVES_D1
+#define CALLER_SAVES_D2
+
+#define MAX_REAL_VANILLA_REG 5
+#define MAX_REAL_FLOAT_REG 4
+#define MAX_REAL_DOUBLE_REG 2
#define MAX_REAL_LONG_REG 0
#endif /* x86_64 */
\end{tabular}
-------------------------------------------------------------------------- */
-#if m68k_TARGET_ARCH
+#if m68k_REGS
#define REG(x) __asm__(#x)
We can steal some, but we might have to save/restore around ccalls.
-------------------------------------------------------------------------- */
-#if mipsel_TARGET_ARCH || mipseb_TARGET_ARCH
+#if mips_REGS
#define REG(x) __asm__("$" #x)
0 system glue? (caller-save, volatile)
1 SP (callee-save, non-volatile)
- 2 RTOC (callee-save, non-volatile)
+ 2 AIX, powerpc64-linux:
+ RTOC (a strange special case)
+ darwin:
+ (caller-save, volatile)
+ powerpc32-linux:
+ reserved for use by system
+
3-10 args/return (caller-save, volatile)
11,12 system glue? (caller-save, volatile)
- 13-31 (callee-save, non-volatile)
+ 13 on 64-bit: reserved for thread state pointer
+ on 32-bit: (callee-save, non-volatile)
+ 14-31 (callee-save, non-volatile)
f0 (caller-save, volatile)
f1-f13 args/return (caller-save, volatile)
f14-f31 (callee-save, non-volatile)
- \tr{13}--\tr{31} are wonderful callee-save registers.
+ \tr{14}--\tr{31} are wonderful callee-save registers on all ppc OSes.
\tr{0}--\tr{12} are caller-save registers.
\tr{%f14}--\tr{%f31} are callee-save floating-point registers.
- I think we can do the Whole Business with callee-save registers only!
+ We can do the Whole Business with callee-save registers only!
-------------------------------------------------------------------------- */
-#if powerpc_TARGET_ARCH || rs6000_TARGET_ARCH
+#if powerpc_REGS
#define REG(x) __asm__(#x)
#define REG_R7 r20
#define REG_R8 r21
+#if darwin_REGS
+
#define REG_F1 f14
#define REG_F2 f15
#define REG_F3 f16
#define REG_D1 f18
#define REG_D2 f19
+#else
+
+#define REG_F1 fr14
+#define REG_F2 fr15
+#define REG_F3 fr16
+#define REG_F4 fr17
+
+#define REG_D1 fr18
+#define REG_D2 fr19
+
+#endif
+
#define REG_Sp r22
#define REG_SpLim r24
#define REG_Hp r25
#define REG_HpLim r26
-#define NCG_SpillTmp_I1 r27
-#define NCG_SpillTmp_I2 r28
-
-#define NCG_SpillTmp_D1 f20
-#define NCG_SpillTmp_D2 f21
+#define REG_Base r27
#endif /* powerpc */
\tr{f16-f32} are the callee-saved floating point registers.
-------------------------------------------------------------------------- */
-#ifdef ia64_TARGET_ARCH
+#if ia64_REGS
#define REG(x) __asm__(#x)
-------------------------------------------------------------------------- */
-#if sparc_TARGET_ARCH
+#if sparc_REGS
#define REG(x) __asm__("%" #x)
#define REG_R3 l3
#define REG_R4 l4
#define REG_R5 l5
-#define REG_R6 l6
-#define REG_R7 l7
-#define REG_R8 i5
+#define REG_R6 i5
#define REG_F1 f22
#define REG_F2 f23