From 73ad6dc77dd2d6a5dff43cf5c5e0e58c8eba6eed Mon Sep 17 00:00:00 2001 From: Michael Munday Date: Mon, 5 Dec 2016 17:21:49 -0500 Subject: [PATCH] Add support for jumps to local labels. Currently limited to 16-bits ONLY. Allows code like: |1: | ... | j <1 --- dynasm/Examples/test_z_inst.c | 23 ++++++++++++++++++++--- dynasm/dasm_s390x.h | 15 ++++++++------- dynasm/dasm_s390x.lua | 10 ++++++++++ 3 files changed, 38 insertions(+), 10 deletions(-) diff --git a/dynasm/Examples/test_z_inst.c b/dynasm/Examples/test_z_inst.c index 7259638b..ad8e6a00 100644 --- a/dynasm/Examples/test_z_inst.c +++ b/dynasm/Examples/test_z_inst.c @@ -8,6 +8,7 @@ // DynASM directives. |.arch s390x |.actionlist actions +|.globals lab_ static void add(dasm_State *state) { @@ -61,6 +62,20 @@ static void rxy(dasm_State *state) | br r14 } +static void lab(dasm_State *state) +{ + dasm_State **Dst = &state; + + // r1 = 0; do { r2 += r2; r1 += 1; } while(r1 < r3); + | la r1, 0(r0) + |1: + | agr r2, r2 + | la r1, 1(r1) + | cgr r1, r3 + | jl <1 + | br r14 +} + typedef struct { int64_t arg1; int64_t arg2; @@ -74,7 +89,8 @@ test_table test[] = { {10, 5, sub, 5, "sub"}, { 2, 3, mul, 6, "mul"}, { 5, 7, rx, 12298, "rx"}, - { 5, 7, rxy, 10, "rxy"} + { 5, 7, rxy, 10, "rxy"}, + { 2, 4, lab, 32, "lab"} }; static void *jitcode(dasm_State **state, size_t *size) @@ -93,9 +109,10 @@ static void *jitcode(dasm_State **state, size_t *size) int main(int argc, char *argv[]) { dasm_State *state; - - for(int i=0; i < sizeof(test)/sizeof(test[0]); i++) { + for(int i = 0; i < sizeof(test)/sizeof(test[0]); i++) { dasm_init(&state, 1); + void* labels[lab__MAX]; + dasm_setupglobal(&state, labels, lab__MAX); dasm_setup(&state, actions); test[i].fn(state); size_t size; diff --git a/dynasm/dasm_s390x.h b/dynasm/dasm_s390x.h index e2cd5197..8fc4cd63 100644 --- a/dynasm/dasm_s390x.h +++ b/dynasm/dasm_s390x.h @@ -219,7 +219,7 @@ void dasm_put(Dst_DECL, int start, ...) b[pos++] = ofs; break; case DASM_REL_LG: - n = (ins & 2047) - 10; + n = *p++ - 10; pl = D->lglabels + n; /* Bkwd rel or global. */ if (n >= 0) { @@ -247,7 +247,7 @@ void dasm_put(Dst_DECL, int start, ...) pos++; break; case DASM_LABEL_LG: - pl = D->lglabels + (ins & 2047) - 10; + pl = D->lglabels + *p++ - 10; CKPL(lg, LG); goto putlabel; case DASM_LABEL_PC: @@ -262,6 +262,7 @@ void dasm_put(Dst_DECL, int start, ...) } *pl = -pos; /* Label exists now. */ b[pos++] = ofs; /* Store pass1 offset estimate. */ + ofs += 2; break; case DASM_IMM16: CK(((short)n) == n, RANGE_I); /* TODO: unsigned immediates? */ @@ -348,10 +349,12 @@ int dasm_link(Dst_DECL, size_t * szp) break; case DASM_REL_LG: case DASM_REL_PC: + p++; pos++; break; case DASM_LABEL_LG: case DASM_LABEL_PC: + p++; b[pos++] += ofs; break; case DASM_IMM16: @@ -421,13 +424,11 @@ int dasm_encode(Dst_DECL, void *buffer) CK(n >= 0, UNDEF_PC); n = *DASM_POS2PTR(D, n) - (int)((char *)cp - base); patchrel: - CK((n & 3) == 0 && - (((n + 4) + ((ins & 2048) ? 0x00008000 : 0x02000000)) >> - ((ins & 2048) ? 16 : 26)) == 0, RANGE_REL); - cp[-1] |= ((n + 4) & ((ins & 2048) ? 0x0000fffc : 0x03fffffc)); + *cp++ = n/2; /* TODO: only 16-bit relative jump currently works. */ + p++; /* skip argument */ break; case DASM_LABEL_LG: - ins &= 2047; + ins = *p++; if (ins >= 20) D->globals[ins - 10] = (void *)(base + n); break; diff --git a/dynasm/dasm_s390x.lua b/dynasm/dasm_s390x.lua index 5abfe3bf..0625d5fc 100644 --- a/dynasm/dasm_s390x.lua +++ b/dynasm/dasm_s390x.lua @@ -1057,6 +1057,14 @@ local function parse_template(params, template, nparams, pos) op2 = op2 + band(shr(d, 4), 0xff00) wputhw(op0); wputhw(op1); wputhw(op2) if a then a() end -- a() emits action. + elseif p == "w" then + local mode, n, s = parse_label(params[1]) + wputhw(op1) + waction("REL_"..mode, n, s) + elseif p == "x" then + local mode, n, s = parse_label(params[1]) + wputhw(op0) + waction("REL_"..mode, n, s) elseif p == "y" then local d, x, b, a = parse_mem_bx(params[1]) op1 = op1 + x @@ -1066,6 +1074,8 @@ local function parse_template(params, template, nparams, pos) elseif p == "z" then op2 = op2 + parse_gpr(params[1]) wputhw(op2) + else + werror("unrecognized encoding") end end