diff --git a/dynasm/dasm_s390x.h b/dynasm/dasm_s390x.h index 8b43a78c..66dfd79a 100644 --- a/dynasm/dasm_s390x.h +++ b/dynasm/dasm_s390x.h @@ -233,8 +233,11 @@ void dasm_put(Dst_DECL, int start, ...) break; case DASM_IMM16: case DASM_IMM32: - case DASM_DISP20: fprintf(stderr, "not implemented\n"); + case DASM_DISP20: + CK(-(1<<19) <= n && n < (1<<19), RANGE_I); + b[pos++] = n; + break; case DASM_DISP12: CK((n>>12) == 0, RANGE_I); b[pos++] = n; @@ -365,9 +368,12 @@ int dasm_encode(Dst_DECL, void *buffer) case DASM_LABEL_PC: break; case DASM_IMM16: case DASM_IMM32: - case DASM_DISP20: fprintf(stderr, "not implemented\n"); break; + case DASM_DISP20: + cp[-2] |= n&0xfff; + cp[-1] |= (n>>4)&0xff00; + break; case DASM_DISP12: cp[-1] |= n&0xfff; break; diff --git a/dynasm/dasm_s390x.lua b/dynasm/dasm_s390x.lua index b3061653..6900944b 100644 --- a/dynasm/dasm_s390x.lua +++ b/dynasm/dasm_s390x.lua @@ -346,8 +346,18 @@ end -- and b and x are GPRs. -- Encoded as: xblllhh (ls are the low-bits of d, and hs are the high bits). local function parse_mem_bxy(arg) - werror("parse_mem_bxy: not implemented") - return nil + local d, x, b = split_memop(arg) + local dval = tonumber(d) + if dval then + if not is_int20(dval) then + werror("displacement out of range: ", dval) + end + return dval, x, b, nil + end + if match(d, "^[rf]1?[0-9]?") then + werror("expected immediate operand, got register") + end + return 0, x, b, function() waction("DISP20", nil, d) end end local function parse_label(label, def) @@ -1024,7 +1034,14 @@ local function parse_template(params, template, nparams, pos) elseif p == "k" then elseif p == "l" then - + local d, x, b, a = parse_mem_bxy(params[2]) + op0 = op0 + shl(parse_gpr(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) + if a then + a() + end elseif p == "m" then elseif p == "n" then