mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-05-07 18:30:25 +02:00
Update code to build and pass test cases in the arm port.
* configure.ac, include/lightning/jit_private.h, lib/jit_arm-cpu.c, lib/jit_arm-swf.c, lib/jit_arm.c, check/Makefile.am: Correct implementation of the arm backend port to build and pass the current test cases. Tested on armv7 with softfp abi. * lib/jit_disasm.c: Rename and change prototype of static disassemble function as in the arm backend it is required to access state information stored in the jit_state_t object. * check/3to2.tst, check/add.tst: Correct test case code assuming JIT_RO and JIT_RET are the same, and even if they are the same, the logic was incorrect because it must always call jit_retval* to fetch a function call return before any other instruction. The arm backend hash a special condition if jit_retval is not called, because "r0" is not JIT_R0, but is JIT_RET and *also* the first argument for a called function, so JIT_RET must be only used as an argument to jit_retval. * TODO: New file listing important tasks to be resolved.
This commit is contained in:
parent
712877a5a4
commit
1c9088beca
11 changed files with 119 additions and 52 deletions
20
ChangeLog
20
ChangeLog
|
@ -1,3 +1,23 @@
|
||||||
|
2012-12-03 Paulo Andrade <pcpa@gnu.org>
|
||||||
|
|
||||||
|
* configure.ac, include/lightning/jit_private.h, lib/jit_arm-cpu.c,
|
||||||
|
lib/jit_arm-swf.c, lib/jit_arm.c, check/Makefile.am: Correct
|
||||||
|
implementation of the arm backend port to build and pass the
|
||||||
|
current test cases. Tested on armv7 with softfp abi.
|
||||||
|
|
||||||
|
* lib/jit_disasm.c: Rename and change prototype of static
|
||||||
|
disassemble function as in the arm backend it is required
|
||||||
|
to access state information stored in the jit_state_t object.
|
||||||
|
|
||||||
|
* check/3to2.tst, check/add.tst: Correct test case code assuming
|
||||||
|
JIT_RO and JIT_RET are the same, and even if they are the same,
|
||||||
|
the logic was incorrect because it must always call jit_retval*
|
||||||
|
to fetch a function call return before any other instruction.
|
||||||
|
The arm backend hash a special condition if jit_retval is not
|
||||||
|
called, because "r0" is not JIT_R0, but is JIT_RET and *also*
|
||||||
|
the first argument for a called function, so JIT_RET must be
|
||||||
|
only used as an argument to jit_retval.
|
||||||
|
|
||||||
2012-12-03 Paulo Andrade <pcpa@gnu.org>
|
2012-12-03 Paulo Andrade <pcpa@gnu.org>
|
||||||
|
|
||||||
* check/all.tst, check/lightning.c: Only declare or use 64 bit
|
* check/all.tst, check/lightning.c: Only declare or use 64 bit
|
||||||
|
|
11
TODO
Normal file
11
TODO
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
* Remove JIT_RET and JIT_FRET. Only interface to these should
|
||||||
|
be jit_retval, jit_retval_f and jit_retval_d, otherwise one
|
||||||
|
may use JIT_RET and/or JIT_FRET as argument to other jit calls,
|
||||||
|
what may cause problems at least on the arm backend.
|
||||||
|
|
||||||
|
* Update documentation to match new implementation.
|
||||||
|
|
||||||
|
* Make an sparc port to not remove previous functionality.
|
||||||
|
|
||||||
|
* Test and correct the ppc and mips ports, after the import and
|
||||||
|
adaptation of the code to lightning.
|
|
@ -22,9 +22,10 @@ test_double_##a##_##b##_##c: \
|
||||||
pushargi_d x \
|
pushargi_d x \
|
||||||
pushargi_d y \
|
pushargi_d y \
|
||||||
finishi test_double_##a##_##b##_##c \
|
finishi test_double_##a##_##b##_##c \
|
||||||
|
retval_d %f0 \
|
||||||
prepare 1 \
|
prepare 1 \
|
||||||
pushargi dfmt \
|
pushargi dfmt \
|
||||||
pushargr_d %fret \
|
pushargr_d %f0 \
|
||||||
finishi @printf
|
finishi @printf
|
||||||
|
|
||||||
#define def_test_int(a, b, c) \
|
#define def_test_int(a, b, c) \
|
||||||
|
@ -42,9 +43,10 @@ test_int_##a##_##b##_##c: \
|
||||||
pushargi x \
|
pushargi x \
|
||||||
pushargi y \
|
pushargi y \
|
||||||
finishi test_int_##a##_##b##_##c \
|
finishi test_int_##a##_##b##_##c \
|
||||||
|
retval %r0 \
|
||||||
prepare 1 \
|
prepare 1 \
|
||||||
pushargi ifmt \
|
pushargi ifmt \
|
||||||
pushargr %ret \
|
pushargr %r0 \
|
||||||
finishi @printf
|
finishi @printf
|
||||||
|
|
||||||
def_test_double(f0, f0, f0)
|
def_test_double(f0, f0, f0)
|
||||||
|
|
|
@ -16,7 +16,7 @@ AM_CFLAGS = -I$(top_srcdir)/include -D_GNU_SOURCE
|
||||||
|
|
||||||
check_PROGRAMS = lightning
|
check_PROGRAMS = lightning
|
||||||
|
|
||||||
lightning_LDADD = $(top_builddir)/lib/liblightning.la -ldl
|
lightning_LDADD = $(top_builddir)/lib/liblightning.la -lm -ldl
|
||||||
|
|
||||||
$(top_builddir)/lib/liblightning.la:
|
$(top_builddir)/lib/liblightning.la:
|
||||||
cd $(top_builddir)/lib; $(MAKE) $(AM_MAKEFLAGS) liblightning.la
|
cd $(top_builddir)/lib; $(MAKE) $(AM_MAKEFLAGS) liblightning.la
|
||||||
|
|
|
@ -21,6 +21,7 @@ main:
|
||||||
pushargi 5
|
pushargi 5
|
||||||
pushargi 4
|
pushargi 4
|
||||||
finishi test
|
finishi test
|
||||||
|
retval %r0
|
||||||
prepare 1
|
prepare 1
|
||||||
pushargi fmt
|
pushargi fmt
|
||||||
pushargi 5
|
pushargi 5
|
||||||
|
|
|
@ -71,6 +71,10 @@ AM_CONDITIONAL(cpu_arm, [test cpu-$cpu = cpu-arm])
|
||||||
AM_CONDITIONAL(cpu_mips, [test cpu-$cpu = cpu-mips])
|
AM_CONDITIONAL(cpu_mips, [test cpu-$cpu = cpu-mips])
|
||||||
AM_CONDITIONAL(cpu_ppc, [test cpu-$cpu = cpu-ppc])
|
AM_CONDITIONAL(cpu_ppc, [test cpu-$cpu = cpu-ppc])
|
||||||
AM_CONDITIONAL(cpu_x86, [test cpu-$cpu = cpu-x86])
|
AM_CONDITIONAL(cpu_x86, [test cpu-$cpu = cpu-x86])
|
||||||
|
if test $cpu = arm; then
|
||||||
|
AC_CHECK_LIB(m, sqrtf, ,
|
||||||
|
[AC_MSG_ERROR([sqrtf required but not available])])
|
||||||
|
fi
|
||||||
|
|
||||||
AC_SUBST([LIGHTNING_CFLAGS])
|
AC_SUBST([LIGHTNING_CFLAGS])
|
||||||
|
|
||||||
|
|
|
@ -261,10 +261,18 @@ struct jit_state {
|
||||||
# if DISASSEMBLER
|
# if DISASSEMBLER
|
||||||
struct {
|
struct {
|
||||||
jit_data_info_t *ptr;
|
jit_data_info_t *ptr;
|
||||||
it_word_t offset;
|
jit_word_t offset;
|
||||||
jit_word_t length;
|
jit_word_t length;
|
||||||
} data_info; /* constant pools information */
|
} data_info; /* constant pools information */
|
||||||
# endif
|
# endif
|
||||||
|
/* Note that this field is somewhat hackish, but required by most
|
||||||
|
* ways to implement jit, unless implementing a pure one function
|
||||||
|
* per jit, as most times it needs to start the jit buffer with a
|
||||||
|
* jump where the "main" prolog starts, and because the initial
|
||||||
|
* code is in "arm mode", need to make an "arm mode" patch on that
|
||||||
|
* jump. A good example is the test suite assembler, where most
|
||||||
|
* test cases start with a "jmpi main" call. */
|
||||||
|
jit_uword_t thumb;
|
||||||
struct {
|
struct {
|
||||||
jit_uint8_t *data; /* pointer to code */
|
jit_uint8_t *data; /* pointer to code */
|
||||||
jit_word_t size; /* size data */
|
jit_word_t size; /* size data */
|
||||||
|
|
|
@ -203,8 +203,8 @@ extern unsigned __aeabi_uidivmod(unsigned, unsigned);
|
||||||
# define THUMB2_CMNI 0xf1100000
|
# define THUMB2_CMNI 0xf1100000
|
||||||
# define ARM_TST 0x01100000
|
# define ARM_TST 0x01100000
|
||||||
# define THUMB_TST 0x4200
|
# define THUMB_TST 0x4200
|
||||||
# define THUMB2_TST 0xea100f00
|
# define THUMB2_TST 0xea100000
|
||||||
# define THUMB2_TSTI 0xf0100f00
|
# define THUMB2_TSTI 0xf0100000
|
||||||
# define ARM_TEQ 0x01300000
|
# define ARM_TEQ 0x01300000
|
||||||
/* branch */
|
/* branch */
|
||||||
# define ARM_BX 0x012fff10
|
# define ARM_BX 0x012fff10
|
||||||
|
@ -2429,7 +2429,8 @@ _jmpi(jit_state_t *_jit, jit_word_t i0)
|
||||||
jit_word_t w;
|
jit_word_t w;
|
||||||
jit_word_t d;
|
jit_word_t d;
|
||||||
w = _jit->pc.w;
|
w = _jit->pc.w;
|
||||||
if (jit_thumb_p()) {
|
/* if thumb and in thumb mode */
|
||||||
|
if (jit_thumb_p() && _jit->thumb) {
|
||||||
d = ((i0 - w) >> 1) - 2;
|
d = ((i0 - w) >> 1) - 2;
|
||||||
if (d >= -1024 && d <= 1023)
|
if (d >= -1024 && d <= 1023)
|
||||||
T1_B(d & 0x7ff);
|
T1_B(d & 0x7ff);
|
||||||
|
@ -2460,7 +2461,8 @@ _jmpi_p(jit_state_t *_jit, jit_word_t i0)
|
||||||
jit_word_t w;
|
jit_word_t w;
|
||||||
jit_word_t d;
|
jit_word_t d;
|
||||||
w = _jit->pc.w;
|
w = _jit->pc.w;
|
||||||
if (jit_thumb_p()) {
|
/* if thumb and in thumb mode */
|
||||||
|
if (jit_thumb_p() && _jit->thumb) {
|
||||||
d = ((i0 - w) >> 1) - 2;
|
d = ((i0 - w) >> 1) - 2;
|
||||||
assert(_s24P(d));
|
assert(_s24P(d));
|
||||||
T2_B(encode_thumb_jump(d));
|
T2_B(encode_thumb_jump(d));
|
||||||
|
@ -3569,6 +3571,8 @@ _prolog(jit_state_t *_jit, jit_node_t *node)
|
||||||
* a pointer to a jit function) */
|
* a pointer to a jit function) */
|
||||||
ADDI(_R12_REGNO, _R15_REGNO, 1);
|
ADDI(_R12_REGNO, _R15_REGNO, 1);
|
||||||
BX(_R12_REGNO);
|
BX(_R12_REGNO);
|
||||||
|
if (!_jit->thumb)
|
||||||
|
_jit->thumb = _jit->pc.w;
|
||||||
if (jit_cpu.abi) {
|
if (jit_cpu.abi) {
|
||||||
T2_PUSH(0x3f0|(1<<_FP_REGNO)|(1<<_LR_REGNO));
|
T2_PUSH(0x3f0|(1<<_FP_REGNO)|(1<<_LR_REGNO));
|
||||||
VPUSH_F64(_D8_REGNO, 8);
|
VPUSH_F64(_D8_REGNO, 8);
|
||||||
|
@ -3617,7 +3621,7 @@ _patch_at(jit_state_t *_jit,
|
||||||
} u;
|
} u;
|
||||||
u.w = instr;
|
u.w = instr;
|
||||||
if (kind == arm_patch_jump) {
|
if (kind == arm_patch_jump) {
|
||||||
if (jit_thumb_p()) {
|
if (jit_thumb_p() && instr >= _jit->thumb) {
|
||||||
code2thumb(thumb.s[0], thumb.s[1], u.s[0], u.s[1]);
|
code2thumb(thumb.s[0], thumb.s[1], u.s[0], u.s[1]);
|
||||||
if ((thumb.i & THUMB2_B) == THUMB2_B) {
|
if ((thumb.i & THUMB2_B) == THUMB2_B) {
|
||||||
d = ((label - instr) >> 1) - 2;
|
d = ((label - instr) >> 1) - 2;
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
#if PROTO
|
#if PROTO
|
||||||
/* match vfpv3 result */
|
/* match vfpv3 result */
|
||||||
#define NAN_TO_INT_IS_ZERO 1
|
#define NAN_TO_INT_IS_ZERO 1
|
||||||
|
extern float sqrtf(float);
|
||||||
|
extern double sqrt(double);
|
||||||
extern float __addsf3(float, float);
|
extern float __addsf3(float, float);
|
||||||
extern double __adddf3(double, double);
|
extern double __adddf3(double, double);
|
||||||
extern float __aeabi_fsub(float, float);
|
extern float __aeabi_fsub(float, float);
|
||||||
|
@ -47,7 +49,7 @@ extern int __aeabi_dcmpun(double, double);
|
||||||
# define swf_ff(i0,r0,r1) _swf_ff(_jit,i0,r0,r1)
|
# define swf_ff(i0,r0,r1) _swf_ff(_jit,i0,r0,r1)
|
||||||
static void
|
static void
|
||||||
_swf_ff(jit_state_t*,float(*)(float),jit_int32_t,jit_int32_t) maybe_unused;
|
_swf_ff(jit_state_t*,float(*)(float),jit_int32_t,jit_int32_t) maybe_unused;
|
||||||
# define swf_dd(i0,r0,r1) _swf_id(_jit,i0,r0,r1)
|
# define swf_dd(i0,r0,r1) _swf_dd(_jit,i0,r0,r1)
|
||||||
static void
|
static void
|
||||||
_swf_dd(jit_state_t*,double(*)(double),jit_int32_t,jit_int32_t) maybe_unused;
|
_swf_dd(jit_state_t*,double(*)(double),jit_int32_t,jit_int32_t) maybe_unused;
|
||||||
# define swf_fff(i0,r0,r1,r2) _swf_fff(_jit,i0,r0,r1,r2)
|
# define swf_fff(i0,r0,r1,r2) _swf_fff(_jit,i0,r0,r1,r2)
|
||||||
|
@ -138,6 +140,8 @@ static void _swf_absr_d(jit_state_t*,jit_int32_t,jit_int32_t);
|
||||||
static void _swf_negr_f(jit_state_t*,jit_int32_t,jit_int32_t);
|
static void _swf_negr_f(jit_state_t*,jit_int32_t,jit_int32_t);
|
||||||
# define swf_negr_d(r0,r1) _swf_negr_d(_jit,r0,r1)
|
# define swf_negr_d(r0,r1) _swf_negr_d(_jit,r0,r1)
|
||||||
static void _swf_negr_d(jit_state_t*,jit_int32_t,jit_int32_t);
|
static void _swf_negr_d(jit_state_t*,jit_int32_t,jit_int32_t);
|
||||||
|
# define swf_sqrtr_f(r0,r1) swf_ff(sqrtf,r0,r1)
|
||||||
|
# define swf_sqrtr_d(r0,r1) swf_dd(sqrt,r0,r1)
|
||||||
# define swf_addr_f(r0,r1,r2) swf_fff(__addsf3,r0,r1,r2)
|
# define swf_addr_f(r0,r1,r2) swf_fff(__addsf3,r0,r1,r2)
|
||||||
# define swf_addi_f(r0,r1,i0) swf_fff_(__addsf3,r0,r1,i0)
|
# define swf_addi_f(r0,r1,i0) swf_fff_(__addsf3,r0,r1,i0)
|
||||||
# define swf_addr_d(r0,r1,r2) swf_ddd(__adddf3,r0,r1,r2)
|
# define swf_addr_d(r0,r1,r2) swf_ddd(__adddf3,r0,r1,r2)
|
||||||
|
|
|
@ -189,7 +189,7 @@ void
|
||||||
_jit_init(jit_state_t *_jit)
|
_jit_init(jit_state_t *_jit)
|
||||||
{
|
{
|
||||||
jit_int32_t regno;
|
jit_int32_t regno;
|
||||||
_jit->reglen = esize(_rvs) - 1;
|
_jit->reglen = jit_size(_rvs) - 1;
|
||||||
/* jit_get_cpu() should have been already called, and only once */
|
/* jit_get_cpu() should have been already called, and only once */
|
||||||
if (!jit_cpu.vfp) {
|
if (!jit_cpu.vfp) {
|
||||||
/* cause register to never be allocated, because simple
|
/* cause register to never be allocated, because simple
|
||||||
|
@ -212,7 +212,7 @@ _jit_prolog(jit_state_t *_jit)
|
||||||
jit_epilog();
|
jit_epilog();
|
||||||
assert(jit_regset_cmp_ui(_jit->regarg, 0) == 0);
|
assert(jit_regset_cmp_ui(_jit->regarg, 0) == 0);
|
||||||
jit_regset_set_ui(_jit->regsav, 0);
|
jit_regset_set_ui(_jit->regsav, 0);
|
||||||
offset = _jit->functions->offset;
|
offset = _jit->functions.offset;
|
||||||
if (offset >= _jit->functions.length) {
|
if (offset >= _jit->functions.length) {
|
||||||
_jit->functions.ptr = realloc(_jit->functions.ptr,
|
_jit->functions.ptr = realloc(_jit->functions.ptr,
|
||||||
(_jit->functions.length + 16) *
|
(_jit->functions.length + 16) *
|
||||||
|
@ -320,7 +320,6 @@ void
|
||||||
_jit_epilog(jit_state_t *_jit)
|
_jit_epilog(jit_state_t *_jit)
|
||||||
{
|
{
|
||||||
assert(_jit->function);
|
assert(_jit->function);
|
||||||
|
|
||||||
_jit->function->stack = ((_jit->function->self.alen -
|
_jit->function->stack = ((_jit->function->self.alen -
|
||||||
/* align stack at 8 bytes */
|
/* align stack at 8 bytes */
|
||||||
_jit->function->self.aoff) + 7) & -8;
|
_jit->function->self.aoff) + 7) & -8;
|
||||||
|
@ -344,7 +343,7 @@ _jit_arg(jit_state_t *_jit)
|
||||||
return (offset);
|
return (offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
ebool_t
|
jit_bool_t
|
||||||
_jit_arg_reg_p(jit_state_t *_jit, jit_int32_t offset)
|
_jit_arg_reg_p(jit_state_t *_jit, jit_int32_t offset)
|
||||||
{
|
{
|
||||||
return (offset >= 0 && offset < 4);
|
return (offset >= 0 && offset < 4);
|
||||||
|
@ -367,7 +366,7 @@ _jit_arg_f(jit_state_t *_jit)
|
||||||
return (offset);
|
return (offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
ebool_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_reg_p(offset));
|
return (jit_arg_reg_p(offset));
|
||||||
|
@ -402,7 +401,7 @@ _jit_arg_d(jit_state_t *_jit)
|
||||||
return (offset);
|
return (offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
ebool_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 (jit_arg_reg_p(offset));
|
return (jit_arg_reg_p(offset));
|
||||||
|
@ -543,7 +542,7 @@ _jit_pushargr_f(jit_state_t *_jit, jit_int32_t u)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_jit_pushargi_f(jit_state_t *_jit, efloat32_t u)
|
_jit_pushargi_f(jit_state_t *_jit, jit_float32_t u)
|
||||||
{
|
{
|
||||||
jit_int32_t regno;
|
jit_int32_t regno;
|
||||||
|
|
||||||
|
@ -598,7 +597,7 @@ _jit_pushargr_d(jit_state_t *_jit, jit_int32_t u)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_jit_pushargi_d(jit_state_t *_jit, efloat64_t u)
|
_jit_pushargi_d(jit_state_t *_jit, jit_float64_t u)
|
||||||
{
|
{
|
||||||
jit_int32_t regno;
|
jit_int32_t regno;
|
||||||
|
|
||||||
|
@ -746,22 +745,24 @@ _jit_emit(jit_state_t *_jit)
|
||||||
jit_node_t *node;
|
jit_node_t *node;
|
||||||
jit_uint8_t *data;
|
jit_uint8_t *data;
|
||||||
jit_word_t word;
|
jit_word_t word;
|
||||||
|
jit_uword_t thumb;
|
||||||
jit_int32_t info_offset;
|
jit_int32_t info_offset;
|
||||||
jit_int32_t const_offset;
|
jit_int32_t const_offset;
|
||||||
jit_int32_t patch_offset;
|
jit_int32_t patch_offset;
|
||||||
} undo;
|
} undo;
|
||||||
|
|
||||||
jit_epilog();
|
if (_jit->function)
|
||||||
|
jit_epilog();
|
||||||
jit_optimize();
|
jit_optimize();
|
||||||
|
|
||||||
_jit->emit = 1;
|
_jit->emit = 1;
|
||||||
|
|
||||||
_jit->code_length = 16 * 1024 * 1024;
|
_jit->code.length = 16 * 1024 * 1024;
|
||||||
_jit->code = mmap(NULL, _jit->code_length,
|
_jit->code.ptr = mmap(NULL, _jit->code.length,
|
||||||
PROT_EXEC | PROT_READ | PROT_WRITE,
|
PROT_EXEC | PROT_READ | PROT_WRITE,
|
||||||
MAP_PRIVATE | MAP_ANON, -1, 0);
|
MAP_PRIVATE | MAP_ANON, -1, 0);
|
||||||
assert(_jit->code.ptr != MAP_FAILED);
|
assert(_jit->code.ptr != MAP_FAILED);
|
||||||
_jit->pc.uc = _jit->code;
|
_jit->pc.uc = _jit->code.ptr;
|
||||||
|
|
||||||
/* clear jit_flag_patch from label nodes if reallocating buffer
|
/* clear jit_flag_patch from label nodes if reallocating buffer
|
||||||
* and starting over
|
* and starting over
|
||||||
|
@ -774,6 +775,7 @@ _jit_emit(jit_state_t *_jit)
|
||||||
undo.word = 0;
|
undo.word = 0;
|
||||||
undo.node = NULL;
|
undo.node = NULL;
|
||||||
undo.data = NULL;
|
undo.data = NULL;
|
||||||
|
undo.thumb = 0;
|
||||||
undo.info_offset = undo.const_offset = undo.patch_offset = 0;
|
undo.info_offset = undo.const_offset = undo.patch_offset = 0;
|
||||||
# define assert_data(node) /**/
|
# define assert_data(node) /**/
|
||||||
#define case_rr(name, type) \
|
#define case_rr(name, type) \
|
||||||
|
@ -1147,6 +1149,7 @@ _jit_emit(jit_state_t *_jit)
|
||||||
case_vvf(div);
|
case_vvf(div);
|
||||||
case_vv(abs, _f);
|
case_vv(abs, _f);
|
||||||
case_vv(neg, _f);
|
case_vv(neg, _f);
|
||||||
|
case_vv(sqrt, _f);
|
||||||
case_vv(ext, _f);
|
case_vv(ext, _f);
|
||||||
case_vv(ld, _f);
|
case_vv(ld, _f);
|
||||||
case_vw(ld, _f);
|
case_vw(ld, _f);
|
||||||
|
@ -1231,6 +1234,7 @@ _jit_emit(jit_state_t *_jit)
|
||||||
case_vvd(div);
|
case_vvd(div);
|
||||||
case_vv(abs, _d);
|
case_vv(abs, _d);
|
||||||
case_vv(neg, _d);
|
case_vv(neg, _d);
|
||||||
|
case_vv(sqrt, _d);
|
||||||
case_vv(ext, _d);
|
case_vv(ext, _d);
|
||||||
case_vv(ld, _d);
|
case_vv(ld, _d);
|
||||||
case_vw(ld, _d);
|
case_vw(ld, _d);
|
||||||
|
@ -1344,9 +1348,10 @@ _jit_emit(jit_state_t *_jit)
|
||||||
undo.node = node;
|
undo.node = node;
|
||||||
undo.word = _jit->pc.w;
|
undo.word = _jit->pc.w;
|
||||||
undo.data = _jit->consts.data;
|
undo.data = _jit->consts.data;
|
||||||
|
undo.thumb = _jit->thumb;
|
||||||
undo.const_offset = _jit->consts.offset;
|
undo.const_offset = _jit->consts.offset;
|
||||||
undo.patch_offset = _jit->patches.offset;
|
undo.patch_offset = _jit->patches.offset;
|
||||||
if (_jit->data_info)
|
if (_jit->data_info.ptr)
|
||||||
undo.info_offset = _jit->data_info.offset;
|
undo.info_offset = _jit->data_info.offset;
|
||||||
restart_function:
|
restart_function:
|
||||||
_jit->again = 0;
|
_jit->again = 0;
|
||||||
|
@ -1365,9 +1370,10 @@ _jit_emit(jit_state_t *_jit)
|
||||||
_jit->pc.w = undo.word;
|
_jit->pc.w = undo.word;
|
||||||
invalidate_consts();
|
invalidate_consts();
|
||||||
_jit->consts.data = undo.data;
|
_jit->consts.data = undo.data;
|
||||||
|
_jit->thumb = undo.thumb;
|
||||||
_jit->consts.offset = undo.const_offset;
|
_jit->consts.offset = undo.const_offset;
|
||||||
_jit->patches.offset = undo.patch_offset;
|
_jit->patches.offset = undo.patch_offset;
|
||||||
if (_jit->data_info)
|
if (_jit->data_info.ptr)
|
||||||
_jit->data_info.offset = undo.info_offset;
|
_jit->data_info.offset = undo.info_offset;
|
||||||
goto restart_function;
|
goto restart_function;
|
||||||
}
|
}
|
||||||
|
@ -1423,9 +1429,9 @@ _jit_emit(jit_state_t *_jit)
|
||||||
|
|
||||||
flush_consts();
|
flush_consts();
|
||||||
for (offset = 0; offset < _jit->patches.offset; offset++) {
|
for (offset = 0; offset < _jit->patches.offset; offset++) {
|
||||||
assert(patches[offset] & arm_patch_node);
|
assert(_jit->patches.ptr[offset].kind & arm_patch_node);
|
||||||
node = _jit->patches.ptr[offset].node;
|
node = _jit->patches.ptr[offset].node;
|
||||||
word = _jit->patches[offset].inst;
|
word = _jit->patches.ptr[offset].inst;
|
||||||
if (node->code == jit_code_movi) {
|
if (node->code == jit_code_movi) {
|
||||||
if (jit_thumb_p())
|
if (jit_thumb_p())
|
||||||
value = node->v.n->u.w;
|
value = node->v.n->u.w;
|
||||||
|
@ -1446,7 +1452,7 @@ _jit_emit(jit_state_t *_jit)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
value = node->u.n->u.w;
|
value = node->u.n->u.w;
|
||||||
patch_at(patches[offset] & ~arm_patch_node, word, value);
|
patch_at(_jit->patches.ptr[offset].kind & ~arm_patch_node, word, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
__clear_cache(_jit->code.ptr, _jit->pc.uc);
|
__clear_cache(_jit->code.ptr, _jit->pc.uc);
|
||||||
|
@ -1618,7 +1624,6 @@ _flush_consts(jit_state_t *_jit)
|
||||||
{
|
{
|
||||||
jit_word_t word;
|
jit_word_t word;
|
||||||
jit_int32_t offset;
|
jit_int32_t offset;
|
||||||
jit_word_t *vector;
|
|
||||||
|
|
||||||
/* if no forward constants */
|
/* if no forward constants */
|
||||||
if (!_jit->consts.length)
|
if (!_jit->consts.length)
|
||||||
|
@ -1632,12 +1637,18 @@ _flush_consts(jit_state_t *_jit)
|
||||||
memcpy(_jit->consts.data, _jit->consts.values, _jit->consts.size);
|
memcpy(_jit->consts.data, _jit->consts.values, _jit->consts.size);
|
||||||
_jit->pc.w += _jit->consts.size;
|
_jit->pc.w += _jit->consts.size;
|
||||||
|
|
||||||
if (_jit->data_info) {
|
if (_jit->data_info.ptr) {
|
||||||
if (_jit->data_info->offset + 2 >= _jit->data_info->length)
|
if (_jit->data_info.offset >= _jit->data_info.length) {
|
||||||
erenew_vector(_jit->data_info, _jit->data_info->length + 1024);
|
_jit->data_info.ptr = realloc(_jit->data_info.ptr,
|
||||||
vector = _jit->data_info->v.obj;
|
(_jit->data_info.length + 1024) *
|
||||||
vector[_jit->data_info->offset++] = word;
|
sizeof(jit_data_info_t));
|
||||||
vector[_jit->data_info->offset++] = _jit->consts.size;
|
memset(_jit->data_info.ptr + _jit->data_info.length, 0,
|
||||||
|
1024 * sizeof(jit_data_info_t));
|
||||||
|
_jit->data_info.length += 1024;
|
||||||
|
}
|
||||||
|
_jit->data_info.ptr[_jit->data_info.offset].code = word;
|
||||||
|
_jit->data_info.ptr[_jit->data_info.offset].length = _jit->consts.size;
|
||||||
|
++_jit->data_info.offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (offset = 0; offset < _jit->consts.offset; offset += 2)
|
for (offset = 0; offset < _jit->consts.offset; offset += 2)
|
||||||
|
@ -1687,7 +1698,7 @@ _patch(jit_state_t *_jit, jit_word_t instr, jit_node_t *node)
|
||||||
_jit->patches.length += 1024;
|
_jit->patches.length += 1024;
|
||||||
}
|
}
|
||||||
_jit->patches.ptr[_jit->patches.offset].kind = kind;
|
_jit->patches.ptr[_jit->patches.offset].kind = kind;
|
||||||
_jit->patches.ptr[_jit->patches.offset].instr = instr;
|
_jit->patches.ptr[_jit->patches.offset].inst = instr;
|
||||||
_jit->patches.ptr[_jit->patches.offset].node = node;
|
_jit->patches.ptr[_jit->patches.offset].node = node;
|
||||||
++_jit->patches.offset;
|
++_jit->patches.offset;
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,8 +29,9 @@ disasm_compare_symbols(const void *ap, const void *bp);
|
||||||
static void
|
static void
|
||||||
disasm_print_address(bfd_vma addr, struct disassemble_info *info);
|
disasm_print_address(bfd_vma addr, struct disassemble_info *info);
|
||||||
|
|
||||||
|
#define disassemble(u, v) _disassemble(_jit, u, v)
|
||||||
static void
|
static void
|
||||||
disassemble(jit_pointer_t code, jit_int32_t length);
|
_disassemble(jit_state_t *_jit, jit_pointer_t code, jit_int32_t length);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -238,19 +239,20 @@ disasm_print_address(bfd_vma addr, struct disassemble_info *info)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
disassemble(jit_pointer_t code, jit_int32_t length)
|
_disassemble(jit_state_t *_jit, jit_pointer_t code, jit_int32_t length)
|
||||||
{
|
{
|
||||||
int bytes;
|
int bytes;
|
||||||
#if __arm__
|
#if __arm__
|
||||||
jit_data_info_t *data_info;
|
jit_int32_t offset;
|
||||||
jit_int32_t data_offset;
|
jit_bool_t data_info;
|
||||||
|
jit_int32_t data_offset;
|
||||||
#endif
|
#endif
|
||||||
bfd_vma pc = (jit_uword_t)code;
|
bfd_vma pc = (jit_uword_t)code;
|
||||||
bfd_vma end = (jit_uword_t)code + length;
|
bfd_vma end = (jit_uword_t)code + length;
|
||||||
char buffer[address_buffer_length];
|
char buffer[address_buffer_length];
|
||||||
|
|
||||||
#if __arm__
|
#if __arm__
|
||||||
data_info = _jit->data_info;
|
data_info = 1;
|
||||||
data_offset = 0;
|
data_offset = 0;
|
||||||
#endif
|
#endif
|
||||||
disasm_info.buffer = code;
|
disasm_info.buffer = code;
|
||||||
|
@ -260,16 +262,16 @@ disassemble(jit_pointer_t code, jit_int32_t length)
|
||||||
#if __arm__
|
#if __arm__
|
||||||
again:
|
again:
|
||||||
if (data_info) {
|
if (data_info) {
|
||||||
while (data_info.ptr[data_offset].code < pc) {
|
while (_jit->data_info.ptr[data_offset].code < pc) {
|
||||||
data_offset += 2;
|
data_offset += 2;
|
||||||
if (data_offset >= data_info.length) {
|
if (data_offset >= _jit->data_info.length) {
|
||||||
data_info = NULL;
|
data_info = 0;
|
||||||
goto again;
|
goto again;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (pc == data_info.ptr[data_offset].code) {
|
if (pc == _jit->data_info.ptr[data_offset].code) {
|
||||||
line = data_info.ptr[data_offset].length;
|
offset = _jit->data_info.ptr[data_offset].length;
|
||||||
for (; line >= 4; line -= 4, pc += 4) {
|
for (; offset >= 4; offset -= 4, pc += 4) {
|
||||||
bytes = sprintf(buffer, address_buffer_format, pc);
|
bytes = sprintf(buffer, address_buffer_format, pc);
|
||||||
(*disasm_info.fprintf_func)(disasm_stream,
|
(*disasm_info.fprintf_func)(disasm_stream,
|
||||||
"%*c0x%s\t.data\t0x%08x\n",
|
"%*c0x%s\t.data\t0x%08x\n",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue