From 3ae1c4fd6b43ea89f9cac2b8634756bfb3864251 Mon Sep 17 00:00:00 2001 From: Michael Munday Date: Tue, 6 Dec 2016 13:15:29 -0500 Subject: [PATCH] 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. --- dynasm/Examples/test_z_inst.c | 65 +++++++++++++++++++++++++++++++++-- dynasm/dasm_s390x.lua | 35 +++++++------------ 2 files changed, 76 insertions(+), 24 deletions(-) diff --git a/dynasm/Examples/test_z_inst.c b/dynasm/Examples/test_z_inst.c index 3938a741..b54c383f 100644 --- a/dynasm/Examples/test_z_inst.c +++ b/dynasm/Examples/test_z_inst.c @@ -101,7 +101,6 @@ static void add_imm16(dasm_State *state) | br r14 } - static void add_imm32(dasm_State *state) { dasm_State **Dst = &state; @@ -110,6 +109,67 @@ static void add_imm32(dasm_State *state) | 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 { int64_t arg1; int64_t arg2; @@ -127,7 +187,8 @@ test_table test[] = { { 2, 4, lab, 32, "lab"}, { 2, 4, labg, 32, "labg"}, { 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) diff --git a/dynasm/dasm_s390x.lua b/dynasm/dasm_s390x.lua index 847a02e7..c799bb6c 100644 --- a/dynasm/dasm_s390x.lua +++ b/dynasm/dasm_s390x.lua @@ -246,8 +246,8 @@ local map_cond = { ------------------------------------------------------------------------------ -local function parse_gpr(expr) - local r = match(expr, "^r(1?[0-9])$") +local function parse_reg(expr) + local r = match(expr, "^[r|f](1?[0-9])$") if r then r = tonumber(r) if r <= 15 then return r, tp end @@ -255,15 +255,6 @@ local function parse_gpr(expr) werror("bad register name `"..expr.."'") 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 loadenv = setfenv and function(s) @@ -308,11 +299,11 @@ local function split_memop(arg) local reg = "r1?[0-9]" local d, x, b = match(arg, "^(.*)%(("..reg.."), ("..reg..")%)$") if d then - return d, parse_gpr(x), parse_gpr(b) + return d, parse_reg(x), parse_reg(b) end local d, b = match(arg, "^(.*)%(("..reg..")%)$") if d then - return d, 0, parse_gpr(b) + return d, 0, parse_reg(b) end -- TODO: handle values without registers? -- 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 local pr1,pr2,pr3 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) 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) elseif p == "i" then - op1 = op1 + shl(parse_gpr(params[1]),4) + op1 = op1 + shl(parse_reg(params[1]),4) wputhw(op1); parse_imm16(params[2]) elseif p == "j" then 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 wputhw(op1); wputhw(op2); if a then a() end @@ -1066,7 +1057,7 @@ local function parse_template(params, template, nparams, pos) elseif p == "l" then 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) op2 = op2 + band(shr(d, 4), 0xff00) wputhw(op0); wputhw(op1); wputhw(op2) @@ -1074,18 +1065,18 @@ local function parse_template(params, template, nparams, pos) elseif p == "m" then elseif p == "n" then - op0 = op0 + shl(parse_gpr(params[1]), 4) + op0 = op0 + shl(parse_reg(params[1]), 4) wputhw(op0); parse_imm(params[2]) elseif p == "q" then 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 wputhw(op1); wputhw(op2) if a then a() end -- a() emits action. elseif p == "s" then 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) op2 = op2 + band(shr(d, 4), 0xff00) wputhw(op0); wputhw(op1); wputhw(op2) @@ -1105,7 +1096,7 @@ local function parse_template(params, template, nparams, pos) wputhw(op1); wputhw(op2); if a then a() end -- a() emits action. elseif p == "z" then - op2 = op2 + parse_gpr(params[1]) + op2 = op2 + parse_reg(params[1]) wputhw(op2) else werror("unrecognized encoding")