diff --git a/lightening.h b/lightening.h index db327fc45..40db318bb 100644 --- a/lightening.h +++ b/lightening.h @@ -228,6 +228,11 @@ JIT_API void jit_move_operands (jit_state_t *_jit, jit_operand_t *dst, JIT_API size_t jit_align_stack (jit_state_t *_jit, size_t expand); JIT_API void jit_shrink_stack (jit_state_t *_jit, size_t diff); +JIT_API size_t jit_enter_jit_abi (jit_state_t *_jit, + size_t v, size_t vf, size_t frame_size); +JIT_API void jit_leave_jit_abi (jit_state_t *_jit, + size_t v, size_t vf, size_t frame_size); + /* Note that all functions that take jit_operand_t args[] use the args as scratch space while shuffling values into position. */ JIT_API void jit_calli(jit_state_t *, jit_pointer_t f, diff --git a/lightening/lightening.c b/lightening/lightening.c index de945e02f..74ecf99cd 100644 --- a/lightening/lightening.c +++ b/lightening/lightening.c @@ -863,6 +863,104 @@ jit_shrink_stack(jit_state_t *_jit, size_t diff) _jit->frame_size -= diff; } +static const jit_gpr_t V[] = { +#ifdef JIT_VTMP + JIT_VTMP , +#endif + JIT_V0, JIT_V1, JIT_V2 +#ifdef JIT_V3 + , JIT_V3 +#endif +#ifdef JIT_V4 + , JIT_V4 +#endif +#ifdef JIT_V5 + , JIT_V5 +#endif +#ifdef JIT_V6 + , JIT_V6 +#endif +#ifdef JIT_V7 + , JIT_V7 +#endif + }; + +static const jit_fpr_t VF[] = { +#ifdef JIT_VFTMP + JIT_VFTMP , +#endif +#ifdef JIT_VF0 + JIT_VF0 +#endif +#ifdef JIT_VF1 + , JIT_VF1 +#endif +#ifdef JIT_VF2 + , JIT_VF2 +#endif +#ifdef JIT_VF3 + , JIT_VF3 +#endif +#ifdef JIT_VF4 + , JIT_VF4 +#endif +#ifdef JIT_VF5 + , JIT_VF5 +#endif +#ifdef JIT_VF6 + , JIT_VF6 +#endif +#ifdef JIT_VF7 + , JIT_VF7 +#endif +}; + +static const size_t v_count = sizeof(V) / sizeof(V[0]); +static const size_t vf_count = sizeof(VF) / sizeof(VF[0]); + +size_t +jit_enter_jit_abi(jit_state_t *_jit, size_t v, size_t vf, size_t frame_size) +{ +#ifdef JIT_VTMP + v++; +#endif +#ifdef JIT_VFTMP + vf++; +#endif + + ASSERT(v <= v_count); + ASSERT(vf <= vf_count); + + /* Save values of callee-save registers. */ + for (size_t i = 0; i < v; i++) + jit_pushr (_jit, V[i]); + for (size_t i = 0; i < vf; i++) + jit_pushr_d (_jit, VF[i]); + + return jit_align_stack(_jit, frame_size); +} + +void +jit_leave_jit_abi(jit_state_t *_jit, size_t v, size_t vf, size_t frame_size) +{ +#ifdef JIT_VTMP + v++; +#endif +#ifdef JIT_VFTMP + vf++; +#endif + + jit_shrink_stack(_jit, frame_size); + + /* Restore callee-save registers. */ + for (size_t i = 0; i < vf; i++) + jit_popr_d (_jit, VF[vf_count - i - 1]); + + for (size_t i = 0; i < v; i++) + jit_popr (_jit, V[v_count - i - 1]); +} + + // Precondition: stack is already aligned. static size_t prepare_call_args(jit_state_t *_jit, size_t argc, jit_operand_t args[]) diff --git a/lightening/x86-cpu.c b/lightening/x86-cpu.c index 537e33184..6d56b114b 100644 --- a/lightening/x86-cpu.c +++ b/lightening/x86-cpu.c @@ -273,8 +273,7 @@ get_temp_gpr(jit_state_t *_jit) #ifdef JIT_RTMP return JIT_RTMP; #else - pushr(_jit, _RBP_REGNO); - return _RBP; + return JIT_VTMP; #endif } @@ -283,9 +282,6 @@ unget_temp_gpr(jit_state_t *_jit) { ASSERT(_jit->temp_gpr_saved); _jit->temp_gpr_saved = 0; -#ifndef JIT_RTMP - popr(_jit, _RBP_REGNO); -#endif } static void diff --git a/lightening/x86.h b/lightening/x86.h index 804af869a..db5072273 100644 --- a/lightening/x86.h +++ b/lightening/x86.h @@ -133,6 +133,7 @@ jit_fpr_is_callee_save (jit_fpr_t reg) # define JIT_V0 _RBX # define JIT_V1 _RSI # define JIT_V2 _RDI +# define JIT_VTMP _RBP # define JIT_F0 _XMM0 # define JIT_F1 _XMM1 # define JIT_F2 _XMM2 diff --git a/tests/qdivr.c b/tests/qdivr.c index 9e1b8da04..665053c56 100644 --- a/tests/qdivr.c +++ b/tests/qdivr.c @@ -1,26 +1,10 @@ #include "test.h" -static void -maybe_save(jit_state_t *j, jit_gpr_t reg) -{ - if (jit_gpr_is_callee_save (reg)) - jit_pushr(j, reg); -} - -static void -maybe_restore(jit_state_t *j, jit_gpr_t reg) -{ - if (jit_gpr_is_callee_save (reg)) - jit_popr(j, reg); -} - static void run_test(jit_state_t *j, uint8_t *arena_base, size_t arena_size) { jit_begin(j, arena_base, arena_size); - maybe_save(j, JIT_V0); - maybe_save(j, JIT_V1); - maybe_save(j, JIT_V2); + size_t align = jit_enter_jit_abi(j, 3, 0, 0); jit_operand_t args[] = { jit_operand_gpr (JIT_OPERAND_ABI_POINTER, JIT_R0), @@ -33,9 +17,7 @@ run_test(jit_state_t *j, uint8_t *arena_base, size_t arena_size) jit_str(j, JIT_R0, JIT_V1); jit_str(j, JIT_R1, JIT_V2); - maybe_restore(j, JIT_V2); - maybe_restore(j, JIT_V1); - maybe_restore(j, JIT_V0); + jit_leave_jit_abi(j, 3, 0, align); jit_ret(j); diff --git a/tests/qdivr_u.c b/tests/qdivr_u.c index 276219971..e2601933c 100644 --- a/tests/qdivr_u.c +++ b/tests/qdivr_u.c @@ -1,27 +1,11 @@ #include "test.h" -static void -maybe_save(jit_state_t *j, jit_gpr_t reg) -{ - if (jit_gpr_is_callee_save (reg)) - jit_pushr(j, reg); -} - -static void -maybe_restore(jit_state_t *j, jit_gpr_t reg) -{ - if (jit_gpr_is_callee_save (reg)) - jit_popr(j, reg); -} - static void run_test(jit_state_t *j, uint8_t *arena_base, size_t arena_size) { jit_begin(j, arena_base, arena_size); - maybe_save(j, JIT_V0); - maybe_save(j, JIT_V1); - maybe_save(j, JIT_V2); + size_t align = jit_enter_jit_abi(j, 3, 0, 0); jit_operand_t args[] = { jit_operand_gpr (JIT_OPERAND_ABI_POINTER, JIT_R0), @@ -34,9 +18,7 @@ run_test(jit_state_t *j, uint8_t *arena_base, size_t arena_size) jit_str(j, JIT_R0, JIT_V1); jit_str(j, JIT_R1, JIT_V2); - maybe_restore(j, JIT_V2); - maybe_restore(j, JIT_V1); - maybe_restore(j, JIT_V0); + jit_leave_jit_abi(j, 3, 0, align); jit_ret(j); diff --git a/tests/qmulr.c b/tests/qmulr.c index eed0d58fd..1645f5a9f 100644 --- a/tests/qmulr.c +++ b/tests/qmulr.c @@ -1,27 +1,11 @@ #include "test.h" -static void -maybe_save(jit_state_t *j, jit_gpr_t reg) -{ - if (jit_gpr_is_callee_save (reg)) - jit_pushr(j, reg); -} - -static void -maybe_restore(jit_state_t *j, jit_gpr_t reg) -{ - if (jit_gpr_is_callee_save (reg)) - jit_popr(j, reg); -} - static void run_test(jit_state_t *j, uint8_t *arena_base, size_t arena_size) { jit_begin(j, arena_base, arena_size); - maybe_save(j, JIT_V0); - maybe_save(j, JIT_V1); - maybe_save(j, JIT_V2); + size_t align = jit_enter_jit_abi(j, 3, 0, 0); jit_operand_t args[] = { jit_operand_gpr (JIT_OPERAND_ABI_POINTER, JIT_R0), @@ -34,9 +18,7 @@ run_test(jit_state_t *j, uint8_t *arena_base, size_t arena_size) jit_str(j, JIT_R0, JIT_V1); jit_str(j, JIT_R1, JIT_V2); - maybe_restore(j, JIT_V2); - maybe_restore(j, JIT_V1); - maybe_restore(j, JIT_V0); + jit_leave_jit_abi(j, 3, 0, align); jit_ret(j); diff --git a/tests/qmulr_u.c b/tests/qmulr_u.c index ff3c92655..bb1d50d17 100644 --- a/tests/qmulr_u.c +++ b/tests/qmulr_u.c @@ -1,27 +1,11 @@ #include "test.h" -static void -maybe_save(jit_state_t *j, jit_gpr_t reg) -{ - if (jit_gpr_is_callee_save (reg)) - jit_pushr(j, reg); -} - -static void -maybe_restore(jit_state_t *j, jit_gpr_t reg) -{ - if (jit_gpr_is_callee_save (reg)) - jit_popr(j, reg); -} - static void run_test(jit_state_t *j, uint8_t *arena_base, size_t arena_size) { jit_begin(j, arena_base, arena_size); - maybe_save(j, JIT_V0); - maybe_save(j, JIT_V1); - maybe_save(j, JIT_V2); + size_t align = jit_enter_jit_abi(j, 3, 0, 0); jit_operand_t args[] = { jit_operand_gpr (JIT_OPERAND_ABI_POINTER, JIT_R0), @@ -34,9 +18,7 @@ run_test(jit_state_t *j, uint8_t *arena_base, size_t arena_size) jit_str(j, JIT_R0, JIT_V1); jit_str(j, JIT_R1, JIT_V2); - maybe_restore(j, JIT_V2); - maybe_restore(j, JIT_V1); - maybe_restore(j, JIT_V0); + jit_leave_jit_abi(j, 3, 0, align); jit_ret(j);