1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-06-11 22:31:12 +02:00

Adjust lightning to work on ppc AIX.

Many thanks to Trent Nelson from snakebite.org for giving access to a
build farm with several different architectures and operating systems.

	* check/lightning.c, lib/jit_disasm.c, lib/jit_ppc-cpu.c,
	lib/jit_ppc-fpu.c, lib/jit_ppc.c, include/lightning.h,
	include/lightning/jit_ppc.h, include/lightning/jit_private.h:
	Adapt code to work on 32 bit AIX ppc using gcc. Most changes
	are basically to adapt the elf64 logic to 32 bit, as it does
	not use the same convention of 32 bit Darwin ppc.

	* check/stack.tst: Add a fake memcpy function to the test
	case if running under AIX, as it is not available to dlsym.

	* configure.ac: Check for getopt.h header, not available in
	AIX.
This commit is contained in:
pcpa 2013-06-07 21:27:52 -03:00
parent ce6ab1f09e
commit 3e5a12f747
11 changed files with 189 additions and 78 deletions

View file

@ -1,3 +1,18 @@
2013-07-01 Paulo Andrade <pcpa@gnu.org>
* check/lightning.c, lib/jit_disasm.c, lib/jit_ppc-cpu.c,
lib/jit_ppc-fpu.c, lib/jit_ppc.c, include/lightning.h,
include/lightning/jit_ppc.h, include/lightning/jit_private.h:
Adapt code to work on 32 bit AIX ppc using gcc. Most changes
are basically to adapt the elf64 logic to 32 bit, as it does
not use the same convention of 32 bit Darwin ppc.
* check/stack.tst: Add a fake memcpy function to the test
case if running under AIX, as it is not available to dlsym.
* configure.ac: Check for getopt.h header, not available in
AIX.
2013-06-01 Paulo Andrade <pcpa@gnu.org>
* include/lightning/jit_hppa.h, lib/jit_hppa-cpu.c,

View file

@ -15,7 +15,15 @@
* Paulo Cesar Pereira de Andrade
*/
#include <getopt.h>
#if HAVE_CONFIG_H
# include "config.h"
#endif
#if HAVE_GETOPT_H
# include <getopt.h>
#else
# include <unistd.h>
#endif
#include <stdio.h>
#include <stdarg.h>
#include <lightning.h>
@ -25,6 +33,11 @@
# include <fpu_control.h>
#endif
/* The label_t identifier clashes with a definition in sys/types.h */
#if defined(_AIX)
# define label_t l_label_t
#endif
#if defined(__GNUC__)
# define noreturn __attribute__ ((noreturn))
# define printf_format(f, v) __attribute__ ((format (printf, f, v)))
@ -3769,25 +3782,34 @@ rehash(hash_t *hash)
static void
usage(void)
{
#if HAVE_GETOPT_H
fprintf(stderr, "\
Usage: %s [jit assembler options] file [jit program options]\n\
Jit assembler options:\n\
-help Display this information\n\
-v[0-3] Verbose output level\n\
-D<macro>[=<val>] Preprocessor options\n"
#if defined(__i386__) && __WORDSIZE == 32
# if defined(__i386__) && __WORDSIZE == 32
" -mx87=1 Force using x87 when sse2 available\n"
#endif
#if defined(__i386__) || defined(__x86_64__)
# endif
# if defined(__i386__) || defined(__x86_64__)
" -msse4_1=0 Do not use sse4_1 instructions when available\n"
#endif
#if defined(__arm__)
# endif
# if defined(__arm__)
" -mcpu=<val> Force cpu version (4, 5, 6 or 7)\n\
-mthumb[=0|1] Enable or disable thumb\n\
-mvfp=<val> Set vpf version (0 to disable)\n\
-mneon[=0|1] Enable or disable neon\n"
#endif
# endif
, progname);
#else
fprintf(stderr, "\
Usage: %s [jit assembler options] file [jit program options]\n\
Jit assembler options:\n\
-h Display this information\n\
-v Verbose output level\n\
-D<macro>[=<val>] Preprocessor options\n", progname);
#endif
finish_jit();
exit(1);
}
@ -3795,23 +3817,26 @@ Jit assembler options:\n\
int
main(int argc, char *argv[])
{
#if HAVE_GETOPT_H
static const char *short_options = "v::";
static struct option long_options[] = {
{ "help", 0, 0, 'h' },
#if defined(__i386__) && __WORDSIZE == 32
# if defined(__i386__) && __WORDSIZE == 32
{ "mx87", 2, 0, '7' },
#endif
#if defined(__i386__) || defined(__x86_64__)
# endif
# if defined(__i386__) || defined(__x86_64__)
{ "msse4_1", 2, 0, '4' },
#endif
#if defined(__arm__)
# endif
# if defined(__arm__)
{ "mcpu", 2, 0, 'c' },
{ "mthumb", 2, 0, 't' },
{ "mvfp", 2, 0, 'f' },
{ "mneon", 2, 0, 'n' },
#endif
# endif
{ 0, 0, 0, 0 }
};
#else
#endif /* HAVE_GETOPT_H */
int offset;
char *endptr;
int opt_index;
@ -3822,6 +3847,7 @@ main(int argc, char *argv[])
init_jit(progname);
#if HAVE_GETOPT_H
for (;;) {
if ((opt_short = getopt_long_only(argc, argv, short_options,
long_options, &opt_index)) < 0)
@ -3903,6 +3929,14 @@ main(int argc, char *argv[])
#endif
}
}
#else
while ((opt_short = getopt(argc, argv, "hv")) >= 0) {
if (opt_short == 'v')
++flag_verbose;
else
usage();
}
#endif
opt_index = optind;
if (opt_index < 0 || opt_index >= argc)
@ -3979,6 +4013,11 @@ main(int argc, char *argv[])
opt_short += snprintf(cmdline + opt_short,
sizeof(cmdline) - opt_short,
" -D__hppa__=1");
#endif
#if defined(_AIX)
opt_short += snprintf(cmdline + opt_short,
sizeof(cmdline) - opt_short,
" -D_AIX=1");
#endif
if ((parser.fp = popen(cmdline, "r")) == NULL)
error("cannot execute %s", cmdline);

View file

@ -181,7 +181,7 @@ test##T##_##N: \
pushargr %v1 \
pushargr %v0 \
pushargi $(N * szof##T) \
finishi @memcpy \
finishi MEMCPY \
/* stack buffer for next function in %v2 */ \
allocai $(M * szof##T) $index \
addi %v2 %fp $index \
@ -235,7 +235,7 @@ test##T##_17: \
pushargr %v1 \
pushargr %v2 \
pushargi $(16 * szof##T) \
finishi @memcpy \
finishi MEMCPY \
/* call next function */ \
prepare \
pushargr %v2 \
@ -286,6 +286,32 @@ ok:
.code
jmpi main
#if _AIX
# define MEMCPY memcpy
/* error: Function not implemented (memcpy) */
name memcpy
memcpy:
prolog
arg $dst
arg $src
arg $len
getarg %r0 $dst
getarg %r1 $src
getarg %r2 $len
movr %v1 %r0
blti memcpy_done %r2 1
memcpy_loop:
subi %r2 %r2 1
ldxr_c %v0 %r1 %r2
stxr_c %r2 %r0 %v0
bgti memcpy_loop %r2 0
memcpy_done:
retr %v1
epilog
#else
# define MEMCPY @memcpy
#endif
FILL(_c)
FILL(_s)
FILL(_i)

View file

@ -27,6 +27,8 @@ AC_PROG_LIBTOOL
AC_CHECK_FUNCS(mremap,,)
AC_CHECK_HEADERS([getopt.h],,,)
AC_ARG_ENABLE(disassembler,
AS_HELP_STRING([--enable-disassembler],
[Enable jit disassembler using binutils]),

View file

@ -28,16 +28,32 @@
#include <string.h>
#ifndef __WORDSIZE
# define __WORDSIZE WORDSIZE
# if defined(_AIX)
# define __WORDSIZE (__SIZEOF_POINTER__ << 3)
# else
# define __WORDSIZE WORDSIZE
# endif
#endif
#ifndef __BYTE_ORDER
# define __BYTE_ORDER BYTE_ORDER
# if defined(_AIX)
# define __BYTE_ORDER __BYTE_ORDER__
# else
# define __BYTE_ORDER BYTE_ORDER
# endif
#endif
#ifndef __LITTLE_ENDIAN
# define __LITTLE_ENDIAN LITTLE_ENDIAN
# if defined(_AIX)
# define __LITTLE_ENDIAN __ORDER_LITTLE_ENDIAN__
# else
# define __LITTLE_ENDIAN LITTLE_ENDIAN
# endif
#endif
#ifndef __BIG_ENDIAN
# define __BIG_ENDIAN BIG_ENDIAN
# if defined(_AIX)
# define __BIG_ENDIAN __ORDER_BIG_ENDIAN__
# else
# define __BIG_ENDIAN BIG_ENDIAN
# endif
#endif
typedef signed char jit_int8_t;

View file

@ -28,7 +28,7 @@ typedef enum {
#define jit_arg_reg_p(i) ((i) >= 0 && (i) < 8)
#define jit_r(i) (_R11 + (i))
#define jit_r_num() 3
#if __WORDSIZE == 32
#if __ppc__
# define jit_v(i) (_R30 - (i))
# define jit_v_num() 17
#else
@ -39,7 +39,7 @@ typedef enum {
#define jit_f(i) (_F14 + (i))
#define jit_f_num() 6
_R0,
#if __WORDSIZE == 32
#if __ppc__
# define JIT_R0 _R11
# define JIT_R1 _R12
# define JIT_R2 _R13
@ -63,7 +63,7 @@ typedef enum {
#define JIT_V11 jit_v(11)
#define JIT_V12 jit_v(12)
#define JIT_V13 jit_v(13)
#if __WORDSIZE == 32
#if __ppc__
# define JIT_V14 jit_v(14)
# define JIT_V15 jit_v(15)
# define JIT_V16 jit_v(16)

View file

@ -405,7 +405,7 @@ struct jit_compiler {
jit_int32_t values[1024]; /* pending constants */
jit_word_t patches[2048];
} consts;
#elif __powerpc64__ || __ia64__
#elif __powerpc__ || __ia64__
/* Keep track of prolog addresses, just for the sake of making
* jit that starts with a jump to a "main" label work like other
* backends. */

View file

@ -81,12 +81,16 @@ jit_init_debug(void)
if (jit_cpu.thumb)
disasm_info.disassembler_options = "force-thumb";
# endif
# if defined(__powerpc64__)
# if defined(__powerpc__)
disasm_info.arch = bfd_arch_powerpc;
disasm_info.mach = bfd_mach_ppc64;
disassemble_init_powerpc(&disasm_info);
# if defined(__powerpc64__)
disasm_info.disassembler_options = "64";
# endif
disassemble_init_powerpc(&disasm_info);
# endif
# if defined(__sparc__)
disasm_info.endian = disasm_info.display_endian = BFD_ENDIAN_BIG;
# endif

View file

@ -35,7 +35,11 @@
# define fpr_save_area 64
# define alloca_offset -(gpr_save_area + fpr_save_area)
# define ii(i) *_jit->pc.ui++ = i
# define il(i) *_jit->pc.ul++ = i
# if __WORDSIZE == 32
# define iw(i) *_jit->pc.ui++ = i
# else
# define iw(i) *_jit->pc.ul++ = i
# endif
# define can_sign_extend_short_p(im) ((im) >= -32768 && (im) <= 32767)
# define can_zero_extend_short_p(im) ((im) >= 0 && (im) <= 65535)
# define can_sign_extend_jump_p(im) ((im) >= -33554432 && (im) <= 33554431)
@ -45,9 +49,11 @@
# define _R11_REGNO 11
# define _FP_REGNO 31
# if __WORDSIZE == 32
# define ldr(r0,r1) ldr_i(r0,r1)
# define ldxi(r0,r1,i0) ldxi_i(r0,r1,i0)
# define stxi(i0,r0,r1) stxi_i(i0,r0,r1)
# else
# define ldr(r0,r1) ldr_l(r0,r1)
# define ldxi(r0,r1,i0) ldxi_l(r0,r1,i0)
# define stxi(i0,r0,r1) stxi_l(i0,r0,r1)
# endif
@ -2992,26 +2998,26 @@ _jmpi_p(jit_state_t *_jit, jit_word_t i0)
static void
_callr(jit_state_t *_jit, jit_int32_t r0)
{
# if __WORDSIZE == 64
stxi(40, _SP_REGNO, _R2_REGNO);
# if __powerpc__
stxi(sizeof(void*) * 5, _SP_REGNO, _R2_REGNO);
/* FIXME Pretend to not know about r11? */
if (r0 == _R0_REGNO) {
movr(_R11_REGNO, _R0_REGNO);
ldxi(_R2_REGNO, _R11_REGNO, 8);
ldxi(_R11_REGNO, _R11_REGNO, 16);
ldxi(_R2_REGNO, _R11_REGNO, sizeof(void*));
ldxi(_R11_REGNO, _R11_REGNO, sizeof(void*) * 2);
}
else {
ldxi(_R2_REGNO, r0, 8);
ldxi(_R11_REGNO, r0, 16);
ldxi(_R2_REGNO, r0, sizeof(void*));
ldxi(_R11_REGNO, r0, sizeof(void*) * 2);
}
LDX(r0, _R0_REGNO, r0);
ldr(r0, r0);
# endif
MTCTR(r0);
BCTRL();
# if __WORDSIZE == 64
ldxi(_R2_REGNO, _SP_REGNO, 40);
# if __powerpc__
ldxi(_R2_REGNO, _SP_REGNO, sizeof(void*) * 5);
# endif
}
@ -3019,11 +3025,11 @@ _callr(jit_state_t *_jit, jit_int32_t r0)
static void
_calli(jit_state_t *_jit, jit_word_t i0)
{
# if __WORDSIZE == 32
# if __ppc__
jit_word_t d;
# endif
jit_int32_t reg;
# if __WORDSIZE == 32
# if __ppc__
d = (i0 - _jit->pc.w) & ~3;
if (can_sign_extend_jump_p(d))
BL(d);
@ -3050,7 +3056,7 @@ _calli_p(jit_state_t *_jit, jit_word_t i0)
return (w);
}
# if __WORDSIZE == 64
# if __powerpc__
/* order is not guaranteed to be sequential */
static jit_int32_t save[] = {
_R14, _R15, _R16, _R17, _R18, _R19, _R20, _R21, _R22,
@ -3074,7 +3080,7 @@ _prolog(jit_state_t *_jit, jit_node_t *node)
/* params >= %r31+params_offset+(8*sizeof(jit_word_t))
* alloca < %r31-80 */
# if __WORDSIZE == 32
#if __ppc__
/* save any clobbered callee save gpr register */
regno = jit_regset_scan1(&_jitc->function->regset, _R14);
if (regno == ULONG_MAX || regno > _R31)
@ -3086,23 +3092,26 @@ _prolog(jit_state_t *_jit, jit_node_t *node)
}
stxi(8, _SP_REGNO, _R0_REGNO);
movr(_FP_REGNO, _SP_REGNO);
STWU(_SP_REGNO, _SP_REGNO, -_jitc->function->stack);
# else
stxi(16, _SP_REGNO, _R0_REGNO);
offset = -144;
for (regno = 0; regno < jit_size(save); regno++, offset += 8) {
#else /* __powerpc__ */
stxi(sizeof(void*) * 2, _SP_REGNO, _R0_REGNO);
offset = -gpr_save_area;
for (regno = 0; regno < jit_size(save); regno++, offset += sizeof(void*)) {
if (jit_regset_tstbit(&_jitc->function->regset, save[regno]))
stxi(offset, _SP_REGNO, rn(save[regno]));
}
for (offset = 0; offset < 8; offset++) {
if (jit_regset_tstbit(&_jitc->function->regset, _F14 + offset))
stxi_d(-(152 + offset * 8), _SP_REGNO, rn(_F14 + offset));
stxi_d(-(gpr_save_area + 8 + offset * 8),
_SP_REGNO, rn(_F14 + offset));
}
stxi(-8, _SP_REGNO, _FP_REGNO);
stxi(-(sizeof(void*)), _SP_REGNO, _FP_REGNO);
#endif
movr(_FP_REGNO, _SP_REGNO);
#if __WORDSIZE == 32
STWU(_SP_REGNO, _SP_REGNO, -_jitc->function->stack);
#else
STDU(_SP_REGNO, _SP_REGNO, -_jitc->function->stack);
#endif
}
@ -3113,7 +3122,7 @@ _epilog(jit_state_t *_jit, jit_node_t *node)
unsigned long regno;
jit_word_t offset;
#if __WORDSIZE == 32
#if __ppc__
LWZ(_SP_REGNO, _SP_REGNO, 0);
ldxi(_R0_REGNO, _SP_REGNO, 8);
@ -3128,21 +3137,22 @@ _epilog(jit_state_t *_jit, jit_node_t *node)
ldxi_d(rn(_F14 + offset), _SP_REGNO, -fpr_save_area + offset * 8);
}
#else
#else /* __powerpc__ */
addi(_SP_REGNO, _SP_REGNO, _jitc->function->stack);
ldxi(_R0_REGNO, _SP_REGNO, 16);
offset = -144;
for (regno = 0; regno < jit_size(save); regno++, offset += 8) {
ldxi(_R0_REGNO, _SP_REGNO, sizeof(void*) * 2);
offset = -gpr_save_area;
for (regno = 0; regno < jit_size(save); regno++, offset += sizeof(void*)) {
if (jit_regset_tstbit(&_jitc->function->regset, save[regno]))
ldxi(rn(save[regno]), _SP_REGNO, offset);
}
for (offset = 0; offset < 8; offset++) {
if (jit_regset_tstbit(&_jitc->function->regset, _F14 + offset))
ldxi_d(rn(_F14 + offset), _SP_REGNO, -(152 + offset * 8));
ldxi_d(rn(_F14 + offset), _SP_REGNO,
-(gpr_save_area + 8 + offset * 8));
}
MTLR(_R0_REGNO);
ldxi(_FP_REGNO, _SP_REGNO, -8);
ldxi(_FP_REGNO, _SP_REGNO, -(sizeof(void*)));
#endif
BLR();
@ -3169,24 +3179,24 @@ _patch_at(jit_state_t *_jit, jit_word_t instr, jit_word_t label)
u.i[0] = (u.i[0] & ~0xfffd) | (d & 0xfffe);
break;
case 18: /* Bx */
# if __powerpc64__
#if __powerpc__
if (_jitc->jump && (!(u.i[0] & 1))) { /* jmpi label */
/* zero is used for toc and env, so, quick check
* if this is a "jmpi main" like initial jit
* instruction */
if (((long *)label)[1] == 0 && ((long *)label)[2] == 0) {
for (d = 0; d < _jitc->prolog.offset; d++) {
/* not so pretty, but hides powerpc64
/* not so pretty, but hides powerpc
* specific abi intrinsics and/or
* implementation from user */
if (_jitc->prolog.ptr[d] == label) {
label += 24;
label += sizeof(void*) * 3;
break;
}
}
}
}
# endif
#endif
d = label - instr;
assert(!(d & 3));
if (!can_sign_extend_jump_p(d)) {
@ -3197,13 +3207,13 @@ _patch_at(jit_state_t *_jit, jit_word_t instr, jit_word_t label)
u.i[0] = (u.i[0] & ~0x3fffffd) | (d & 0x3fffffe);
break;
case 15: /* LI */
# if __WORDSIZE == 32
#if __WORDSIZE == 32
assert(!(u.i[0] & 0x1f0000));
u.i[0] = (u.i[0] & ~0xffff) | ((label >> 16) & 0xffff);
assert((u.i[1] & 0xfc000000) >> 26 == 24); /* ORI */
assert(((u.i[1] >> 16) & 0x1f) == ((u.i[1] >> 21) & 0x1f));
u.i[1] = (u.i[1] & ~0xffff) | (label & 0xffff);
# else
#else
assert(!(u.i[0] & 0x1f0000));
u.i[0] = (u.i[0] & ~0xffff) | ((label >> 48) & 0xffff);
assert((u.i[1] & 0xfc000000) >> 26 == 24); /* ORI */
@ -3221,7 +3231,7 @@ _patch_at(jit_state_t *_jit, jit_word_t instr, jit_word_t label)
assert((u.i[5] & 0xfc000000) >> 26 == 24); /* ORI */
assert(((u.i[5] >> 16) & 0x1f) == ((u.i[5] >> 21) & 0x1f));
u.i[5] = (u.i[5] & ~0xffff) | (label & 0xffff);
# endif
#endif
break;
default:
assert(!"unhandled branch opcode");

View file

@ -21,7 +21,7 @@
static void _FA(jit_state_t*,int,int,int,int,int,int,int);
#define FXFL(o,m,b,x) _FXFL(_jit,o,m,b,x,0)
#define FXFL_(o,m,b,x) _FXFL(_jit,o,m,b,x,1)
static void _FXFL(jit_state_t*,int,int,int,int,int);
static void _FXFL(jit_state_t*,int,int,int,int,int) maybe_unused;
# define FABS(d,b) FX(63,d,0,b,264)
# define FABS_(d,b) FX_(63,d,0,b,264)

View file

@ -37,7 +37,7 @@ extern void __clear_cache(void *, void *);
*/
jit_register_t _rvs[] = {
{ rc(gpr) | 0, "r0" },
#if __WORDSIZE == 32
#if __ppc__
{ rc(gpr) | 11, "r11" },
{ rc(gpr) | 12, "r12" },
{ rc(gpr) | 13, "r13" },
@ -761,7 +761,7 @@ _emit_code(jit_state_t *_jit)
jit_node_t *node;
jit_word_t word;
jit_word_t patch_offset;
#if __powerpc64__
#if __powerpc__
jit_word_t prolog_offset;
#endif
} undo;
@ -773,13 +773,13 @@ _emit_code(jit_state_t *_jit)
undo.word = 0;
undo.node = NULL;
undo.patch_offset = 0;
#if __powerpc64__
undo.prolog_offset = 0;
#if __powerpc__
undo.prolog_offset = 0;
/* code may start with a jump so add an initial function descriptor */
il(_jit->pc.w + 24); /* addr */
il(0); /* toc */
il(0); /* env */
iw(_jit->pc.w + sizeof(void*) * 3); /* addr */
iw(0); /* toc */
iw(0); /* env */
#endif
#define case_rr(name, type) \
@ -1233,8 +1233,8 @@ _emit_code(jit_state_t *_jit)
jmpr(rn(node->u.w));
break;
case jit_code_jmpi:
#if __powerpc64__
if (_jit->pc.uc == _jit->code.ptr + 24)
#if __powerpc__
if (_jit->pc.uc == _jit->code.ptr + sizeof(void*) * 3)
_jitc->jump = 1;
#endif
temp = node->u.n;
@ -1268,12 +1268,12 @@ _emit_code(jit_state_t *_jit)
undo.node = node;
undo.word = _jit->pc.w;
undo.patch_offset = _jitc->patches.offset;
#if __powerpc64__
#if __powerpc__
undo.prolog_offset = _jitc->prolog.offset;
#endif
restart_function:
_jitc->again = 0;
#if __powerpc64__
#if __powerpc__
if (_jitc->jump) {
/* remember prolog to hide offset adjustment for a jump
* to the start of a function, what is expected to be
@ -1287,9 +1287,9 @@ _emit_code(jit_state_t *_jit)
}
_jitc->prolog.ptr[_jitc->prolog.offset++] = _jit->pc.w;
/* function descriptor */
il(_jit->pc.w + 24); /* addr */
il(0); /* toc */
il(0); /* env */
iw(_jit->pc.w + sizeof(void*) * 3); /* addr */
iw(0); /* toc */
iw(0); /* env */
}
#endif
prolog(node);
@ -1307,7 +1307,7 @@ _emit_code(jit_state_t *_jit)
node = undo.node;
_jit->pc.w = undo.word;
_jitc->patches.offset = undo.patch_offset;
#if __powerpc64__
#if __powerpc__
_jitc->prolog.offset = undo.prolog_offset;
#endif
goto restart_function;
@ -1393,7 +1393,6 @@ static void
_patch(jit_state_t *_jit, jit_word_t instr, jit_node_t *node)
{
jit_int32_t flag;
jit_word_t *patches;
assert(node->flag & jit_flag_node);
if (node->code == jit_code_movi)