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 */
void call_engine(Code *entry_point)
{
{{
/*
** Allocate some space for local variables in other
** 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));
engine_done:
Define_label(engine_done);
/*
** Save any registers which will get clobbered by the normal
** C function call / return mechanism
@@ -180,7 +180,7 @@ engine_done:
}
#endif
}
}}
/* with nonlocal gotos, we don't save the previous locations */
void dump_prev_locations(void) {}

View File

@@ -35,6 +35,7 @@
#define paste(a,b) a##b
#define stringify(string) #string
#define entry(label) paste(entry_,label)
#define skip(label) paste(skip_,label)
#ifdef SPLIT_C_FILES
#define MODULE_STATIC_OR_EXTERN extern
@@ -42,6 +43,84 @@
#define MODULE_STATIC_OR_EXTERN static
#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)
#ifndef __GNUC__
@@ -97,22 +176,24 @@
/* body of module goes here */
#define END_MODULE } }
#if defined(USE_ASM_LABELS)
#define Declare_entry(label) \
extern void label(void) __asm__("entry_" stringify(label))
#define Declare_static(label) \
static void label(void) __asm__("entry_" stringify(label))
#define Define_extern_entry(label) Declare_entry(label)
#define Define_entry(label) \
} \
label: \
__asm__(".globl entry_" stringify(label) "\n" \
"entry_" stringify(label) ":"); \
#define Define_entry(label) \
ASM_ENTRY(label) \
} \
label: \
PRETEND_ADDRESS_IS_USED(&&entry(label)); \
{
#define Define_static(label) \
} \
label: \
__asm__("entry_" stringify(label) ":"); \
ASM_STATIC_ENTRY(label) \
} \
label: \
PRETEND_ADDRESS_IS_USED(&&entry(label)); \
{
/*
The PRETEND_ADDRESS_IS_USED macro is necessary to
@@ -125,6 +206,8 @@
#define ENTRY(label) (&label)
#define JUMP(label) ASM_JUMP(label)
#else
/* !defined(USE_ASM_LABELS) */
@@ -144,24 +227,24 @@
entry(label) = &&label
#define ENTRY(label) (entry(label))
#define JUMP(label) goto (*label)
#endif
#define Declare_local(label) /* no declaration required */
#define Define_local(label) \
ASM_LOCAL_ENTRY(label) \
} \
label: \
{
#define init_local(label) make_local(stringify(label), &&label)
#define Declare_label(label) /* no declaration required */
#define Define_label(label) \
} \
label: \
{
#define Define_label(label) Define_local(label)
#define init_label(label) make_label(stringify(label), &&label)
#define LOCAL(label) (&&label)
#define LABEL(label) (&&label)
#define GOTO(label) do { debuggoto(label); goto *(label); } while(0)
#define LOCAL(label) (&&entry(label))
#define LABEL(label) (&&entry(label))
#define GOTO(label) do { debuggoto(label); JUMP(label); } while(0)
#define GOTO_ENTRY(label) GOTO(ENTRY(label))
#define GOTO_LOCAL(label) GOTO_LABEL(label)
#define GOTO_LABEL(label) do { debuggoto(&&label); goto label; } while(0)

View File

@@ -66,6 +66,37 @@ typedef void (*Cont) (void);
GOTO_LABEL(label); \
} 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) \
do { \
debugcall((proc), (succ_cont)); \
@@ -73,6 +104,9 @@ typedef void (*Cont) (void);
set_prof_current_proc(proc); \
GOTO(proc); \
} while (0)
#define noprof_call_localret(proc, succ_cont) \
noprof_call((proc), LABEL(succ_cont))
#endif
#define localcall(label, succ_cont, current_label) \
do { \
@@ -85,11 +119,14 @@ typedef void (*Cont) (void);
#define call(proc, succ_cont, current_label) \
do { \
debugcall((proc), (succ_cont)); \
succip = (succ_cont); \
PROFILE((proc), (current_label)); \
set_prof_current_proc(proc); \
GOTO(proc); \
noprof_call((proc), (succ_cont)); \
} while (0)
#define call_localret(proc, succ_cont, current_label) \
do { \
PROFILE((proc), (current_label)); \
noprof_call_localret(proc, succ_cont); \
} while (0)
#define call_det_closure(succ_cont, current_label) \