1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-06-28 22:10:29 +02:00

x86: Implement support for the x32 abi

* include/lightning/jit_private.h, include/lightning/jit_x86.h,
	lib/jit_disasm.c, lib/jit_x86-cpu.c, lib/jit_x86-sse.c,
	lib/jit_x86-sz.c, lib/jit_x86-x87.c, lib/jit_x86.c,
	size.c: Implement support for the x32 abi. Built and
	tested on Gentoo default/linux/amd64/13.0/x32 profile.
This commit is contained in:
Paulo Andrade 2014-12-24 14:14:38 -02:00
parent 3b829ab075
commit fdf41c1fa4
10 changed files with 637 additions and 183 deletions

View file

@ -23,10 +23,11 @@
#define rc(value) jit_class_##value
#define rn(reg) (jit_regno(_rvs[jit_regno(reg)].spec))
#if __WORDSIZE == 32
#if __X32
# define stack_framesize 20
# define stack_adjust 12
# define CVT_OFFSET -12
# define REAL_WORDSIZE 4
#else
# if __CYGWIN__
# define stack_framesize 152
@ -35,8 +36,10 @@
# endif
# define stack_adjust 8
# define CVT_OFFSET -8
# define REAL_WORDSIZE 8
#endif
/*
* Prototypes
*/
@ -62,7 +65,7 @@ static void _x87_from_sse_d(jit_state_t*,jit_int32_t,jit_int32_t);
*/
jit_cpu_t jit_cpu;
jit_register_t _rvs[] = {
#if __WORDSIZE == 32
#if __X32
{ rc(gpr) | rc(rg8) | 0, "%eax" },
{ rc(gpr) | rc(rg8) | 1, "%ecx" },
{ rc(gpr) | rc(rg8) | 2, "%edx" },
@ -248,12 +251,12 @@ jit_get_cpu(void)
} bits;
jit_uword_t cpuid;
} edx;
#if __WORDSIZE == 32
#if __X32
int ac, flags;
#endif
jit_uword_t eax, ebx;
#if __WORDSIZE == 32
#if __X32
/* adapted from glibc __sysconf */
__asm__ volatile ("pushfl;\n\t"
"popl %0;\n\t"
@ -275,7 +278,7 @@ jit_get_cpu(void)
#endif
/* query %eax = 1 function */
#if __WORDSIZE == 32
#if __X32 || __X64_32
__asm__ volatile ("xchgl %%ebx, %1; cpuid; xchgl %%ebx, %1"
#else
__asm__ volatile ("xchgq %%rbx, %1; cpuid; xchgq %%rbx, %1"
@ -302,9 +305,13 @@ jit_get_cpu(void)
jit_cpu.aes = ecx.bits.aes;
jit_cpu.avx = ecx.bits.avx;
#if __WORDSIZE == 64
/* query %eax = 0x80000001 function */
#if __X64
# if __X64_32
__asm__ volatile ("xchgl %%ebx, %1; cpuid; xchgl %%ebx, %1"
# else
__asm__ volatile ("xchgq %%rbx, %1; cpuid; xchgq %%rbx, %1"
# endif
: "=a" (eax), "=r" (ebx),
"=c" (ecx.cpuid), "=d" (edx.cpuid)
: "0" (0x80000001));
@ -315,13 +322,13 @@ jit_get_cpu(void)
void
_jit_init(jit_state_t *_jit)
{
#if __WORDSIZE == 32
#if __X32
jit_int32_t regno;
static jit_bool_t first = 1;
#endif
_jitc->reglen = jit_size(_rvs) - 1;
#if __WORDSIZE == 32
#if __X32
if (first) {
if (!jit_cpu.sse2) {
for (regno = _jitc->reglen; regno >= 0; regno--) {
@ -467,7 +474,7 @@ _jit_arg(jit_state_t *_jit)
jit_int32_t offset;
assert(_jitc->function);
#if __WORDSIZE == 64
#if __X64
if (jit_arg_reg_p(_jitc->function->self.argi)) {
offset = _jitc->function->self.argi++;
# if __CYGWIN__
@ -478,7 +485,7 @@ _jit_arg(jit_state_t *_jit)
#endif
{
offset = _jitc->function->self.size;
_jitc->function->self.size += sizeof(jit_word_t);
_jitc->function->self.size += REAL_WORDSIZE;
}
return (jit_new_node_w(jit_code_arg, offset));
}
@ -486,7 +493,7 @@ _jit_arg(jit_state_t *_jit)
jit_bool_t
_jit_arg_reg_p(jit_state_t *_jit, jit_int32_t offset)
{
#if __WORDSIZE == 32
#if __X32
return (0);
#else
# if __CYGWIN__
@ -503,7 +510,7 @@ _jit_arg_f(jit_state_t *_jit)
jit_int32_t offset;
assert(_jitc->function);
#if __WORDSIZE == 64
#if __X64
# if __CYGWIN__
if (jit_arg_reg_p(_jitc->function->self.argi)) {
offset = _jitc->function->self.argi++;
@ -517,11 +524,7 @@ _jit_arg_f(jit_state_t *_jit)
#endif
{
offset = _jitc->function->self.size;
#if __WORDSIZE == 32
_jitc->function->self.size += sizeof(jit_float32_t);
#else
_jitc->function->self.size += sizeof(jit_float64_t);
#endif
_jitc->function->self.size += REAL_WORDSIZE;
}
return (jit_new_node_w(jit_code_arg_f, offset));
}
@ -529,7 +532,7 @@ _jit_arg_f(jit_state_t *_jit)
jit_bool_t
_jit_arg_f_reg_p(jit_state_t *_jit, jit_int32_t offset)
{
#if __WORDSIZE == 32
#if __X32
return (0);
#else
# if __CYGWIN__
@ -546,7 +549,7 @@ _jit_arg_d(jit_state_t *_jit)
jit_int32_t offset;
assert(_jitc->function);
#if __WORDSIZE == 64
#if __X64
# if __CYGWIN__
if (jit_arg_reg_p(_jitc->function->self.argi)) {
offset = _jitc->function->self.argi++;
@ -574,7 +577,7 @@ _jit_arg_d_reg_p(jit_state_t *_jit, jit_int32_t offset)
void
_jit_getarg_c(jit_state_t *_jit, jit_int32_t u, jit_node_t *v)
{
#if __WORDSIZE == 64
#if __X64
if (jit_arg_reg_p(v->u.w))
jit_extr_c(u, JIT_RA0 - v->u.w);
else
@ -585,7 +588,7 @@ _jit_getarg_c(jit_state_t *_jit, jit_int32_t u, jit_node_t *v)
void
_jit_getarg_uc(jit_state_t *_jit, jit_int32_t u, jit_node_t *v)
{
#if __WORDSIZE == 64
#if __X64
if (jit_arg_reg_p(v->u.w))
jit_extr_uc(u, JIT_RA0 - v->u.w);
else
@ -596,7 +599,7 @@ _jit_getarg_uc(jit_state_t *_jit, jit_int32_t u, jit_node_t *v)
void
_jit_getarg_s(jit_state_t *_jit, jit_int32_t u, jit_node_t *v)
{
#if __WORDSIZE == 64
#if __X64
if (jit_arg_reg_p(v->u.w))
jit_extr_s(u, JIT_RA0 - v->u.w);
else
@ -607,7 +610,7 @@ _jit_getarg_s(jit_state_t *_jit, jit_int32_t u, jit_node_t *v)
void
_jit_getarg_us(jit_state_t *_jit, jit_int32_t u, jit_node_t *v)
{
#if __WORDSIZE == 64
#if __X64
if (jit_arg_reg_p(v->u.w))
jit_extr_us(u, JIT_RA0 - v->u.w);
else
@ -618,15 +621,20 @@ _jit_getarg_us(jit_state_t *_jit, jit_int32_t u, jit_node_t *v)
void
_jit_getarg_i(jit_state_t *_jit, jit_int32_t u, jit_node_t *v)
{
#if __WORDSIZE == 64
if (jit_arg_reg_p(v->u.w))
#if __X64
if (jit_arg_reg_p(v->u.w)) {
# if __X64_32
jit_movr(u, JIT_RA0 - v->u.w);
# else
jit_extr_i(u, JIT_RA0 - v->u.w);
# endif
}
else
#endif
jit_ldxi_i(u, _RBP, v->u.w);
}
#if __WORDSIZE == 64
#if __X64 && !__X64_32
void
_jit_getarg_ui(jit_state_t *_jit, jit_int32_t u, jit_node_t *v)
{
@ -649,7 +657,7 @@ _jit_getarg_l(jit_state_t *_jit, jit_int32_t u, jit_node_t *v)
void
_jit_getarg_f(jit_state_t *_jit, jit_int32_t u, jit_node_t *v)
{
#if __WORDSIZE == 64
#if __X64
if (jit_arg_f_reg_p(v->u.w))
jit_movr_f(u, _XMM0 - v->u.w);
else
@ -660,7 +668,7 @@ _jit_getarg_f(jit_state_t *_jit, jit_int32_t u, jit_node_t *v)
void
_jit_getarg_d(jit_state_t *_jit, jit_int32_t u, jit_node_t *v)
{
#if __WORDSIZE == 64
#if __X64
if (jit_arg_f_reg_p(v->u.w))
jit_movr_d(u, _XMM0 - v->u.w);
else
@ -672,7 +680,7 @@ void
_jit_pushargr(jit_state_t *_jit, jit_int32_t u)
{
assert(_jitc->function);
#if __WORDSIZE == 64
#if __X64
if (jit_arg_reg_p(_jitc->function->call.argi)) {
jit_movr(JIT_RA0 - _jitc->function->call.argi, u);
++_jitc->function->call.argi;
@ -684,7 +692,7 @@ _jit_pushargr(jit_state_t *_jit, jit_int32_t u)
#endif
{
jit_stxi(_jitc->function->call.size, _RSP, u);
_jitc->function->call.size += sizeof(jit_word_t);
_jitc->function->call.size += REAL_WORDSIZE;
}
}
@ -694,7 +702,7 @@ _jit_pushargi(jit_state_t *_jit, jit_word_t u)
jit_int32_t regno;
assert(_jitc->function);
#if __WORDSIZE == 64
#if __X64
if (jit_arg_reg_p(_jitc->function->call.argi)) {
jit_movi(JIT_RA0 - _jitc->function->call.argi, u);
++_jitc->function->call.argi;
@ -708,7 +716,7 @@ _jit_pushargi(jit_state_t *_jit, jit_word_t u)
regno = jit_get_reg(jit_class_gpr);
jit_movi(regno, u);
jit_stxi(_jitc->function->call.size, _RSP, regno);
_jitc->function->call.size += sizeof(jit_word_t);
_jitc->function->call.size += REAL_WORDSIZE;
jit_unget_reg(regno);
}
}
@ -717,7 +725,7 @@ void
_jit_pushargr_f(jit_state_t *_jit, jit_int32_t u)
{
assert(_jitc->function);
#if __WORDSIZE == 64
#if __X64
# if __CYGWIN__
if (jit_arg_reg_p(_jitc->function->call.argi)) {
jit_movr_f(_XMM0 - _jitc->function->call.argi, u);
@ -740,7 +748,7 @@ _jit_pushargr_f(jit_state_t *_jit, jit_int32_t u)
#endif
{
jit_stxi_f(_jitc->function->call.size, _RSP, u);
_jitc->function->call.size += sizeof(jit_word_t);
_jitc->function->call.size += REAL_WORDSIZE;
}
}
@ -750,7 +758,7 @@ _jit_pushargi_f(jit_state_t *_jit, jit_float32_t u)
jit_int32_t regno;
assert(_jitc->function);
#if __WORDSIZE == 64
#if __X64
# if __CYGWIN__
if (jit_arg_reg_p(_jitc->function->call.argi)) {
jit_movi_f(_XMM0 - _jitc->function->call.argi, u);
@ -775,7 +783,7 @@ _jit_pushargi_f(jit_state_t *_jit, jit_float32_t u)
regno = jit_get_reg(jit_class_fpr);
jit_movi_f(regno, u);
jit_stxi_f(_jitc->function->call.size, _RSP, regno);
_jitc->function->call.size += sizeof(jit_word_t);
_jitc->function->call.size += REAL_WORDSIZE;
jit_unget_reg(regno);
}
}
@ -784,7 +792,7 @@ void
_jit_pushargr_d(jit_state_t *_jit, jit_int32_t u)
{
assert(_jitc->function);
#if __WORDSIZE == 64
#if __X64
# if __CYGWIN__
if (jit_arg_reg_p(_jitc->function->call.argi)) {
jit_movr_d(_XMM0 - _jitc->function->call.argi, u);
@ -817,7 +825,7 @@ _jit_pushargi_d(jit_state_t *_jit, jit_float64_t u)
jit_int32_t regno;
assert(_jitc->function);
#if __WORDSIZE == 64
#if __X64
# if __CYGWIN__
if (jit_arg_reg_p(_jitc->function->call.argi)) {
jit_movi_d(_XMM0 - _jitc->function->call.argi, u);
@ -850,7 +858,7 @@ _jit_pushargi_d(jit_state_t *_jit, jit_float64_t u)
jit_bool_t
_jit_regarg_p(jit_state_t *_jit, jit_node_t *node, jit_int32_t regno)
{
#if __WORDSIZE == 64
#if __X64
jit_int32_t spec;
spec = jit_class(_rvs[regno].spec);
@ -880,7 +888,7 @@ _jit_finishr(jit_state_t *_jit, jit_int32_t r0)
assert(_jitc->function);
if (_jitc->function->self.alen < _jitc->function->call.size)
_jitc->function->self.alen = _jitc->function->call.size;
#if __WORDSIZE == 64
#if __X64
# if !__CYGWIN__
if (_jitc->function->call.call & jit_call_varargs) {
if (jit_regno(reg) == _RAX) {
@ -907,7 +915,7 @@ _jit_finishr(jit_state_t *_jit, jit_int32_t r0)
jit_node_t *
_jit_finishi(jit_state_t *_jit, jit_pointer_t i0)
{
#if __WORDSIZE == 64
#if __X64
jit_int32_t reg;
#endif
jit_node_t *node;
@ -915,7 +923,7 @@ _jit_finishi(jit_state_t *_jit, jit_pointer_t i0)
assert(_jitc->function);
if (_jitc->function->self.alen < _jitc->function->call.size)
_jitc->function->self.alen = _jitc->function->call.size;
#if __WORDSIZE == 64
#if __X64
/* FIXME preventing %rax allocation is good enough, but for consistency
* it should automatically detect %rax is dead, in case it has run out
* registers, and not save/restore it, what would be wrong if using the
@ -966,7 +974,7 @@ _jit_retval_us(jit_state_t *_jit, jit_int32_t r0)
void
_jit_retval_i(jit_state_t *_jit, jit_int32_t r0)
{
#if __WORDSIZE == 32
#if __X32 || __X64_32
if (r0 != JIT_RET)
jit_movr(r0, JIT_RET);
#else
@ -974,7 +982,7 @@ _jit_retval_i(jit_state_t *_jit, jit_int32_t r0)
#endif
}
#if __WORDSIZE == 64
#if __X64 && !__X64_32
void
_jit_retval_ui(jit_state_t *_jit, jit_int32_t r0)
{
@ -992,7 +1000,7 @@ _jit_retval_l(jit_state_t *_jit, jit_int32_t r0)
void
_jit_retval_f(jit_state_t *_jit, jit_int32_t r0)
{
# if __WORDSIZE == 32
# if __X32
jit_new_node_w(jit_code_x86_retval_f, r0);
# else
if (r0 != JIT_FRET)
@ -1003,7 +1011,7 @@ _jit_retval_f(jit_state_t *_jit, jit_int32_t r0)
void
_jit_retval_d(jit_state_t *_jit, jit_int32_t r0)
{
# if __WORDSIZE == 32
# if __X32
jit_new_node_w(jit_code_x86_retval_d, r0);
# else
if (r0 != JIT_FRET)
@ -1373,13 +1381,13 @@ _emit_code(jit_state_t *_jit)
case_rr(ext, _uc);
case_rr(ext, _s);
case_rr(ext, _us);
#if __WORDSIZE == 64
#if __X64 && !__X64_32
case_rr(ext, _i);
case_rr(ext, _ui);
#endif
case_rf(trunc, _f_i);
case_rf(trunc, _d_i);
#if __WORDSIZE == 64
#if __X64
case_rf(trunc, _f_l);
case_rf(trunc, _d_l);
#endif
@ -1393,7 +1401,7 @@ _emit_code(jit_state_t *_jit)
case_rw(ld, _us);
case_rr(ld, _i);
case_rw(ld, _i);
#if __WORDSIZE == 64
#if __X64 && !__X64_32
case_rr(ld, _ui);
case_rw(ld, _ui);
case_rr(ld, _l);
@ -1409,7 +1417,7 @@ _emit_code(jit_state_t *_jit)
case_rrw(ldx, _us);
case_rrr(ldx, _i);
case_rrw(ldx, _i);
#if __WORDSIZE == 64
#if __X64 && !__X64_32
case_rrr(ldx, _ui);
case_rrw(ldx, _ui);
case_rrr(ldx, _l);
@ -1421,7 +1429,7 @@ _emit_code(jit_state_t *_jit)
case_wr(st, _s);
case_rr(st, _i);
case_wr(st, _i);
#if __WORDSIZE == 64
#if __X64 && !__X64_32
case_rr(st, _l);
case_wr(st, _l);
#endif
@ -1431,7 +1439,7 @@ _emit_code(jit_state_t *_jit)
case_wrr(stx, _s);
case_rrr(stx, _i);
case_wrr(stx, _i);
#if __WORDSIZE == 64
#if __X64 && !__X64_32
case_rrr(stx, _l);
case_wrr(stx, _l);
#endif
@ -1739,7 +1747,7 @@ _emit_code(jit_state_t *_jit)
epilog(node);
_jitc->function = NULL;
break;
#if __WORDSIZE == 32
#if __X32
case jit_code_x86_retval_f:
if (jit_sse_reg_p(node->u.w)) {
fstpr(_ST1_REGNO);