diff options
Diffstat (limited to 'dynasm/dasm_ppc.h')
-rw-r--r-- | dynasm/dasm_ppc.h | 35 |
1 files changed, 20 insertions, 15 deletions
diff --git a/dynasm/dasm_ppc.h b/dynasm/dasm_ppc.h index e2d6f1fc..4c7d7289 100644 --- a/dynasm/dasm_ppc.h +++ b/dynasm/dasm_ppc.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** DynASM PPC encoding engine. | 2 | ** DynASM PPC/PPC64 encoding engine. |
3 | ** Copyright (C) 2005-2023 Mike Pall. All rights reserved. | 3 | ** Copyright (C) 2005-2023 Mike Pall. All rights reserved. |
4 | ** Released under the MIT license. See dynasm.lua for full copyright notice. | 4 | ** Released under the MIT license. See dynasm.lua for full copyright notice. |
5 | */ | 5 | */ |
@@ -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_IMMSH, |
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 | } |
@@ -244,6 +239,10 @@ void dasm_put(Dst_DECL, int start, ...) | |||
244 | #endif | 239 | #endif |
245 | b[pos++] = n; | 240 | b[pos++] = n; |
246 | break; | 241 | break; |
242 | case DASM_IMMSH: | ||
243 | CK((n >> 6) == 0, RANGE_I); | ||
244 | b[pos++] = n; | ||
245 | break; | ||
247 | } | 246 | } |
248 | } | 247 | } |
249 | } | 248 | } |
@@ -273,7 +272,7 @@ int dasm_link(Dst_DECL, size_t *szp) | |||
273 | 272 | ||
274 | { /* Handle globals not defined in this translation unit. */ | 273 | { /* Handle globals not defined in this translation unit. */ |
275 | int idx; | 274 | int idx; |
276 | for (idx = 20; idx*sizeof(int) < D->lgsize; idx++) { | 275 | for (idx = 10; idx*sizeof(int) < D->lgsize; idx++) { |
277 | int n = D->lglabels[idx]; | 276 | int n = D->lglabels[idx]; |
278 | /* Undefined label: Collapse rel chain and replace with marker (< 0). */ | 277 | /* Undefined label: Collapse rel chain and replace with marker (< 0). */ |
279 | while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = -idx; } | 278 | while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = -idx; } |
@@ -299,7 +298,7 @@ int dasm_link(Dst_DECL, size_t *szp) | |||
299 | case DASM_ALIGN: ofs -= (b[pos++] + ofs) & (ins & 255); break; | 298 | case DASM_ALIGN: ofs -= (b[pos++] + ofs) & (ins & 255); break; |
300 | case DASM_REL_LG: case DASM_REL_PC: pos++; break; | 299 | case DASM_REL_LG: case DASM_REL_PC: pos++; break; |
301 | case DASM_LABEL_LG: case DASM_LABEL_PC: b[pos++] += ofs; break; | 300 | case DASM_LABEL_LG: case DASM_LABEL_PC: b[pos++] += ofs; break; |
302 | case DASM_IMM: pos++; break; | 301 | case DASM_IMM: case DASM_IMMSH: pos++; break; |
303 | } | 302 | } |
304 | } | 303 | } |
305 | stop: (void)0; | 304 | stop: (void)0; |
@@ -349,7 +348,10 @@ int dasm_encode(Dst_DECL, void *buffer) | |||
349 | ins &= 255; while ((((char *)cp - base) & ins)) *cp++ = 0x60000000; | 348 | ins &= 255; while ((((char *)cp - base) & ins)) *cp++ = 0x60000000; |
350 | break; | 349 | break; |
351 | case DASM_REL_LG: | 350 | case DASM_REL_LG: |
352 | CK(n >= 0, UNDEF_LG); | 351 | if (n < 0) { |
352 | n = (int)((ptrdiff_t)D->globals[-n-10] - (ptrdiff_t)cp); | ||
353 | goto patchrel; | ||
354 | } | ||
353 | /* fallthrough */ | 355 | /* fallthrough */ |
354 | case DASM_REL_PC: | 356 | case DASM_REL_PC: |
355 | CK(n >= 0, UNDEF_PC); | 357 | CK(n >= 0, UNDEF_PC); |
@@ -361,12 +363,15 @@ int dasm_encode(Dst_DECL, void *buffer) | |||
361 | cp[-1] |= ((n+4) & ((ins & 2048) ? 0x0000fffc: 0x03fffffc)); | 363 | cp[-1] |= ((n+4) & ((ins & 2048) ? 0x0000fffc: 0x03fffffc)); |
362 | break; | 364 | break; |
363 | case DASM_LABEL_LG: | 365 | case DASM_LABEL_LG: |
364 | ins &= 2047; if (ins >= 20) D->globals[ins-10] = (void *)(base + n); | 366 | ins &= 2047; if (ins >= 20) D->globals[ins-20] = (void *)(base + n); |
365 | break; | 367 | break; |
366 | case DASM_LABEL_PC: break; | 368 | case DASM_LABEL_PC: break; |
367 | case DASM_IMM: | 369 | case DASM_IMM: |
368 | cp[-1] |= (n & ((1<<((ins>>5)&31))-1)) << (ins&31); | 370 | cp[-1] |= (n & ((1<<((ins>>5)&31))-1)) << (ins&31); |
369 | break; | 371 | break; |
372 | case DASM_IMMSH: | ||
373 | cp[-1] |= (ins & 1) ? ((n&31)<<11)|((n&32)>>4) : ((n&31)<<6)|(n&32); | ||
374 | break; | ||
370 | default: *cp++ = ins; break; | 375 | default: *cp++ = ins; break; |
371 | } | 376 | } |
372 | } | 377 | } |