diff options
Diffstat (limited to 'dynasm/dasm_x86.h')
-rw-r--r-- | dynasm/dasm_x86.h | 79 |
1 files changed, 58 insertions, 21 deletions
diff --git a/dynasm/dasm_x86.h b/dynasm/dasm_x86.h index ae5c6200..ff54c9f1 100644 --- a/dynasm/dasm_x86.h +++ b/dynasm/dasm_x86.h | |||
@@ -68,7 +68,7 @@ struct dasm_State { | |||
68 | size_t lgsize; | 68 | size_t lgsize; |
69 | int *pclabels; /* PC label chains/pos ptrs. */ | 69 | int *pclabels; /* PC label chains/pos ptrs. */ |
70 | size_t pcsize; | 70 | size_t pcsize; |
71 | void **globals; /* Array of globals (bias -10). */ | 71 | void **globals; /* Array of globals. */ |
72 | dasm_Section *section; /* Pointer to active section. */ | 72 | dasm_Section *section; /* Pointer to active section. */ |
73 | size_t codesize; /* Total size of all code sections. */ | 73 | size_t codesize; /* Total size of all code sections. */ |
74 | int maxsection; /* 0 <= sectionidx < maxsection. */ | 74 | int maxsection; /* 0 <= sectionidx < maxsection. */ |
@@ -85,7 +85,6 @@ void dasm_init(Dst_DECL, int maxsection) | |||
85 | { | 85 | { |
86 | dasm_State *D; | 86 | dasm_State *D; |
87 | size_t psz = 0; | 87 | size_t psz = 0; |
88 | int i; | ||
89 | Dst_REF = NULL; | 88 | Dst_REF = NULL; |
90 | DASM_M_GROW(Dst, struct dasm_State, Dst_REF, psz, DASM_PSZ(maxsection)); | 89 | DASM_M_GROW(Dst, struct dasm_State, Dst_REF, psz, DASM_PSZ(maxsection)); |
91 | D = Dst_REF; | 90 | D = Dst_REF; |
@@ -96,12 +95,7 @@ void dasm_init(Dst_DECL, int maxsection) | |||
96 | D->pcsize = 0; | 95 | D->pcsize = 0; |
97 | D->globals = NULL; | 96 | D->globals = NULL; |
98 | D->maxsection = maxsection; | 97 | D->maxsection = maxsection; |
99 | for (i = 0; i < maxsection; i++) { | 98 | memset((void *)D->sections, 0, maxsection * sizeof(dasm_Section)); |
100 | D->sections[i].buf = NULL; /* Need this for pass3. */ | ||
101 | D->sections[i].rbuf = D->sections[i].buf - DASM_SEC2POS(i); | ||
102 | D->sections[i].bsize = 0; | ||
103 | D->sections[i].epos = 0; /* Wrong, but is recalculated after resize. */ | ||
104 | } | ||
105 | } | 99 | } |
106 | 100 | ||
107 | /* Free DynASM state. */ | 101 | /* Free DynASM state. */ |
@@ -121,7 +115,7 @@ void dasm_free(Dst_DECL) | |||
121 | void dasm_setupglobal(Dst_DECL, void **gl, unsigned int maxgl) | 115 | void dasm_setupglobal(Dst_DECL, void **gl, unsigned int maxgl) |
122 | { | 116 | { |
123 | dasm_State *D = Dst_REF; | 117 | dasm_State *D = Dst_REF; |
124 | D->globals = gl - 10; /* Negative bias to compensate for locals. */ | 118 | D->globals = gl; |
125 | DASM_M_GROW(Dst, int, D->lglabels, D->lgsize, (10+maxgl)*sizeof(int)); | 119 | DASM_M_GROW(Dst, int, D->lglabels, D->lgsize, (10+maxgl)*sizeof(int)); |
126 | } | 120 | } |
127 | 121 | ||
@@ -146,6 +140,7 @@ void dasm_setup(Dst_DECL, const void *actionlist) | |||
146 | if (D->pclabels) memset((void *)D->pclabels, 0, D->pcsize); | 140 | if (D->pclabels) memset((void *)D->pclabels, 0, D->pcsize); |
147 | for (i = 0; i < D->maxsection; i++) { | 141 | for (i = 0; i < D->maxsection; i++) { |
148 | D->sections[i].pos = DASM_SEC2POS(i); | 142 | D->sections[i].pos = DASM_SEC2POS(i); |
143 | D->sections[i].rbuf = D->sections[i].buf - D->sections[i].pos; | ||
149 | D->sections[i].ofs = 0; | 144 | D->sections[i].ofs = 0; |
150 | } | 145 | } |
151 | } | 146 | } |
@@ -170,7 +165,7 @@ void dasm_put(Dst_DECL, int start, ...) | |||
170 | dasm_State *D = Dst_REF; | 165 | dasm_State *D = Dst_REF; |
171 | dasm_ActList p = D->actionlist + start; | 166 | dasm_ActList p = D->actionlist + start; |
172 | dasm_Section *sec = D->section; | 167 | dasm_Section *sec = D->section; |
173 | int pos = sec->pos, ofs = sec->ofs, mrm = 4; | 168 | int pos = sec->pos, ofs = sec->ofs, mrm = -1; |
174 | int *b; | 169 | int *b; |
175 | 170 | ||
176 | if (pos >= sec->epos) { | 171 | if (pos >= sec->epos) { |
@@ -193,7 +188,7 @@ void dasm_put(Dst_DECL, int start, ...) | |||
193 | b[pos++] = n; | 188 | b[pos++] = n; |
194 | switch (action) { | 189 | switch (action) { |
195 | case DASM_DISP: | 190 | case DASM_DISP: |
196 | if (n == 0) { if ((mrm&7) == 4) mrm = p[-2]; if ((mrm&7) != 5) break; } | 191 | if (n == 0) { if (mrm < 0) mrm = p[-2]; if ((mrm&7) != 5) break; } |
197 | /* fallthrough */ | 192 | /* fallthrough */ |
198 | case DASM_IMM_DB: if (((n+128)&-256) == 0) goto ob; /* fallthrough */ | 193 | case DASM_IMM_DB: if (((n+128)&-256) == 0) goto ob; /* fallthrough */ |
199 | case DASM_REL_A: /* Assumes ptrdiff_t is int. !x64 */ | 194 | case DASM_REL_A: /* Assumes ptrdiff_t is int. !x64 */ |
@@ -204,11 +199,17 @@ void dasm_put(Dst_DECL, int start, ...) | |||
204 | case DASM_IMM_W: CK((n&-65536) == 0, RANGE_I); ofs += 2; break; | 199 | case DASM_IMM_W: CK((n&-65536) == 0, RANGE_I); ofs += 2; break; |
205 | case DASM_SPACE: p++; ofs += n; break; | 200 | case DASM_SPACE: p++; ofs += n; break; |
206 | case DASM_SETLABEL: b[pos-2] = -0x40000000; break; /* Neg. label ofs. */ | 201 | 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); | 202 | case DASM_VREG: CK((n&-16) == 0 && (n != 4 || (*p>>5) != 2), RANGE_VREG); |
208 | if (*p++ == 1 && *p == DASM_DISP) mrm = n; | 203 | if (*p < 0x40 && p[1] == DASM_DISP) mrm = n; |
204 | if (*p < 0x20 && (n&7) == 4) ofs++; | ||
205 | switch ((*p++ >> 3) & 3) { | ||
206 | case 3: n |= b[pos-3]; /* fallthrough */ | ||
207 | case 2: n |= b[pos-2]; /* fallthrough */ | ||
208 | case 1: if (n <= 7) { b[pos-1] |= 0x10; ofs--; } | ||
209 | } | ||
209 | continue; | 210 | continue; |
210 | } | 211 | } |
211 | mrm = 4; | 212 | mrm = -1; |
212 | } else { | 213 | } else { |
213 | int *pl, n; | 214 | int *pl, n; |
214 | switch (action) { | 215 | switch (action) { |
@@ -233,8 +234,11 @@ void dasm_put(Dst_DECL, int start, ...) | |||
233 | } | 234 | } |
234 | pos++; | 235 | pos++; |
235 | ofs += 4; /* Maximum offset needed. */ | 236 | ofs += 4; /* Maximum offset needed. */ |
236 | if (action == DASM_REL_LG || action == DASM_REL_PC) | 237 | if (action == DASM_REL_LG || action == DASM_REL_PC) { |
237 | b[pos++] = ofs; /* Store pass1 offset estimate. */ | 238 | b[pos++] = ofs; /* Store pass1 offset estimate. */ |
239 | } else if (sizeof(ptrdiff_t) == 8) { | ||
240 | ofs += 4; | ||
241 | } | ||
238 | break; | 242 | break; |
239 | case DASM_LABEL_LG: pl = D->lglabels + *p++; CKPL(lg, LG); goto putlabel; | 243 | 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); | 244 | case DASM_LABEL_PC: pl = D->pclabels + va_arg(ap, int); CKPL(pc, PC); |
@@ -359,10 +363,22 @@ int dasm_link(Dst_DECL, size_t *szp) | |||
359 | do { *((unsigned short *)cp) = (unsigned short)(x); cp+=2; } while (0) | 363 | do { *((unsigned short *)cp) = (unsigned short)(x); cp+=2; } while (0) |
360 | #define dasmd(x) \ | 364 | #define dasmd(x) \ |
361 | do { *((unsigned int *)cp) = (unsigned int)(x); cp+=4; } while (0) | 365 | do { *((unsigned int *)cp) = (unsigned int)(x); cp+=4; } while (0) |
366 | #define dasmq(x) \ | ||
367 | do { *((unsigned long long *)cp) = (unsigned long long)(x); cp+=8; } while (0) | ||
362 | #else | 368 | #else |
363 | #define dasmw(x) do { dasmb(x); dasmb((x)>>8); } while (0) | 369 | #define dasmw(x) do { dasmb(x); dasmb((x)>>8); } while (0) |
364 | #define dasmd(x) do { dasmw(x); dasmw((x)>>16); } while (0) | 370 | #define dasmd(x) do { dasmw(x); dasmw((x)>>16); } while (0) |
371 | #define dasmq(x) do { dasmd(x); dasmd((x)>>32); } while (0) | ||
365 | #endif | 372 | #endif |
373 | static unsigned char *dasma_(unsigned char *cp, ptrdiff_t x) | ||
374 | { | ||
375 | if (sizeof(ptrdiff_t) == 8) | ||
376 | dasmq((unsigned long long)x); | ||
377 | else | ||
378 | dasmd((unsigned int)x); | ||
379 | return cp; | ||
380 | } | ||
381 | #define dasma(x) (cp = dasma_(cp, (x))) | ||
366 | 382 | ||
367 | /* Pass 3: Encode sections. */ | 383 | /* Pass 3: Encode sections. */ |
368 | int dasm_encode(Dst_DECL, void *buffer) | 384 | int dasm_encode(Dst_DECL, void *buffer) |
@@ -402,9 +418,29 @@ int dasm_encode(Dst_DECL, void *buffer) | |||
402 | case DASM_IMM_WB: if (((n+128)&-256) == 0) goto db; else mark = NULL; | 418 | case DASM_IMM_WB: if (((n+128)&-256) == 0) goto db; else mark = NULL; |
403 | /* fallthrough */ | 419 | /* fallthrough */ |
404 | case DASM_IMM_W: dasmw(n); break; | 420 | case DASM_IMM_W: dasmw(n); break; |
405 | case DASM_VREG: { int t = *p++; if (t >= 2) n<<=3; cp[-1] |= n; break; } | 421 | case DASM_VREG: { |
422 | int t = *p++; | ||
423 | unsigned char *ex = cp - (t&7); | ||
424 | if ((n & 8) && t < 0xa0) { | ||
425 | if (*ex & 0x80) ex[1] ^= 0x20 << (t>>6); else *ex ^= 1 << (t>>6); | ||
426 | n &= 7; | ||
427 | } else if (n & 0x10) { | ||
428 | if (*ex & 0x80) { | ||
429 | *ex = 0xc5; ex[1] = (ex[1] & 0x80) | ex[2]; ex += 2; | ||
430 | } | ||
431 | while (++ex < cp) ex[-1] = *ex; | ||
432 | if (mark) mark--; | ||
433 | cp--; | ||
434 | n &= 7; | ||
435 | } | ||
436 | if (t >= 0xc0) n <<= 4; | ||
437 | else if (t >= 0x40) n <<= 3; | ||
438 | else if (n == 4 && t < 0x20) { cp[-1] ^= n; *cp++ = 0x20; } | ||
439 | cp[-1] ^= n; | ||
440 | break; | ||
441 | } | ||
406 | case DASM_REL_LG: p++; if (n >= 0) goto rel_pc; | 442 | case DASM_REL_LG: p++; if (n >= 0) goto rel_pc; |
407 | b++; n = (int)(ptrdiff_t)D->globals[-n]; | 443 | b++; n = (int)(ptrdiff_t)D->globals[-n-10]; |
408 | /* fallthrough */ | 444 | /* fallthrough */ |
409 | case DASM_REL_A: rel_a: | 445 | case DASM_REL_A: rel_a: |
410 | n -= (unsigned int)(ptrdiff_t)(cp+4); goto wd; /* !x64 */ | 446 | n -= (unsigned int)(ptrdiff_t)(cp+4); goto wd; /* !x64 */ |
@@ -417,17 +453,18 @@ int dasm_encode(Dst_DECL, void *buffer) | |||
417 | goto wb; | 453 | goto wb; |
418 | } | 454 | } |
419 | case DASM_IMM_LG: | 455 | case DASM_IMM_LG: |
420 | p++; if (n < 0) { n = (int)(ptrdiff_t)D->globals[-n]; goto wd; } | 456 | p++; |
457 | if (n < 0) { dasma((ptrdiff_t)D->globals[-n-10]); break; } | ||
421 | /* fallthrough */ | 458 | /* fallthrough */ |
422 | case DASM_IMM_PC: { | 459 | case DASM_IMM_PC: { |
423 | int *pb = DASM_POS2PTR(D, n); | 460 | int *pb = DASM_POS2PTR(D, n); |
424 | n = *pb < 0 ? pb[1] : (*pb + (int)(ptrdiff_t)base); | 461 | dasma(*pb < 0 ? (ptrdiff_t)pb[1] : (*pb + (ptrdiff_t)base)); |
425 | goto wd; | 462 | break; |
426 | } | 463 | } |
427 | case DASM_LABEL_LG: { | 464 | case DASM_LABEL_LG: { |
428 | int idx = *p++; | 465 | int idx = *p++; |
429 | if (idx >= 10) | 466 | if (idx >= 10) |
430 | D->globals[idx] = (void *)(base + (*p == DASM_SETLABEL ? *b : n)); | 467 | D->globals[idx-10] = (void *)(base + (*p == DASM_SETLABEL ? *b : n)); |
431 | break; | 468 | break; |
432 | } | 469 | } |
433 | case DASM_LABEL_PC: case DASM_SETLABEL: break; | 470 | case DASM_LABEL_PC: case DASM_SETLABEL: break; |