Support floating point register arguments.

It would be nice to verify that floating-point/general-purpose
registers are indeed expected by the instruction, but for now treat
them both the same so we can use floating-point instructions.
This commit is contained in:
Michael Munday 2016-12-06 13:15:29 -05:00
parent 53b627b21c
commit 3ae1c4fd6b
2 changed files with 76 additions and 24 deletions

View File

@ -101,7 +101,6 @@ static void add_imm16(dasm_State *state)
| br r14 | br r14
} }
static void add_imm32(dasm_State *state) static void add_imm32(dasm_State *state)
{ {
dasm_State **Dst = &state; dasm_State **Dst = &state;
@ -110,6 +109,67 @@ static void add_imm32(dasm_State *state)
| br r14 | br r14
} }
static void save(dasm_State *state)
{
dasm_State **Dst = &state;
|.define CFRAME_SPACE, 224 // Delta for sp, 8 byte aligned.
|
|// Register save area.
|.define SAVE_GPRS, 264(sp) // Save area for r6-r15 (10*8 bytes).
|
|// Argument save area, each slot is 8-bytes (32-bit types are sign/zero extended).
|.define RESERVED, 232(sp) // Reserved for compiler use.
|.define BACKCHAIN, 224(sp)
|
|// Current stack frame.
|.define SAVE_FPR15, 216(sp)
|.define SAVE_FPR14, 208(sp)
|.define SAVE_FPR13, 200(sp)
|.define SAVE_FPR12, 192(sp)
|.define SAVE_FPR11, 184(sp)
|.define SAVE_FPR10, 176(sp)
|.define SAVE_FPR9, 168(sp)
|.define SAVE_FPR8, 160(sp)
|
|// Callee save area.
|.define CALLEESAVE, 000(sp)
|
|.macro saveregs
| lay sp, -CFRAME_SPACE(sp) // Allocate stack frame.
| stmg r6, r15, SAVE_GPRS // Technically we restore r15 regardless.
| std f8, SAVE_FPR8 // f8-f15 are callee-saved.
| std f9, SAVE_FPR9
| std f10, SAVE_FPR10
| std f11, SAVE_FPR11
| std f12, SAVE_FPR12
| std f13, SAVE_FPR13
| std f14, SAVE_FPR14
| std f15, SAVE_FPR15
|.endmacro
|
|.macro restoreregs
| ld f8, SAVE_FPR8 // f8-f15 are callee-saved.
| ld f9, SAVE_FPR9
| ld f10, SAVE_FPR10
| ld f11, SAVE_FPR11
| ld f12, SAVE_FPR12
| ld f13, SAVE_FPR13
| ld f14, SAVE_FPR14
| ld f15, SAVE_FPR15
| lmg r6, r15, SAVE_GPRS // Restores the stack pointer.
|.endmacro
|
| saveregs
| lgfi r7, 10 // 16
| lgfi r8, 20 // 32
| agr r2, r3
| agr r7, r8
| msgr r2, r7
| restoreregs
| br r14
}
typedef struct { typedef struct {
int64_t arg1; int64_t arg1;
int64_t arg2; int64_t arg2;
@ -127,7 +187,8 @@ test_table test[] = {
{ 2, 4, lab, 32, "lab"}, { 2, 4, lab, 32, "lab"},
{ 2, 4, labg, 32, "labg"}, { 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"},
{ 7, 3, save, 480, "save"}
}; };
static void *jitcode(dasm_State **state, size_t *size) static void *jitcode(dasm_State **state, size_t *size)

View File

@ -246,8 +246,8 @@ local map_cond = {
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
local function parse_gpr(expr) local function parse_reg(expr)
local r = match(expr, "^r(1?[0-9])$") local r = match(expr, "^[r|f](1?[0-9])$")
if r then if r then
r = tonumber(r) r = tonumber(r)
if r <= 15 then return r, tp end if r <= 15 then return r, tp end
@ -255,15 +255,6 @@ local function parse_gpr(expr)
werror("bad register name `"..expr.."'") werror("bad register name `"..expr.."'")
end end
local function parse_fpr(expr)
local r = match(expr, "^f(1?[0-9])$")
if r then
r = tonumber(r)
if r <= 15 then return r end
end
werror("bad register name `"..expr.."'")
end
local parse_ctx = {} local parse_ctx = {}
local loadenv = setfenv and function(s) local loadenv = setfenv and function(s)
@ -308,11 +299,11 @@ local function split_memop(arg)
local reg = "r1?[0-9]" local reg = "r1?[0-9]"
local d, x, b = match(arg, "^(.*)%(("..reg.."), ("..reg..")%)$") local d, x, b = match(arg, "^(.*)%(("..reg.."), ("..reg..")%)$")
if d then if d then
return d, parse_gpr(x), parse_gpr(b) return d, parse_reg(x), parse_reg(b)
end end
local d, b = match(arg, "^(.*)%(("..reg..")%)$") local d, b = match(arg, "^(.*)%(("..reg..")%)$")
if d then if d then
return d, 0, parse_gpr(b) return d, 0, parse_reg(b)
end end
-- TODO: handle values without registers? -- TODO: handle values without registers?
-- TODO: handle registers without a displacement? -- TODO: handle registers without a displacement?
@ -1047,18 +1038,18 @@ local function parse_template(params, template, nparams, pos)
for p in gmatch(sub(template, 13), ".") do for p in gmatch(sub(template, 13), ".") do
local pr1,pr2,pr3 local pr1,pr2,pr3
if p == "g" then if p == "g" then
op2 = op2 + shl(parse_gpr(params[1]),4) + parse_gpr(params[2]) op2 = op2 + shl(parse_reg(params[1]),4) + parse_reg(params[2])
wputhw(op2) wputhw(op2)
elseif p == "h" then elseif p == "h" then
op2 = op2 + shl(parse_gpr(params[1]),4) + parse_gpr(params[2]) op2 = op2 + shl(parse_reg(params[1]),4) + parse_reg(params[2])
wputhw(op1); wputhw(op2) wputhw(op1); wputhw(op2)
elseif p == "i" then elseif p == "i" then
op1 = op1 + shl(parse_gpr(params[1]),4) op1 = op1 + shl(parse_reg(params[1]),4)
wputhw(op1); wputhw(op1);
parse_imm16(params[2]) parse_imm16(params[2])
elseif p == "j" then elseif p == "j" then
local d, x, b, a = parse_mem_bx(params[2]) local d, x, b, a = parse_mem_bx(params[2])
op1 = op1 + shl(parse_gpr(params[1]), 4) + x op1 = op1 + shl(parse_reg(params[1]), 4) + x
op2 = op2 + shl(b, 12) + d op2 = op2 + shl(b, 12) + d
wputhw(op1); wputhw(op2); wputhw(op1); wputhw(op2);
if a then a() end if a then a() end
@ -1066,7 +1057,7 @@ local function parse_template(params, template, nparams, pos)
elseif p == "l" then elseif p == "l" then
local d, x, b, a = parse_mem_bxy(params[2]) local d, x, b, a = parse_mem_bxy(params[2])
op0 = op0 + shl(parse_gpr(params[1]), 4) + x op0 = op0 + shl(parse_reg(params[1]), 4) + x
op1 = op1 + shl(b, 12) + band(d, 0xfff) op1 = op1 + shl(b, 12) + band(d, 0xfff)
op2 = op2 + band(shr(d, 4), 0xff00) op2 = op2 + band(shr(d, 4), 0xff00)
wputhw(op0); wputhw(op1); wputhw(op2) wputhw(op0); wputhw(op1); wputhw(op2)
@ -1074,18 +1065,18 @@ local function parse_template(params, template, nparams, pos)
elseif p == "m" then elseif p == "m" then
elseif p == "n" then elseif p == "n" then
op0 = op0 + shl(parse_gpr(params[1]), 4) op0 = op0 + shl(parse_reg(params[1]), 4)
wputhw(op0); wputhw(op0);
parse_imm(params[2]) parse_imm(params[2])
elseif p == "q" then elseif p == "q" then
local d, b, a = parse_mem_b(params[3]) local d, b, a = parse_mem_b(params[3])
op1 = op1 + shl(parse_gpr(params[1]), 4) + parse_gpr(params[2]) op1 = op1 + shl(parse_reg(params[1]), 4) + parse_reg(params[2])
op2 = op2 + shl(b, 12) + d op2 = op2 + shl(b, 12) + d
wputhw(op1); wputhw(op2) wputhw(op1); wputhw(op2)
if a then a() end -- a() emits action. if a then a() end -- a() emits action.
elseif p == "s" then elseif p == "s" then
local d, b, a = parse_mem_by(params[3]) local d, b, a = parse_mem_by(params[3])
op0 = op0 + shl(parse_gpr(params[1]), 4) + parse_gpr(params[2]) op0 = op0 + shl(parse_reg(params[1]), 4) + parse_reg(params[2])
op1 = op1 + shl(b, 12) + band(d, 0xfff) op1 = op1 + shl(b, 12) + band(d, 0xfff)
op2 = op2 + band(shr(d, 4), 0xff00) op2 = op2 + band(shr(d, 4), 0xff00)
wputhw(op0); wputhw(op1); wputhw(op2) wputhw(op0); wputhw(op1); wputhw(op2)
@ -1105,7 +1096,7 @@ local function parse_template(params, template, nparams, pos)
wputhw(op1); wputhw(op2); wputhw(op1); wputhw(op2);
if a then a() end -- a() emits action. if a then a() end -- a() emits action.
elseif p == "z" then elseif p == "z" then
op2 = op2 + parse_gpr(params[1]) op2 = op2 + parse_reg(params[1])
wputhw(op2) wputhw(op2)
else else
werror("unrecognized encoding") werror("unrecognized encoding")