diff options
Diffstat (limited to 'dynasm/dasm_arm.h')
-rw-r--r-- | dynasm/dasm_arm.h | 20 |
1 files changed, 14 insertions, 6 deletions
diff --git a/dynasm/dasm_arm.h b/dynasm/dasm_arm.h index 3fd795b7..87db7f00 100644 --- a/dynasm/dasm_arm.h +++ b/dynasm/dasm_arm.h | |||
@@ -360,7 +360,7 @@ int dasm_encode(Dst_DECL, void *buffer) | |||
360 | case DASM_STOP: case DASM_SECTION: goto stop; | 360 | case DASM_STOP: case DASM_SECTION: goto stop; |
361 | case DASM_ESC: *cp++ = *p++; break; | 361 | case DASM_ESC: *cp++ = *p++; break; |
362 | case DASM_REL_EXT: | 362 | case DASM_REL_EXT: |
363 | n = DASM_EXTERN(Dst, (unsigned char *)cp, (ins & 2047), 1); | 363 | n = DASM_EXTERN(Dst, (unsigned char *)cp, (ins&2047), !(ins&2048)); |
364 | goto patchrel; | 364 | goto patchrel; |
365 | case DASM_ALIGN: | 365 | case DASM_ALIGN: |
366 | ins &= 255; while ((((char *)cp - base) & ins)) *cp++ = 0xe1a00000; | 366 | ins &= 255; while ((((char *)cp - base) & ins)) *cp++ = 0xe1a00000; |
@@ -369,10 +369,18 @@ int dasm_encode(Dst_DECL, void *buffer) | |||
369 | CK(n >= 0, UNDEF_LG); | 369 | CK(n >= 0, UNDEF_LG); |
370 | case DASM_REL_PC: | 370 | case DASM_REL_PC: |
371 | CK(n >= 0, UNDEF_PC); | 371 | CK(n >= 0, UNDEF_PC); |
372 | n = *DASM_POS2PTR(D, n) - (int)((char *)cp - base); | 372 | n = *DASM_POS2PTR(D, n) - (int)((char *)cp - base) - 4; |
373 | patchrel: | 373 | patchrel: |
374 | CK((n & 3) == 0 && ((n-4+0x02000000) >> 26) == 0, RANGE_REL); | 374 | if ((ins & 0x800) == 0) { |
375 | cp[-1] |= (((n-4) >> 2) & 0x00ffffff); | 375 | CK((n & 3) == 0 && ((n+0x02000000) >> 26) == 0, RANGE_REL); |
376 | cp[-1] |= ((n >> 2) & 0x00ffffff); | ||
377 | } else if ((ins & 0x1000)) { | ||
378 | CK((n & 3) == 0 && -256 <= n && n <= 256, RANGE_REL); | ||
379 | goto patchimml8; | ||
380 | } else { | ||
381 | CK((n & 3) == 0 && -4096 <= n && n <= 4096, RANGE_REL); | ||
382 | goto patchimml12; | ||
383 | } | ||
376 | break; | 384 | break; |
377 | case DASM_LABEL_LG: | 385 | case DASM_LABEL_LG: |
378 | ins &= 2047; if (ins >= 20) D->globals[ins-10] = (void *)(base + n); | 386 | ins &= 2047; if (ins >= 20) D->globals[ins-10] = (void *)(base + n); |
@@ -387,11 +395,11 @@ int dasm_encode(Dst_DECL, void *buffer) | |||
387 | case DASM_IMM16: | 395 | case DASM_IMM16: |
388 | cp[-1] |= ((n & 0xf000) << 4) | (n & 0x0fff); | 396 | cp[-1] |= ((n & 0xf000) << 4) | (n & 0x0fff); |
389 | break; | 397 | break; |
390 | case DASM_IMML8: | 398 | case DASM_IMML8: patchimml8: |
391 | cp[-1] |= n >= 0 ? (0x00800000 | (n & 0x0f) | ((n & 0xf0) << 4)) : | 399 | cp[-1] |= n >= 0 ? (0x00800000 | (n & 0x0f) | ((n & 0xf0) << 4)) : |
392 | ((-n & 0x0f) | ((-n & 0xf0) << 4)); | 400 | ((-n & 0x0f) | ((-n & 0xf0) << 4)); |
393 | break; | 401 | break; |
394 | case DASM_IMML12: | 402 | case DASM_IMML12: patchimml12: |
395 | cp[-1] |= n >= 0 ? (0x00800000 | n) : (-n); | 403 | cp[-1] |= n >= 0 ? (0x00800000 | n) : (-n); |
396 | break; | 404 | break; |
397 | default: *cp++ = ins; break; | 405 | default: *cp++ = ins; break; |