1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-06-21 03:00:19 +02:00

Adapt PowerPC port to work in Darwin 32 bit and Linux 64 bit.

* include/lightning.h: Add check for __powerpc__ defined
	in Linux, while Darwin defines __ppc__.

	* include/lightning/jit_ppc.h: Adjust register definitions
	for Darwin 32 bit and Linux 64 bit ppc usage and/or ABI.

	* include/lightning/jit_private.h: Add proper check for
	Linux __powerpc__ and an data definition for an workaround
	to properly handle code that starts with a jump to a "main"
	label.

	* lib/jit_disasm.c: Add extra disassembler initialization
	for __powerpc64__.

	* lib/jit_ppc-cpu.c: Add extra macros and functions, and
	correct/adapt previous ones to handle powerpc64.

	* lib/jit_ppc-fpu.c: Adapt for 64 bit wordsize. Basically
	add conversion from/to int32/int64 and proper handling of
	load/store offsets too large for 32 bit.

	* lib/jit_ppc.c: Add calls to 64 bit codes and adaptation
	for the PowerPC 64 bit Linux ABI.

	* lib/jit_arm.c, lib/jit_mips.c, lib/jit_sparc, lib/jit_x86.c,
	lib/lightning.c: Correct off by one error when restarting jit
	of a function due to finding too late that needs to spill/reload
	some register. Problem was found by accident on a very special
	condition during PowerPC 64 code adaptation.
This commit is contained in:
pcpa 2013-03-10 15:36:25 -03:00
parent 19123bae5d
commit 7ef8060fb2
13 changed files with 1038 additions and 123 deletions

View file

@ -1,3 +1,35 @@
2013-03-10 Paulo Andrade <pcpa@gnu.org>
* include/lightning.h: Add check for __powerpc__ defined
in Linux, while Darwin defines __ppc__.
* include/lightning/jit_ppc.h: Adjust register definitions
for Darwin 32 bit and Linux 64 bit ppc usage and/or ABI.
* include/lightning/jit_private.h: Add proper check for
Linux __powerpc__ and an data definition for an workaround
to properly handle code that starts with a jump to a "main"
label.
* lib/jit_disasm.c: Add extra disassembler initialization
for __powerpc64__.
* lib/jit_ppc-cpu.c: Add extra macros and functions, and
correct/adapt previous ones to handle powerpc64.
* lib/jit_ppc-fpu.c: Adapt for 64 bit wordsize. Basically
add conversion from/to int32/int64 and proper handling of
load/store offsets too large for 32 bit.
* lib/jit_ppc.c: Add calls to 64 bit codes and adaptation
for the PowerPC 64 bit Linux ABI.
* lib/jit_arm.c, lib/jit_mips.c, lib/jit_sparc, lib/jit_x86.c,
lib/lightning.c: Correct off by one error when restarting jit
of a function due to finding too late that needs to spill/reload
some register. Problem was found by accident on a very special
condition during PowerPC 64 code adaptation.
2013-03-08 Paulo Andrade <pcpa@gnu.org> 2013-03-08 Paulo Andrade <pcpa@gnu.org>
* check/lightning.c: Add missing ppc preprocessor definition. * check/lightning.c: Add missing ppc preprocessor definition.

View file

@ -70,7 +70,7 @@ typedef jit_int32_t jit_fpr_t;
# include <lightning/jit_mips.h> # include <lightning/jit_mips.h>
#elif defined(__arm__) #elif defined(__arm__)
# include <lightning/jit_arm.h> # include <lightning/jit_arm.h>
#elif defined(__ppc__) #elif defined(__ppc__) || defined(__powerpc__)
# include <lightning/jit_ppc.h> # include <lightning/jit_ppc.h>
#elif defined(__sparc__) #elif defined(__sparc__)
# include <lightning/jit_sparc.h> # include <lightning/jit_sparc.h>

View file

@ -28,34 +28,46 @@ typedef enum {
#define jit_arg_reg_p(i) ((i) >= 0 && (i) < 8) #define jit_arg_reg_p(i) ((i) >= 0 && (i) < 8)
#define jit_r(i) (_R11 + (i)) #define jit_r(i) (_R11 + (i))
#define jit_r_num() 3 #define jit_r_num() 3
#define jit_v(i) (_R30 - (i)) #if __WORDSIZE == 32
#define jit_v_num() 17 # define jit_v(i) (_R30 - (i))
# define jit_v_num() 17
#else
# define jit_v(i) (_R27 - (i))
# define jit_v_num() 14
#endif
#define jit_arg_f_reg_p(i) ((i) >= 0 && (i) < 13) #define jit_arg_f_reg_p(i) ((i) >= 0 && (i) < 13)
#define jit_f(i) (_F14 + (i)) #define jit_f(i) (_F14 + (i))
#define jit_f_num() 6 #define jit_f_num() 6
_R0, _R0,
#define JIT_R0 _R11 #if __WORDSIZE == 32
#define JIT_R1 _R12 # define JIT_R0 _R11
#define JIT_R2 _R13 # define JIT_R1 _R12
#define JIT_R3 _R2 # define JIT_R2 _R13
#else
# define JIT_R0 _R28
# define JIT_R1 _R29
# define JIT_R2 _R30
#endif
_R11, _R12, _R13, _R2, _R11, _R12, _R13, _R2,
#define JIT_V0 _R30 #define JIT_V0 jit_v(0)
#define JIT_V1 _R29 #define JIT_V1 jit_v(1)
#define JIT_V2 _R28 #define JIT_V2 jit_v(2)
#define JIT_V3 _R28 #define JIT_V3 jit_v(3)
#define JIT_V4 _R26 #define JIT_V4 jit_v(4)
#define JIT_V5 _R25 #define JIT_V5 jit_v(5)
#define JIT_V6 _R24 #define JIT_V6 jit_v(6)
#define JIT_V7 _R23 #define JIT_V7 jit_v(7)
#define JIT_V8 _R22 #define JIT_V8 jit_v(8)
#define JIT_V9 _R21 #define JIT_V9 jit_v(9)
#define JIT_V10 _R20 #define JIT_V10 jit_v(10)
#define JIT_V11 _R19 #define JIT_V11 jit_v(11)
#define JIT_V12 _R18 #define JIT_V12 jit_v(12)
#define JIT_V13 _R17 #define JIT_V13 jit_v(13)
#define JIT_V14 _R16 #if __WORDSIZE == 32
#define JIT_V15 _R15 # define JIT_V14 jit_v(14)
#define JIT_V16 _R14 # define JIT_V15 jit_v(15)
# define JIT_V16 jit_v(16)
#endif
_R14, _R15, _R16, _R17, _R18, _R19, _R20, _R21, _R14, _R15, _R16, _R17, _R18, _R19, _R20, _R21,
_R22, _R23, _R24, _R25, _R26, _R27, _R28, _R29, _R22, _R23, _R24, _R25, _R26, _R27, _R28, _R29,
_R30, _R30,

View file

@ -66,7 +66,7 @@
# else # else
# define JIT_FRET _R0 # define JIT_FRET _R0
# endif # endif
#elif defined(__ppc__) #elif defined(__ppc__) || defined(__powerpc__)
# define JIT_SP _R1 # define JIT_SP _R1
# define JIT_RET _R3 # define JIT_RET _R3
# define JIT_FRET _F1 # define JIT_FRET _F1
@ -347,6 +347,16 @@ struct jit_compiler {
jit_int32_t values[1024]; /* pending constants */ jit_int32_t values[1024]; /* pending constants */
jit_word_t patches[2048]; jit_word_t patches[2048];
} consts; } consts;
#elif __powerpc64__
/* 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. */
struct {
jit_word_t *ptr;
jit_word_t offset;
jit_word_t length;
} prolog;
jit_bool_t jump;
#endif #endif
}; };

View file

@ -1437,6 +1437,7 @@ _emit_code(jit_state_t *_jit)
temp->code == jit_code_epilog) temp->code == jit_code_epilog)
temp->flag &= ~jit_flag_patch; temp->flag &= ~jit_flag_patch;
} }
temp->flag &= ~jit_flag_patch;
node = undo.node; node = undo.node;
_jit->pc.w = undo.word; _jit->pc.w = undo.word;
invalidate_consts(); invalidate_consts();

View file

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

View file

@ -1186,6 +1186,7 @@ _emit_code(jit_state_t *_jit)
temp->code == jit_code_epilog) temp->code == jit_code_epilog)
temp->flag &= ~jit_flag_patch; temp->flag &= ~jit_flag_patch;
} }
temp->flag &= ~jit_flag_patch;
node = undo.node; node = undo.node;
_jit->pc.w = undo.word; _jit->pc.w = undo.word;
_jitc->patches.offset = undo.patch_offset; _jitc->patches.offset = undo.patch_offset;

File diff suppressed because it is too large Load diff

View file

@ -36,6 +36,10 @@ static void _FXFL(jit_state_t*,int,int,int,int,int);
# define FCTIW_(d,b) FX_(63,d,0,b,14) # define FCTIW_(d,b) FX_(63,d,0,b,14)
# define FCTIWZ(d,b) FX(63,d,0,b,15) # define FCTIWZ(d,b) FX(63,d,0,b,15)
# define FCTIWZ_(d,b) FX_(63,d,0,b,15) # define FCTIWZ_(d,b) FX_(63,d,0,b,15)
# define FCTID(d,b) FX(63,d,0,b,814)
# define FCTID_(d,b) FX_(63,d,0,b,814)
# define FCTIDZ(d,b) FX(63,d,0,b,815)
# define FCTIDZ_(d,b) FX_(63,d,0,b,815)
# define FDIV(d,a,b) FA(63,d,a,b,0,18) # define FDIV(d,a,b) FA(63,d,a,b,0,18)
# define FDIV_(d,a,b) FA_(63,d,a,b,0,18) # define FDIV_(d,a,b) FA_(63,d,a,b,0,18)
# define FDIVS(d,a,b) FA(59,d,a,b,0,18) # define FDIVS(d,a,b) FA(59,d,a,b,0,18)
@ -121,10 +125,20 @@ static void _movi_d(jit_state_t*,jit_int32_t,jit_float64_t*);
# define extr_f(r0,r1) extr_d(r0,r1) # define extr_f(r0,r1) extr_d(r0,r1)
# define extr_d(r0,r1) _extr_d(_jit,r0,r1) # define extr_d(r0,r1) _extr_d(_jit,r0,r1)
static void _extr_d(jit_state_t*,jit_int32_t,jit_int32_t); static void _extr_d(jit_state_t*,jit_int32_t,jit_int32_t);
# define truncr_f_i(r0,r1) truncr_d(r0,r1)
# define truncr_d_i(r0,r1) truncr_d(r0,r1) # define truncr_f(r0,r1) truncr_d(r0,r1)
# define truncr_d(r0,r1) _truncr_d(_jit,r0,r1) # define truncr_f_i(r0,r1) truncr_d_i(r0,r1)
static void _truncr_d(jit_state_t*,jit_int32_t,jit_int32_t); # define truncr_d_i(r0,r1) _truncr_d_i(_jit,r0,r1)
static void _truncr_d_i(jit_state_t*,jit_int32_t,jit_int32_t);
# if __WORDSIZE == 32
# define truncr_d(r0,r1) truncr_d_i(r0,r1)
# else
# define truncr_d(r0,r1) truncr_d_l(r0,r1)
# define truncr_f_l(r0,r1) truncr_d_l(r0,r1)
# define truncr_d_l(r0,r1) _truncr_d_l(_jit,r0,r1)
static void _truncr_d_l(jit_state_t*,jit_int32_t,jit_int32_t);
# endif
# define extr_d_f(r0,r1) FRSP(r0,r1) # define extr_d_f(r0,r1) FRSP(r0,r1)
# define extr_f_d(r0,r1) movr_d(r0,r1) # define extr_f_d(r0,r1) movr_d(r0,r1)
@ -436,6 +450,7 @@ _movi_d(jit_state_t *_jit, jit_int32_t r0, jit_float64_t *i0)
static void static void
_extr_d(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1) _extr_d(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
{ {
# if __WORDSIZE == 32
jit_int32_t reg; jit_int32_t reg;
reg = jit_get_reg(jit_class_gpr); reg = jit_get_reg(jit_class_gpr);
rshi(rn(reg), r1, 31); rshi(rn(reg), r1, 31);
@ -443,22 +458,39 @@ _extr_d(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
stxi(alloca_offset - 4, _FP_REGNO, r1); stxi(alloca_offset - 4, _FP_REGNO, r1);
stxi(alloca_offset - 8, _FP_REGNO, rn(reg)); stxi(alloca_offset - 8, _FP_REGNO, rn(reg));
jit_unget_reg(reg); jit_unget_reg(reg);
# else
stxi(alloca_offset - 8, _FP_REGNO, r1);
# endif
ldxi_d(r0, _FP_REGNO, alloca_offset - 8); ldxi_d(r0, _FP_REGNO, alloca_offset - 8);
FCFID(r0, r0); FCFID(r0, r0);
} }
static void static void
_truncr_d(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1) _truncr_d_i(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
{ {
jit_int32_t reg; jit_int32_t reg;
reg = jit_get_reg(jit_class_fpr); reg = jit_get_reg(jit_class_fpr);
FCTIWZ(rn(reg), r1); FCTIWZ(rn(reg), r1);
/* use reserved 8 bytes area */ /* use reserved 8 bytes area */
stxi_d(alloca_offset - 8, _FP_REGNO, rn(reg)); stxi_d(alloca_offset - 8, _FP_REGNO, rn(reg));
ldxi(r0, _FP_REGNO, alloca_offset - 4); ldxi_i(r0, _FP_REGNO, alloca_offset - 4);
jit_unget_reg(reg); jit_unget_reg(reg);
} }
# if __WORDSIZE == 64
static void
_truncr_d_l(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
{
jit_int32_t reg;
reg = jit_get_reg(jit_class_fpr);
FCTIDZ(rn(reg), r1);
/* use reserved 8 bytes area */
stxi_d(alloca_offset - 8, _FP_REGNO, rn(reg));
ldxi(r0, _FP_REGNO, alloca_offset - 8);
jit_unget_reg(reg);
}
# endif
# define fpr_opi(name, type, size) \ # define fpr_opi(name, type, size) \
static void \ static void \
_##name##i_##type(jit_state_t *_jit, \ _##name##i_##type(jit_state_t *_jit, \
@ -843,8 +875,8 @@ _ldi_f(jit_state_t *_jit, jit_int32_t r0, jit_word_t i0)
jit_word_t lo, hi; jit_word_t lo, hi;
if (can_sign_extend_short_p(i0)) if (can_sign_extend_short_p(i0))
LFS(r0, _R0_REGNO, i0); LFS(r0, _R0_REGNO, i0);
else { else if (can_sign_extend_int_p(i0)) {
hi = (i0 >> 16) + ((jit_uint16_t)i0 >> 15); hi = (jit_int16_t)((i0 >> 16) + ((jit_uint16_t)i0 >> 15));
lo = (jit_int16_t)(i0 - (hi << 16)); lo = (jit_int16_t)(i0 - (hi << 16));
reg = jit_get_reg(jit_class_gpr); reg = jit_get_reg(jit_class_gpr);
if ((inv = reg == _R0)) reg = jit_get_reg(jit_class_gpr); if ((inv = reg == _R0)) reg = jit_get_reg(jit_class_gpr);
@ -853,6 +885,12 @@ _ldi_f(jit_state_t *_jit, jit_int32_t r0, jit_word_t i0)
jit_unget_reg(reg); jit_unget_reg(reg);
if (inv) jit_unget_reg(_R0); if (inv) jit_unget_reg(_R0);
} }
else {
reg = jit_get_reg(jit_class_gpr);
movi(rn(reg), i0);
ldr_f(r0, rn(reg));
jit_unget_reg(reg);
}
} }
static void static void
@ -863,8 +901,8 @@ _ldi_d(jit_state_t *_jit, jit_int32_t r0, jit_word_t i0)
jit_word_t lo, hi; jit_word_t lo, hi;
if (can_sign_extend_short_p(i0)) if (can_sign_extend_short_p(i0))
LFD(r0, _R0_REGNO, i0); LFD(r0, _R0_REGNO, i0);
else { else if (can_sign_extend_int_p(i0)) {
hi = (i0 >> 16) + ((jit_uint16_t)i0 >> 15); hi = (jit_int16_t)((i0 >> 16) + ((jit_uint16_t)i0 >> 15));
lo = (jit_int16_t)(i0 - (hi << 16)); lo = (jit_int16_t)(i0 - (hi << 16));
reg = jit_get_reg(jit_class_gpr); reg = jit_get_reg(jit_class_gpr);
if ((inv = reg == _R0)) reg = jit_get_reg(jit_class_gpr); if ((inv = reg == _R0)) reg = jit_get_reg(jit_class_gpr);
@ -873,6 +911,12 @@ _ldi_d(jit_state_t *_jit, jit_int32_t r0, jit_word_t i0)
jit_unget_reg(reg); jit_unget_reg(reg);
if (inv) jit_unget_reg(_R0); if (inv) jit_unget_reg(_R0);
} }
else {
reg = jit_get_reg(jit_class_gpr);
movi(rn(reg), i0);
ldr_d(r0, rn(reg));
jit_unget_reg(reg);
}
} }
static void static void
@ -967,8 +1011,8 @@ _sti_f(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0)
jit_word_t lo, hi; jit_word_t lo, hi;
if (can_sign_extend_short_p(i0)) if (can_sign_extend_short_p(i0))
STFS(r0, _R0_REGNO, i0); STFS(r0, _R0_REGNO, i0);
else { else if (can_sign_extend_int_p(i0)) {
hi = (i0 >> 16) + ((jit_uint16_t)i0 >> 15); hi = (jit_int16_t)((i0 >> 16) + ((jit_uint16_t)i0 >> 15));
lo = (jit_int16_t)(i0 - (hi << 16)); lo = (jit_int16_t)(i0 - (hi << 16));
reg = jit_get_reg(jit_class_gpr); reg = jit_get_reg(jit_class_gpr);
if ((inv = reg == _R0)) reg = jit_get_reg(jit_class_gpr); if ((inv = reg == _R0)) reg = jit_get_reg(jit_class_gpr);
@ -977,6 +1021,12 @@ _sti_f(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0)
jit_unget_reg(reg); jit_unget_reg(reg);
if (inv) jit_unget_reg(_R0); if (inv) jit_unget_reg(_R0);
} }
else {
reg = jit_get_reg(jit_class_gpr);
movi(rn(reg), i0);
str_f(rn(reg), r0);
jit_unget_reg(reg);
}
} }
static void static void
@ -987,8 +1037,8 @@ _sti_d(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0)
jit_word_t lo, hi; jit_word_t lo, hi;
if (can_sign_extend_short_p(i0)) if (can_sign_extend_short_p(i0))
STFD(r0, _R0_REGNO, i0); STFD(r0, _R0_REGNO, i0);
else { else if (can_sign_extend_int_p(i0)) {
hi = (i0 >> 16) + ((jit_uint16_t)i0 >> 15); hi = (jit_int16_t)((i0 >> 16) + ((jit_uint16_t)i0 >> 15));
lo = (jit_int16_t)(i0 - (hi << 16)); lo = (jit_int16_t)(i0 - (hi << 16));
reg = jit_get_reg(jit_class_gpr); reg = jit_get_reg(jit_class_gpr);
if ((inv = reg == _R0)) reg = jit_get_reg(jit_class_gpr); if ((inv = reg == _R0)) reg = jit_get_reg(jit_class_gpr);
@ -997,6 +1047,12 @@ _sti_d(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0)
jit_unget_reg(reg); jit_unget_reg(reg);
if (inv) jit_unget_reg(_R0); if (inv) jit_unget_reg(_R0);
} }
else {
reg = jit_get_reg(jit_class_gpr);
movi(rn(reg), i0);
str_d(rn(reg), r0);
jit_unget_reg(reg);
}
} }
static void static void

View file

@ -37,10 +37,17 @@ extern void __clear_cache(void *, void *);
*/ */
jit_register_t _rvs[] = { jit_register_t _rvs[] = {
{ rc(gpr) | 0, "r0" }, { rc(gpr) | 0, "r0" },
#if __WORDSIZE == 32
{ rc(gpr) | 11, "r11" }, { rc(gpr) | 11, "r11" },
{ rc(gpr) | 12, "r12" }, { rc(gpr) | 12, "r12" },
{ rc(gpr) | 13, "r13" }, { rc(gpr) | 13, "r13" },
{ rc(gpr) | 2, "r2" }, { rc(gpr) | 2, "r2" },
#else
{ rc(sav) | 11, "r11" }, /* env */
{ rc(sav) | 12, "r12" }, /* exception */
{ rc(sav) | 13, "r13" }, /* thread */
{ rc(sav) | 2, "r2" }, /* toc */
#endif
{ rc(sav) | rc(gpr) | 14, "r14" }, { rc(sav) | rc(gpr) | 14, "r14" },
{ rc(sav) | rc(gpr) | 15, "r15" }, { rc(sav) | rc(gpr) | 15, "r15" },
{ rc(sav) | rc(gpr) | 16, "r16" }, { rc(sav) | rc(gpr) | 16, "r16" },
@ -270,16 +277,21 @@ _jit_arg_f(jit_state_t *_jit)
assert(_jitc->function); assert(_jitc->function);
if (_jitc->function->self.argf < 13) if (_jitc->function->self.argf < 13)
offset = _jitc->function->self.argf++; offset = _jitc->function->self.argf++;
else else {
#if __WORDSIZE == 32
offset = _jitc->function->self.size; offset = _jitc->function->self.size;
_jitc->function->self.size += sizeof(jit_float32_t); #else
offset = _jitc->function->self.size + 4;
#endif
}
_jitc->function->self.size += sizeof(jit_word_t);
return (jit_new_node_w(jit_code_arg_f, offset)); return (jit_new_node_w(jit_code_arg_f, offset));
} }
jit_bool_t jit_bool_t
_jit_arg_f_reg_p(jit_state_t *_jit, jit_int32_t offset) _jit_arg_f_reg_p(jit_state_t *_jit, jit_int32_t offset)
{ {
return (jit_arg_d_reg_p(offset)); return (offset >= 0 && offset < 13);
} }
jit_node_t * jit_node_t *
@ -298,7 +310,7 @@ _jit_arg_d(jit_state_t *_jit)
jit_bool_t jit_bool_t
_jit_arg_d_reg_p(jit_state_t *_jit, jit_int32_t offset) _jit_arg_d_reg_p(jit_state_t *_jit, jit_int32_t offset)
{ {
return (offset >= 0 && offset < 13); return (jit_arg_f_reg_p(offset));
} }
void void
@ -364,8 +376,13 @@ _jit_getarg_us(jit_state_t *_jit, jit_int32_t u, jit_node_t *v)
void void
_jit_getarg_i(jit_state_t *_jit, jit_int32_t u, jit_node_t *v) _jit_getarg_i(jit_state_t *_jit, jit_int32_t u, jit_node_t *v)
{ {
if (v->u.w < 8) if (v->u.w < 8) {
#if __WORDSIZE == 32
jit_movr(u, JIT_RA0 - v->u.w); jit_movr(u, JIT_RA0 - v->u.w);
#else
jit_extr_i(u, JIT_RA0 - v->u.w);
#endif
}
else { else {
#if __BYTE_ORDER == __LITTLE_ENDIAN #if __BYTE_ORDER == __LITTLE_ENDIAN
jit_ldxi_i(u, JIT_FP, v->u.w); jit_ldxi_i(u, JIT_FP, v->u.w);
@ -460,9 +477,14 @@ _jit_pushargr_f(jit_state_t *_jit, jit_int32_t u)
++_jitc->function->call.argf; ++_jitc->function->call.argf;
if (!(_jitc->function->call.call & jit_call_varargs)) { if (!(_jitc->function->call.call & jit_call_varargs)) {
/* in case of excess arguments */ /* in case of excess arguments */
if (_jitc->function->call.argi < 8) if (_jitc->function->call.argi < 8) {
#if __WORDSIZE == 32
_jitc->function->call.argi += 2; _jitc->function->call.argi += 2;
_jitc->function->call.size += sizeof(jit_float32_t); #else
_jitc->function->call.argi++;
#endif
}
_jitc->function->call.size += sizeof(jit_word_t);
return; return;
} }
} }
@ -472,13 +494,21 @@ _jit_pushargr_f(jit_state_t *_jit, jit_int32_t u)
jit_ldxi(JIT_RA0 - _jitc->function->call.argi, JIT_FP, jit_ldxi(JIT_RA0 - _jitc->function->call.argi, JIT_FP,
alloca_offset - 8); alloca_offset - 8);
_jitc->function->call.argi++; _jitc->function->call.argi++;
#if __WORDSIZE == 32
jit_ldxi(JIT_RA0 - _jitc->function->call.argi, JIT_FP, jit_ldxi(JIT_RA0 - _jitc->function->call.argi, JIT_FP,
alloca_offset - 4); alloca_offset - 4);
_jitc->function->call.argi++; _jitc->function->call.argi++;
#endif
} }
else else {
#if __WORDSIZE == 32
jit_stxi_f(_jitc->function->call.size + params_offset, JIT_SP, u); jit_stxi_f(_jitc->function->call.size + params_offset, JIT_SP, u);
_jitc->function->call.size += sizeof(jit_float32_t); #else
jit_stxi_f(_jitc->function->call.size + params_offset + 4,
JIT_SP, u);
#endif
}
_jitc->function->call.size += sizeof(jit_word_t);
} }
void void
@ -492,9 +522,14 @@ _jit_pushargi_f(jit_state_t *_jit, jit_float32_t u)
++_jitc->function->call.argf; ++_jitc->function->call.argf;
if (!(_jitc->function->call.call & jit_call_varargs)) { if (!(_jitc->function->call.call & jit_call_varargs)) {
/* in case of excess arguments */ /* in case of excess arguments */
if (_jitc->function->call.argi < 8) if (_jitc->function->call.argi < 8) {
#if __WORDSIZE == 32
_jitc->function->call.argi += 2; _jitc->function->call.argi += 2;
_jitc->function->call.size += sizeof(jit_float32_t); #else
_jitc->function->call.argi++;
#endif
}
_jitc->function->call.size += sizeof(jit_word_t);
return; return;
} }
} }
@ -506,13 +541,21 @@ _jit_pushargi_f(jit_state_t *_jit, jit_float32_t u)
jit_ldxi(JIT_RA0 - _jitc->function->call.argi, JIT_FP, jit_ldxi(JIT_RA0 - _jitc->function->call.argi, JIT_FP,
alloca_offset - 8); alloca_offset - 8);
_jitc->function->call.argi++; _jitc->function->call.argi++;
#if __WORDSIZE == 32
jit_ldxi(JIT_RA0 - _jitc->function->call.argi, JIT_FP, jit_ldxi(JIT_RA0 - _jitc->function->call.argi, JIT_FP,
alloca_offset - 4); alloca_offset - 4);
_jitc->function->call.argi++; _jitc->function->call.argi++;
#endif
} }
else else {
#if __WORDSIZE == 32
jit_stxi_f(_jitc->function->call.size + params_offset, JIT_SP, regno); jit_stxi_f(_jitc->function->call.size + params_offset, JIT_SP, regno);
_jitc->function->call.size += sizeof(jit_float32_t); #else
jit_stxi_f(_jitc->function->call.size + params_offset + 4,
JIT_SP, regno);
#endif
}
_jitc->function->call.size += sizeof(jit_word_t);
jit_unget_reg(regno); jit_unget_reg(regno);
} }
@ -525,8 +568,13 @@ _jit_pushargr_d(jit_state_t *_jit, jit_int32_t u)
++_jitc->function->call.argf; ++_jitc->function->call.argf;
if (!(_jitc->function->call.call & jit_call_varargs)) { if (!(_jitc->function->call.call & jit_call_varargs)) {
/* in case of excess arguments */ /* in case of excess arguments */
if (_jitc->function->call.argi < 8) if (_jitc->function->call.argi < 8) {
#if __WORDSIZE == 32
_jitc->function->call.argi += 2; _jitc->function->call.argi += 2;
#else
_jitc->function->call.argi++;
#endif
}
_jitc->function->call.size += sizeof(jit_float64_t); _jitc->function->call.size += sizeof(jit_float64_t);
return; return;
} }
@ -537,9 +585,11 @@ _jit_pushargr_d(jit_state_t *_jit, jit_int32_t u)
jit_ldxi(JIT_RA0 - _jitc->function->call.argi, JIT_FP, jit_ldxi(JIT_RA0 - _jitc->function->call.argi, JIT_FP,
alloca_offset - 8); alloca_offset - 8);
_jitc->function->call.argi++; _jitc->function->call.argi++;
#if __WORDSIZE == 32
jit_ldxi(JIT_RA0 - _jitc->function->call.argi, JIT_FP, jit_ldxi(JIT_RA0 - _jitc->function->call.argi, JIT_FP,
alloca_offset - 4); alloca_offset - 4);
_jitc->function->call.argi++; _jitc->function->call.argi++;
#endif
} }
else else
jit_stxi_d(_jitc->function->call.size + params_offset, JIT_SP, u); jit_stxi_d(_jitc->function->call.size + params_offset, JIT_SP, u);
@ -557,8 +607,13 @@ _jit_pushargi_d(jit_state_t *_jit, jit_float64_t u)
++_jitc->function->call.argf; ++_jitc->function->call.argf;
if (!(_jitc->function->call.call & jit_call_varargs)) { if (!(_jitc->function->call.call & jit_call_varargs)) {
/* in case of excess arguments */ /* in case of excess arguments */
if (_jitc->function->call.argi < 8) if (_jitc->function->call.argi < 8) {
#if __WORDSIZE == 32
_jitc->function->call.argi += 2; _jitc->function->call.argi += 2;
#else
_jitc->function->call.argi++;
#endif
}
_jitc->function->call.size += sizeof(jit_float64_t); _jitc->function->call.size += sizeof(jit_float64_t);
return; return;
} }
@ -571,9 +626,11 @@ _jit_pushargi_d(jit_state_t *_jit, jit_float64_t u)
jit_ldxi(JIT_RA0 - _jitc->function->call.argi, JIT_FP, jit_ldxi(JIT_RA0 - _jitc->function->call.argi, JIT_FP,
alloca_offset - 8); alloca_offset - 8);
_jitc->function->call.argi++; _jitc->function->call.argi++;
#if __WORDSIZE == 32
jit_ldxi(JIT_RA0 - _jitc->function->call.argi, JIT_FP, jit_ldxi(JIT_RA0 - _jitc->function->call.argi, JIT_FP,
alloca_offset - 4); alloca_offset - 4);
_jitc->function->call.argi++; _jitc->function->call.argi++;
#endif
} }
else else
jit_stxi_d(_jitc->function->call.size + params_offset, JIT_SP, regno); jit_stxi_d(_jitc->function->call.size + params_offset, JIT_SP, regno);
@ -704,7 +761,10 @@ _emit_code(jit_state_t *_jit)
struct { struct {
jit_node_t *node; jit_node_t *node;
jit_word_t word; jit_word_t word;
jit_int32_t patch_offset; jit_word_t patch_offset;
#if __powerpc64__
jit_word_t prolog_offset;
#endif
} undo; } undo;
_jitc->function = NULL; _jitc->function = NULL;
@ -714,6 +774,14 @@ _emit_code(jit_state_t *_jit)
undo.word = 0; undo.word = 0;
undo.node = NULL; undo.node = NULL;
undo.patch_offset = 0; undo.patch_offset = 0;
#if __powerpc64__
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 */
#endif
#define case_rr(name, type) \ #define case_rr(name, type) \
case jit_code_##name##r##type: \ case jit_code_##name##r##type: \
@ -859,6 +927,10 @@ _emit_code(jit_state_t *_jit)
case_rr(ext, _uc); case_rr(ext, _uc);
case_rr(ext, _s); case_rr(ext, _s);
case_rr(ext, _us); case_rr(ext, _us);
# if __WORDSIZE == 64
case_rr(ext, _i);
case_rr(ext, _ui);
# endif
case_rr(hton,); case_rr(hton,);
case_rr(neg,); case_rr(neg,);
case_rr(com,); case_rr(com,);
@ -882,6 +954,10 @@ _emit_code(jit_state_t *_jit)
break; break;
case_rr(trunc, _f_i); case_rr(trunc, _f_i);
case_rr(trunc, _d_i); case_rr(trunc, _d_i);
# if __WORDSIZE == 64
case_rr(trunc, _f_l);
case_rr(trunc, _d_l);
# endif
case_rrr(lt,); case_rrr(lt,);
case_rrw(lt,); case_rrw(lt,);
case_rrr(lt, _u); case_rrr(lt, _u);
@ -962,6 +1038,16 @@ _emit_code(jit_state_t *_jit)
case_rw(ld, _i); case_rw(ld, _i);
case_rrr(ldx, _i); case_rrr(ldx, _i);
case_rrw(ldx, _i); case_rrw(ldx, _i);
#if __WORDSIZE == 64
case_rr(ld, _ui);
case_rw(ld, _ui);
case_rrr(ldx, _ui);
case_rrw(ldx, _ui);
case_rr(ld, _l);
case_rw(ld, _l);
case_rrr(ldx, _l);
case_rrw(ldx, _l);
#endif
case_rr(st, _c); case_rr(st, _c);
case_wr(st, _c); case_wr(st, _c);
case_rrr(stx, _c); case_rrr(stx, _c);
@ -974,6 +1060,12 @@ _emit_code(jit_state_t *_jit)
case_wr(st, _i); case_wr(st, _i);
case_rrr(stx, _i); case_rrr(stx, _i);
case_wrr(stx, _i); case_wrr(stx, _i);
#if __WORDSIZE == 64
case_rr(st, _l);
case_wr(st, _l);
case_rrr(stx, _l);
case_wrr(stx, _l);
#endif
case_rr(mov, _f); case_rr(mov, _f);
case jit_code_movi_f: case jit_code_movi_f:
assert(node->flag & jit_flag_data); assert(node->flag & jit_flag_data);
@ -1142,6 +1234,10 @@ _emit_code(jit_state_t *_jit)
jmpr(rn(node->u.w)); jmpr(rn(node->u.w));
break; break;
case jit_code_jmpi: case jit_code_jmpi:
#if __powerpc64__
if (_jit->pc.uc == _jit->code.ptr + 24)
_jitc->jump = 1;
#endif
temp = node->u.n; temp = node->u.n;
assert(temp->code == jit_code_label || assert(temp->code == jit_code_label ||
temp->code == jit_code_epilog); temp->code == jit_code_epilog);
@ -1173,8 +1269,29 @@ _emit_code(jit_state_t *_jit)
undo.node = node; undo.node = node;
undo.word = _jit->pc.w; undo.word = _jit->pc.w;
undo.patch_offset = _jitc->patches.offset; undo.patch_offset = _jitc->patches.offset;
#if __powerpc64__
undo.prolog_offset = _jitc->prolog.offset;
#endif
restart_function: restart_function:
_jitc->again = 0; _jitc->again = 0;
#if __powerpc64__
if (_jitc->jump) {
/* remember prolog to hide offset adjustment for a jump
* to the start of a function, what is expected to be
* a common practice as first jit instruction */
if (_jitc->prolog.offset >= _jitc->prolog.length) {
_jitc->prolog.length += 16;
_jitc->prolog.ptr = realloc(_jitc->prolog.ptr,
_jitc->prolog.length *
sizeof(jit_word_t));
}
_jitc->prolog.ptr[_jitc->prolog.offset++] = _jit->pc.w;
/* function descriptor */
il(_jit->pc.w + 24); /* addr */
il(0); /* toc */
il(0); /* env */
}
#endif
prolog(node); prolog(node);
break; break;
case jit_code_epilog: case jit_code_epilog:
@ -1186,9 +1303,13 @@ _emit_code(jit_state_t *_jit)
temp->code == jit_code_epilog) temp->code == jit_code_epilog)
temp->flag &= ~jit_flag_patch; temp->flag &= ~jit_flag_patch;
} }
temp->flag &= ~jit_flag_patch;
node = undo.node; node = undo.node;
_jit->pc.w = undo.word; _jit->pc.w = undo.word;
_jitc->patches.offset = undo.patch_offset; _jitc->patches.offset = undo.patch_offset;
#if __powerpc64__
_jitc->prolog.offset = undo.prolog_offset;
#endif
goto restart_function; goto restart_function;
} }
/* remember label is defined */ /* remember label is defined */

View file

@ -1076,6 +1076,7 @@ _emit_code(jit_state_t *_jit)
temp->code == jit_code_epilog) temp->code == jit_code_epilog)
temp->flag &= ~jit_flag_patch; temp->flag &= ~jit_flag_patch;
} }
temp->flag &= ~jit_flag_patch;
node = undo.node; node = undo.node;
_jit->pc.w = undo.word; _jit->pc.w = undo.word;
_jitc->patches.offset = undo.patch_offset; _jitc->patches.offset = undo.patch_offset;

View file

@ -1575,6 +1575,7 @@ _emit_code(jit_state_t *_jit)
temp->code == jit_code_epilog) temp->code == jit_code_epilog)
temp->flag &= ~jit_flag_patch; temp->flag &= ~jit_flag_patch;
} }
temp->flag &= ~jit_flag_patch;
node = undo.node; node = undo.node;
_jit->pc.w = undo.word; _jit->pc.w = undo.word;
_jitc->patches.offset = undo.patch_offset; _jitc->patches.offset = undo.patch_offset;

View file

@ -587,6 +587,11 @@ _jit_clear_state(jit_state_t *_jit)
_jitc->data_info.ptr = NULL; _jitc->data_info.ptr = NULL;
#endif #endif
#if __powerpc64__
free(_jitc->prolog.ptr);
_jitc->prolog.ptr = NULL;
#endif
free(_jitc); free(_jitc);
} }
@ -1402,7 +1407,9 @@ _jit_emit(jit_state_t *_jit)
for (;;) { for (;;) {
if ((code = emit_code()) == NULL) { if ((code = emit_code()) == NULL) {
for (node = _jitc->head; node; node = node->next) { for (node = _jitc->head; node; node = node->next) {
if (node->code == jit_code_label && node->link) if (node->link &&
(node->code == jit_code_label ||
node->code == jit_code_epilog))
node->flag &= ~jit_flag_patch; node->flag &= ~jit_flag_patch;
} }
++mult; ++mult;
@ -1439,7 +1446,7 @@ _jit_emit(jit_state_t *_jit)
result = mprotect(_jit->code.ptr, _jit->code.length, PROT_READ | PROT_EXEC); result = mprotect(_jit->code.ptr, _jit->code.length, PROT_READ | PROT_EXEC);
assert(result == 0); assert(result == 0);
return (code); return (_jit->code.ptr);
} }
/* Compute initial reglive and regmask set values of a basic block. /* Compute initial reglive and regmask set values of a basic block.
@ -2605,7 +2612,7 @@ _patch_register(jit_state_t *_jit, jit_node_t *node, jit_node_t *link,
# include "jit_mips.c" # include "jit_mips.c"
#elif defined(__arm__) #elif defined(__arm__)
# include "jit_arm.c" # include "jit_arm.c"
#elif defined(__ppc__) #elif defined(__ppc__) || defined(__powerpc__)
# include "jit_ppc.c" # include "jit_ppc.c"
#elif defined(__sparc__) #elif defined(__sparc__)
# include "jit_sparc.c" # include "jit_sparc.c"