From 4290adb33a5d36a044cb6cda5e96aa784b24558d Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 6 Nov 2006 08:28:04 +0000 Subject: [PATCH] add jit_allocai for SPARC Patches applied: * lcourtes@laas.fr--2005-libre/lightning--stable--1.2--patch-28 Implemented `jit_allocai' for SPARC. * lcourtes@laas.fr--2005-libre/lightning--stable--1.2--patch-29 tests/allocai.c: New test case. * lcourtes@laas.fr--2005-libre/lightning--stable--1.2--patch-30 Fixed `_d22 ()' on SPARC (fixes "displacement too large" errors). git-archimport-id: bonzini@gnu.org--2004b/lightning--stable--1.2--patch-35 --- lightning/sparc/asm.h | 4 +- lightning/sparc/core.h | 52 +++++++++++++++++++- tests/Makefile.am | 8 +-- tests/allocai.c | 109 +++++++++++++++++++++++++++++++++++++++++ tests/allocai.ok | 2 + 5 files changed, 169 insertions(+), 6 deletions(-) create mode 100644 tests/allocai.c create mode 100644 tests/allocai.ok diff --git a/lightning/sparc/asm.h b/lightning/sparc/asm.h index 9cc7ee776..0992f509d 100644 --- a/lightning/sparc/asm.h +++ b/lightning/sparc/asm.h @@ -50,8 +50,8 @@ typedef unsigned int jit_insn; #ifndef LIGHTNING_DEBUG -#define _d30(BD) ((_jit_UL(BD) - _jit_UL(_jit.x.pc))>>2) -#define _d22(BD) _ck_d(22, _d30(BD)) +#define _d30(BD) (_ck_d (30, ((_jit_SL (_jit_UL (BD) - _jit_UL (_jit.x.pc))) >> 2))) +#define _d22(BD) (_ck_d (22, ((_jit_SL (_jit_UL (BD) - _jit_UL (_jit.x.pc)) >> 2)))) #define _HI(I) (_jit_UL(I) >> (10)) #define _LO(I) (_jit_UL(I) & _MASK(10)) diff --git a/lightning/sparc/core.h b/lightning/sparc/core.h index 2795a4a4a..10ca15526 100644 --- a/lightning/sparc/core.h +++ b/lightning/sparc/core.h @@ -41,6 +41,8 @@ #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 */ #define JIT_SP _Ro(6) +#define JIT_FP _Ri(6) + #define JIT_RZERO _Rg(0) #define JIT_RET _Ri(0) @@ -59,12 +61,60 @@ * `--- _jit.x.pc */ + +/* Implementation of `allocai'. + * + * The SysV ABI for SPARC is specified in "System V Application Binary + * Interface, SPARC Processor Supplement, Third Edition", available from + * http://www.sparc.org/resource.htm . + * + * According to the SysV ABI specs: "At all times the stack pointer must + * point to a doubleword aligned, 16- word window save area." (p 3-12). The + * stack layout is shown in Figure 3-16 and the layout of a C stack frame is + * given in Figure 3-47: the area between %sp and %sp+104 is reserved for + * specific purposes, and automatic variables go between %sp+104 and %fp and + * are typically addressed using negative offsets relative to %fp. + * + * 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'. */ + + 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 + offset relative to %fp) */ jit_insn delay; }; +/* Minimum size of a stack frame. */ +#define JIT_SPARC_MIN_FRAME_SIZE 104 + + +/* Round AMOUNT to the closest higher multiple of 2^ALIGNMENT. */ +#define _jit_round(alignment, amount) \ + (((amount) & (_MASK (alignment))) \ + ? (((amount) & (~_MASK (alignment))) + (1 << (alignment))) \ + : (amount)) + +/* Patch a `save' instruction (with immediate operand) so that it increases + %sp by AMOUNT. AMOUNT is rounded so that %sp remains 8-octet aligned. */ +#define jit_patch_save(amount) \ + (* (_jitl).save &= ~_MASK (13), \ + * (_jitl).save |= _ck_d (13, -_jit_round (3, amount))) + +/* Allocate AMOUNT octets on the frame by patching the `save' instruction. */ +#define jit_allocai(amount) \ + (jit_patch_save ((_jitl).frame_size + (amount)), \ + (_jitl).frame_size += (amount), \ + (_jitl).alloca_offset -= (amount), \ + (_jitl).alloca_offset) + #define jit_fill_delay_after(branch) (_jitl.delay = *--_jit.x.pc, \ ((branch) == _jit.x.pc /* check if NOP was inserted */ \ ? (_jit.x.pc[-1] ^= 1<<29) /* no if branch, toggle annul bit */ \ @@ -240,7 +290,7 @@ struct jit_local_state { #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) (SAVErir(JIT_SP, -120, JIT_SP), _jitl.nextarg_get = _Ri(0)) +#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_pusharg_i(rs) (--_jitl.nextarg_put, MOVrr((rs), _Ro(_jitl.nextarg_put))) #define jit_ret() (RET(), RESTORE()) diff --git a/tests/Makefile.am b/tests/Makefile.am index 69cc0396a..4b38437fa 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,11 +1,13 @@ 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 + add bp testfp funcfp rpnfp modi ldxi divi movi ret \ + allocai 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 + bp.ok modi.ok ldxi.ok divi.ok movi.ok ret.ok \ + allocai.ok EXTRA_DIST = $(noinst_DATA) run-test @@ -15,7 +17,7 @@ endif if REGRESSION_TESTING TESTS = fib fibit fibdelay incr printf printf2 rpn add bp \ - testfp funcfp rpnfp modi ldxi divi movi ret + testfp funcfp rpnfp modi ldxi divi movi ret allocai TESTS_ENVIRONMENT=$(srcdir)/run-test endif diff --git a/tests/allocai.c b/tests/allocai.c new file mode 100644 index 000000000..c9947b4ab --- /dev/null +++ b/tests/allocai.c @@ -0,0 +1,109 @@ +/******************************** -*- C -*- **************************** + * + * Test `jit_allocai' + * + ***********************************************************************/ + + +/* Contributed by Ludovic Courtès. */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include "lightning.h" + +typedef int (* int_return_int_t) (int); + +static int +identity (int arg) +{ + printf ("received %i\n", arg); + return arg; +} + +static int_return_int_t +generate_function_proxy (int_return_int_t func) +{ + static const char failure_message[] = "numbers don't add up to zero\n"; + static char buffer[1024]; + + int_return_int_t result; + int arg, arg_offset, argneg_offset; + jit_insn *branch; + + result = (int_return_int_t)(jit_set_ip (buffer).ptr); + jit_prolog (1); + arg = jit_arg_i (); + jit_getarg_i (JIT_R1, arg); + + /* Store the argument on the stack. */ + arg_offset = jit_allocai (sizeof (int)); + jit_stxi_i (arg_offset, JIT_FP, JIT_R1); + + /* Store the negative of the argument on the stack. */ + argneg_offset = jit_allocai (sizeof (int)); + jit_negr_i (JIT_R2, JIT_R1); + jit_stxi_i (argneg_offset, JIT_FP, JIT_R2); + + /* Invoke FUNC. */ + jit_prepare (1); + jit_pusharg_i (JIT_R1); + (void)jit_finish (func); + + /* Ignore the result. */ + + /* Restore the negative and the argument from the stack. */ + jit_ldxi_i (JIT_R2, JIT_FP, argneg_offset); + jit_ldxi_i (JIT_V1, JIT_FP, arg_offset); + + /* Make sure they still add to zero. */ + jit_addr_i (JIT_R0, JIT_V1, JIT_R2); + branch = jit_bnei_i (jit_forward (), JIT_R0, 0); + + /* Return it. */ + jit_movr_i (JIT_RET, JIT_V1); + jit_ret (); + + /* Display a failure message. */ + jit_patch (branch); + jit_movi_p (JIT_R2, failure_message); + jit_prepare (1); + jit_pusharg_p (JIT_R2); + jit_finish (printf); + + /* Leave. */ + jit_movr_i (JIT_RET, JIT_V1); + jit_ret (); + + jit_flush_code (buffer, jit_get_ip ().ptr); + + return result; +} + + +int +main (int argc, char *argv[]) +{ + int_return_int_t identity_func; + + identity_func = generate_function_proxy (identity); + if (identity_func (7777) != 7777) + { + printf ("failed: got %i instead of %i\n", + identity_func (7777), 7777); + return 1; + } + else + printf ("succeeded\n"); + + return 0; +} + +/* + Local Variables: + coding: latin-1 + End: + */ diff --git a/tests/allocai.ok b/tests/allocai.ok new file mode 100644 index 000000000..2962f7a57 --- /dev/null +++ b/tests/allocai.ok @@ -0,0 +1,2 @@ +received 7777 +succeeded