Add inline assembler hacks for restoring the $gp register on the alpha,

Estimated hours taken: 24

Add inline assembler hacks for restoring the $gp register on the alpha,
to make the `asm_fast.gc' grade work on the alpha.

runtime/goto.h:
	For the alpha, change the GOTO macro so that it sets up
	register $27 (the "procedure value" register) to contain the
	address to which you are going to jump, and change the
	Define_{entry,local,static} macros so that they have a `ldgp'
	instruction after the label which restores the gp register from
	$27.

runtime/call.mod:
	For the alpha, change the call macro so that it uses a `ldgp'
	instruction to restore the gp register on return from a call.
	Add new call_localret macro, for the case when the continuation
	label is a local label (this is like the inverse of the localcall
	macro), because a call_localret is two instructions cheaper
	than the equivalent call would be.

runtime/engine.mod:
	In call_engine(), we need to use `Define_label(engine_done)'
	rather than just `engine_done:', so that it works on the alpha.

These changes improve the speed of the compiler by about 21%,
and cut executable size by about 24%.

There's still a fair bit of room for improving efficiency by
avoiding moves to $27 and `ldgp' instructions in situations
where they aren't needed.
This commit is contained in:
Fergus Henderson
1996-04-01 19:03:47 +00:00
parent 06d359d2d2
commit 913cda0f4a
3 changed files with 142 additions and 22 deletions

View File

@@ -80,7 +80,7 @@ static void init_registers(void)
/* The gcc-specific version */ /* The gcc-specific version */
void call_engine(Code *entry_point) void call_engine(Code *entry_point)
{ {{
/* /*
** Allocate some space for local variables in other ** Allocate some space for local variables in other
** procedures. This used to be done by just calling ** procedures. This used to be done by just calling
@@ -134,7 +134,7 @@ void call_engine(Code *entry_point)
noprof_call(entry_point, LABEL(engine_done)); noprof_call(entry_point, LABEL(engine_done));
engine_done: Define_label(engine_done);
/* /*
** Save any registers which will get clobbered by the normal ** Save any registers which will get clobbered by the normal
** C function call / return mechanism ** C function call / return mechanism
@@ -180,7 +180,7 @@ engine_done:
} }
#endif #endif
} }}
/* with nonlocal gotos, we don't save the previous locations */ /* with nonlocal gotos, we don't save the previous locations */
void dump_prev_locations(void) {} void dump_prev_locations(void) {}

View File

@@ -35,6 +35,7 @@
#define paste(a,b) a##b #define paste(a,b) a##b
#define stringify(string) #string #define stringify(string) #string
#define entry(label) paste(entry_,label) #define entry(label) paste(entry_,label)
#define skip(label) paste(skip_,label)
#ifdef SPLIT_C_FILES #ifdef SPLIT_C_FILES
#define MODULE_STATIC_OR_EXTERN extern #define MODULE_STATIC_OR_EXTERN extern
@@ -42,6 +43,84 @@
#define MODULE_STATIC_OR_EXTERN static #define MODULE_STATIC_OR_EXTERN static
#endif #endif
/*---------------------------------------------------------------------------*/
/* MACHINE SPECIFIC STUFF REQUIRED FOR NON-LOCAL GOTOS */
#if defined(__alpha__)
/* when doing a jump, we need to set $27, the "procedure value" register,
to the address we are jumping to, so that we can use an `ldgp'
instruction in ASM_ENTRY to set up the right gp value.
*/
#define ASM_JUMP(address) \
__asm__("bis %0, %0, $27\n\t" \
: : "r"(address) : "$27"); \
goto *(address)
/* Explanation:
Move `address' to register $27
Jump to `address'
*/
/* on entry to a procedure, we need to load the $gp register
with the correct value relative to the current address in $27 */
#define ASM_ENTRY(label) \
/* on fall-thru, we need to skip the ldgp instruction */ \
goto skip(label); \
entry(label): \
__asm__ __volatile__ ( \
".globl entry_" stringify(label) "\n" \
"entry_" stringify(label) ":\n\t" \
"ldgp $gp, 0($27)" \
: : : "memory" \
); \
skip(label):
/* even static entry points must fix up the $gp register, since
although there won't be any direct calls to them from another
C file, their address may be taken and so there may be indirect
calls */
#define ASM_STATIC_ENTRY(label) \
/* on fall-thru, we need to skip the ldgp instruction */ \
goto skip(label); \
entry(label): \
__asm__ __volatile__ ( \
"entry_" stringify(label) ":\n\t" \
"ldgp $gp, 0($27)" \
: : : "memory" \
); \
skip(label):
/* even local entry points must fix up the $gp register, since
although there won't be any direct calls to them from another
C file, their address may be taken and so there may be indirect
calls */
#define ASM_LOCAL_ENTRY(label) \
/* on fall-thru, we need to skip the ldgp instruction */ \
goto skip(label); \
entry(label): \
__asm__ __volatile__ ( \
"ldgp $gp, 0($27)" \
: : : "memory" \
); \
skip(label):
#else
#define ASM_JUMP(label) goto *(label)
#define ASM_ENTRY(label) \
entry(label): \
__asm__(".globl entry_" stringify(label) "\n\t" \
"entry_" stringify(label) ":" \
);
#define ASM_STATIC_ENTRY(label) \
entry(label): \
__asm__ ( \
"entry_" stringify(label) ":" \
);
#define ASM_LOCAL_ENTRY(label) \
entry(label): ;
#endif
/*---------------------------------------------------------------------------*/
#if defined(USE_GCC_NONLOCAL_GOTOS) #if defined(USE_GCC_NONLOCAL_GOTOS)
#ifndef __GNUC__ #ifndef __GNUC__
@@ -97,22 +176,24 @@
/* body of module goes here */ /* body of module goes here */
#define END_MODULE } } #define END_MODULE } }
#if defined(USE_ASM_LABELS) #if defined(USE_ASM_LABELS)
#define Declare_entry(label) \ #define Declare_entry(label) \
extern void label(void) __asm__("entry_" stringify(label)) extern void label(void) __asm__("entry_" stringify(label))
#define Declare_static(label) \ #define Declare_static(label) \
static void label(void) __asm__("entry_" stringify(label)) static void label(void) __asm__("entry_" stringify(label))
#define Define_extern_entry(label) Declare_entry(label) #define Define_extern_entry(label) Declare_entry(label)
#define Define_entry(label) \ #define Define_entry(label) \
} \ ASM_ENTRY(label) \
label: \ } \
__asm__(".globl entry_" stringify(label) "\n" \ label: \
"entry_" stringify(label) ":"); \ PRETEND_ADDRESS_IS_USED(&&entry(label)); \
{ {
#define Define_static(label) \ #define Define_static(label) \
} \ ASM_STATIC_ENTRY(label) \
label: \ } \
__asm__("entry_" stringify(label) ":"); \ label: \
PRETEND_ADDRESS_IS_USED(&&entry(label)); \
{ {
/* /*
The PRETEND_ADDRESS_IS_USED macro is necessary to The PRETEND_ADDRESS_IS_USED macro is necessary to
@@ -125,6 +206,8 @@
#define ENTRY(label) (&label) #define ENTRY(label) (&label)
#define JUMP(label) ASM_JUMP(label)
#else #else
/* !defined(USE_ASM_LABELS) */ /* !defined(USE_ASM_LABELS) */
@@ -144,24 +227,24 @@
entry(label) = &&label entry(label) = &&label
#define ENTRY(label) (entry(label)) #define ENTRY(label) (entry(label))
#define JUMP(label) goto (*label)
#endif #endif
#define Declare_local(label) /* no declaration required */ #define Declare_local(label) /* no declaration required */
#define Define_local(label) \ #define Define_local(label) \
ASM_LOCAL_ENTRY(label) \
} \ } \
label: \ label: \
{ {
#define init_local(label) make_local(stringify(label), &&label) #define init_local(label) make_local(stringify(label), &&label)
#define Declare_label(label) /* no declaration required */ #define Declare_label(label) /* no declaration required */
#define Define_label(label) \ #define Define_label(label) Define_local(label)
} \
label: \
{
#define init_label(label) make_label(stringify(label), &&label) #define init_label(label) make_label(stringify(label), &&label)
#define LOCAL(label) (&&label) #define LOCAL(label) (&&entry(label))
#define LABEL(label) (&&label) #define LABEL(label) (&&entry(label))
#define GOTO(label) do { debuggoto(label); goto *(label); } while(0) #define GOTO(label) do { debuggoto(label); JUMP(label); } while(0)
#define GOTO_ENTRY(label) GOTO(ENTRY(label)) #define GOTO_ENTRY(label) GOTO(ENTRY(label))
#define GOTO_LOCAL(label) GOTO_LABEL(label) #define GOTO_LOCAL(label) GOTO_LABEL(label)
#define GOTO_LABEL(label) do { debuggoto(&&label); goto label; } while(0) #define GOTO_LABEL(label) do { debuggoto(&&label); goto label; } while(0)

View File

@@ -66,6 +66,37 @@ typedef void (*Cont) (void);
GOTO_LABEL(label); \ GOTO_LABEL(label); \
} while (0) } while (0)
#if defined(__alpha__) && defined(USE_ASM_LABELS)
#define noprof_call(proc, succ_cont) \
({ \
__label__ fixup_gp; \
debugcall((proc), (succ_cont)); \
succip = (&&fixup_gp); \
set_prof_current_proc(proc); \
GOTO(proc); \
fixup_gp: \
__asm__ __volatile__ ( \
"ldgp $gp, 0($27)" \
: : : "memory" \
); \
GOTO(succ_cont); \
})
/* same as above, but with GOTO_LABEL rather than GOTO */
#define noprof_call_localret(proc, succ_cont) \
({ \
__label__ fixup_gp; \
debugcall((proc), (succ_cont)); \
succip = (&&fixup_gp); \
set_prof_current_proc(proc); \
GOTO(proc); \
fixup_gp: \
__asm__ __volatile__ ( \
"ldgp $gp, 0($27)" \
: : : "memory" \
); \
GOTO_LABEL(succ_cont); \
})
#else
#define noprof_call(proc, succ_cont) \ #define noprof_call(proc, succ_cont) \
do { \ do { \
debugcall((proc), (succ_cont)); \ debugcall((proc), (succ_cont)); \
@@ -73,6 +104,9 @@ typedef void (*Cont) (void);
set_prof_current_proc(proc); \ set_prof_current_proc(proc); \
GOTO(proc); \ GOTO(proc); \
} while (0) } while (0)
#define noprof_call_localret(proc, succ_cont) \
noprof_call((proc), LABEL(succ_cont))
#endif
#define localcall(label, succ_cont, current_label) \ #define localcall(label, succ_cont, current_label) \
do { \ do { \
@@ -85,11 +119,14 @@ typedef void (*Cont) (void);
#define call(proc, succ_cont, current_label) \ #define call(proc, succ_cont, current_label) \
do { \ do { \
debugcall((proc), (succ_cont)); \
succip = (succ_cont); \
PROFILE((proc), (current_label)); \ PROFILE((proc), (current_label)); \
set_prof_current_proc(proc); \ noprof_call((proc), (succ_cont)); \
GOTO(proc); \ } while (0)
#define call_localret(proc, succ_cont, current_label) \
do { \
PROFILE((proc), (current_label)); \
noprof_call_localret(proc, succ_cont); \
} while (0) } while (0)
#define call_det_closure(succ_cont, current_label) \ #define call_det_closure(succ_cont, current_label) \