X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Fincludes%2FMachRegs.h;h=92944e146792b9c9ee4804acab06620414d54978;hb=28a464a75e14cece5db40f2765a29348273ff2d2;hp=3a57495dd7518f8eaf9ab9b4cd4e8a2ee2abbdf5;hpb=f9be4bf7bed29ca0826bbd3943c02442d3ef8369;p=ghc-hetmet.git diff --git a/ghc/includes/MachRegs.h b/ghc/includes/MachRegs.h index 3a57495..92944e1 100644 --- a/ghc/includes/MachRegs.h +++ b/ghc/includes/MachRegs.h @@ -1,5 +1,4 @@ /* ----------------------------------------------------------------------------- - * $Id: MachRegs.h,v 1.8 2000/04/14 15:10:20 sewardj Exp $ * * (c) The GHC Team, 1998-1999 * @@ -15,29 +14,54 @@ * 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_ for each 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, F, D - are caller-saves. - - CALLER_SAVES_SYSTEM one or more of Sp, Su, 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. -------------------------------------------------------------------------- */ /* ----------------------------------------------------------------------------- @@ -69,7 +93,6 @@ t6 $7 R7 t7 $8 R8 s0 $9 Sp - s1 $10 Su s2 $11 SpLim s3 $12 Hp s4 $13 HpLim @@ -77,7 +100,7 @@ t12 $27 NCG_reserved -------------------------------------------------------------------------- */ -#if defined(alpha_TARGET_ARCH) +#if alpha_REGS # define REG(x) __asm__("$" #x) # define CALLER_SAVES_R2 @@ -108,7 +131,6 @@ # define REG_D2 f7 # define REG_Sp 9 -# define REG_Su 10 # define REG_SpLim 11 # define REG_Hp 12 @@ -119,7 +141,7 @@ # define NCG_Reserved_F1 f29 # define NCG_Reserved_F2 f30 -#endif /* alpha_TARGET_ARCH */ +#endif /* alpha_REGS */ /* ----------------------------------------------------------------------------- The HP-PA register mapping @@ -142,7 +164,7 @@ \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) @@ -164,7 +186,6 @@ #define REG_D2 fr21 /* L & R */ #define REG_Sp r4 -#define REG_Su r5 #define REG_SpLim r6 #define REG_Hp r7 @@ -194,11 +215,11 @@ esi R1 edi Hp - Leaving Su, SpLim, and HpLim out of the picture. + Leaving SpLim, and HpLim out of the picture. -------------------------------------------------------------------------- */ -#if i386_TARGET_ARCH +#if i386_REGS #define REG(x) __asm__("%" #x) @@ -206,7 +227,10 @@ #define REG_Base ebx #endif #define REG_Sp ebp -/* #define REG_Su ebx*/ + +#ifndef STOLEN_X86_REGS +#define STOLEN_X86_REGS 4 +#endif #if STOLEN_X86_REGS >= 3 # define REG_R1 esi @@ -224,6 +248,78 @@ #endif /* iX86 */ /* ----------------------------------------------------------------------------- + The x86-64 register mapping + + %rax caller-saves, don't steal this one + %rbx 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 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_REGS + +#define REG(x) __asm__("%" #x) + +#define REG_Base r13 +#define REG_Sp rbp +#define REG_Hp r12 +#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 + +#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 */ + +/* ----------------------------------------------------------------------------- The Motorola 680x0 register mapping A Sun3 (mc680x0) has eight address registers, \tr{a0} to \tr{a7}, and @@ -255,14 +351,13 @@ \end{tabular} -------------------------------------------------------------------------- */ -#if m68k_TARGET_ARCH +#if m68k_REGS #define REG(x) __asm__(#x) #define REG_Base a2 #define REG_Sp a3 -#define REG_Su a4 #define REG_SpLim d3 #define REG_Hp d4 @@ -298,7 +393,7 @@ 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) @@ -331,7 +426,6 @@ #define REG_D2 f30 #define REG_Sp 16 -#define REG_Su 17 #define REG_SpLim 18 #define REG_Hp 19 @@ -344,24 +438,32 @@ 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) @@ -374,6 +476,18 @@ #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_F4 f17 + +#define REG_D1 f18 +#define REG_D2 f19 + +#else + #define REG_F1 fr14 #define REG_F2 fr15 #define REG_F3 fr16 @@ -382,16 +496,60 @@ #define REG_D1 fr18 #define REG_D2 fr19 +#endif + #define REG_Sp r22 -#define REG_Su r23 #define REG_SpLim r24 #define REG_Hp r25 #define REG_HpLim r26 +#define REG_Base r27 + #endif /* powerpc */ /* ----------------------------------------------------------------------------- + The IA64 register mapping + + We place the general registers in the locals area of the register stack, + so that the call mechanism takes care of saving them for us. We reserve + the first 16 for gcc's use - since gcc uses the highest used register to + determine the register stack frame size, this gives us a constant size + register stack frame. + + \tr{f16-f32} are the callee-saved floating point registers. + -------------------------------------------------------------------------- */ + +#if ia64_REGS + +#define REG(x) __asm__(#x) + +#define REG_R1 loc16 +#define REG_R2 loc17 +#define REG_R3 loc18 +#define REG_R4 loc19 +#define REG_R5 loc20 +#define REG_R6 loc21 +#define REG_R7 loc22 +#define REG_R8 loc23 + +#define REG_F1 f16 +#define REG_F2 f17 +#define REG_F3 f18 +#define REG_F4 f19 + +#define REG_D1 f20 +#define REG_D2 f21 + +#define REG_Sp loc24 +#define REG_SpLim loc26 + +#define REG_Hp loc27 +#define REG_HpLim loc28 + +#endif /* ia64 */ + +/* ----------------------------------------------------------------------------- The Sun SPARC register mapping The SPARC register (window) story: Remember, within the Haskell @@ -414,9 +572,40 @@ Note: %g3 is *definitely* clobbered in the builtin divide code (and our save/restore machinery is NOT GOOD ENOUGH for that); discretion being the better part of valor, we also don't take %g4. + + The paired nature of the floating point registers causes complications for + the native code generator. For convenience, we pretend that the first 22 + fp regs %f0 .. %f21 are actually 11 double regs, and the remaining 10 are + float (single) regs. The NCG acts accordingly. That means that the + following FP assignment is rather fragile, and should only be changed + with extreme care. The current scheme is: + + %f0 /%f1 FP return from C + %f2 /%f3 D1 + %f4 /%f5 D2 + %f6 /%f7 ncg double spill tmp #1 + %f8 /%f9 ncg double spill tmp #2 + %f10/%f11 allocatable + %f12/%f13 allocatable + %f14/%f15 allocatable + %f16/%f17 allocatable + %f18/%f19 allocatable + %f20/%f21 allocatable + + %f22 F1 + %f23 F2 + %f24 F3 + %f25 F4 + %f26 ncg single spill tmp #1 + %f27 ncg single spill tmp #2 + %f28 allocatable + %f29 allocatable + %f30 allocatable + %f31 allocatable + -------------------------------------------------------------------------- */ -#if sparc_TARGET_ARCH +#if sparc_REGS #define REG(x) __asm__("%" #x) @@ -434,54 +623,110 @@ #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 f2 -#define REG_F2 f3 -#define REG_F3 f4 -#define REG_F4 f5 -#define REG_D1 f6 -#define REG_D2 f8 +#define REG_F1 f22 +#define REG_F2 f23 +#define REG_F3 f24 +#define REG_F4 f25 +#define REG_D1 f2 +#define REG_D2 f4 #define REG_Sp i0 -#define REG_Su i1 #define REG_SpLim i2 #define REG_Hp i3 #define REG_HpLim i4 -#define NCG_Reserved_I1 g1 -#define NCG_Reserved_I2 g2 -#define NCG_Reserved_F1 f14 -#define NCG_Reserved_F2 f15 -#define NCG_Reserved_D1 f16 -#define NCG_Reserved_D2 f18 +#define NCG_SpillTmp_I1 g1 +#define NCG_SpillTmp_I2 g2 +#define NCG_SpillTmp_F1 f26 +#define NCG_SpillTmp_F2 f27 +#define NCG_SpillTmp_D1 f6 +#define NCG_SpillTmp_D2 f8 + +#define NCG_FirstFloatReg f22 #endif /* sparc */ -/* These constants define how many stg registers are *actually* in - * registers: the code generator uses this information to avoid - * generating code to load/store registers which are really offsets - * from BaseReg. +#endif /* NO_REGS */ + +/* ----------------------------------------------------------------------------- + * These constants define how many stg registers will be used for + * passing arguments (and results, in the case of an unboxed-tuple + * return). + * + * We usually set MAX_REAL_VANILLA_REG and co. to be the number of the + * highest STG register to occupy a real machine register, otherwise + * the calling conventions will needlessly shuffle data between the + * stack and memory-resident STG registers. We might occasionally + * set these macros to other values for testing, though. * * Registers above these values might still be used, for instance to * communicate with PrimOps and RTS functions. */ #ifndef MAX_REAL_VANILLA_REG -#define MAX_REAL_VANILLA_REG 8 +# if defined(REG_R8) +# define MAX_REAL_VANILLA_REG 8 +# elif defined(REG_R7) +# define MAX_REAL_VANILLA_REG 7 +# elif defined(REG_R6) +# define MAX_REAL_VANILLA_REG 6 +# elif defined(REG_R5) +# define MAX_REAL_VANILLA_REG 5 +# elif defined(REG_R4) +# define MAX_REAL_VANILLA_REG 4 +# elif defined(REG_R3) +# define MAX_REAL_VANILLA_REG 3 +# elif defined(REG_R2) +# define MAX_REAL_VANILLA_REG 2 +# elif defined(REG_R1) +# define MAX_REAL_VANILLA_REG 1 +# else +# define MAX_REAL_VANILLA_REG 0 +# endif #endif #ifndef MAX_REAL_FLOAT_REG -#define MAX_REAL_FLOAT_REG 4 +# if defined(REG_F4) +# define MAX_REAL_FLOAT_REG 4 +# elif defined(REG_F3) +# define MAX_REAL_FLOAT_REG 3 +# elif defined(REG_F2) +# define MAX_REAL_FLOAT_REG 2 +# elif defined(REG_F1) +# define MAX_REAL_FLOAT_REG 1 +# else +# define MAX_REAL_FLOAT_REG 0 +# endif #endif #ifndef MAX_REAL_DOUBLE_REG -#define MAX_REAL_DOUBLE_REG 2 +# if defined(REG_D2) +# define MAX_REAL_DOUBLE_REG 2 +# elif defined(REG_D1) +# define MAX_REAL_DOUBLE_REG 1 +# else +# define MAX_REAL_DOUBLE_REG 0 +# endif #endif -#endif /* NO_REGS */ +#ifndef MAX_REAL_LONG_REG +# if defined(REG_L1) +# define MAX_REAL_LONG_REG 1 +# else +# define MAX_REAL_LONG_REG 0 +# endif +#endif + +/* define NO_ARG_REGS if we have no argument registers at all (we can + * optimise certain code paths using this predicate). + */ +#if MAX_REAL_VANILLA_REG < 2 +#define NO_ARG_REGS +#else +#undef NO_ARG_REGS +#endif #endif /* MACHREGS_H */