guile-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Guile-commits] 377/437: aarch64: Add initial jit_va_ calls to aarch64


From: Andy Wingo
Subject: [Guile-commits] 377/437: aarch64: Add initial jit_va_ calls to aarch64
Date: Mon, 2 Jul 2018 05:14:59 -0400 (EDT)

wingo pushed a commit to branch lightning
in repository guile.

commit 0986ae8a862028e0acc95795de13254fe1559638
Author: pcpa <address@hidden>
Date:   Thu Apr 30 17:40:14 2015 -0300

    aarch64: Add initial jit_va_ calls to aarch64
    
        * lib/jit_aarch64-cpu.c, lib/jit_aarch64-fpu.c,
        lib/jit_aarch64.c: Add base support to jit vararg
        functions to the aarch64 backend.
---
 ChangeLog             |   6 +++
 lib/jit_aarch64-cpu.c | 112 ++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/jit_aarch64-fpu.c |  55 +++++++++++++++++++++++++
 lib/jit_aarch64.c     |  65 +++++++++++++++++++++++++++++
 4 files changed, 238 insertions(+)

diff --git a/ChangeLog b/ChangeLog
index 0354685..7ace2c5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2015-05-30 Paulo Andrade <address@hidden>
+
+       * lib/jit_aarch64-cpu.c, lib/jit_aarch64-fpu.c,
+       lib/jit_aarch64.c: Add base support to jit vararg
+       functions to the aarch64 backend.
+
 2015-05-27 Paulo Andrade <address@hidden>
 
        * include/lightning.h, include/lightning/jit_private.h,
diff --git a/lib/jit_aarch64-cpu.c b/lib/jit_aarch64-cpu.c
index 2363d28..4b15629 100644
--- a/lib/jit_aarch64-cpu.c
+++ b/lib/jit_aarch64-cpu.c
@@ -212,6 +212,8 @@ typedef union {
 } instr_t;
 #  define stack_framesize              160
 #  define ii(i)                                *_jit->pc.ui++ = i
+#  define ldr(r0,r1)                   ldr_l(r0,r1)
+#  define ldxr(r0,r1,r2)               ldxr_l(r0,r1,r2)
 #  define ldxi(r0,r1,i0)               ldxi_l(r0,r1,i0)
 #  define stxi(i0,r0,r1)               stxi_l(i0,r0,r1)
 #  define FP_REGNO                     0x1d
@@ -782,6 +784,10 @@ static jit_word_t _calli_p(jit_state_t*,jit_word_t);
 static void _prolog(jit_state_t*,jit_node_t*);
 #  define epilog(i0)                   _epilog(_jit,i0)
 static void _epilog(jit_state_t*,jit_node_t*);
+#  define vastart(r0)                  _vastart(_jit, r0)
+static void _vastart(jit_state_t*, jit_int32_t);
+#  define vaarg(r0, r1)                        _vaarg(_jit, r0, r1)
+static void _vaarg(jit_state_t*, jit_int32_t, jit_int32_t);
 #  define patch_at(jump,label)         _patch_at(_jit,jump,label)
 static void _patch_at(jit_state_t*,jit_word_t,jit_word_t);
 #endif
@@ -2241,6 +2247,24 @@ _prolog(jit_state_t *_jit, jit_node_t *node)
        stxi_i(_jitc->function->aoffoff, FP_REGNO, rn(reg));
        jit_unget_reg(reg);
     }
+
+    if (_jitc->function->self.call & jit_call_varargs) {
+       /* Save gp registers in the save area, if any is a vararg */
+       for (reg = 8 - _jitc->function->vagp / -8;
+            jit_arg_reg_p(reg); ++reg)
+           stxi(_jitc->function->vaoff + offsetof(jit_va_list_t, x0) +
+                reg * 8, FP_REGNO, rn(JIT_RA0 - reg));
+
+       for (reg = 8 - _jitc->function->vafp / -16;
+            jit_arg_f_reg_p(reg); ++reg)
+           /* Save fp registers in the save area, if any is a vararg */
+           /* Note that the full 16 byte register is not saved, because
+            * lightning only handles float and double, and, while
+            * attempting to provide a va_list compatible pointer as
+            * jit_va_start return, does not guarantee it (on all ports). */
+           stxi_d(_jitc->function->vaoff + offsetof(jit_va_list_t, q0) +
+                  reg * 16 + offsetof(jit_qreg_t, l), FP_REGNO, rn(_V0 - reg));
+    }
 }
 
 static void
@@ -2286,6 +2310,94 @@ _epilog(jit_state_t *_jit, jit_node_t *node)
 }
 
 static void
+_vastart(jit_state_t *_jit, jit_int32_t r0)
+{
+    jit_int32_t                reg;
+
+    assert(_jitc->function->self.call & jit_call_varargs);
+
+    /* Return jit_va_list_t in the register argument */
+    addi(r0, FP_REGNO, _jitc->function->vaoff);
+
+    reg = jit_get_reg(jit_class_gpr);
+
+    /* Initialize stack pointer to the first stack argument. */
+    addi(rn(reg), FP_REGNO, _jitc->function->self.size);
+    stxi(offsetof(jit_va_list_t, stack), r0, rn(reg));
+
+    /* Initialize gp top pointer to the first stack argument. */
+    addi(rn(reg), r0, va_gp_top_offset);
+    stxi(offsetof(jit_va_list_t, gptop), r0, rn(reg));
+
+    /* Initialize fp top pointer to the first stack argument. */
+    addi(rn(reg), r0, va_fp_top_offset);
+    stxi(offsetof(jit_va_list_t, fptop), r0, rn(reg));
+
+    /* Initialize gp offset in the save area. */
+    movi(rn(reg), _jitc->function->vagp);
+    stxi_i(offsetof(jit_va_list_t, gpoff), r0, rn(reg));
+
+    /* Initialize fp offset in the save area. */
+    movi(rn(reg), _jitc->function->vafp);
+    stxi_i(offsetof(jit_va_list_t, fpoff), r0, rn(reg));
+
+    jit_unget_reg(reg);
+}
+
+static void
+_vaarg(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
+{
+    jit_word_t         ge_code;
+    jit_word_t         lt_code;
+    jit_int32_t                rg0, rg1;
+
+    assert(_jitc->function->self.call & jit_call_varargs);
+
+    rg0 = jit_get_reg(jit_class_gpr);
+    rg1 = jit_get_reg(jit_class_gpr);
+
+    /* Load the gp offset in save area in the first temporary. */
+    ldxi_i(rn(rg0), r1, offsetof(jit_va_list_t, gpoff));
+
+    /* Jump over if there are no remaining arguments in the save area. */
+    ge_code = bgei(_jit->pc.w, rn(rg0), 0);
+
+    /* Load the gp save pointer in the second temporary. */
+    ldxi(rn(rg1), r1, offsetof(jit_va_list_t, gptop));
+
+    /* Load the vararg argument in the first argument. */
+    ldxr(r0, rn(rg1), rn(rg0));
+
+    /* Update the gp offset. */
+    addi(rn(rg0), rn(rg0), 8);
+    stxi_i(offsetof(jit_va_list_t, gpoff), r1, rn(rg0));
+
+    /* Will only need one temporary register below. */
+    jit_unget_reg(rg1);
+
+    /* Jump over overflow code. */
+    lt_code = jmpi_p(_jit->pc.w);
+
+    /* Where to land if argument is in overflow area. */
+    patch_at(ge_code, _jit->pc.w);
+
+    /* Load stack pointer. */
+    ldxi(rn(rg0), r1, offsetof(jit_va_list_t, stack));
+
+    /* Load argument. */
+    ldr(r0, rn(rg0));
+
+    /* Update stack pointer. */
+    addi(rn(rg0), rn(rg0), 8);
+    stxi(offsetof(jit_va_list_t, stack), r1, rn(rg0));
+
+    /* Where to land if argument is in gp save area. */
+    patch_at(lt_code, _jit->pc.w);
+
+    jit_unget_reg(rg0);
+}
+
+static void
 _patch_at(jit_state_t *_jit, jit_word_t instr, jit_word_t label)
 {
     instr_t             i;
diff --git a/lib/jit_aarch64-fpu.c b/lib/jit_aarch64-fpu.c
index 386f068..1f13a14 100644
--- a/lib/jit_aarch64-fpu.c
+++ b/lib/jit_aarch64-fpu.c
@@ -310,6 +310,8 @@ static jit_word_t 
_bltgti_d(jit_state_t*,jit_word_t,jit_int32_t,jit_float64_t);
 #  define bordi_d(i0,r0,i1)            dbcci(BCC_VC,i0,r0,i1)
 #  define bunordr_d(i0,r0,r1)          dbccr(BCC_VS,i0,r0,r1)
 #  define bunordi_d(i0,r0,i1)          dbcci(BCC_VS,i0,r0,i1)
+#  define vaarg_d(r0, r1)              _vaarg_d(_jit, r0, r1)
+static void _vaarg_d(jit_state_t*, jit_int32_t, jit_int32_t);
 #endif
 
 #if CODE
@@ -856,4 +858,57 @@ _bltgtr_d(jit_state_t *_jit, jit_word_t i0, jit_int32_t 
r0, jit_int32_t r1)
     return (w);
 }
 dbopi(ltgt)
+
+static void
+_vaarg_d(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
+{
+    jit_word_t         ge_code;
+    jit_word_t         lt_code;
+    jit_int32_t                rg0, rg1;
+
+    assert(_jitc->function->self.call & jit_call_varargs);
+
+    rg0 = jit_get_reg(jit_class_gpr);
+    rg1 = jit_get_reg(jit_class_gpr);
+
+    /* Load the fp offset in save area in the first temporary. */
+    ldxi_i(rn(rg0), r1, offsetof(jit_va_list_t, fpoff));
+
+    /* Jump over if there are no remaining arguments in the save area. */
+    ge_code = bgei(_jit->pc.w, rn(rg0), 0);
+
+    /* Load the gp save pointer in the second temporary. */
+    ldxi(rn(rg1), r1, offsetof(jit_va_list_t, fptop));
+
+    /* Load the vararg argument in the first argument. */
+    ldxr_d(r0, rn(rg1), rn(rg0));
+
+    /* Update the fp offset. */
+    addi(rn(rg0), rn(rg0), 16);
+    stxi_i(offsetof(jit_va_list_t, fpoff), r1, rn(rg0));
+
+    /* Will only need one temporary register below. */
+    jit_unget_reg(rg1);
+
+    /* Jump over overflow code. */
+    lt_code = jmpi_p(_jit->pc.w);
+
+    /* Where to land if argument is in overflow area. */
+    patch_at(ge_code, _jit->pc.w);
+
+    /* Load stack pointer. */
+    ldxi(rn(rg0), r1, offsetof(jit_va_list_t, stack));
+
+    /* Load argument. */
+    ldr(r0, rn(rg0));
+
+    /* Update stack pointer. */
+    addi(rn(rg0), rn(rg0), 8);
+    stxi(offsetof(jit_va_list_t, stack), r1, rn(rg0));
+
+    /* Where to land if argument is in gp save area. */
+    patch_at(lt_code, _jit->pc.w);
+
+    jit_unget_reg(rg0);
+}
 #endif
diff --git a/lib/jit_aarch64.c b/lib/jit_aarch64.c
index 77256c9..89c3eda 100644
--- a/lib/jit_aarch64.c
+++ b/lib/jit_aarch64.c
@@ -22,6 +22,41 @@
 #define jit_arg_reg_p(i)               ((i) >= 0 && (i) < 8)
 #define jit_arg_f_reg_p(i)             ((i) >= 0 && (i) < 8)
 
+typedef struct jit_qreg {
+    jit_float64_t      l;
+    jit_float64_t      h;
+} jit_qreg_t;
+
+#define va_gp_min_offset               -64
+#define va_gp_top_offset               offsetof(jit_va_list_t, q0)
+#define va_fp_min_offset               -128
+#define va_fp_top_offset               sizeof(jit_va_list_t)
+typedef struct jit_va_list {
+    jit_pointer_t      stack;
+    jit_pointer_t      gptop;
+    jit_pointer_t      fptop;
+    jit_int32_t                gpoff;
+    jit_int32_t                fpoff;
+
+    jit_int64_t                x0;
+    jit_int64_t                x1;
+    jit_int64_t                x2;
+    jit_int64_t                x3;
+    jit_int64_t                x4;
+    jit_int64_t                x5;
+    jit_int64_t                x6;
+    jit_int64_t                x7;
+
+    jit_qreg_t         q0;
+    jit_qreg_t         q1;
+    jit_qreg_t         q2;
+    jit_qreg_t         q3;
+    jit_qreg_t         q4;
+    jit_qreg_t         q5;
+    jit_qreg_t         q6;
+    jit_qreg_t         q7;
+} jit_va_list_t;
+
 /*
  * Prototypes
  */
@@ -295,6 +330,23 @@ _jit_ellipsis(jit_state_t *_jit)
     else {
        assert(!(_jitc->function->self.call & jit_call_varargs));
        _jitc->function->self.call |= jit_call_varargs;
+
+       /* Allocate va_list like object in the stack,
+        * with enough space to save all argument
+        * registers, and use fixed offsets for them. */
+       _jitc->function->vaoff = jit_allocai(sizeof(jit_va_list_t));
+
+       /* Initialize gp offset in save area. */
+       if (jit_arg_reg_p(_jitc->function->self.argi))
+           _jitc->function->vagp = (8 - _jitc->function->self.argi) * -8;
+       else
+           _jitc->function->vagp = va_gp_min_offset;
+
+       /* Initialize fp offset in save area. */
+       if (jit_arg_f_reg_p(_jitc->function->self.argf))
+           _jitc->function->vafp = (8 - _jitc->function->self.argf) * -16;
+       else
+           _jitc->function->vafp = va_fp_min_offset;
     }
 }
 
@@ -303,6 +355,7 @@ _jit_arg(jit_state_t *_jit)
 {
     jit_int32_t                offset;
     assert(_jitc->function);
+    assert(!(_jitc->function->self.call & jit_call_varargs));
     if (jit_arg_reg_p(_jitc->function->self.argi))
        offset = _jitc->function->self.argi++;
     else {
@@ -317,6 +370,7 @@ _jit_arg_f(jit_state_t *_jit)
 {
     jit_int32_t                offset;
     assert(_jitc->function);
+    assert(!(_jitc->function->self.call & jit_call_varargs));
     if (jit_arg_f_reg_p(_jitc->function->self.argf))
        offset = _jitc->function->self.argf++;
     else {
@@ -331,6 +385,7 @@ _jit_arg_d(jit_state_t *_jit)
 {
     jit_int32_t                offset;
     assert(_jitc->function);
+    assert(!(_jitc->function->self.call & jit_call_varargs));
     if (jit_arg_f_reg_p(_jitc->function->self.argf))
        offset = _jitc->function->self.argf++;
     else {
@@ -1268,9 +1323,19 @@ _emit_code(jit_state_t *_jit)
                epilog(node);
                _jitc->function = NULL;
                break;
+           case jit_code_va_start:
+               vastart(rn(node->u.w));
+               break;
+           case jit_code_va_arg:
+               vaarg(rn(node->u.w), rn(node->v.w));
+               break;
+           case jit_code_va_arg_d:
+               vaarg_d(rn(node->u.w), rn(node->v.w));
+               break;
            case jit_code_live:
            case jit_code_arg:
            case jit_code_arg_f:                case jit_code_arg_d:
+           case jit_code_va_end:
                break;
            default:
                abort();



reply via email to

[Prev in Thread] Current Thread [Next in Thread]