diff options
Diffstat (limited to 'dynasm/dasm_mips.h')
-rw-r--r-- | dynasm/dasm_mips.h | 29 |
1 files changed, 18 insertions, 11 deletions
diff --git a/dynasm/dasm_mips.h b/dynasm/dasm_mips.h index 15b4b137..c92c9bf4 100644 --- a/dynasm/dasm_mips.h +++ b/dynasm/dasm_mips.h | |||
@@ -21,7 +21,7 @@ enum { | |||
21 | /* The following actions need a buffer position. */ | 21 | /* The following actions need a buffer position. */ |
22 | DASM_ALIGN, DASM_REL_LG, DASM_LABEL_LG, | 22 | DASM_ALIGN, DASM_REL_LG, DASM_LABEL_LG, |
23 | /* The following actions also have an argument. */ | 23 | /* The following actions also have an argument. */ |
24 | DASM_REL_PC, DASM_LABEL_PC, DASM_IMM, | 24 | DASM_REL_PC, DASM_LABEL_PC, DASM_IMM, DASM_IMMS, |
25 | DASM__MAX | 25 | DASM__MAX |
26 | }; | 26 | }; |
27 | 27 | ||
@@ -231,7 +231,7 @@ void dasm_put(Dst_DECL, int start, ...) | |||
231 | *pl = -pos; /* Label exists now. */ | 231 | *pl = -pos; /* Label exists now. */ |
232 | b[pos++] = ofs; /* Store pass1 offset estimate. */ | 232 | b[pos++] = ofs; /* Store pass1 offset estimate. */ |
233 | break; | 233 | break; |
234 | case DASM_IMM: | 234 | case DASM_IMM: case DASM_IMMS: |
235 | #ifdef DASM_CHECKS | 235 | #ifdef DASM_CHECKS |
236 | CK((n & ((1<<((ins>>10)&31))-1)) == 0, RANGE_I); | 236 | CK((n & ((1<<((ins>>10)&31))-1)) == 0, RANGE_I); |
237 | #endif | 237 | #endif |
@@ -273,7 +273,7 @@ int dasm_link(Dst_DECL, size_t *szp) | |||
273 | 273 | ||
274 | { /* Handle globals not defined in this translation unit. */ | 274 | { /* Handle globals not defined in this translation unit. */ |
275 | int idx; | 275 | int idx; |
276 | for (idx = 20; idx*sizeof(int) < D->lgsize; idx++) { | 276 | for (idx = 10; idx*sizeof(int) < D->lgsize; idx++) { |
277 | int n = D->lglabels[idx]; | 277 | int n = D->lglabels[idx]; |
278 | /* Undefined label: Collapse rel chain and replace with marker (< 0). */ | 278 | /* Undefined label: Collapse rel chain and replace with marker (< 0). */ |
279 | while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = -idx; } | 279 | while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = -idx; } |
@@ -299,7 +299,7 @@ int dasm_link(Dst_DECL, size_t *szp) | |||
299 | case DASM_ALIGN: ofs -= (b[pos++] + ofs) & (ins & 255); break; | 299 | case DASM_ALIGN: ofs -= (b[pos++] + ofs) & (ins & 255); break; |
300 | case DASM_REL_LG: case DASM_REL_PC: pos++; break; | 300 | case DASM_REL_LG: case DASM_REL_PC: pos++; break; |
301 | case DASM_LABEL_LG: case DASM_LABEL_PC: b[pos++] += ofs; break; | 301 | case DASM_LABEL_LG: case DASM_LABEL_PC: b[pos++] += ofs; break; |
302 | case DASM_IMM: pos++; break; | 302 | case DASM_IMM: case DASM_IMMS: pos++; break; |
303 | } | 303 | } |
304 | } | 304 | } |
305 | stop: (void)0; | 305 | stop: (void)0; |
@@ -349,25 +349,32 @@ int dasm_encode(Dst_DECL, void *buffer) | |||
349 | ins &= 255; while ((((char *)cp - base) & ins)) *cp++ = 0x60000000; | 349 | ins &= 255; while ((((char *)cp - base) & ins)) *cp++ = 0x60000000; |
350 | break; | 350 | break; |
351 | case DASM_REL_LG: | 351 | case DASM_REL_LG: |
352 | CK(n >= 0, UNDEF_LG); | 352 | if (n < 0) { |
353 | n = (int)((ptrdiff_t)D->globals[-n] - (ptrdiff_t)cp); | ||
354 | goto patchrel; | ||
355 | } | ||
353 | /* fallthrough */ | 356 | /* fallthrough */ |
354 | case DASM_REL_PC: | 357 | case DASM_REL_PC: |
355 | CK(n >= 0, UNDEF_PC); | 358 | CK(n >= 0, UNDEF_PC); |
356 | n = *DASM_POS2PTR(D, n); | 359 | n = *DASM_POS2PTR(D, n); |
357 | if (ins & 2048) | 360 | if (ins & 2048) |
358 | n = n - (int)((char *)cp - base); | 361 | n = (n + (int)(size_t)base) & 0x0fffffff; |
359 | else | 362 | else |
360 | n = (n + (int)base) & 0x0fffffff; | 363 | n = n - (int)((char *)cp - base); |
361 | patchrel: | 364 | patchrel: { |
365 | unsigned int e = 16 + ((ins >> 12) & 15); | ||
362 | CK((n & 3) == 0 && | 366 | CK((n & 3) == 0 && |
363 | ((n + ((ins & 2048) ? 0x00020000 : 0)) >> | 367 | ((n + ((ins & 2048) ? 0 : (1<<(e+1)))) >> (e+2)) == 0, RANGE_REL); |
364 | ((ins & 2048) ? 18 : 28)) == 0, RANGE_REL); | 368 | cp[-1] |= ((n>>2) & ((1<<e)-1)); |
365 | cp[-1] |= ((n>>2) & ((ins & 2048) ? 0x0000ffff: 0x03ffffff)); | 369 | } |
366 | break; | 370 | break; |
367 | case DASM_LABEL_LG: | 371 | case DASM_LABEL_LG: |
368 | ins &= 2047; if (ins >= 20) D->globals[ins-10] = (void *)(base + n); | 372 | ins &= 2047; if (ins >= 20) D->globals[ins-10] = (void *)(base + n); |
369 | break; | 373 | break; |
370 | case DASM_LABEL_PC: break; | 374 | case DASM_LABEL_PC: break; |
375 | case DASM_IMMS: | ||
376 | cp[-1] |= ((n>>3) & 4); n &= 0x1f; | ||
377 | /* fallthrough */ | ||
371 | case DASM_IMM: | 378 | case DASM_IMM: |
372 | cp[-1] |= (n & ((1<<((ins>>5)&31))-1)) << (ins&31); | 379 | cp[-1] |= (n & ((1<<((ins>>5)&31))-1)) << (ins&31); |
373 | break; | 380 | break; |