Support forward local branches.

This commit is contained in:
Michael Munday 2016-12-06 11:56:37 -05:00
parent b24d490a42
commit e3ab67aed4
3 changed files with 40 additions and 5 deletions

View File

@ -76,6 +76,23 @@ static void lab(dasm_State *state)
| br r14 | br r14
} }
static void labg(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
| jgl <1
| jgnl >1
| stg r0, 0(r0)
|1:
| br r14
}
static void add_imm16(dasm_State *state) static void add_imm16(dasm_State *state)
{ {
dasm_State **Dst = &state; dasm_State **Dst = &state;
@ -108,6 +125,7 @@ test_table test[] = {
{ 5, 7, rx, 12298, "rx"}, { 5, 7, rx, 12298, "rx"},
{ 5, 7, rxy, 10, "rxy"}, { 5, 7, rxy, 10, "rxy"},
{ 2, 4, lab, 32, "lab"}, { 2, 4, lab, 32, "lab"},
{ 2, 4, labg, 32, "labg"},
{ 2, 0, add_imm16, 17, "imm16"}, { 2, 0, add_imm16, 17, "imm16"},
{ 2, 0, add_imm32, 16, "imm32"} { 2, 0, add_imm32, 16, "imm32"}
}; };

View File

@ -210,7 +210,7 @@ void dasm_put(Dst_DECL, int start, ...)
goto stop; goto stop;
case DASM_ESC: case DASM_ESC:
p++; p++;
ofs += 4; ofs += 2;
break; break;
case DASM_REL_EXT: case DASM_REL_EXT:
break; break;
@ -244,6 +244,10 @@ void dasm_put(Dst_DECL, int start, ...)
b[pos] = n; /* Else link to rel chain, anchored at label. */ b[pos] = n; /* Else link to rel chain, anchored at label. */
*pl = pos; *pl = pos;
} }
ofs += 2;
if (p[-3] >> 12 == 0xc) { /* RIL instruction needs 32-bit immediate. */
ofs += 2;
}
pos++; pos++;
break; break;
case DASM_LABEL_LG: case DASM_LABEL_LG:
@ -262,7 +266,6 @@ void dasm_put(Dst_DECL, int start, ...)
} }
*pl = -pos; /* Label exists now. */ *pl = -pos; /* Label exists now. */
b[pos++] = ofs; /* Store pass1 offset estimate. */ b[pos++] = ofs; /* Store pass1 offset estimate. */
ofs += 2;
break; break;
case DASM_IMM16: case DASM_IMM16:
CK(((short)n) == n, RANGE_I); /* TODO: unsigned immediates? */ CK(((short)n) == n, RANGE_I); /* TODO: unsigned immediates? */
@ -424,7 +427,14 @@ int dasm_encode(Dst_DECL, void *buffer)
CK(n >= 0, UNDEF_PC); CK(n >= 0, UNDEF_PC);
n = *DASM_POS2PTR(D, n) - (int)((char *)cp - base); n = *DASM_POS2PTR(D, n) - (int)((char *)cp - base);
patchrel: patchrel:
*cp++ = n/2; /* TODO: only 16-bit relative jump currently works. */ /* Offsets are halfword aligned (so need to be halved). */
n += 2; /* Offset is relative to start of instruction. */
if (cp[-1] >> 12 == 0xc) {
*cp++ = n >> 17;
} else {
CK(-(1 << 16) <= n && n < (1 << 16) && n & 1 == 0, RANGE_LG);
}
*cp++ = n >> 1;
p++; /* skip argument */ p++; /* skip argument */
break; break;
case DASM_LABEL_LG: case DASM_LABEL_LG:

View File

@ -75,6 +75,13 @@ local function dumpactions(out)
out:write("\n") out:write("\n")
end end
local function havearg(a)
return a == "ESC" or
a == "SECTION" or
a == "REL_LG" or
a == "LABEL_LG"
end
-- Write action list buffer as a huge static C array. -- Write action list buffer as a huge static C array.
local function writeactions(out, name) local function writeactions(out, name)
local nn = #actlist local nn = #actlist
@ -87,7 +94,7 @@ local function writeactions(out, name)
local name = action_names[actlist[i]+1] local name = action_names[actlist[i]+1]
if not esc and name then if not esc and name then
assert(out:write(" /* ", name, " */")) assert(out:write(" /* ", name, " */"))
esc = name == "ESC" or name == "SECTION" esc = havearg(name)
else else
esc = false esc = false
end end