diff options
Diffstat (limited to 'dynasm/dasm_x86.h')
-rw-r--r-- | dynasm/dasm_x86.h | 62 |
1 files changed, 52 insertions, 10 deletions
diff --git a/dynasm/dasm_x86.h b/dynasm/dasm_x86.h index c3089d91..f0327302 100644 --- a/dynasm/dasm_x86.h +++ b/dynasm/dasm_x86.h | |||
@@ -170,7 +170,7 @@ void dasm_put(Dst_DECL, int start, ...) | |||
170 | dasm_State *D = Dst_REF; | 170 | dasm_State *D = Dst_REF; |
171 | dasm_ActList p = D->actionlist + start; | 171 | dasm_ActList p = D->actionlist + start; |
172 | dasm_Section *sec = D->section; | 172 | dasm_Section *sec = D->section; |
173 | int pos = sec->pos, ofs = sec->ofs, mrm = 4; | 173 | int pos = sec->pos, ofs = sec->ofs, mrm = -1; |
174 | int *b; | 174 | int *b; |
175 | 175 | ||
176 | if (pos >= sec->epos) { | 176 | if (pos >= sec->epos) { |
@@ -193,7 +193,7 @@ void dasm_put(Dst_DECL, int start, ...) | |||
193 | b[pos++] = n; | 193 | b[pos++] = n; |
194 | switch (action) { | 194 | switch (action) { |
195 | case DASM_DISP: | 195 | case DASM_DISP: |
196 | if (n == 0) { if ((mrm&7) == 4) mrm = p[-2]; if ((mrm&7) != 5) break; } | 196 | if (n == 0) { if (mrm < 0) mrm = p[-2]; if ((mrm&7) != 5) break; } |
197 | /* fallthrough */ | 197 | /* fallthrough */ |
198 | case DASM_IMM_DB: if (((n+128)&-256) == 0) goto ob; /* fallthrough */ | 198 | case DASM_IMM_DB: if (((n+128)&-256) == 0) goto ob; /* fallthrough */ |
199 | case DASM_REL_A: /* Assumes ptrdiff_t is int. !x64 */ | 199 | case DASM_REL_A: /* Assumes ptrdiff_t is int. !x64 */ |
@@ -204,11 +204,17 @@ void dasm_put(Dst_DECL, int start, ...) | |||
204 | case DASM_IMM_W: CK((n&-65536) == 0, RANGE_I); ofs += 2; break; | 204 | case DASM_IMM_W: CK((n&-65536) == 0, RANGE_I); ofs += 2; break; |
205 | case DASM_SPACE: p++; ofs += n; break; | 205 | case DASM_SPACE: p++; ofs += n; break; |
206 | case DASM_SETLABEL: b[pos-2] = -0x40000000; break; /* Neg. label ofs. */ | 206 | case DASM_SETLABEL: b[pos-2] = -0x40000000; break; /* Neg. label ofs. */ |
207 | case DASM_VREG: CK((n&-8) == 0 && (n != 4 || (*p&1) == 0), RANGE_VREG); | 207 | case DASM_VREG: CK((n&-16) == 0 && (n != 4 || (*p>>5) != 2), RANGE_VREG); |
208 | if (*p++ == 1 && *p == DASM_DISP) mrm = n; | 208 | if (*p < 0x40 && p[1] == DASM_DISP) mrm = n; |
209 | if (*p < 0x20 && (n&7) == 4) ofs++; | ||
210 | switch ((*p++ >> 3) & 3) { | ||
211 | case 3: n |= b[pos-3]; /* fallthrough */ | ||
212 | case 2: n |= b[pos-2]; /* fallthrough */ | ||
213 | case 1: if (n <= 7) { b[pos-1] |= 0x10; ofs--; } | ||
214 | } | ||
209 | continue; | 215 | continue; |
210 | } | 216 | } |
211 | mrm = 4; | 217 | mrm = -1; |
212 | } else { | 218 | } else { |
213 | int *pl, n; | 219 | int *pl, n; |
214 | switch (action) { | 220 | switch (action) { |
@@ -233,8 +239,11 @@ void dasm_put(Dst_DECL, int start, ...) | |||
233 | } | 239 | } |
234 | pos++; | 240 | pos++; |
235 | ofs += 4; /* Maximum offset needed. */ | 241 | ofs += 4; /* Maximum offset needed. */ |
236 | if (action == DASM_REL_LG || action == DASM_REL_PC) | 242 | if (action == DASM_REL_LG || action == DASM_REL_PC) { |
237 | 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 | } | ||
238 | break; | 247 | break; |
239 | 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; |
240 | 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); |
@@ -359,10 +368,22 @@ int dasm_link(Dst_DECL, size_t *szp) | |||
359 | do { *((unsigned short *)cp) = (unsigned short)(x); cp+=2; } while (0) | 368 | do { *((unsigned short *)cp) = (unsigned short)(x); cp+=2; } while (0) |
360 | #define dasmd(x) \ | 369 | #define dasmd(x) \ |
361 | 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) | ||
362 | #else | 373 | #else |
363 | #define dasmw(x) do { dasmb(x); dasmb((x)>>8); } while (0) | 374 | #define dasmw(x) do { dasmb(x); dasmb((x)>>8); } while (0) |
364 | #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) | ||
365 | #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))) | ||
366 | 387 | ||
367 | /* Pass 3: Encode sections. */ | 388 | /* Pass 3: Encode sections. */ |
368 | int dasm_encode(Dst_DECL, void *buffer) | 389 | int dasm_encode(Dst_DECL, void *buffer) |
@@ -402,7 +423,27 @@ int dasm_encode(Dst_DECL, void *buffer) | |||
402 | case DASM_IMM_WB: if (((n+128)&-256) == 0) goto db; else mark = NULL; | 423 | case DASM_IMM_WB: if (((n+128)&-256) == 0) goto db; else mark = NULL; |
403 | /* fallthrough */ | 424 | /* fallthrough */ |
404 | case DASM_IMM_W: dasmw(n); break; | 425 | case DASM_IMM_W: dasmw(n); break; |
405 | case DASM_VREG: { int t = *p++; if (t >= 2) n<<=3; cp[-1] |= n; break; } | 426 | case DASM_VREG: { |
427 | int t = *p++; | ||
428 | unsigned char *ex = cp - (t&7); | ||
429 | if ((n & 8) && t < 0xa0) { | ||
430 | if (*ex & 0x80) ex[1] ^= 0x20 << (t>>6); else *ex ^= 1 << (t>>6); | ||
431 | n &= 7; | ||
432 | } else if (n & 0x10) { | ||
433 | if (*ex & 0x80) { | ||
434 | *ex = 0xc5; ex[1] = (ex[1] & 0x80) | ex[2]; ex += 2; | ||
435 | } | ||
436 | while (++ex < cp) ex[-1] = *ex; | ||
437 | if (mark) mark--; | ||
438 | cp--; | ||
439 | n &= 7; | ||
440 | } | ||
441 | if (t >= 0xc0) n <<= 4; | ||
442 | else if (t >= 0x40) n <<= 3; | ||
443 | else if (n == 4 && t < 0x20) { cp[-1] ^= n; *cp++ = 0x20; } | ||
444 | cp[-1] ^= n; | ||
445 | break; | ||
446 | } | ||
406 | case DASM_REL_LG: p++; if (n >= 0) goto rel_pc; | 447 | case DASM_REL_LG: p++; if (n >= 0) goto rel_pc; |
407 | b++; n = (int)(ptrdiff_t)D->globals[-n]; | 448 | b++; n = (int)(ptrdiff_t)D->globals[-n]; |
408 | /* fallthrough */ | 449 | /* fallthrough */ |
@@ -417,12 +458,13 @@ int dasm_encode(Dst_DECL, void *buffer) | |||
417 | goto wb; | 458 | goto wb; |
418 | } | 459 | } |
419 | case DASM_IMM_LG: | 460 | case DASM_IMM_LG: |
420 | 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; } | ||
421 | /* fallthrough */ | 463 | /* fallthrough */ |
422 | case DASM_IMM_PC: { | 464 | case DASM_IMM_PC: { |
423 | int *pb = DASM_POS2PTR(D, n); | 465 | int *pb = DASM_POS2PTR(D, n); |
424 | n = *pb < 0 ? pb[1] : (*pb + (int)(ptrdiff_t)base); | 466 | dasma(*pb < 0 ? (ptrdiff_t)pb[1] : (*pb + (ptrdiff_t)base)); |
425 | goto wd; | 467 | break; |
426 | } | 468 | } |
427 | case DASM_LABEL_LG: { | 469 | case DASM_LABEL_LG: { |
428 | int idx = *p++; | 470 | int idx = *p++; |