diff --git a/dynasm/dasm_x86.h b/dynasm/dasm_x86.h index 2e2f2334..9a1d8b54 100644 --- a/dynasm/dasm_x86.h +++ b/dynasm/dasm_x86.h @@ -17,11 +17,11 @@ /* Action definitions. DASM_STOP must be 255. */ enum { - DASM_DISP = 233, + DASM_DISP = 231, DASM_IMM_S, DASM_IMM_B, DASM_IMM_W, DASM_IMM_D, DASM_IMM_WB, DASM_IMM_DB, DASM_VREG, DASM_SPACE, DASM_SETLABEL, DASM_REL_A, DASM_REL_LG, DASM_REL_PC, - DASM_IMM_LG, DASM_IMM_PC, DASM_LABEL_LG, DASM_LABEL_PC, DASM_ALIGN, - DASM_EXTERN, DASM_ESC, DASM_MARK, DASM_SECTION, DASM_STOP + DASM_IMM_LG, DASM_IMM_LG64, DASM_IMM_PC, DASM_IMM_PC64, DASM_LABEL_LG, DASM_LABEL_PC, + DASM_ALIGN, DASM_EXTERN, DASM_ESC, DASM_MARK, DASM_SECTION, DASM_STOP }; /* Maximum number of section buffer positions for a single dasm_put() call. */ @@ -218,6 +218,7 @@ void dasm_put(Dst_DECL, int start, ...) } else { int *pl, n; switch (action) { + case DASM_IMM_LG64: ofs += 4; case DASM_REL_LG: case DASM_IMM_LG: n = *p++; pl = D->lglabels + n; @@ -226,6 +227,7 @@ void dasm_put(Dst_DECL, int start, ...) pl -= 246; n = *pl; if (n < 0) n = 0; /* Start new chain for fwd rel if label exists. */ goto linkrel; + case DASM_IMM_PC64: ofs += 4; case DASM_REL_PC: case DASM_IMM_PC: pl = D->pclabels + va_arg(ap, int); CKPL(pc, PC); putrel: @@ -333,11 +335,12 @@ int dasm_link(Dst_DECL, size_t *szp) break; } /* fallthrough */ - case DASM_SPACE: case DASM_IMM_LG: case DASM_VREG: p++; + case DASM_SPACE: case DASM_IMM_LG: case DASM_IMM_LG64: case DASM_VREG: p++; /* fallthrough */ case DASM_DISP: case DASM_IMM_S: case DASM_IMM_B: case DASM_IMM_W: case DASM_IMM_D: case DASM_IMM_WB: case DASM_IMM_DB: - case DASM_SETLABEL: case DASM_REL_A: case DASM_IMM_PC: pos++; break; + case DASM_SETLABEL: case DASM_REL_A: case DASM_IMM_PC: case DASM_IMM_PC64: + pos++; break; case DASM_LABEL_LG: p++; /* fallthrough */ case DASM_LABEL_PC: b[pos++] += ofs; break; /* Fix label offset. */ @@ -365,9 +368,12 @@ int dasm_link(Dst_DECL, size_t *szp) do { *((unsigned short *)cp) = (unsigned short)(x); cp+=2; } while (0) #define dasmd(x) \ do { *((unsigned int *)cp) = (unsigned int)(x); cp+=4; } while (0) +#define dasmq(x) \ + do { *((uint64_t *)cp) = (uint64_t)(x); cp+=8; } while (0) #else #define dasmw(x) do { dasmb(x); dasmb((x)>>8); } while (0) #define dasmd(x) do { dasmw(x); dasmw((x)>>16); } while (0) +#define dasmq(x) do { dasmd(x); dasmd((x)>>32); } while (0) #endif /* Pass 3: Encode sections. */ @@ -450,6 +456,16 @@ int dasm_encode(Dst_DECL, void *buffer) n = *pb < 0 ? pb[1] : (*pb + (int)(ptrdiff_t)base); goto wd; } + case DASM_IMM_LG64: { + p++; + if (n < 0) + dasmq((ptrdiff_t)D->globals[-n]); + } + case DASM_IMM_PC64: { + int *pb = DASM_POS2PTR(D, n); + dasmq(*pb < 0 ? pb[1] : (*pb + (ptrdiff_t)base)); + break; + } case DASM_LABEL_LG: { int idx = *p++; if (idx >= 10) diff --git a/dynasm/dasm_x86.lua b/dynasm/dasm_x86.lua index bc9a0001..659db2d0 100644 --- a/dynasm/dasm_x86.lua +++ b/dynasm/dasm_x86.lua @@ -46,8 +46,8 @@ local action_names = { "SETLABEL", "REL_A", -- action arg (1 byte) or int arg, 2 buffer pos (link, offset): "REL_LG", "REL_PC", - -- action arg (1 byte) or int arg, 1 buffer pos (link): - "IMM_LG", "IMM_PC", + -- action arg (1 byte) or ptrdiff_t arg, 1 buffer pos (link): + "IMM_LG", "IMM_LG64", "IMM_PC", "IMM_PC64", -- action arg (1 byte) or int arg, 1 buffer pos (offset): "LABEL_LG", "LABEL_PC", -- action arg (1 byte), 1 buffer pos (offset): @@ -438,6 +438,16 @@ local function wputlabel(aprefix, imm, num) end end +-- Put action for label arg (IMM_LG64, IMM_PC64, REL_LG, REL_PC). +local function wputlabel64(aprefix, imm, num) + if type(imm) == "number" then + waction("IMM_LG64", nil, num); + wputxb(imm) + else + waction("IMM_PC64", imm, num) + end +end + -- Put signed byte or arg. local function wputsbarg(n) if type(n) == "number" then @@ -469,6 +479,26 @@ local function wputwarg(n) else waction("IMM_W", n) end end +-- Put signed or unsigned qword or arg. +local function wputqarg(n) + local tn = type(n) + if tn == "number" then + wputb(band(n, 255)) + wputb(band(shr(n, 8), 255)) + wputb(band(shr(n, 16), 255)) + wputb(band(shr(n, 24), 255)) + wputb(band(shr(n, 32), 255)) + wputb(band(shr(n, 40), 255)) + wputb(band(shr(n, 48), 255)) + wputb(shr(n, 56)) + elseif tn == "table" then + wputlabel64("IMM_", n[1], 1) + else + waction("IMM_D", format("(unsigned int)(%s)", n)) + waction("IMM_D", format("(unsigned int)((%s)>>32)", n)) + end +end + -- Put signed or unsigned dword or arg. local function wputdarg(n) local tn = type(n) @@ -2151,9 +2181,17 @@ local function op_data(params) werror("bad mode or size in `"..p.."'") end if a.mode == "iJ" then - wputlabel("IMM_", a.imm, 1) + if sz == 'q' then + wputlabel64("IMM_", a.imm, 1) + else + wputlabel("IMM_", a.imm, 1) + end else - wputszarg(sz, a.imm) + if sz == 'q' then + wputqarg(a.imm) + else + wputszarg(sz, a.imm) + end end if secpos+2 > maxsecpos then wflush() end end