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.h79
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)
121void dasm_setupglobal(Dst_DECL, void **gl, unsigned int maxgl) 115void 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
373static 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. */
368int dasm_encode(Dst_DECL, void *buffer) 384int 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;