From 24794b0e83a9727da4e81c0eb917d0fe238482c8 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 20 Nov 2006 13:36:02 +0000 Subject: [PATCH] add JIT_NEED_PUSH_POP and merge correct implementation of push/pop for SPARC 2006-11-20 Paolo Bonzini Ludovic Courtes * lightning/i386/core-32.h: Disable jit_push and jit_pop if stack not needed. * lightning/i386/core-64.h: Disable jit_push and jit_pop if stack not needed. * lightning/sparc/core.h: Merge final implementation of jit_pushr and jit_popr. * lightning/ppc/core.h: Fix implementation of jit_pushr and jit_popr to work (more or less) across function calls. * tests/push-pop.c, tests/push-pop.ok: New test. * tests/Makefile.am: Run it. Patches applied: * lcourtes@laas.fr--2005-libre/lightning--stable--1.2--patch-32 Added missing SPARC changes from lightning@sv.gnu.org/lightning--stable--1.2--patch-10. * lcourtes@laas.fr--2005-libre/lightning--stable--1.2--patch-33 SPARC: Fixed pushr/popr using %l7 to hold the pushed register offset. * lcourtes@laas.fr--2005-libre/lightning--stable--1.2--patch-34 tests/push-pop.c: define `JIT_NEED_PUSH_POP'. git-archimport-id: bonzini@gnu.org--2004b/lightning--stable--1.2--patch-40 --- ChangeLog | 12 ++++++ doc/using.texi | 8 ++-- lightning/i386/core-32.h | 2 + lightning/i386/core-64.h | 2 + lightning/ppc/core.h | 8 +++- lightning/sparc/core.h | 53 ++++++++++++++++++----- tests/Makefile.am | 7 ++-- tests/Makefile.in | 24 +++++++---- tests/push-pop.c | 91 ++++++++++++++++++++++++++++++++++++++++ tests/push-pop.ok | 2 + 10 files changed, 182 insertions(+), 27 deletions(-) create mode 100644 tests/push-pop.c create mode 100644 tests/push-pop.ok diff --git a/ChangeLog b/ChangeLog index c99af4666..d10cc3157 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2006-11-20 Paolo Bonzini + Ludovic Courtes + + * lightning/i386/core-32.h: Disable jit_push and jit_pop if stack not needed. + * lightning/i386/core-64.h: Disable jit_push and jit_pop if stack not needed. + * lightning/sparc/core.h: Merge final implementation of jit_pushr and jit_popr. + * lightning/ppc/core.h: Fix implementation of jit_pushr and jit_popr to + work (more or less) across function calls. + + * tests/push-pop.c, tests/push-pop.ok: New test. + * tests/Makefile.am: Run it. + 2006-11-20 Paolo Bonzini * lightning/asm-common.h: Make 64-bit safe. diff --git a/doc/using.texi b/doc/using.texi index af139011d..2bc4cf1dd 100644 --- a/doc/using.texi +++ b/doc/using.texi @@ -768,16 +768,16 @@ variables, and pass the address around. typedef int (*pifi)(int); @rem{/* Pointer to Int Function of Int */} void stack_push(int reg, int *sp) -{ +@{ jit_stxi_i (*sp, JIT_FP, reg); *sp += sizeof (int); -} +@} void stack_pop(int reg, int *sp) -{ +@{ *sp -= sizeof (int); jit_ldxi_i (reg, JIT_FP, *sp); -} +@} pifi compile_rpn(char *expr) @{ diff --git a/lightning/i386/core-32.h b/lightning/i386/core-32.h index 87ebc802a..bc522314e 100644 --- a/lightning/i386/core-32.h +++ b/lightning/i386/core-32.h @@ -63,8 +63,10 @@ struct jit_local_state { _jitl.alloca_offset -= (amount)) /* Stack */ +#ifdef JIT_NEED_PUSH_POP #define jit_pushr_i(rs) PUSHLr(rs) #define jit_popr_i(rs) POPLr(rs) +#endif /* The += in argssize allows for stack pollution */ diff --git a/lightning/i386/core-64.h b/lightning/i386/core-64.h index 0f974760e..dfe845cdc 100644 --- a/lightning/i386/core-64.h +++ b/lightning/i386/core-64.h @@ -106,8 +106,10 @@ struct jit_local_state { #define jit_rshr_ul(d, r1, r2) jit_replace((r1), (r2), _ECX, jit_qop_ ((d), (r1), SHRQrr(_CL, (d)) )) /* Stack */ +#ifdef JIT_NEED_PUSH_POP #define jit_pushr_i(rs) PUSHQr(rs) #define jit_popr_i(rs) POPQr(rs) +#endif #define jit_base_prolog() (PUSHQr(_EBP), MOVQrr(_ESP, _EBP), PUSHQr(_EBX), PUSHQr(_R12), PUSHQr(_R13)) #define jit_prolog(n) (_jitl.nextarg_geti = 0, _jitl.alloca_offset = -24, jit_base_prolog()) diff --git a/lightning/ppc/core.h b/lightning/ppc/core.h index 962aa7bad..d52489f56 100644 --- a/lightning/ppc/core.h +++ b/lightning/ppc/core.h @@ -257,12 +257,16 @@ struct jit_local_state { #define jit_nop() NOP() #define jit_ori_i(d, rs, is) jit_chk_imu((is), ORIrri((d), (rs), (is)), ORrrr((d), (rs), JIT_AUX)) #define jit_orr_i(d, s1, s2) ORrrr((d), (s1), (s2)) -#define jit_popr_i(rs) (LWZrm((rs), 0, 1), ADDIrri(1, 1, 4)) + +#ifdef JIT_NEED_PUSH_POP +#define jit_popr_i(rs) (LWZrm((rs), 8, 1), ADDIrri(1, 1, 4)) +#define jit_pushr_i(rs) (STWrm((rs), 4, 1), ADDIrri (1, 1, -4)) +#endif + #define jit_prepare_i(numi) (_jitl.nextarg_puti = numi) #define jit_prepare_f(numf) (_jitl.nextarg_putf = numf) #define jit_prepare_d(numd) (_jitl.nextarg_putd = numd) #define jit_prolog(n) _jit_prolog(&_jit, (n)) -#define jit_pushr_i(rs) STWUrm((rs), -4, 1) #define jit_pusharg_i(rs) (--_jitl.nextarg_puti, MRrr((3 + _jitl.nextarg_putd * 2 + _jitl.nextarg_putf + _jitl.nextarg_puti), (rs))) #define jit_ret() _jit_epilog(&_jit) #define jit_retval_i(rd) MRrr((rd), 3) diff --git a/lightning/sparc/core.h b/lightning/sparc/core.h index 10ca15526..29a245199 100644 --- a/lightning/sparc/core.h +++ b/lightning/sparc/core.h @@ -34,9 +34,14 @@ #define __lightning_core_h #define JIT_R_NUM 3 -#define JIT_V_NUM 6 -#define JIT_R(i) ((i) ? _Rl((i) - 1) : _Rg(2)) -#define JIT_V(i) _Rl((i)+2) +#ifdef JIT_NEED_PUSH_POP +# define JIT_V_NUM 7 +#else +# define JIT_V_NUM 8 +#endif + +#define JIT_R(i) _Rg(2 + (i)) +#define JIT_V(i) _Rl(i) #define JIT_BIG _Rg(1) /* %g1 used to make 32-bit operands */ #define JIT_BIG2 _Ro(7) /* %o7 used to make 32-bit compare operands */ @@ -62,7 +67,7 @@ */ -/* Implementation of `allocai'. +/* Implementation of `allocai', `pushr' and `popr'. * * The SysV ABI for SPARC is specified in "System V Application Binary * Interface, SPARC Processor Supplement, Third Edition", available from @@ -77,14 +82,20 @@ * * Stack space may be allocated dynamically as decribed in Section * "Allocating Stack Space Dynamically", p. 3-36, and shown in Figure 3-49. - * `allocai' is implementing by patching a function prolog's `save' - * instruction in order to increase the initial frame size. Thus, - * %fp and below is used for the memory allocated via `allocai'. */ + * `allocai' is implemented by patching a function prolog's `save' + * instruction in order to increase the initial frame size. `pushr' is + * implemented by storing register into a fixed-size region right below %fp + * (thereby limiting the number of registers that may be pushed). + * + * Thus, %fp to %fp - JIT_SPARC_MAX_STACK_REGISTER_AREA is reserved for + * pushed registers, and %fp - JIT_SPARC_MAX_STACK_REGISTER_AREA and below is + * used for the memory allocated via `allocai'. */ struct jit_local_state { int nextarg_put; /* Next %o reg. to be written */ int nextarg_get; /* Next %i reg. to be read */ + jit_insn *save; /* Pointer to the `save' instruction */ unsigned frame_size; /* Current frame size as allocated by `save' */ int alloca_offset; /* Current offset to the alloca'd memory (negative @@ -92,8 +103,24 @@ struct jit_local_state { jit_insn delay; }; +#ifdef JIT_NEED_PUSH_POP +/* Maximum size for the "automatic variables" area on the stack (the area + that starts from %fp-1 and ends at %sp+104, see the ABI doc). This must + be a multiple of 8 so that %sp remains double-word aligned as required by + SysV ABI (see page 3-10). In lightning, this effectively limits the + number of registers that can be pushed with `pushr'. + + Initialize %l7 to contain the (negative) offset relative to %fp of the last + register pushed. */ +# define JIT_SPARC_MAX_STACK_REGISTER_AREA (8 * sizeof (void *)) +# define JIT_SPARC_INIT_PUSH_POP() (MOVrr (_Rg(0), _Rl(7))) +#else +# define JIT_SPARC_MAX_STACK_REGISTER_AREA 0 +# define JIT_SPARC_INIT_PUSH_POP() ((void)0) +#endif + /* Minimum size of a stack frame. */ -#define JIT_SPARC_MIN_FRAME_SIZE 104 +#define JIT_SPARC_MIN_FRAME_SIZE (104 + JIT_SPARC_MAX_STACK_REGISTER_AREA) /* Round AMOUNT to the closest higher multiple of 2^ALIGNMENT. */ @@ -288,10 +315,9 @@ struct jit_local_state { #define jit_ori_i(d, rs, is) jit_chk_imm((is), ORrir((rs), (is), (d)), ORrrr((rs), JIT_BIG, (d))) #define jit_orr_i(d, s1, s2) ORrrr((s1), (s2), (d)) #define jit_patch_at(delay_pc, pv) jit_patch_ (((delay_pc) - 1) , (pv)) -#define jit_popr_i(rs) (LDmr(JIT_SP, 0, (rs)), ADDrir(JIT_SP, 8, JIT_SP)) #define jit_prepare_i(num) (_jitl.nextarg_put += (num)) -#define jit_prolog(numargs) (_jitl.save = (jit_insn *) _jit.x.pc, SAVErir (JIT_SP, -JIT_SPARC_MIN_FRAME_SIZE, JIT_SP), _jitl.frame_size = JIT_SPARC_MIN_FRAME_SIZE, _jitl.alloca_offset = 0, _jitl.nextarg_get = _Ri(0), _jitl.next_push = 0) -#define jit_pushr_i(rs) (STrm((rs), JIT_SP, -8), SUBrir(JIT_SP, 8, JIT_SP)) +#define jit_prolog(numargs) (_jitl.save = (jit_insn *) _jit.x.pc, SAVErir (JIT_SP, -JIT_SPARC_MIN_FRAME_SIZE, JIT_SP), _jitl.frame_size = JIT_SPARC_MIN_FRAME_SIZE, _jitl.alloca_offset = -JIT_SPARC_MAX_STACK_REGISTER_AREA, _jitl.nextarg_get = _Ri(0), JIT_SPARC_INIT_PUSH_POP ()) + #define jit_pusharg_i(rs) (--_jitl.nextarg_put, MOVrr((rs), _Ro(_jitl.nextarg_put))) #define jit_ret() (RET(), RESTORE()) #define jit_retval_i(rd) MOVrr(_Ro(0), (rd)) @@ -312,4 +338,9 @@ struct jit_local_state { #define jit_xori_i(d, rs, is) jit_chk_imm((is), XORrir((rs), (is), (d)), XORrrr((rs), JIT_BIG, (d))) #define jit_xorr_i(d, s1, s2) XORrrr((s1), (s2), (d)) +#ifdef JIT_NEED_PUSH_POP +# define jit_pushr_i(rs) (SUBrir(_Rl(7), sizeof (void *), _Rl(7)), STWrx((rs), JIT_FP, _Rl(7))) +# define jit_popr_i(rd) (LDSWxr(_Rl(7), JIT_FP, (rd)), ADDrir(_Rl(7), sizeof (void *), _Rl(7))) +#endif + #endif /* __lightning_core_h */ diff --git a/tests/Makefile.am b/tests/Makefile.am index 4b38437fa..c9cac9e89 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -2,12 +2,12 @@ AM_CPPFLAGS = -I$(top_builddir) -I$(top_srcdir) -I$(top_srcdir)/lightning/$(cpu) check_PROGRAMS = fibit incr printf printf2 rpn fib fibdelay \ add bp testfp funcfp rpnfp modi ldxi divi movi ret \ - allocai + allocai push-pop noinst_DATA = fibit.ok incr.ok printf.ok printf2.ok rpn.ok \ fib.ok fibdelay.ok testfp.ok funcfp.ok rpnfp.ok add.ok \ bp.ok modi.ok ldxi.ok divi.ok movi.ok ret.ok \ - allocai.ok + allocai.ok push-pop.ok EXTRA_DIST = $(noinst_DATA) run-test @@ -17,7 +17,8 @@ endif if REGRESSION_TESTING TESTS = fib fibit fibdelay incr printf printf2 rpn add bp \ - testfp funcfp rpnfp modi ldxi divi movi ret allocai + testfp funcfp rpnfp modi ldxi divi movi ret allocai \ + push-pop TESTS_ENVIRONMENT=$(srcdir)/run-test endif diff --git a/tests/Makefile.in b/tests/Makefile.in index 96613a18a..eda7bcae6 100644 --- a/tests/Makefile.in +++ b/tests/Makefile.in @@ -41,7 +41,7 @@ check_PROGRAMS = fibit$(EXEEXT) incr$(EXEEXT) printf$(EXEEXT) \ printf2$(EXEEXT) rpn$(EXEEXT) fib$(EXEEXT) fibdelay$(EXEEXT) \ add$(EXEEXT) bp$(EXEEXT) testfp$(EXEEXT) funcfp$(EXEEXT) \ rpnfp$(EXEEXT) modi$(EXEEXT) ldxi$(EXEEXT) divi$(EXEEXT) \ - movi$(EXEEXT) ret$(EXEEXT) allocai$(EXEEXT) + movi$(EXEEXT) ret$(EXEEXT) allocai$(EXEEXT) push-pop$(EXEEXT) subdir = tests DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -111,6 +111,11 @@ printf2_OBJECTS = printf2.$(OBJEXT) printf2_LDADD = $(LDADD) @DISASS_TRUE@printf2_DEPENDENCIES = \ @DISASS_TRUE@ $(top_builddir)/opcode/libdisass.a +push_pop_SOURCES = push-pop.c +push_pop_OBJECTS = push-pop.$(OBJEXT) +push_pop_LDADD = $(LDADD) +@DISASS_TRUE@push_pop_DEPENDENCIES = \ +@DISASS_TRUE@ $(top_builddir)/opcode/libdisass.a ret_SOURCES = ret.c ret_OBJECTS = ret.$(OBJEXT) ret_LDADD = $(LDADD) @@ -135,11 +140,11 @@ COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ CCLD = $(CC) LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ SOURCES = add.c allocai.c bp.c divi.c fib.c fibdelay.c fibit.c \ - funcfp.c incr.c ldxi.c modi.c movi.c printf.c printf2.c ret.c \ - rpn.c rpnfp.c testfp.c + funcfp.c incr.c ldxi.c modi.c movi.c printf.c printf2.c \ + push-pop.c ret.c rpn.c rpnfp.c testfp.c DIST_SOURCES = add.c allocai.c bp.c divi.c fib.c fibdelay.c fibit.c \ - funcfp.c incr.c ldxi.c modi.c movi.c printf.c printf2.c ret.c \ - rpn.c rpnfp.c testfp.c + funcfp.c incr.c ldxi.c modi.c movi.c printf.c printf2.c \ + push-pop.c ret.c rpn.c rpnfp.c testfp.c DATA = $(noinst_DATA) ETAGS = etags CTAGS = ctags @@ -248,12 +253,13 @@ AM_CPPFLAGS = -I$(top_builddir) -I$(top_srcdir) -I$(top_srcdir)/lightning/$(cpu) noinst_DATA = fibit.ok incr.ok printf.ok printf2.ok rpn.ok \ fib.ok fibdelay.ok testfp.ok funcfp.ok rpnfp.ok add.ok \ bp.ok modi.ok ldxi.ok divi.ok movi.ok ret.ok \ - allocai.ok + allocai.ok push-pop.ok EXTRA_DIST = $(noinst_DATA) run-test @DISASS_TRUE@LDADD = $(top_builddir)/opcode/libdisass.a @REGRESSION_TESTING_TRUE@TESTS = fib fibit fibdelay incr printf printf2 rpn add bp \ -@REGRESSION_TESTING_TRUE@ testfp funcfp rpnfp modi ldxi divi movi ret allocai +@REGRESSION_TESTING_TRUE@ testfp funcfp rpnfp modi ldxi divi movi ret allocai \ +@REGRESSION_TESTING_TRUE@ push-pop @REGRESSION_TESTING_TRUE@TESTS_ENVIRONMENT = $(srcdir)/run-test all: all-am @@ -334,6 +340,9 @@ printf$(EXEEXT): $(printf_OBJECTS) $(printf_DEPENDENCIES) printf2$(EXEEXT): $(printf2_OBJECTS) $(printf2_DEPENDENCIES) @rm -f printf2$(EXEEXT) $(LINK) $(printf2_LDFLAGS) $(printf2_OBJECTS) $(printf2_LDADD) $(LIBS) +push-pop$(EXEEXT): $(push_pop_OBJECTS) $(push_pop_DEPENDENCIES) + @rm -f push-pop$(EXEEXT) + $(LINK) $(push_pop_LDFLAGS) $(push_pop_OBJECTS) $(push_pop_LDADD) $(LIBS) ret$(EXEEXT): $(ret_OBJECTS) $(ret_DEPENDENCIES) @rm -f ret$(EXEEXT) $(LINK) $(ret_LDFLAGS) $(ret_OBJECTS) $(ret_LDADD) $(LIBS) @@ -367,6 +376,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/movi.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/printf.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/printf2.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/push-pop.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ret.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rpn.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rpnfp.Po@am__quote@ diff --git a/tests/push-pop.c b/tests/push-pop.c new file mode 100644 index 000000000..75738f504 --- /dev/null +++ b/tests/push-pop.c @@ -0,0 +1,91 @@ +/******************************** -*- C -*- **************************** + * + * Test `jit_pushr_i' and `jit_popr_i' + * + ***********************************************************************/ + + +/* Contributed by Ludovic Courtès. */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#define JIT_NEED_PUSH_POP + +#include +#include +#include "lightning.h" + +typedef int (* stakumilo_t) (int); + +static void +display_message (const char *fmt, int i) +{ + printf (fmt, i); +} + +static stakumilo_t +generate_push_pop (void) +{ + static const char msg[] = "we got %i\n"; + static char buffer[1024]; + stakumilo_t result; + int arg; + + result = (stakumilo_t)(jit_set_ip (buffer).ptr); + jit_prolog (1); + arg = jit_arg_i (); + jit_getarg_i (JIT_R1, arg); + + /* Save R1 on the stack. */ + jit_pushr_i (JIT_R1); + + /* Save two other registers just for the sake of using the stack. */ + jit_movi_i (JIT_R0, -1); + jit_movi_i (JIT_R2, -1); + jit_pushr_i (JIT_R0); + jit_pushr_i (JIT_R2); + + jit_movr_i (JIT_R0, JIT_R1); + jit_movi_p (JIT_R1, msg); + + /* Invoke a function that may modify R1. */ + jit_prepare (2); + jit_pusharg_i (JIT_R0); + jit_pusharg_p (JIT_R1); + (void)jit_finish (display_message); + + /* Restore the dummy registers. */ + jit_popr_i (JIT_R2); + jit_popr_i (JIT_R0); + + /* Restore R1. */ + jit_popr_i (JIT_R1); + + jit_movr_i (JIT_RET, JIT_R1); + + jit_ret (); + jit_flush_code (buffer, jit_get_ip ().ptr); + + return result; +} + + +int +main (int argc, char *argv[]) +{ + stakumilo_t stakumilo; + + stakumilo = generate_push_pop (); + if (stakumilo (7777) != 7777) + { + printf ("failed: got %i instead of %i\n", + stakumilo (7777), 7777); + return 1; + } + else + printf ("succeeded\n"); + + return 0; +} diff --git a/tests/push-pop.ok b/tests/push-pop.ok new file mode 100644 index 000000000..758480fe3 --- /dev/null +++ b/tests/push-pop.ok @@ -0,0 +1,2 @@ +we got 7777 +succeeded