diff options
author | Mike Pall <mike> | 2021-05-02 22:25:16 +0200 |
---|---|---|
committer | Mike Pall <mike> | 2021-05-02 22:25:16 +0200 |
commit | 1449663ecff3a51b15fe0113b62979b72690178f (patch) | |
tree | c4cda077423d534f3634b5194dfe4182ea68f1cd /dynasm | |
parent | 521b367567dc5d91d7f9ae29c257998953e24e53 (diff) | |
download | luajit-1449663ecff3a51b15fe0113b62979b72690178f.tar.gz luajit-1449663ecff3a51b15fe0113b62979b72690178f.tar.bz2 luajit-1449663ecff3a51b15fe0113b62979b72690178f.zip |
DynASM/x86: Fix x64 .aword refs. Add .qword, .quad, .addr and .long.
Suggested by Dmitry Stogov.
Diffstat (limited to 'dynasm')
-rw-r--r-- | dynasm/dasm_x86.h | 24 | ||||
-rw-r--r-- | dynasm/dasm_x86.lua | 42 |
2 files changed, 55 insertions, 11 deletions
diff --git a/dynasm/dasm_x86.h b/dynasm/dasm_x86.h index 2e2f2334..d8d4928c 100644 --- a/dynasm/dasm_x86.h +++ b/dynasm/dasm_x86.h | |||
@@ -239,8 +239,11 @@ void dasm_put(Dst_DECL, int start, ...) | |||
239 | } | 239 | } |
240 | pos++; | 240 | pos++; |
241 | ofs += 4; /* Maximum offset needed. */ | 241 | ofs += 4; /* Maximum offset needed. */ |
242 | if (action == DASM_REL_LG || action == DASM_REL_PC) | 242 | if (action == DASM_REL_LG || action == DASM_REL_PC) { |
243 | b[pos++] = ofs; /* Store pass1 offset estimate. */ | 243 | b[pos++] = ofs; /* Store pass1 offset estimate. */ |
244 | } else if (sizeof(ptrdiff_t) == 8) { | ||
245 | ofs += 4; | ||
246 | } | ||
244 | break; | 247 | break; |
245 | case DASM_LABEL_LG: pl = D->lglabels + *p++; CKPL(lg, LG); goto putlabel; | 248 | case DASM_LABEL_LG: pl = D->lglabels + *p++; CKPL(lg, LG); goto putlabel; |
246 | case DASM_LABEL_PC: pl = D->pclabels + va_arg(ap, int); CKPL(pc, PC); | 249 | case DASM_LABEL_PC: pl = D->pclabels + va_arg(ap, int); CKPL(pc, PC); |
@@ -365,10 +368,22 @@ int dasm_link(Dst_DECL, size_t *szp) | |||
365 | do { *((unsigned short *)cp) = (unsigned short)(x); cp+=2; } while (0) | 368 | do { *((unsigned short *)cp) = (unsigned short)(x); cp+=2; } while (0) |
366 | #define dasmd(x) \ | 369 | #define dasmd(x) \ |
367 | do { *((unsigned int *)cp) = (unsigned int)(x); cp+=4; } while (0) | 370 | do { *((unsigned int *)cp) = (unsigned int)(x); cp+=4; } while (0) |
371 | #define dasmq(x) \ | ||
372 | do { *((unsigned long long *)cp) = (unsigned long long)(x); cp+=8; } while (0) | ||
368 | #else | 373 | #else |
369 | #define dasmw(x) do { dasmb(x); dasmb((x)>>8); } while (0) | 374 | #define dasmw(x) do { dasmb(x); dasmb((x)>>8); } while (0) |
370 | #define dasmd(x) do { dasmw(x); dasmw((x)>>16); } while (0) | 375 | #define dasmd(x) do { dasmw(x); dasmw((x)>>16); } while (0) |
376 | #define dasmq(x) do { dasmd(x); dasmd((x)>>32); } while (0) | ||
371 | #endif | 377 | #endif |
378 | static unsigned char *dasma_(unsigned char *cp, ptrdiff_t x) | ||
379 | { | ||
380 | if (sizeof(ptrdiff_t) == 8) | ||
381 | dasmq((unsigned long long)x); | ||
382 | else | ||
383 | dasmd((unsigned int)x); | ||
384 | return cp; | ||
385 | } | ||
386 | #define dasma(x) (cp = dasma_(cp, (x))) | ||
372 | 387 | ||
373 | /* Pass 3: Encode sections. */ | 388 | /* Pass 3: Encode sections. */ |
374 | int dasm_encode(Dst_DECL, void *buffer) | 389 | int dasm_encode(Dst_DECL, void *buffer) |
@@ -443,12 +458,13 @@ int dasm_encode(Dst_DECL, void *buffer) | |||
443 | goto wb; | 458 | goto wb; |
444 | } | 459 | } |
445 | case DASM_IMM_LG: | 460 | case DASM_IMM_LG: |
446 | p++; if (n < 0) { n = (int)(ptrdiff_t)D->globals[-n]; goto wd; } | 461 | p++; |
462 | if (n < 0) { dasma((ptrdiff_t)D->globals[-n]); break; } | ||
447 | /* fallthrough */ | 463 | /* fallthrough */ |
448 | case DASM_IMM_PC: { | 464 | case DASM_IMM_PC: { |
449 | int *pb = DASM_POS2PTR(D, n); | 465 | int *pb = DASM_POS2PTR(D, n); |
450 | n = *pb < 0 ? pb[1] : (*pb + (int)(ptrdiff_t)base); | 466 | dasma(*pb < 0 ? (ptrdiff_t)pb[1] : (*pb + (ptrdiff_t)base)); |
451 | goto wd; | 467 | break; |
452 | } | 468 | } |
453 | case DASM_LABEL_LG: { | 469 | case DASM_LABEL_LG: { |
454 | int idx = *p++; | 470 | int idx = *p++; |
diff --git a/dynasm/dasm_x86.lua b/dynasm/dasm_x86.lua index bc9a0001..0c803dcd 100644 --- a/dynasm/dasm_x86.lua +++ b/dynasm/dasm_x86.lua | |||
@@ -484,6 +484,22 @@ local function wputdarg(n) | |||
484 | end | 484 | end |
485 | end | 485 | end |
486 | 486 | ||
487 | -- Put signed or unsigned qword or arg. | ||
488 | local function wputqarg(n) | ||
489 | local tn = type(n) | ||
490 | if tn == "number" then -- This is only used for numbers from -2^31..2^32-1. | ||
491 | wputb(band(n, 255)) | ||
492 | wputb(band(shr(n, 8), 255)) | ||
493 | wputb(band(shr(n, 16), 255)) | ||
494 | wputb(shr(n, 24)) | ||
495 | local sign = n < 0 and 255 or 0 | ||
496 | wputb(sign); wputb(sign); wputb(sign); wputb(sign) | ||
497 | else | ||
498 | waction("IMM_D", format("(unsigned int)(%s)", n)) | ||
499 | waction("IMM_D", format("(unsigned int)((unsigned long long)(%s)>>32)", n)) | ||
500 | end | ||
501 | end | ||
502 | |||
487 | -- Put operand-size dependent number or arg (defaults to dword). | 503 | -- Put operand-size dependent number or arg (defaults to dword). |
488 | local function wputszarg(sz, n) | 504 | local function wputszarg(sz, n) |
489 | if not sz or sz == "d" or sz == "q" then wputdarg(n) | 505 | if not sz or sz == "d" or sz == "q" then wputdarg(n) |
@@ -663,10 +679,16 @@ local function opmodestr(op, args) | |||
663 | end | 679 | end |
664 | 680 | ||
665 | -- Convert number to valid integer or nil. | 681 | -- Convert number to valid integer or nil. |
666 | local function toint(expr) | 682 | local function toint(expr, isqword) |
667 | local n = tonumber(expr) | 683 | local n = tonumber(expr) |
668 | if n then | 684 | if n then |
669 | if n % 1 ~= 0 or n < -2147483648 or n > 4294967295 then | 685 | if n % 1 ~= 0 then |
686 | werror("not an integer number `"..expr.."'") | ||
687 | elseif isqword then | ||
688 | if n < -2147483648 or n > 2147483647 then | ||
689 | n = nil -- Handle it as an expression to avoid precision loss. | ||
690 | end | ||
691 | elseif n < -2147483648 or n > 4294967295 then | ||
670 | werror("bad integer number `"..expr.."'") | 692 | werror("bad integer number `"..expr.."'") |
671 | end | 693 | end |
672 | return n | 694 | return n |
@@ -749,7 +771,7 @@ local function rtexpr(expr) | |||
749 | end | 771 | end |
750 | 772 | ||
751 | -- Parse operand and return { mode, opsize, reg, xreg, xsc, disp, imm }. | 773 | -- Parse operand and return { mode, opsize, reg, xreg, xsc, disp, imm }. |
752 | local function parseoperand(param) | 774 | local function parseoperand(param, isqword) |
753 | local t = {} | 775 | local t = {} |
754 | 776 | ||
755 | local expr = param | 777 | local expr = param |
@@ -837,7 +859,7 @@ local function parseoperand(param) | |||
837 | t.disp = dispexpr(tailx) | 859 | t.disp = dispexpr(tailx) |
838 | else | 860 | else |
839 | -- imm or opsize*imm | 861 | -- imm or opsize*imm |
840 | local imm = toint(expr) | 862 | local imm = toint(expr, isqword) |
841 | if not imm and sub(expr, 1, 1) == "*" and t.opsize then | 863 | if not imm and sub(expr, 1, 1) == "*" and t.opsize then |
842 | imm = toint(sub(expr, 2)) | 864 | imm = toint(sub(expr, 2)) |
843 | if imm then | 865 | if imm then |
@@ -1952,7 +1974,7 @@ local function dopattern(pat, args, sz, op, needrex) | |||
1952 | local a = args[narg] | 1974 | local a = args[narg] |
1953 | narg = narg + 1 | 1975 | narg = narg + 1 |
1954 | local mode, imm = a.mode, a.imm | 1976 | local mode, imm = a.mode, a.imm |
1955 | if mode == "iJ" and not match("iIJ", c) then | 1977 | if mode == "iJ" and not match(x64 and "J" or "iIJ", c) then |
1956 | werror("bad operand size for label") | 1978 | werror("bad operand size for label") |
1957 | end | 1979 | end |
1958 | if c == "S" then | 1980 | if c == "S" then |
@@ -2144,14 +2166,16 @@ end | |||
2144 | local function op_data(params) | 2166 | local function op_data(params) |
2145 | if not params then return "imm..." end | 2167 | if not params then return "imm..." end |
2146 | local sz = sub(params.op, 2, 2) | 2168 | local sz = sub(params.op, 2, 2) |
2147 | if sz == "a" then sz = addrsize end | 2169 | if sz == "l" then sz = "d" elseif sz == "a" then sz = addrsize end |
2148 | for _,p in ipairs(params) do | 2170 | for _,p in ipairs(params) do |
2149 | local a = parseoperand(p) | 2171 | local a = parseoperand(p, sz == "q") |
2150 | if sub(a.mode, 1, 1) ~= "i" or (a.opsize and a.opsize ~= sz) then | 2172 | if sub(a.mode, 1, 1) ~= "i" or (a.opsize and a.opsize ~= sz) then |
2151 | werror("bad mode or size in `"..p.."'") | 2173 | werror("bad mode or size in `"..p.."'") |
2152 | end | 2174 | end |
2153 | if a.mode == "iJ" then | 2175 | if a.mode == "iJ" then |
2154 | wputlabel("IMM_", a.imm, 1) | 2176 | wputlabel("IMM_", a.imm, 1) |
2177 | elseif sz == "q" then | ||
2178 | wputqarg(a.imm) | ||
2155 | else | 2179 | else |
2156 | wputszarg(sz, a.imm) | 2180 | wputszarg(sz, a.imm) |
2157 | end | 2181 | end |
@@ -2163,7 +2187,11 @@ map_op[".byte_*"] = op_data | |||
2163 | map_op[".sbyte_*"] = op_data | 2187 | map_op[".sbyte_*"] = op_data |
2164 | map_op[".word_*"] = op_data | 2188 | map_op[".word_*"] = op_data |
2165 | map_op[".dword_*"] = op_data | 2189 | map_op[".dword_*"] = op_data |
2190 | map_op[".qword_*"] = op_data | ||
2166 | map_op[".aword_*"] = op_data | 2191 | map_op[".aword_*"] = op_data |
2192 | map_op[".long_*"] = op_data | ||
2193 | map_op[".quad_*"] = op_data | ||
2194 | map_op[".addr_*"] = op_data | ||
2167 | 2195 | ||
2168 | ------------------------------------------------------------------------------ | 2196 | ------------------------------------------------------------------------------ |
2169 | 2197 | ||