aboutsummaryrefslogtreecommitdiff
path: root/dynasm/dasm_x86.h
diff options
context:
space:
mode:
Diffstat (limited to 'dynasm/dasm_x86.h')
-rw-r--r--dynasm/dasm_x86.h62
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
378static 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. */
368int dasm_encode(Dst_DECL, void *buffer) 389int 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++;