diff options
Diffstat (limited to 'dynasm/dasm_mips.h')
-rw-r--r-- | dynasm/dasm_mips.h | 52 |
1 files changed, 27 insertions, 25 deletions
diff --git a/dynasm/dasm_mips.h b/dynasm/dasm_mips.h index bd18ab65..3fa2ef42 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 | ||
@@ -69,7 +69,7 @@ struct dasm_State { | |||
69 | size_t lgsize; | 69 | size_t lgsize; |
70 | int *pclabels; /* PC label chains/pos ptrs. */ | 70 | int *pclabels; /* PC label chains/pos ptrs. */ |
71 | size_t pcsize; | 71 | size_t pcsize; |
72 | void **globals; /* Array of globals (bias -10). */ | 72 | void **globals; /* Array of globals. */ |
73 | dasm_Section *section; /* Pointer to active section. */ | 73 | dasm_Section *section; /* Pointer to active section. */ |
74 | size_t codesize; /* Total size of all code sections. */ | 74 | size_t codesize; /* Total size of all code sections. */ |
75 | int maxsection; /* 0 <= sectionidx < maxsection. */ | 75 | int maxsection; /* 0 <= sectionidx < maxsection. */ |
@@ -86,7 +86,6 @@ void dasm_init(Dst_DECL, int maxsection) | |||
86 | { | 86 | { |
87 | dasm_State *D; | 87 | dasm_State *D; |
88 | size_t psz = 0; | 88 | size_t psz = 0; |
89 | int i; | ||
90 | Dst_REF = NULL; | 89 | Dst_REF = NULL; |
91 | DASM_M_GROW(Dst, struct dasm_State, Dst_REF, psz, DASM_PSZ(maxsection)); | 90 | DASM_M_GROW(Dst, struct dasm_State, Dst_REF, psz, DASM_PSZ(maxsection)); |
92 | D = Dst_REF; | 91 | D = Dst_REF; |
@@ -97,12 +96,7 @@ void dasm_init(Dst_DECL, int maxsection) | |||
97 | D->pcsize = 0; | 96 | D->pcsize = 0; |
98 | D->globals = NULL; | 97 | D->globals = NULL; |
99 | D->maxsection = maxsection; | 98 | D->maxsection = maxsection; |
100 | for (i = 0; i < maxsection; i++) { | 99 | memset((void *)D->sections, 0, maxsection * sizeof(dasm_Section)); |
101 | D->sections[i].buf = NULL; /* Need this for pass3. */ | ||
102 | D->sections[i].rbuf = D->sections[i].buf - DASM_SEC2POS(i); | ||
103 | D->sections[i].bsize = 0; | ||
104 | D->sections[i].epos = 0; /* Wrong, but is recalculated after resize. */ | ||
105 | } | ||
106 | } | 100 | } |
107 | 101 | ||
108 | /* Free DynASM state. */ | 102 | /* Free DynASM state. */ |
@@ -122,7 +116,7 @@ void dasm_free(Dst_DECL) | |||
122 | void dasm_setupglobal(Dst_DECL, void **gl, unsigned int maxgl) | 116 | void dasm_setupglobal(Dst_DECL, void **gl, unsigned int maxgl) |
123 | { | 117 | { |
124 | dasm_State *D = Dst_REF; | 118 | dasm_State *D = Dst_REF; |
125 | D->globals = gl - 10; /* Negative bias to compensate for locals. */ | 119 | D->globals = gl; |
126 | DASM_M_GROW(Dst, int, D->lglabels, D->lgsize, (10+maxgl)*sizeof(int)); | 120 | DASM_M_GROW(Dst, int, D->lglabels, D->lgsize, (10+maxgl)*sizeof(int)); |
127 | } | 121 | } |
128 | 122 | ||
@@ -147,6 +141,7 @@ void dasm_setup(Dst_DECL, const void *actionlist) | |||
147 | if (D->pclabels) memset((void *)D->pclabels, 0, D->pcsize); | 141 | if (D->pclabels) memset((void *)D->pclabels, 0, D->pcsize); |
148 | for (i = 0; i < D->maxsection; i++) { | 142 | for (i = 0; i < D->maxsection; i++) { |
149 | D->sections[i].pos = DASM_SEC2POS(i); | 143 | D->sections[i].pos = DASM_SEC2POS(i); |
144 | D->sections[i].rbuf = D->sections[i].buf - D->sections[i].pos; | ||
150 | D->sections[i].ofs = 0; | 145 | D->sections[i].ofs = 0; |
151 | } | 146 | } |
152 | } | 147 | } |
@@ -155,10 +150,10 @@ void dasm_setup(Dst_DECL, const void *actionlist) | |||
155 | #ifdef DASM_CHECKS | 150 | #ifdef DASM_CHECKS |
156 | #define CK(x, st) \ | 151 | #define CK(x, st) \ |
157 | do { if (!(x)) { \ | 152 | do { if (!(x)) { \ |
158 | D->status = DASM_S_##st|(p-D->actionlist-1); return; } } while (0) | 153 | D->status = DASM_S_##st|(int)(p-D->actionlist-1); return; } } while (0) |
159 | #define CKPL(kind, st) \ | 154 | #define CKPL(kind, st) \ |
160 | do { if ((size_t)((char *)pl-(char *)D->kind##labels) >= D->kind##size) { \ | 155 | do { if ((size_t)((char *)pl-(char *)D->kind##labels) >= D->kind##size) { \ |
161 | D->status = DASM_S_RANGE_##st|(p-D->actionlist-1); return; } } while (0) | 156 | D->status = DASM_S_RANGE_##st|(int)(p-D->actionlist-1); return; } } while (0) |
162 | #else | 157 | #else |
163 | #define CK(x, st) ((void)0) | 158 | #define CK(x, st) ((void)0) |
164 | #define CKPL(kind, st) ((void)0) | 159 | #define CKPL(kind, st) ((void)0) |
@@ -231,7 +226,7 @@ void dasm_put(Dst_DECL, int start, ...) | |||
231 | *pl = -pos; /* Label exists now. */ | 226 | *pl = -pos; /* Label exists now. */ |
232 | b[pos++] = ofs; /* Store pass1 offset estimate. */ | 227 | b[pos++] = ofs; /* Store pass1 offset estimate. */ |
233 | break; | 228 | break; |
234 | case DASM_IMM: | 229 | case DASM_IMM: case DASM_IMMS: |
235 | #ifdef DASM_CHECKS | 230 | #ifdef DASM_CHECKS |
236 | CK((n & ((1<<((ins>>10)&31))-1)) == 0, RANGE_I); | 231 | CK((n & ((1<<((ins>>10)&31))-1)) == 0, RANGE_I); |
237 | #endif | 232 | #endif |
@@ -273,7 +268,7 @@ int dasm_link(Dst_DECL, size_t *szp) | |||
273 | 268 | ||
274 | { /* Handle globals not defined in this translation unit. */ | 269 | { /* Handle globals not defined in this translation unit. */ |
275 | int idx; | 270 | int idx; |
276 | for (idx = 20; idx*sizeof(int) < D->lgsize; idx++) { | 271 | for (idx = 10; idx*sizeof(int) < D->lgsize; idx++) { |
277 | int n = D->lglabels[idx]; | 272 | int n = D->lglabels[idx]; |
278 | /* Undefined label: Collapse rel chain and replace with marker (< 0). */ | 273 | /* Undefined label: Collapse rel chain and replace with marker (< 0). */ |
279 | while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = -idx; } | 274 | while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = -idx; } |
@@ -299,7 +294,7 @@ int dasm_link(Dst_DECL, size_t *szp) | |||
299 | case DASM_ALIGN: ofs -= (b[pos++] + ofs) & (ins & 255); break; | 294 | case DASM_ALIGN: ofs -= (b[pos++] + ofs) & (ins & 255); break; |
300 | case DASM_REL_LG: case DASM_REL_PC: pos++; break; | 295 | case DASM_REL_LG: case DASM_REL_PC: pos++; break; |
301 | case DASM_LABEL_LG: case DASM_LABEL_PC: b[pos++] += ofs; break; | 296 | case DASM_LABEL_LG: case DASM_LABEL_PC: b[pos++] += ofs; break; |
302 | case DASM_IMM: pos++; break; | 297 | case DASM_IMM: case DASM_IMMS: pos++; break; |
303 | } | 298 | } |
304 | } | 299 | } |
305 | stop: (void)0; | 300 | stop: (void)0; |
@@ -314,7 +309,7 @@ int dasm_link(Dst_DECL, size_t *szp) | |||
314 | 309 | ||
315 | #ifdef DASM_CHECKS | 310 | #ifdef DASM_CHECKS |
316 | #define CK(x, st) \ | 311 | #define CK(x, st) \ |
317 | do { if (!(x)) return DASM_S_##st|(p-D->actionlist-1); } while (0) | 312 | do { if (!(x)) return DASM_S_##st|(int)(p-D->actionlist-1); } while (0) |
318 | #else | 313 | #else |
319 | #define CK(x, st) ((void)0) | 314 | #define CK(x, st) ((void)0) |
320 | #endif | 315 | #endif |
@@ -349,25 +344,32 @@ int dasm_encode(Dst_DECL, void *buffer) | |||
349 | ins &= 255; while ((((char *)cp - base) & ins)) *cp++ = 0x60000000; | 344 | ins &= 255; while ((((char *)cp - base) & ins)) *cp++ = 0x60000000; |
350 | break; | 345 | break; |
351 | case DASM_REL_LG: | 346 | case DASM_REL_LG: |
352 | CK(n >= 0, UNDEF_LG); | 347 | if (n < 0) { |
348 | n = (int)((ptrdiff_t)D->globals[-n-10] - (ptrdiff_t)cp); | ||
349 | goto patchrel; | ||
350 | } | ||
353 | /* fallthrough */ | 351 | /* fallthrough */ |
354 | case DASM_REL_PC: | 352 | case DASM_REL_PC: |
355 | CK(n >= 0, UNDEF_PC); | 353 | CK(n >= 0, UNDEF_PC); |
356 | n = *DASM_POS2PTR(D, n); | 354 | n = *DASM_POS2PTR(D, n); |
357 | if (ins & 2048) | 355 | if (ins & 2048) |
358 | n = n - (int)((char *)cp - base); | 356 | n = (n + (int)(size_t)base) & 0x0fffffff; |
359 | else | 357 | else |
360 | n = (n + (int)base) & 0x0fffffff; | 358 | n = n - (int)((char *)cp - base); |
361 | patchrel: | 359 | patchrel: { |
360 | unsigned int e = 16 + ((ins >> 12) & 15); | ||
362 | CK((n & 3) == 0 && | 361 | CK((n & 3) == 0 && |
363 | ((n + ((ins & 2048) ? 0x00020000 : 0)) >> | 362 | ((n + ((ins & 2048) ? 0 : (1<<(e+1)))) >> (e+2)) == 0, RANGE_REL); |
364 | ((ins & 2048) ? 18 : 28)) == 0, RANGE_REL); | 363 | cp[-1] |= ((n>>2) & ((1<<e)-1)); |
365 | cp[-1] |= ((n>>2) & ((ins & 2048) ? 0x0000ffff: 0x03ffffff)); | 364 | } |
366 | break; | 365 | break; |
367 | case DASM_LABEL_LG: | 366 | case DASM_LABEL_LG: |
368 | ins &= 2047; if (ins >= 20) D->globals[ins-10] = (void *)(base + n); | 367 | ins &= 2047; if (ins >= 20) D->globals[ins-20] = (void *)(base + n); |
369 | break; | 368 | break; |
370 | case DASM_LABEL_PC: break; | 369 | case DASM_LABEL_PC: break; |
370 | case DASM_IMMS: | ||
371 | cp[-1] |= ((n>>3) & 4); n &= 0x1f; | ||
372 | /* fallthrough */ | ||
371 | case DASM_IMM: | 373 | case DASM_IMM: |
372 | cp[-1] |= (n & ((1<<((ins>>5)&31))-1)) << (ins&31); | 374 | cp[-1] |= (n & ((1<<((ins>>5)&31))-1)) << (ins&31); |
373 | break; | 375 | break; |
@@ -410,7 +412,7 @@ int dasm_checkstep(Dst_DECL, int secmatch) | |||
410 | } | 412 | } |
411 | if (D->status == DASM_S_OK && secmatch >= 0 && | 413 | if (D->status == DASM_S_OK && secmatch >= 0 && |
412 | D->section != &D->sections[secmatch]) | 414 | D->section != &D->sections[secmatch]) |
413 | D->status = DASM_S_MATCH_SEC|(D->section-D->sections); | 415 | D->status = DASM_S_MATCH_SEC|(int)(D->section-D->sections); |
414 | return D->status; | 416 | return D->status; |
415 | } | 417 | } |
416 | #endif | 418 | #endif |