diff options
Diffstat (limited to 'dynasm/dasm_x86.h')
-rw-r--r-- | dynasm/dasm_x86.h | 38 |
1 files changed, 32 insertions, 6 deletions
diff --git a/dynasm/dasm_x86.h b/dynasm/dasm_x86.h index 84b9d17f..edaddf54 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) { |
@@ -399,7 +405,27 @@ int dasm_encode(Dst_DECL, void *buffer) | |||
399 | case DASM_IMM_WB: if (((n+128)&-256) == 0) goto db; else mark = NULL; | 405 | case DASM_IMM_WB: if (((n+128)&-256) == 0) goto db; else mark = NULL; |
400 | /* fallthrough */ | 406 | /* fallthrough */ |
401 | case DASM_IMM_W: dasmw(n); break; | 407 | case DASM_IMM_W: dasmw(n); break; |
402 | case DASM_VREG: { int t = *p++; if (t >= 2) n<<=3; cp[-1] |= n; break; } | 408 | case DASM_VREG: { |
409 | int t = *p++; | ||
410 | unsigned char *ex = cp - (t&7); | ||
411 | if ((n & 8) && t < 0xa0) { | ||
412 | if (*ex & 0x80) ex[1] ^= 0x20 << (t>>6); else *ex ^= 1 << (t>>6); | ||
413 | n &= 7; | ||
414 | } else if (n & 0x10) { | ||
415 | if (*ex & 0x80) { | ||
416 | *ex = 0xc5; ex[1] = (ex[1] & 0x80) | ex[2]; ex += 2; | ||
417 | } | ||
418 | while (++ex < cp) ex[-1] = *ex; | ||
419 | if (mark) mark--; | ||
420 | cp--; | ||
421 | n &= 7; | ||
422 | } | ||
423 | if (t >= 0xc0) n <<= 4; | ||
424 | else if (t >= 0x40) n <<= 3; | ||
425 | else if (n == 4 && t < 0x20) { cp[-1] ^= n; *cp++ = 0x20; } | ||
426 | cp[-1] ^= n; | ||
427 | break; | ||
428 | } | ||
403 | case DASM_REL_LG: p++; if (n >= 0) goto rel_pc; | 429 | case DASM_REL_LG: p++; if (n >= 0) goto rel_pc; |
404 | b++; n = (int)(ptrdiff_t)D->globals[-n]; | 430 | b++; n = (int)(ptrdiff_t)D->globals[-n]; |
405 | /* fallthrough */ | 431 | /* fallthrough */ |