Add support for jumps to local labels.

Currently limited to 16-bits ONLY.

Allows code like:

|1:
| ...
| j <1
This commit is contained in:
Michael Munday 2016-12-05 17:21:49 -05:00
parent 410bdb8182
commit 73ad6dc77d
3 changed files with 38 additions and 10 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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