diff options
Diffstat (limited to 'libraries/luajit-2.0/dynasm')
-rw-r--r-- | libraries/luajit-2.0/dynasm/dasm_arm.h | 448 | ||||
-rw-r--r-- | libraries/luajit-2.0/dynasm/dasm_arm.lua | 949 | ||||
-rw-r--r-- | libraries/luajit-2.0/dynasm/dasm_mips.h | 415 | ||||
-rw-r--r-- | libraries/luajit-2.0/dynasm/dasm_mips.lua | 948 | ||||
-rw-r--r-- | libraries/luajit-2.0/dynasm/dasm_ppc.h | 411 | ||||
-rw-r--r-- | libraries/luajit-2.0/dynasm/dasm_ppc.lua | 1230 | ||||
-rw-r--r-- | libraries/luajit-2.0/dynasm/dasm_proto.h | 83 | ||||
-rw-r--r-- | libraries/luajit-2.0/dynasm/dasm_x64.lua | 12 | ||||
-rw-r--r-- | libraries/luajit-2.0/dynasm/dasm_x86.h | 470 | ||||
-rw-r--r-- | libraries/luajit-2.0/dynasm/dasm_x86.lua | 1931 | ||||
-rw-r--r-- | libraries/luajit-2.0/dynasm/dynasm.lua | 1076 |
11 files changed, 7973 insertions, 0 deletions
diff --git a/libraries/luajit-2.0/dynasm/dasm_arm.h b/libraries/luajit-2.0/dynasm/dasm_arm.h new file mode 100644 index 0000000..43d2963 --- /dev/null +++ b/libraries/luajit-2.0/dynasm/dasm_arm.h | |||
@@ -0,0 +1,448 @@ | |||
1 | /* | ||
2 | ** DynASM ARM encoding engine. | ||
3 | ** Copyright (C) 2005-2011 Mike Pall. All rights reserved. | ||
4 | ** Released under the MIT license. See dynasm.lua for full copyright notice. | ||
5 | */ | ||
6 | |||
7 | #include <stddef.h> | ||
8 | #include <stdarg.h> | ||
9 | #include <string.h> | ||
10 | #include <stdlib.h> | ||
11 | |||
12 | #define DASM_ARCH "arm" | ||
13 | |||
14 | #ifndef DASM_EXTERN | ||
15 | #define DASM_EXTERN(a,b,c,d) 0 | ||
16 | #endif | ||
17 | |||
18 | /* Action definitions. */ | ||
19 | enum { | ||
20 | DASM_STOP, DASM_SECTION, DASM_ESC, DASM_REL_EXT, | ||
21 | /* The following actions need a buffer position. */ | ||
22 | DASM_ALIGN, DASM_REL_LG, DASM_LABEL_LG, | ||
23 | /* The following actions also have an argument. */ | ||
24 | DASM_REL_PC, DASM_LABEL_PC, | ||
25 | DASM_IMM, DASM_IMM12, DASM_IMM16, DASM_IMML8, DASM_IMML12, | ||
26 | DASM__MAX | ||
27 | }; | ||
28 | |||
29 | /* Maximum number of section buffer positions for a single dasm_put() call. */ | ||
30 | #define DASM_MAXSECPOS 25 | ||
31 | |||
32 | /* DynASM encoder status codes. Action list offset or number are or'ed in. */ | ||
33 | #define DASM_S_OK 0x00000000 | ||
34 | #define DASM_S_NOMEM 0x01000000 | ||
35 | #define DASM_S_PHASE 0x02000000 | ||
36 | #define DASM_S_MATCH_SEC 0x03000000 | ||
37 | #define DASM_S_RANGE_I 0x11000000 | ||
38 | #define DASM_S_RANGE_SEC 0x12000000 | ||
39 | #define DASM_S_RANGE_LG 0x13000000 | ||
40 | #define DASM_S_RANGE_PC 0x14000000 | ||
41 | #define DASM_S_RANGE_REL 0x15000000 | ||
42 | #define DASM_S_UNDEF_LG 0x21000000 | ||
43 | #define DASM_S_UNDEF_PC 0x22000000 | ||
44 | |||
45 | /* Macros to convert positions (8 bit section + 24 bit index). */ | ||
46 | #define DASM_POS2IDX(pos) ((pos)&0x00ffffff) | ||
47 | #define DASM_POS2BIAS(pos) ((pos)&0xff000000) | ||
48 | #define DASM_SEC2POS(sec) ((sec)<<24) | ||
49 | #define DASM_POS2SEC(pos) ((pos)>>24) | ||
50 | #define DASM_POS2PTR(D, pos) (D->sections[DASM_POS2SEC(pos)].rbuf + (pos)) | ||
51 | |||
52 | /* Action list type. */ | ||
53 | typedef const unsigned int *dasm_ActList; | ||
54 | |||
55 | /* Per-section structure. */ | ||
56 | typedef struct dasm_Section { | ||
57 | int *rbuf; /* Biased buffer pointer (negative section bias). */ | ||
58 | int *buf; /* True buffer pointer. */ | ||
59 | size_t bsize; /* Buffer size in bytes. */ | ||
60 | int pos; /* Biased buffer position. */ | ||
61 | int epos; /* End of biased buffer position - max single put. */ | ||
62 | int ofs; /* Byte offset into section. */ | ||
63 | } dasm_Section; | ||
64 | |||
65 | /* Core structure holding the DynASM encoding state. */ | ||
66 | struct dasm_State { | ||
67 | size_t psize; /* Allocated size of this structure. */ | ||
68 | dasm_ActList actionlist; /* Current actionlist pointer. */ | ||
69 | int *lglabels; /* Local/global chain/pos ptrs. */ | ||
70 | size_t lgsize; | ||
71 | int *pclabels; /* PC label chains/pos ptrs. */ | ||
72 | size_t pcsize; | ||
73 | void **globals; /* Array of globals (bias -10). */ | ||
74 | dasm_Section *section; /* Pointer to active section. */ | ||
75 | size_t codesize; /* Total size of all code sections. */ | ||
76 | int maxsection; /* 0 <= sectionidx < maxsection. */ | ||
77 | int status; /* Status code. */ | ||
78 | dasm_Section sections[1]; /* All sections. Alloc-extended. */ | ||
79 | }; | ||
80 | |||
81 | /* The size of the core structure depends on the max. number of sections. */ | ||
82 | #define DASM_PSZ(ms) (sizeof(dasm_State)+(ms-1)*sizeof(dasm_Section)) | ||
83 | |||
84 | |||
85 | /* Initialize DynASM state. */ | ||
86 | void dasm_init(Dst_DECL, int maxsection) | ||
87 | { | ||
88 | dasm_State *D; | ||
89 | size_t psz = 0; | ||
90 | int i; | ||
91 | Dst_REF = NULL; | ||
92 | DASM_M_GROW(Dst, struct dasm_State, Dst_REF, psz, DASM_PSZ(maxsection)); | ||
93 | D = Dst_REF; | ||
94 | D->psize = psz; | ||
95 | D->lglabels = NULL; | ||
96 | D->lgsize = 0; | ||
97 | D->pclabels = NULL; | ||
98 | D->pcsize = 0; | ||
99 | D->globals = NULL; | ||
100 | D->maxsection = maxsection; | ||
101 | for (i = 0; i < maxsection; i++) { | ||
102 | D->sections[i].buf = NULL; /* Need this for pass3. */ | ||
103 | D->sections[i].rbuf = D->sections[i].buf - DASM_SEC2POS(i); | ||
104 | D->sections[i].bsize = 0; | ||
105 | D->sections[i].epos = 0; /* Wrong, but is recalculated after resize. */ | ||
106 | } | ||
107 | } | ||
108 | |||
109 | /* Free DynASM state. */ | ||
110 | void dasm_free(Dst_DECL) | ||
111 | { | ||
112 | dasm_State *D = Dst_REF; | ||
113 | int i; | ||
114 | for (i = 0; i < D->maxsection; i++) | ||
115 | if (D->sections[i].buf) | ||
116 | DASM_M_FREE(Dst, D->sections[i].buf, D->sections[i].bsize); | ||
117 | if (D->pclabels) DASM_M_FREE(Dst, D->pclabels, D->pcsize); | ||
118 | if (D->lglabels) DASM_M_FREE(Dst, D->lglabels, D->lgsize); | ||
119 | DASM_M_FREE(Dst, D, D->psize); | ||
120 | } | ||
121 | |||
122 | /* Setup global label array. Must be called before dasm_setup(). */ | ||
123 | void dasm_setupglobal(Dst_DECL, void **gl, unsigned int maxgl) | ||
124 | { | ||
125 | dasm_State *D = Dst_REF; | ||
126 | D->globals = gl - 10; /* Negative bias to compensate for locals. */ | ||
127 | DASM_M_GROW(Dst, int, D->lglabels, D->lgsize, (10+maxgl)*sizeof(int)); | ||
128 | } | ||
129 | |||
130 | /* Grow PC label array. Can be called after dasm_setup(), too. */ | ||
131 | void dasm_growpc(Dst_DECL, unsigned int maxpc) | ||
132 | { | ||
133 | dasm_State *D = Dst_REF; | ||
134 | size_t osz = D->pcsize; | ||
135 | DASM_M_GROW(Dst, int, D->pclabels, D->pcsize, maxpc*sizeof(int)); | ||
136 | memset((void *)(((unsigned char *)D->pclabels)+osz), 0, D->pcsize-osz); | ||
137 | } | ||
138 | |||
139 | /* Setup encoder. */ | ||
140 | void dasm_setup(Dst_DECL, const void *actionlist) | ||
141 | { | ||
142 | dasm_State *D = Dst_REF; | ||
143 | int i; | ||
144 | D->actionlist = (dasm_ActList)actionlist; | ||
145 | D->status = DASM_S_OK; | ||
146 | D->section = &D->sections[0]; | ||
147 | memset((void *)D->lglabels, 0, D->lgsize); | ||
148 | if (D->pclabels) memset((void *)D->pclabels, 0, D->pcsize); | ||
149 | for (i = 0; i < D->maxsection; i++) { | ||
150 | D->sections[i].pos = DASM_SEC2POS(i); | ||
151 | D->sections[i].ofs = 0; | ||
152 | } | ||
153 | } | ||
154 | |||
155 | |||
156 | #ifdef DASM_CHECKS | ||
157 | #define CK(x, st) \ | ||
158 | do { if (!(x)) { \ | ||
159 | D->status = DASM_S_##st|(p-D->actionlist-1); return; } } while (0) | ||
160 | #define CKPL(kind, st) \ | ||
161 | do { if ((size_t)((char *)pl-(char *)D->kind##labels) >= D->kind##size) { \ | ||
162 | D->status = DASM_S_RANGE_##st|(p-D->actionlist-1); return; } } while (0) | ||
163 | #else | ||
164 | #define CK(x, st) ((void)0) | ||
165 | #define CKPL(kind, st) ((void)0) | ||
166 | #endif | ||
167 | |||
168 | static int dasm_imm12(unsigned int n) | ||
169 | { | ||
170 | int i; | ||
171 | for (i = 0; i < 16; i++, n = (n << 2) | (n >> 30)) | ||
172 | if (n <= 255) return (int)(n + (i << 8)); | ||
173 | return -1; | ||
174 | } | ||
175 | |||
176 | /* Pass 1: Store actions and args, link branches/labels, estimate offsets. */ | ||
177 | void dasm_put(Dst_DECL, int start, ...) | ||
178 | { | ||
179 | va_list ap; | ||
180 | dasm_State *D = Dst_REF; | ||
181 | dasm_ActList p = D->actionlist + start; | ||
182 | dasm_Section *sec = D->section; | ||
183 | int pos = sec->pos, ofs = sec->ofs; | ||
184 | int *b; | ||
185 | |||
186 | if (pos >= sec->epos) { | ||
187 | DASM_M_GROW(Dst, int, sec->buf, sec->bsize, | ||
188 | sec->bsize + 2*DASM_MAXSECPOS*sizeof(int)); | ||
189 | sec->rbuf = sec->buf - DASM_POS2BIAS(pos); | ||
190 | sec->epos = (int)sec->bsize/sizeof(int) - DASM_MAXSECPOS+DASM_POS2BIAS(pos); | ||
191 | } | ||
192 | |||
193 | b = sec->rbuf; | ||
194 | b[pos++] = start; | ||
195 | |||
196 | va_start(ap, start); | ||
197 | while (1) { | ||
198 | unsigned int ins = *p++; | ||
199 | unsigned int action = (ins >> 16); | ||
200 | if (action >= DASM__MAX) { | ||
201 | ofs += 4; | ||
202 | } else { | ||
203 | int *pl, n = action >= DASM_REL_PC ? va_arg(ap, int) : 0; | ||
204 | switch (action) { | ||
205 | case DASM_STOP: goto stop; | ||
206 | case DASM_SECTION: | ||
207 | n = (ins & 255); CK(n < D->maxsection, RANGE_SEC); | ||
208 | D->section = &D->sections[n]; goto stop; | ||
209 | case DASM_ESC: p++; ofs += 4; break; | ||
210 | case DASM_REL_EXT: break; | ||
211 | case DASM_ALIGN: ofs += (ins & 255); b[pos++] = ofs; break; | ||
212 | case DASM_REL_LG: | ||
213 | n = (ins & 2047) - 10; pl = D->lglabels + n; | ||
214 | if (n >= 0) { CKPL(lg, LG); goto putrel; } /* Bkwd rel or global. */ | ||
215 | pl += 10; n = *pl; | ||
216 | if (n < 0) n = 0; /* Start new chain for fwd rel if label exists. */ | ||
217 | goto linkrel; | ||
218 | case DASM_REL_PC: | ||
219 | pl = D->pclabels + n; CKPL(pc, PC); | ||
220 | putrel: | ||
221 | n = *pl; | ||
222 | if (n < 0) { /* Label exists. Get label pos and store it. */ | ||
223 | b[pos] = -n; | ||
224 | } else { | ||
225 | linkrel: | ||
226 | b[pos] = n; /* Else link to rel chain, anchored at label. */ | ||
227 | *pl = pos; | ||
228 | } | ||
229 | pos++; | ||
230 | break; | ||
231 | case DASM_LABEL_LG: | ||
232 | pl = D->lglabels + (ins & 2047) - 10; CKPL(lg, LG); goto putlabel; | ||
233 | case DASM_LABEL_PC: | ||
234 | pl = D->pclabels + n; CKPL(pc, PC); | ||
235 | putlabel: | ||
236 | n = *pl; /* n > 0: Collapse rel chain and replace with label pos. */ | ||
237 | while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = pos; | ||
238 | } | ||
239 | *pl = -pos; /* Label exists now. */ | ||
240 | b[pos++] = ofs; /* Store pass1 offset estimate. */ | ||
241 | break; | ||
242 | case DASM_IMM: | ||
243 | case DASM_IMM16: | ||
244 | #ifdef DASM_CHECKS | ||
245 | CK((n & ((1<<((ins>>10)&31))-1)) == 0, RANGE_I); | ||
246 | if ((ins & 0x8000)) | ||
247 | CK(((n + (1<<(((ins>>5)&31)-1)))>>((ins>>5)&31)) == 0, RANGE_I); | ||
248 | else | ||
249 | CK((n>>((ins>>5)&31)) == 0, RANGE_I); | ||
250 | #endif | ||
251 | b[pos++] = n; | ||
252 | break; | ||
253 | case DASM_IMML8: | ||
254 | case DASM_IMML12: | ||
255 | CK(n >= 0 ? ((n>>((ins>>5)&31)) == 0) : | ||
256 | (((-n)>>((ins>>5)&31)) == 0), RANGE_I); | ||
257 | b[pos++] = n; | ||
258 | break; | ||
259 | case DASM_IMM12: | ||
260 | CK(dasm_imm12((unsigned int)n) != -1, RANGE_I); | ||
261 | b[pos++] = n; | ||
262 | break; | ||
263 | } | ||
264 | } | ||
265 | } | ||
266 | stop: | ||
267 | va_end(ap); | ||
268 | sec->pos = pos; | ||
269 | sec->ofs = ofs; | ||
270 | } | ||
271 | #undef CK | ||
272 | |||
273 | /* Pass 2: Link sections, shrink aligns, fix label offsets. */ | ||
274 | int dasm_link(Dst_DECL, size_t *szp) | ||
275 | { | ||
276 | dasm_State *D = Dst_REF; | ||
277 | int secnum; | ||
278 | int ofs = 0; | ||
279 | |||
280 | #ifdef DASM_CHECKS | ||
281 | *szp = 0; | ||
282 | if (D->status != DASM_S_OK) return D->status; | ||
283 | { | ||
284 | int pc; | ||
285 | for (pc = 0; pc*sizeof(int) < D->pcsize; pc++) | ||
286 | if (D->pclabels[pc] > 0) return DASM_S_UNDEF_PC|pc; | ||
287 | } | ||
288 | #endif | ||
289 | |||
290 | { /* Handle globals not defined in this translation unit. */ | ||
291 | int idx; | ||
292 | for (idx = 20; idx*sizeof(int) < D->lgsize; idx++) { | ||
293 | int n = D->lglabels[idx]; | ||
294 | /* Undefined label: Collapse rel chain and replace with marker (< 0). */ | ||
295 | while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = -idx; } | ||
296 | } | ||
297 | } | ||
298 | |||
299 | /* Combine all code sections. No support for data sections (yet). */ | ||
300 | for (secnum = 0; secnum < D->maxsection; secnum++) { | ||
301 | dasm_Section *sec = D->sections + secnum; | ||
302 | int *b = sec->rbuf; | ||
303 | int pos = DASM_SEC2POS(secnum); | ||
304 | int lastpos = sec->pos; | ||
305 | |||
306 | while (pos != lastpos) { | ||
307 | dasm_ActList p = D->actionlist + b[pos++]; | ||
308 | while (1) { | ||
309 | unsigned int ins = *p++; | ||
310 | unsigned int action = (ins >> 16); | ||
311 | switch (action) { | ||
312 | case DASM_STOP: case DASM_SECTION: goto stop; | ||
313 | case DASM_ESC: p++; break; | ||
314 | case DASM_REL_EXT: break; | ||
315 | case DASM_ALIGN: ofs -= (b[pos++] + ofs) & (ins & 255); break; | ||
316 | case DASM_REL_LG: case DASM_REL_PC: pos++; break; | ||
317 | case DASM_LABEL_LG: case DASM_LABEL_PC: b[pos++] += ofs; break; | ||
318 | case DASM_IMM: case DASM_IMM12: case DASM_IMM16: | ||
319 | case DASM_IMML8: case DASM_IMML12: pos++; break; | ||
320 | } | ||
321 | } | ||
322 | stop: (void)0; | ||
323 | } | ||
324 | ofs += sec->ofs; /* Next section starts right after current section. */ | ||
325 | } | ||
326 | |||
327 | D->codesize = ofs; /* Total size of all code sections */ | ||
328 | *szp = ofs; | ||
329 | return DASM_S_OK; | ||
330 | } | ||
331 | |||
332 | #ifdef DASM_CHECKS | ||
333 | #define CK(x, st) \ | ||
334 | do { if (!(x)) return DASM_S_##st|(p-D->actionlist-1); } while (0) | ||
335 | #else | ||
336 | #define CK(x, st) ((void)0) | ||
337 | #endif | ||
338 | |||
339 | /* Pass 3: Encode sections. */ | ||
340 | int dasm_encode(Dst_DECL, void *buffer) | ||
341 | { | ||
342 | dasm_State *D = Dst_REF; | ||
343 | char *base = (char *)buffer; | ||
344 | unsigned int *cp = (unsigned int *)buffer; | ||
345 | int secnum; | ||
346 | |||
347 | /* Encode all code sections. No support for data sections (yet). */ | ||
348 | for (secnum = 0; secnum < D->maxsection; secnum++) { | ||
349 | dasm_Section *sec = D->sections + secnum; | ||
350 | int *b = sec->buf; | ||
351 | int *endb = sec->rbuf + sec->pos; | ||
352 | |||
353 | while (b != endb) { | ||
354 | dasm_ActList p = D->actionlist + *b++; | ||
355 | while (1) { | ||
356 | unsigned int ins = *p++; | ||
357 | unsigned int action = (ins >> 16); | ||
358 | int n = (action >= DASM_ALIGN && action < DASM__MAX) ? *b++ : 0; | ||
359 | switch (action) { | ||
360 | case DASM_STOP: case DASM_SECTION: goto stop; | ||
361 | case DASM_ESC: *cp++ = *p++; break; | ||
362 | case DASM_REL_EXT: | ||
363 | n = DASM_EXTERN(Dst, (unsigned char *)cp, (ins&2047), !(ins&2048)); | ||
364 | goto patchrel; | ||
365 | case DASM_ALIGN: | ||
366 | ins &= 255; while ((((char *)cp - base) & ins)) *cp++ = 0xe1a00000; | ||
367 | break; | ||
368 | case DASM_REL_LG: | ||
369 | CK(n >= 0, UNDEF_LG); | ||
370 | case DASM_REL_PC: | ||
371 | CK(n >= 0, UNDEF_PC); | ||
372 | n = *DASM_POS2PTR(D, n) - (int)((char *)cp - base) - 4; | ||
373 | patchrel: | ||
374 | if ((ins & 0x800) == 0) { | ||
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 | } | ||
384 | break; | ||
385 | case DASM_LABEL_LG: | ||
386 | ins &= 2047; if (ins >= 20) D->globals[ins-10] = (void *)(base + n); | ||
387 | break; | ||
388 | case DASM_LABEL_PC: break; | ||
389 | case DASM_IMM: | ||
390 | cp[-1] |= ((n>>((ins>>10)&31)) & ((1<<((ins>>5)&31))-1)) << (ins&31); | ||
391 | break; | ||
392 | case DASM_IMM12: | ||
393 | cp[-1] |= dasm_imm12((unsigned int)n); | ||
394 | break; | ||
395 | case DASM_IMM16: | ||
396 | cp[-1] |= ((n & 0xf000) << 4) | (n & 0x0fff); | ||
397 | break; | ||
398 | case DASM_IMML8: patchimml8: | ||
399 | cp[-1] |= n >= 0 ? (0x00800000 | (n & 0x0f) | ((n & 0xf0) << 4)) : | ||
400 | ((-n & 0x0f) | ((-n & 0xf0) << 4)); | ||
401 | break; | ||
402 | case DASM_IMML12: patchimml12: | ||
403 | cp[-1] |= n >= 0 ? (0x00800000 | n) : (-n); | ||
404 | break; | ||
405 | default: *cp++ = ins; break; | ||
406 | } | ||
407 | } | ||
408 | stop: (void)0; | ||
409 | } | ||
410 | } | ||
411 | |||
412 | if (base + D->codesize != (char *)cp) /* Check for phase errors. */ | ||
413 | return DASM_S_PHASE; | ||
414 | return DASM_S_OK; | ||
415 | } | ||
416 | #undef CK | ||
417 | |||
418 | /* Get PC label offset. */ | ||
419 | int dasm_getpclabel(Dst_DECL, unsigned int pc) | ||
420 | { | ||
421 | dasm_State *D = Dst_REF; | ||
422 | if (pc*sizeof(int) < D->pcsize) { | ||
423 | int pos = D->pclabels[pc]; | ||
424 | if (pos < 0) return *DASM_POS2PTR(D, -pos); | ||
425 | if (pos > 0) return -1; /* Undefined. */ | ||
426 | } | ||
427 | return -2; /* Unused or out of range. */ | ||
428 | } | ||
429 | |||
430 | #ifdef DASM_CHECKS | ||
431 | /* Optional sanity checker to call between isolated encoding steps. */ | ||
432 | int dasm_checkstep(Dst_DECL, int secmatch) | ||
433 | { | ||
434 | dasm_State *D = Dst_REF; | ||
435 | if (D->status == DASM_S_OK) { | ||
436 | int i; | ||
437 | for (i = 1; i <= 9; i++) { | ||
438 | if (D->lglabels[i] > 0) { D->status = DASM_S_UNDEF_LG|i; break; } | ||
439 | D->lglabels[i] = 0; | ||
440 | } | ||
441 | } | ||
442 | if (D->status == DASM_S_OK && secmatch >= 0 && | ||
443 | D->section != &D->sections[secmatch]) | ||
444 | D->status = DASM_S_MATCH_SEC|(D->section-D->sections); | ||
445 | return D->status; | ||
446 | } | ||
447 | #endif | ||
448 | |||
diff --git a/libraries/luajit-2.0/dynasm/dasm_arm.lua b/libraries/luajit-2.0/dynasm/dasm_arm.lua new file mode 100644 index 0000000..b8a595b --- /dev/null +++ b/libraries/luajit-2.0/dynasm/dasm_arm.lua | |||
@@ -0,0 +1,949 @@ | |||
1 | ------------------------------------------------------------------------------ | ||
2 | -- DynASM ARM module. | ||
3 | -- | ||
4 | -- Copyright (C) 2005-2011 Mike Pall. All rights reserved. | ||
5 | -- See dynasm.lua for full copyright notice. | ||
6 | ------------------------------------------------------------------------------ | ||
7 | |||
8 | -- Module information: | ||
9 | local _info = { | ||
10 | arch = "arm", | ||
11 | description = "DynASM ARM module", | ||
12 | version = "1.3.0", | ||
13 | vernum = 10300, | ||
14 | release = "2011-05-05", | ||
15 | author = "Mike Pall", | ||
16 | license = "MIT", | ||
17 | } | ||
18 | |||
19 | -- Exported glue functions for the arch-specific module. | ||
20 | local _M = { _info = _info } | ||
21 | |||
22 | -- Cache library functions. | ||
23 | local type, tonumber, pairs, ipairs = type, tonumber, pairs, ipairs | ||
24 | local assert, setmetatable, rawget = assert, setmetatable, rawget | ||
25 | local _s = string | ||
26 | local sub, format, byte, char = _s.sub, _s.format, _s.byte, _s.char | ||
27 | local match, gmatch, gsub = _s.match, _s.gmatch, _s.gsub | ||
28 | local concat, sort, insert = table.concat, table.sort, table.insert | ||
29 | |||
30 | -- Inherited tables and callbacks. | ||
31 | local g_opt, g_arch | ||
32 | local wline, werror, wfatal, wwarn | ||
33 | |||
34 | -- Action name list. | ||
35 | -- CHECK: Keep this in sync with the C code! | ||
36 | local action_names = { | ||
37 | "STOP", "SECTION", "ESC", "REL_EXT", | ||
38 | "ALIGN", "REL_LG", "LABEL_LG", | ||
39 | "REL_PC", "LABEL_PC", "IMM", "IMM12", "IMM16", "IMML8", "IMML12", | ||
40 | } | ||
41 | |||
42 | -- Maximum number of section buffer positions for dasm_put(). | ||
43 | -- CHECK: Keep this in sync with the C code! | ||
44 | local maxsecpos = 25 -- Keep this low, to avoid excessively long C lines. | ||
45 | |||
46 | -- Action name -> action number. | ||
47 | local map_action = {} | ||
48 | for n,name in ipairs(action_names) do | ||
49 | map_action[name] = n-1 | ||
50 | end | ||
51 | |||
52 | -- Action list buffer. | ||
53 | local actlist = {} | ||
54 | |||
55 | -- Argument list for next dasm_put(). Start with offset 0 into action list. | ||
56 | local actargs = { 0 } | ||
57 | |||
58 | -- Current number of section buffer positions for dasm_put(). | ||
59 | local secpos = 1 | ||
60 | |||
61 | ------------------------------------------------------------------------------ | ||
62 | |||
63 | -- Return 8 digit hex number. | ||
64 | local function tohex(x) | ||
65 | return sub(format("%08x", x), -8) -- Avoid 64 bit portability problem in Lua. | ||
66 | end | ||
67 | |||
68 | -- Dump action names and numbers. | ||
69 | local function dumpactions(out) | ||
70 | out:write("DynASM encoding engine action codes:\n") | ||
71 | for n,name in ipairs(action_names) do | ||
72 | local num = map_action[name] | ||
73 | out:write(format(" %-10s %02X %d\n", name, num, num)) | ||
74 | end | ||
75 | out:write("\n") | ||
76 | end | ||
77 | |||
78 | -- Write action list buffer as a huge static C array. | ||
79 | local function writeactions(out, name) | ||
80 | local nn = #actlist | ||
81 | if nn == 0 then nn = 1; actlist[0] = map_action.STOP end | ||
82 | out:write("static const unsigned int ", name, "[", nn, "] = {\n") | ||
83 | for i = 1,nn-1 do | ||
84 | assert(out:write("0x", tohex(actlist[i]), ",\n")) | ||
85 | end | ||
86 | assert(out:write("0x", tohex(actlist[nn]), "\n};\n\n")) | ||
87 | end | ||
88 | |||
89 | ------------------------------------------------------------------------------ | ||
90 | |||
91 | -- Add word to action list. | ||
92 | local function wputxw(n) | ||
93 | assert(n >= 0 and n <= 0xffffffff and n % 1 == 0, "word out of range") | ||
94 | actlist[#actlist+1] = n | ||
95 | end | ||
96 | |||
97 | -- Add action to list with optional arg. Advance buffer pos, too. | ||
98 | local function waction(action, val, a, num) | ||
99 | local w = assert(map_action[action], "bad action name `"..action.."'") | ||
100 | wputxw(w * 0x10000 + (val or 0)) | ||
101 | if a then actargs[#actargs+1] = a end | ||
102 | if a or num then secpos = secpos + (num or 1) end | ||
103 | end | ||
104 | |||
105 | -- Flush action list (intervening C code or buffer pos overflow). | ||
106 | local function wflush(term) | ||
107 | if #actlist == actargs[1] then return end -- Nothing to flush. | ||
108 | if not term then waction("STOP") end -- Terminate action list. | ||
109 | wline(format("dasm_put(Dst, %s);", concat(actargs, ", ")), true) | ||
110 | actargs = { #actlist } -- Actionlist offset is 1st arg to next dasm_put(). | ||
111 | secpos = 1 -- The actionlist offset occupies a buffer position, too. | ||
112 | end | ||
113 | |||
114 | -- Put escaped word. | ||
115 | local function wputw(n) | ||
116 | if n <= 0x000fffff then waction("ESC") end | ||
117 | wputxw(n) | ||
118 | end | ||
119 | |||
120 | -- Reserve position for word. | ||
121 | local function wpos() | ||
122 | local pos = #actlist+1 | ||
123 | actlist[pos] = "" | ||
124 | return pos | ||
125 | end | ||
126 | |||
127 | -- Store word to reserved position. | ||
128 | local function wputpos(pos, n) | ||
129 | assert(n >= 0 and n <= 0xffffffff and n % 1 == 0, "word out of range") | ||
130 | if n <= 0x000fffff then | ||
131 | insert(actlist, pos+1, n) | ||
132 | n = map_action.ESC * 0x10000 | ||
133 | end | ||
134 | actlist[pos] = n | ||
135 | end | ||
136 | |||
137 | ------------------------------------------------------------------------------ | ||
138 | |||
139 | -- Global label name -> global label number. With auto assignment on 1st use. | ||
140 | local next_global = 20 | ||
141 | local map_global = setmetatable({}, { __index = function(t, name) | ||
142 | if not match(name, "^[%a_][%w_]*$") then werror("bad global label") end | ||
143 | local n = next_global | ||
144 | if n > 2047 then werror("too many global labels") end | ||
145 | next_global = n + 1 | ||
146 | t[name] = n | ||
147 | return n | ||
148 | end}) | ||
149 | |||
150 | -- Dump global labels. | ||
151 | local function dumpglobals(out, lvl) | ||
152 | local t = {} | ||
153 | for name, n in pairs(map_global) do t[n] = name end | ||
154 | out:write("Global labels:\n") | ||
155 | for i=20,next_global-1 do | ||
156 | out:write(format(" %s\n", t[i])) | ||
157 | end | ||
158 | out:write("\n") | ||
159 | end | ||
160 | |||
161 | -- Write global label enum. | ||
162 | local function writeglobals(out, prefix) | ||
163 | local t = {} | ||
164 | for name, n in pairs(map_global) do t[n] = name end | ||
165 | out:write("enum {\n") | ||
166 | for i=20,next_global-1 do | ||
167 | out:write(" ", prefix, t[i], ",\n") | ||
168 | end | ||
169 | out:write(" ", prefix, "_MAX\n};\n") | ||
170 | end | ||
171 | |||
172 | -- Write global label names. | ||
173 | local function writeglobalnames(out, name) | ||
174 | local t = {} | ||
175 | for name, n in pairs(map_global) do t[n] = name end | ||
176 | out:write("static const char *const ", name, "[] = {\n") | ||
177 | for i=20,next_global-1 do | ||
178 | out:write(" \"", t[i], "\",\n") | ||
179 | end | ||
180 | out:write(" (const char *)0\n};\n") | ||
181 | end | ||
182 | |||
183 | ------------------------------------------------------------------------------ | ||
184 | |||
185 | -- Extern label name -> extern label number. With auto assignment on 1st use. | ||
186 | local next_extern = 0 | ||
187 | local map_extern_ = {} | ||
188 | local map_extern = setmetatable({}, { __index = function(t, name) | ||
189 | -- No restrictions on the name for now. | ||
190 | local n = next_extern | ||
191 | if n > 2047 then werror("too many extern labels") end | ||
192 | next_extern = n + 1 | ||
193 | t[name] = n | ||
194 | map_extern_[n] = name | ||
195 | return n | ||
196 | end}) | ||
197 | |||
198 | -- Dump extern labels. | ||
199 | local function dumpexterns(out, lvl) | ||
200 | out:write("Extern labels:\n") | ||
201 | for i=0,next_extern-1 do | ||
202 | out:write(format(" %s\n", map_extern_[i])) | ||
203 | end | ||
204 | out:write("\n") | ||
205 | end | ||
206 | |||
207 | -- Write extern label names. | ||
208 | local function writeexternnames(out, name) | ||
209 | out:write("static const char *const ", name, "[] = {\n") | ||
210 | for i=0,next_extern-1 do | ||
211 | out:write(" \"", map_extern_[i], "\",\n") | ||
212 | end | ||
213 | out:write(" (const char *)0\n};\n") | ||
214 | end | ||
215 | |||
216 | ------------------------------------------------------------------------------ | ||
217 | |||
218 | -- Arch-specific maps. | ||
219 | |||
220 | -- Ext. register name -> int. name. | ||
221 | local map_archdef = { sp = "r13", lr = "r14", pc = "r15", } | ||
222 | |||
223 | -- Int. register name -> ext. name. | ||
224 | local map_reg_rev = { r13 = "sp", r14 = "lr", r15 = "pc", } | ||
225 | |||
226 | local map_type = {} -- Type name -> { ctype, reg } | ||
227 | local ctypenum = 0 -- Type number (for Dt... macros). | ||
228 | |||
229 | -- Reverse defines for registers. | ||
230 | function _M.revdef(s) | ||
231 | return map_reg_rev[s] or s | ||
232 | end | ||
233 | |||
234 | local map_shift = { lsl = 0, lsr = 1, asr = 2, ror = 3, } | ||
235 | |||
236 | local map_cond = { | ||
237 | eq = 0, ne = 1, cs = 2, cc = 3, mi = 4, pl = 5, vs = 6, vc = 7, | ||
238 | hi = 8, ls = 9, ge = 10, lt = 11, gt = 12, le = 13, al = 14, | ||
239 | hs = 2, lo = 3, | ||
240 | } | ||
241 | |||
242 | ------------------------------------------------------------------------------ | ||
243 | |||
244 | -- Template strings for ARM instructions. | ||
245 | local map_op = { | ||
246 | -- Basic data processing instructions. | ||
247 | and_3 = "e0000000DNPs", | ||
248 | eor_3 = "e0200000DNPs", | ||
249 | sub_3 = "e0400000DNPs", | ||
250 | rsb_3 = "e0600000DNPs", | ||
251 | add_3 = "e0800000DNPs", | ||
252 | adc_3 = "e0a00000DNPs", | ||
253 | sbc_3 = "e0c00000DNPs", | ||
254 | rsc_3 = "e0e00000DNPs", | ||
255 | tst_2 = "e1100000NP", | ||
256 | teq_2 = "e1300000NP", | ||
257 | cmp_2 = "e1500000NP", | ||
258 | cmn_2 = "e1700000NP", | ||
259 | orr_3 = "e1800000DNPs", | ||
260 | mov_2 = "e1a00000DPs", | ||
261 | bic_3 = "e1c00000DNPs", | ||
262 | mvn_2 = "e1e00000DPs", | ||
263 | |||
264 | and_4 = "e0000000DNMps", | ||
265 | eor_4 = "e0200000DNMps", | ||
266 | sub_4 = "e0400000DNMps", | ||
267 | rsb_4 = "e0600000DNMps", | ||
268 | add_4 = "e0800000DNMps", | ||
269 | adc_4 = "e0a00000DNMps", | ||
270 | sbc_4 = "e0c00000DNMps", | ||
271 | rsc_4 = "e0e00000DNMps", | ||
272 | tst_3 = "e1100000NMp", | ||
273 | teq_3 = "e1300000NMp", | ||
274 | cmp_3 = "e1500000NMp", | ||
275 | cmn_3 = "e1700000NMp", | ||
276 | orr_4 = "e1800000DNMps", | ||
277 | mov_3 = "e1a00000DMps", | ||
278 | bic_4 = "e1c00000DNMps", | ||
279 | mvn_3 = "e1e00000DMps", | ||
280 | |||
281 | lsl_3 = "e1a00000DMws", | ||
282 | lsr_3 = "e1a00020DMws", | ||
283 | asr_3 = "e1a00040DMws", | ||
284 | ror_3 = "e1a00060DMws", | ||
285 | rrx_2 = "e1a00060DMs", | ||
286 | |||
287 | -- Multiply and multiply-accumulate. | ||
288 | mul_3 = "e0000090NMSs", | ||
289 | mla_4 = "e0200090NMSDs", | ||
290 | umaal_4 = "e0400090DNMSs", -- v6 | ||
291 | mls_4 = "e0600090DNMSs", -- v6T2 | ||
292 | umull_4 = "e0800090DNMSs", | ||
293 | umlal_4 = "e0a00090DNMSs", | ||
294 | smull_4 = "e0c00090DNMSs", | ||
295 | smlal_4 = "e0e00090DNMSs", | ||
296 | |||
297 | -- Halfword multiply and multiply-accumulate. | ||
298 | smlabb_4 = "e1000080NMSD", -- v5TE | ||
299 | smlatb_4 = "e10000a0NMSD", -- v5TE | ||
300 | smlabt_4 = "e10000c0NMSD", -- v5TE | ||
301 | smlatt_4 = "e10000e0NMSD", -- v5TE | ||
302 | smlawb_4 = "e1200080NMSD", -- v5TE | ||
303 | smulwb_3 = "e12000a0NMS", -- v5TE | ||
304 | smlawt_4 = "e12000c0NMSD", -- v5TE | ||
305 | smulwt_3 = "e12000e0NMS", -- v5TE | ||
306 | smlalbb_4 = "e1400080NMSD", -- v5TE | ||
307 | smlaltb_4 = "e14000a0NMSD", -- v5TE | ||
308 | smlalbt_4 = "e14000c0NMSD", -- v5TE | ||
309 | smlaltt_4 = "e14000e0NMSD", -- v5TE | ||
310 | smulbb_3 = "e1600080NMS", -- v5TE | ||
311 | smultb_3 = "e16000a0NMS", -- v5TE | ||
312 | smulbt_3 = "e16000c0NMS", -- v5TE | ||
313 | smultt_3 = "e16000e0NMS", -- v5TE | ||
314 | |||
315 | -- Miscellaneous data processing instructions. | ||
316 | clz_2 = "e16f0f10DM", -- v5T | ||
317 | rev_2 = "e6bf0f30DM", -- v6 | ||
318 | rev16_2 = "e6bf0fb0DM", -- v6 | ||
319 | revsh_2 = "e6ff0fb0DM", -- v6 | ||
320 | sel_3 = "e6800fb0DNM", -- v6 | ||
321 | usad8_3 = "e780f010NMS", -- v6 | ||
322 | usada8_4 = "e7800010NMSD", -- v6 | ||
323 | rbit_2 = "e6ff0f30DM", -- v6T2 | ||
324 | movw_2 = "e3000000DW", -- v6T2 | ||
325 | movt_2 = "e3400000DW", -- v6T2 | ||
326 | -- Note: the X encodes width-1, not width. | ||
327 | sbfx_4 = "e7a00050DMvX", -- v6T2 | ||
328 | ubfx_4 = "e7e00050DMvX", -- v6T2 | ||
329 | -- Note: the X encodes the msb field, not the width. | ||
330 | bfc_3 = "e7c0001fDvX", -- v6T2 | ||
331 | bfi_4 = "e7c00010DMvX", -- v6T2 | ||
332 | |||
333 | -- Packing and unpacking instructions. | ||
334 | pkhbt_3 = "e6800010DNM", pkhbt_4 = "e6800010DNMv", -- v6 | ||
335 | pkhtb_3 = "e6800050DNM", pkhtb_4 = "e6800050DNMv", -- v6 | ||
336 | sxtab_3 = "e6a00070DNM", sxtab_4 = "e6a00070DNMv", -- v6 | ||
337 | sxtab16_3 = "e6800070DNM", sxtab16_4 = "e6800070DNMv", -- v6 | ||
338 | sxtah_3 = "e6b00070DNM", sxtah_4 = "e6b00070DNMv", -- v6 | ||
339 | sxtb_2 = "e6af0070DM", sxtb_3 = "e6af0070DMv", -- v6 | ||
340 | sxtb16_2 = "e68f0070DM", sxtb16_3 = "e68f0070DMv", -- v6 | ||
341 | sxth_2 = "e6bf0070DM", sxth_3 = "e6bf0070DMv", -- v6 | ||
342 | uxtab_3 = "e6e00070DNM", uxtab_4 = "e6e00070DNMv", -- v6 | ||
343 | uxtab16_3 = "e6c00070DNM", uxtab16_4 = "e6c00070DNMv", -- v6 | ||
344 | uxtah_3 = "e6f00070DNM", uxtah_4 = "e6f00070DNMv", -- v6 | ||
345 | uxtb_2 = "e6ef0070DM", uxtb_3 = "e6ef0070DMv", -- v6 | ||
346 | uxtb16_2 = "e6cf0070DM", uxtb16_3 = "e6cf0070DMv", -- v6 | ||
347 | uxth_2 = "e6ff0070DM", uxth_3 = "e6ff0070DMv", -- v6 | ||
348 | |||
349 | -- Saturating instructions. | ||
350 | qadd_3 = "e1000050DMN", -- v5TE | ||
351 | qsub_3 = "e1200050DMN", -- v5TE | ||
352 | qdadd_3 = "e1400050DMN", -- v5TE | ||
353 | qdsub_3 = "e1600050DMN", -- v5TE | ||
354 | -- Note: the X for ssat* encodes sat_imm-1, not sat_imm. | ||
355 | ssat_3 = "e6a00010DXM", ssat_4 = "e6a00010DXMp", -- v6 | ||
356 | usat_3 = "e6e00010DXM", usat_4 = "e6e00010DXMp", -- v6 | ||
357 | ssat16_3 = "e6a00f30DXM", -- v6 | ||
358 | usat16_3 = "e6e00f30DXM", -- v6 | ||
359 | |||
360 | -- Parallel addition and subtraction. | ||
361 | sadd16_3 = "e6100f10DNM", -- v6 | ||
362 | sasx_3 = "e6100f30DNM", -- v6 | ||
363 | ssax_3 = "e6100f50DNM", -- v6 | ||
364 | ssub16_3 = "e6100f70DNM", -- v6 | ||
365 | sadd8_3 = "e6100f90DNM", -- v6 | ||
366 | ssub8_3 = "e6100ff0DNM", -- v6 | ||
367 | qadd16_3 = "e6200f10DNM", -- v6 | ||
368 | qasx_3 = "e6200f30DNM", -- v6 | ||
369 | qsax_3 = "e6200f50DNM", -- v6 | ||
370 | qsub16_3 = "e6200f70DNM", -- v6 | ||
371 | qadd8_3 = "e6200f90DNM", -- v6 | ||
372 | qsub8_3 = "e6200ff0DNM", -- v6 | ||
373 | shadd16_3 = "e6300f10DNM", -- v6 | ||
374 | shasx_3 = "e6300f30DNM", -- v6 | ||
375 | shsax_3 = "e6300f50DNM", -- v6 | ||
376 | shsub16_3 = "e6300f70DNM", -- v6 | ||
377 | shadd8_3 = "e6300f90DNM", -- v6 | ||
378 | shsub8_3 = "e6300ff0DNM", -- v6 | ||
379 | uadd16_3 = "e6500f10DNM", -- v6 | ||
380 | uasx_3 = "e6500f30DNM", -- v6 | ||
381 | usax_3 = "e6500f50DNM", -- v6 | ||
382 | usub16_3 = "e6500f70DNM", -- v6 | ||
383 | uadd8_3 = "e6500f90DNM", -- v6 | ||
384 | usub8_3 = "e6500ff0DNM", -- v6 | ||
385 | uqadd16_3 = "e6600f10DNM", -- v6 | ||
386 | uqasx_3 = "e6600f30DNM", -- v6 | ||
387 | uqsax_3 = "e6600f50DNM", -- v6 | ||
388 | uqsub16_3 = "e6600f70DNM", -- v6 | ||
389 | uqadd8_3 = "e6600f90DNM", -- v6 | ||
390 | uqsub8_3 = "e6600ff0DNM", -- v6 | ||
391 | uhadd16_3 = "e6700f10DNM", -- v6 | ||
392 | uhasx_3 = "e6700f30DNM", -- v6 | ||
393 | uhsax_3 = "e6700f50DNM", -- v6 | ||
394 | uhsub16_3 = "e6700f70DNM", -- v6 | ||
395 | uhadd8_3 = "e6700f90DNM", -- v6 | ||
396 | uhsub8_3 = "e6700ff0DNM", -- v6 | ||
397 | |||
398 | -- Load/store instructions. | ||
399 | str_2 = "e4000000DL", str_3 = "e4000000DL", str_4 = "e4000000DL", | ||
400 | strb_2 = "e4400000DL", strb_3 = "e4400000DL", strb_4 = "e4400000DL", | ||
401 | ldr_2 = "e4100000DL", ldr_3 = "e4100000DL", ldr_4 = "e4100000DL", | ||
402 | ldrb_2 = "e4500000DL", ldrb_3 = "e4500000DL", ldrb_4 = "e4500000DL", | ||
403 | strh_2 = "e00000b0DL", strh_3 = "e00000b0DL", | ||
404 | ldrh_2 = "e01000b0DL", ldrh_3 = "e01000b0DL", | ||
405 | ldrd_2 = "e00000d0DL", ldrd_3 = "e00000d0DL", -- v5TE | ||
406 | ldrsb_2 = "e01000d0DL", ldrsb_3 = "e01000d0DL", | ||
407 | strd_2 = "e00000f0DL", strd_3 = "e00000f0DL", -- v5TE | ||
408 | ldrsh_2 = "e01000f0DL", ldrsh_3 = "e01000f0DL", | ||
409 | |||
410 | ldm_2 = "e8900000nR", ldmia_2 = "e8900000nR", ldmfd_2 = "e8900000nR", | ||
411 | ldmda_2 = "e8100000nR", ldmfa_2 = "e8100000nR", | ||
412 | ldmdb_2 = "e9100000nR", ldmea_2 = "e9100000nR", | ||
413 | ldmib_2 = "e9900000nR", ldmed_2 = "e9900000nR", | ||
414 | stm_2 = "e8800000nR", stmia_2 = "e8800000nR", stmfd_2 = "e8800000nR", | ||
415 | stmda_2 = "e8000000nR", stmfa_2 = "e8000000nR", | ||
416 | stmdb_2 = "e9000000nR", stmea_2 = "e9000000nR", | ||
417 | stmib_2 = "e9800000nR", stmed_2 = "e9800000nR", | ||
418 | pop_1 = "e8bd0000R", push_1 = "e92d0000R", | ||
419 | |||
420 | -- Branch instructions. | ||
421 | b_1 = "ea000000B", | ||
422 | bl_1 = "eb000000B", | ||
423 | blx_1 = "e12fff30C", | ||
424 | bx_1 = "e12fff10M", | ||
425 | |||
426 | -- Miscellaneous instructions. | ||
427 | nop_0 = "e1a00000", | ||
428 | mrs_1 = "e10f0000D", | ||
429 | bkpt_1 = "e1200070K", -- v5T | ||
430 | svc_1 = "ef000000T", swi_1 = "ef000000T", | ||
431 | ud_0 = "e7f001f0", | ||
432 | |||
433 | -- NYI: Advanced SIMD and VFP instructions. | ||
434 | |||
435 | -- NYI instructions, since I have no need for them right now: | ||
436 | -- swp, swpb, strex, ldrex, strexd, ldrexd, strexb, ldrexb, strexh, ldrexh | ||
437 | -- msr, nopv6, yield, wfe, wfi, sev, dbg, bxj, smc, srs, rfe | ||
438 | -- cps, setend, pli, pld, pldw, clrex, dsb, dmb, isb | ||
439 | -- stc, ldc, mcr, mcr2, mrc, mrc2, mcrr, mcrr2, mrrc, mrrc2, cdp, cdp2 | ||
440 | } | ||
441 | |||
442 | -- Add mnemonics for "s" variants. | ||
443 | do | ||
444 | local t = {} | ||
445 | for k,v in pairs(map_op) do | ||
446 | if sub(v, -1) == "s" then | ||
447 | local v2 = sub(v, 1, 2)..char(byte(v, 3)+1)..sub(v, 4, -2) | ||
448 | t[sub(k, 1, -3).."s"..sub(k, -2)] = v2 | ||
449 | end | ||
450 | end | ||
451 | for k,v in pairs(t) do | ||
452 | map_op[k] = v | ||
453 | end | ||
454 | end | ||
455 | |||
456 | ------------------------------------------------------------------------------ | ||
457 | |||
458 | local function parse_gpr(expr) | ||
459 | local tname, ovreg = match(expr, "^([%w_]+):(r1?[0-9])$") | ||
460 | local tp = map_type[tname or expr] | ||
461 | if tp then | ||
462 | local reg = ovreg or tp.reg | ||
463 | if not reg then | ||
464 | werror("type `"..(tname or expr).."' needs a register override") | ||
465 | end | ||
466 | expr = reg | ||
467 | end | ||
468 | local r = match(expr, "^r(1?[0-9])$") | ||
469 | if r then | ||
470 | r = tonumber(r) | ||
471 | if r <= 15 then return r, tp end | ||
472 | end | ||
473 | werror("bad register name `"..expr.."'") | ||
474 | end | ||
475 | |||
476 | local function parse_gpr_pm(expr) | ||
477 | local pm, expr2 = match(expr, "^([+-]?)(.*)$") | ||
478 | return parse_gpr(expr2), (pm == "-") | ||
479 | end | ||
480 | |||
481 | local function parse_reglist(reglist) | ||
482 | reglist = match(reglist, "^{%s*([^}]*)}$") | ||
483 | if not reglist then werror("register list expected") end | ||
484 | local rr = 0 | ||
485 | for p in gmatch(reglist..",", "%s*([^,]*),") do | ||
486 | local rbit = 2^parse_gpr(gsub(p, "%s+$", "")) | ||
487 | if ((rr - (rr % rbit)) / rbit) % 2 ~= 0 then | ||
488 | werror("duplicate register `"..p.."'") | ||
489 | end | ||
490 | rr = rr + rbit | ||
491 | end | ||
492 | return rr | ||
493 | end | ||
494 | |||
495 | local function parse_imm(imm, bits, shift, scale, signed) | ||
496 | imm = match(imm, "^#(.*)$") | ||
497 | if not imm then werror("expected immediate operand") end | ||
498 | local n = tonumber(imm) | ||
499 | if n then | ||
500 | if n % 2^scale == 0 then | ||
501 | n = n / 2^scale | ||
502 | if signed then | ||
503 | if n >= 0 then | ||
504 | if n < 2^(bits-1) then return n*2^shift end | ||
505 | else | ||
506 | if n >= -(2^(bits-1))-1 then return (n+2^bits)*2^shift end | ||
507 | end | ||
508 | else | ||
509 | if n >= 0 and n <= 2^bits-1 then return n*2^shift end | ||
510 | end | ||
511 | end | ||
512 | werror("out of range immediate `"..imm.."'") | ||
513 | else | ||
514 | waction("IMM", (signed and 32768 or 0)+scale*1024+bits*32+shift, imm) | ||
515 | return 0 | ||
516 | end | ||
517 | end | ||
518 | |||
519 | local function parse_imm12(imm) | ||
520 | local n = tonumber(imm) | ||
521 | if n then | ||
522 | local m = n | ||
523 | for i=0,-15,-1 do | ||
524 | if m >= 0 and m <= 255 and n % 1 == 0 then return m + (i%16) * 256 end | ||
525 | local t = m % 4 | ||
526 | m = (m - t) / 4 + t * 2^30 | ||
527 | end | ||
528 | werror("out of range immediate `"..imm.."'") | ||
529 | else | ||
530 | waction("IMM12", 0, imm) | ||
531 | return 0 | ||
532 | end | ||
533 | end | ||
534 | |||
535 | local function parse_imm16(imm) | ||
536 | imm = match(imm, "^#(.*)$") | ||
537 | if not imm then werror("expected immediate operand") end | ||
538 | local n = tonumber(imm) | ||
539 | if n then | ||
540 | if n >= 0 and n <= 65535 and n % 1 == 0 then | ||
541 | local t = n % 4096 | ||
542 | return (n - t) * 16 + t | ||
543 | end | ||
544 | werror("out of range immediate `"..imm.."'") | ||
545 | else | ||
546 | waction("IMM16", 32*16, imm) | ||
547 | return 0 | ||
548 | end | ||
549 | end | ||
550 | |||
551 | local function parse_imm_load(imm, ext) | ||
552 | local n = tonumber(imm) | ||
553 | if n then | ||
554 | if ext then | ||
555 | if n >= -255 and n <= 255 then | ||
556 | local up = 0x00800000 | ||
557 | if n < 0 then n = -n; up = 0 end | ||
558 | return (n-(n%16))*16+(n%16) + up | ||
559 | end | ||
560 | else | ||
561 | if n >= -4095 and n <= 4095 then | ||
562 | if n >= 0 then return n+0x00800000 end | ||
563 | return -n | ||
564 | end | ||
565 | end | ||
566 | werror("out of range immediate `"..imm.."'") | ||
567 | else | ||
568 | waction(ext and "IMML8" or "IMML12", 32768 + 32*(ext and 8 or 12), imm) | ||
569 | return 0 | ||
570 | end | ||
571 | end | ||
572 | |||
573 | local function parse_shift(shift, gprok) | ||
574 | if shift == "rrx" then | ||
575 | return 3 * 32 | ||
576 | else | ||
577 | local s, s2 = match(shift, "^(%S+)%s*(.*)$") | ||
578 | s = map_shift[s] | ||
579 | if not s then werror("expected shift operand") end | ||
580 | if sub(s2, 1, 1) == "#" then | ||
581 | return parse_imm(s2, 5, 7, 0, false) + s * 32 | ||
582 | else | ||
583 | if not gprok then werror("expected immediate shift operand") end | ||
584 | return parse_gpr(s2) * 256 + s * 32 + 16 | ||
585 | end | ||
586 | end | ||
587 | end | ||
588 | |||
589 | local function parse_label(label, def) | ||
590 | local prefix = sub(label, 1, 2) | ||
591 | -- =>label (pc label reference) | ||
592 | if prefix == "=>" then | ||
593 | return "PC", 0, sub(label, 3) | ||
594 | end | ||
595 | -- ->name (global label reference) | ||
596 | if prefix == "->" then | ||
597 | return "LG", map_global[sub(label, 3)] | ||
598 | end | ||
599 | if def then | ||
600 | -- [1-9] (local label definition) | ||
601 | if match(label, "^[1-9]$") then | ||
602 | return "LG", 10+tonumber(label) | ||
603 | end | ||
604 | else | ||
605 | -- [<>][1-9] (local label reference) | ||
606 | local dir, lnum = match(label, "^([<>])([1-9])$") | ||
607 | if dir then -- Fwd: 1-9, Bkwd: 11-19. | ||
608 | return "LG", lnum + (dir == ">" and 0 or 10) | ||
609 | end | ||
610 | -- extern label (extern label reference) | ||
611 | local extname = match(label, "^extern%s+(%S+)$") | ||
612 | if extname then | ||
613 | return "EXT", map_extern[extname] | ||
614 | end | ||
615 | end | ||
616 | werror("bad label `"..label.."'") | ||
617 | end | ||
618 | |||
619 | local function parse_load(params, nparams, n, op) | ||
620 | local oplo = op % 256 | ||
621 | local ext, ldrd = (oplo ~= 0), (oplo == 208) | ||
622 | local d | ||
623 | if (ldrd or oplo == 240) then | ||
624 | d = ((op - (op % 4096)) / 4096) % 16 | ||
625 | if d % 2 ~= 0 then werror("odd destination register") end | ||
626 | end | ||
627 | local pn = params[n] | ||
628 | local p1, wb = match(pn, "^%[%s*(.-)%s*%](!?)$") | ||
629 | local p2 = params[n+1] | ||
630 | if not p1 then | ||
631 | if not p2 then | ||
632 | if match(pn, "^[<>=%-]") or match(pn, "^extern%s+") then | ||
633 | local mode, n, s = parse_label(pn, false) | ||
634 | waction("REL_"..mode, n + (ext and 0x1800 or 0x0800), s, 1) | ||
635 | return op + 15 * 65536 + 0x01000000 + (ext and 0x00400000 or 0) | ||
636 | end | ||
637 | local reg, tailr = match(pn, "^([%w_:]+)%s*(.*)$") | ||
638 | if reg and tailr ~= "" then | ||
639 | local d, tp = parse_gpr(reg) | ||
640 | if tp then | ||
641 | waction(ext and "IMML8" or "IMML12", 32768 + 32*(ext and 8 or 12), | ||
642 | format(tp.ctypefmt, tailr)) | ||
643 | return op + d * 65536 + 0x01000000 + (ext and 0x00400000 or 0) | ||
644 | end | ||
645 | end | ||
646 | end | ||
647 | werror("expected address operand") | ||
648 | end | ||
649 | if wb == "!" then op = op + 0x00200000 end | ||
650 | if p2 then | ||
651 | if wb == "!" then werror("bad use of '!'") end | ||
652 | local p3 = params[n+2] | ||
653 | op = op + parse_gpr(p1) * 65536 | ||
654 | local imm = match(p2, "^#(.*)$") | ||
655 | if imm then | ||
656 | local m = parse_imm_load(imm, ext) | ||
657 | if p3 then werror("too many parameters") end | ||
658 | op = op + m + (ext and 0x00400000 or 0) | ||
659 | else | ||
660 | local m, neg = parse_gpr_pm(p2) | ||
661 | if ldrd and (m == d or m-1 == d) then werror("register conflict") end | ||
662 | op = op + m + (neg and 0 or 0x00800000) + (ext and 0 or 0x02000000) | ||
663 | if p3 then op = op + parse_shift(p3) end | ||
664 | end | ||
665 | else | ||
666 | local p1a, p2 = match(p1, "^([^,%s]*)%s*(.*)$") | ||
667 | op = op + parse_gpr(p1a) * 65536 + 0x01000000 | ||
668 | if p2 ~= "" then | ||
669 | local imm = match(p2, "^,%s*#(.*)$") | ||
670 | if imm then | ||
671 | local m = parse_imm_load(imm, ext) | ||
672 | op = op + m + (ext and 0x00400000 or 0) | ||
673 | else | ||
674 | local p2a, p3 = match(p2, "^,%s*([^,%s]*)%s*,?%s*(.*)$") | ||
675 | local m, neg = parse_gpr_pm(p2a) | ||
676 | if ldrd and (m == d or m-1 == d) then werror("register conflict") end | ||
677 | op = op + m + (neg and 0 or 0x00800000) + (ext and 0 or 0x02000000) | ||
678 | if p3 ~= "" then | ||
679 | if ext then werror("too many parameters") end | ||
680 | op = op + parse_shift(p3) | ||
681 | end | ||
682 | end | ||
683 | else | ||
684 | if wb == "!" then werror("bad use of '!'") end | ||
685 | op = op + (ext and 0x00c00000 or 0x00800000) | ||
686 | end | ||
687 | end | ||
688 | return op | ||
689 | end | ||
690 | |||
691 | ------------------------------------------------------------------------------ | ||
692 | |||
693 | -- Handle opcodes defined with template strings. | ||
694 | map_op[".template__"] = function(params, template, nparams) | ||
695 | if not params then return sub(template, 9) end | ||
696 | local op = tonumber(sub(template, 1, 8), 16) | ||
697 | local n = 1 | ||
698 | |||
699 | -- Limit number of section buffer positions used by a single dasm_put(). | ||
700 | -- A single opcode needs a maximum of 3 positions. | ||
701 | if secpos+3 > maxsecpos then wflush() end | ||
702 | local pos = wpos() | ||
703 | |||
704 | -- Process each character. | ||
705 | for p in gmatch(sub(template, 9), ".") do | ||
706 | if p == "D" then | ||
707 | op = op + parse_gpr(params[n]) * 4096; n = n + 1 | ||
708 | elseif p == "N" then | ||
709 | op = op + parse_gpr(params[n]) * 65536; n = n + 1 | ||
710 | elseif p == "S" then | ||
711 | op = op + parse_gpr(params[n]) * 256; n = n + 1 | ||
712 | elseif p == "M" then | ||
713 | op = op + parse_gpr(params[n]); n = n + 1 | ||
714 | elseif p == "P" then | ||
715 | local imm = match(params[n], "^#(.*)$") | ||
716 | if imm then | ||
717 | op = op + parse_imm12(imm) + 0x02000000 | ||
718 | else | ||
719 | op = op + parse_gpr(params[n]) | ||
720 | end | ||
721 | n = n + 1 | ||
722 | elseif p == "p" then | ||
723 | op = op + parse_shift(params[n], true); n = n + 1 | ||
724 | elseif p == "L" then | ||
725 | op = parse_load(params, nparams, n, op) | ||
726 | elseif p == "B" then | ||
727 | local mode, n, s = parse_label(params[n], false) | ||
728 | waction("REL_"..mode, n, s, 1) | ||
729 | elseif p == "C" then -- blx gpr vs. blx label. | ||
730 | local p = params[n] | ||
731 | if match(p, "^([%w_]+):(r1?[0-9])$") or match(p, "^r(1?[0-9])$") then | ||
732 | op = op + parse_gpr(p) | ||
733 | else | ||
734 | if op < 0xe0000000 then werror("unconditional instruction") end | ||
735 | local mode, n, s = parse_label(p, false) | ||
736 | waction("REL_"..mode, n, s, 1) | ||
737 | op = 0xfa000000 | ||
738 | end | ||
739 | elseif p == "n" then | ||
740 | local r, wb = match(params[n], "^([^!]*)(!?)$") | ||
741 | op = op + parse_gpr(r) * 65536 + (wb == "!" and 0x00200000 or 0) | ||
742 | n = n + 1 | ||
743 | elseif p == "R" then | ||
744 | op = op + parse_reglist(params[n]); n = n + 1 | ||
745 | elseif p == "W" then | ||
746 | op = op + parse_imm16(params[n]); n = n + 1 | ||
747 | elseif p == "v" then | ||
748 | op = op + parse_imm(params[n], 5, 7, 0, false); n = n + 1 | ||
749 | elseif p == "w" then | ||
750 | local imm = match(params[n], "^#(.*)$") | ||
751 | if imm then | ||
752 | op = op + parse_imm(params[n], 5, 7, 0, false); n = n + 1 | ||
753 | else | ||
754 | op = op + parse_gpr(params[n]) * 256 + 16 | ||
755 | end | ||
756 | elseif p == "X" then | ||
757 | op = op + parse_imm(params[n], 5, 16, 0, false); n = n + 1 | ||
758 | elseif p == "K" then | ||
759 | local imm = tonumber(match(params[n], "^#(.*)$")); n = n + 1 | ||
760 | if not imm or imm % 1 ~= 0 or imm < 0 or imm > 0xffff then | ||
761 | werror("bad immediate operand") | ||
762 | end | ||
763 | local t = imm % 16 | ||
764 | op = op + (imm - t) * 16 + t | ||
765 | elseif p == "T" then | ||
766 | op = op + parse_imm(params[n], 24, 0, 0, false); n = n + 1 | ||
767 | elseif p == "s" then | ||
768 | -- Ignored. | ||
769 | else | ||
770 | assert(false) | ||
771 | end | ||
772 | end | ||
773 | wputpos(pos, op) | ||
774 | end | ||
775 | |||
776 | ------------------------------------------------------------------------------ | ||
777 | |||
778 | -- Pseudo-opcode to mark the position where the action list is to be emitted. | ||
779 | map_op[".actionlist_1"] = function(params) | ||
780 | if not params then return "cvar" end | ||
781 | local name = params[1] -- No syntax check. You get to keep the pieces. | ||
782 | wline(function(out) writeactions(out, name) end) | ||
783 | end | ||
784 | |||
785 | -- Pseudo-opcode to mark the position where the global enum is to be emitted. | ||
786 | map_op[".globals_1"] = function(params) | ||
787 | if not params then return "prefix" end | ||
788 | local prefix = params[1] -- No syntax check. You get to keep the pieces. | ||
789 | wline(function(out) writeglobals(out, prefix) end) | ||
790 | end | ||
791 | |||
792 | -- Pseudo-opcode to mark the position where the global names are to be emitted. | ||
793 | map_op[".globalnames_1"] = function(params) | ||
794 | if not params then return "cvar" end | ||
795 | local name = params[1] -- No syntax check. You get to keep the pieces. | ||
796 | wline(function(out) writeglobalnames(out, name) end) | ||
797 | end | ||
798 | |||
799 | -- Pseudo-opcode to mark the position where the extern names are to be emitted. | ||
800 | map_op[".externnames_1"] = function(params) | ||
801 | if not params then return "cvar" end | ||
802 | local name = params[1] -- No syntax check. You get to keep the pieces. | ||
803 | wline(function(out) writeexternnames(out, name) end) | ||
804 | end | ||
805 | |||
806 | ------------------------------------------------------------------------------ | ||
807 | |||
808 | -- Label pseudo-opcode (converted from trailing colon form). | ||
809 | map_op[".label_1"] = function(params) | ||
810 | if not params then return "[1-9] | ->global | =>pcexpr" end | ||
811 | if secpos+1 > maxsecpos then wflush() end | ||
812 | local mode, n, s = parse_label(params[1], true) | ||
813 | if mode == "EXT" then werror("bad label definition") end | ||
814 | waction("LABEL_"..mode, n, s, 1) | ||
815 | end | ||
816 | |||
817 | ------------------------------------------------------------------------------ | ||
818 | |||
819 | -- Pseudo-opcodes for data storage. | ||
820 | map_op[".long_*"] = function(params) | ||
821 | if not params then return "imm..." end | ||
822 | for _,p in ipairs(params) do | ||
823 | local n = tonumber(p) | ||
824 | if not n then werror("bad immediate `"..p.."'") end | ||
825 | if n < 0 then n = n + 2^32 end | ||
826 | wputw(n) | ||
827 | if secpos+2 > maxsecpos then wflush() end | ||
828 | end | ||
829 | end | ||
830 | |||
831 | -- Alignment pseudo-opcode. | ||
832 | map_op[".align_1"] = function(params) | ||
833 | if not params then return "numpow2" end | ||
834 | if secpos+1 > maxsecpos then wflush() end | ||
835 | local align = tonumber(params[1]) | ||
836 | if align then | ||
837 | local x = align | ||
838 | -- Must be a power of 2 in the range (2 ... 256). | ||
839 | for i=1,8 do | ||
840 | x = x / 2 | ||
841 | if x == 1 then | ||
842 | waction("ALIGN", align-1, nil, 1) -- Action byte is 2**n-1. | ||
843 | return | ||
844 | end | ||
845 | end | ||
846 | end | ||
847 | werror("bad alignment") | ||
848 | end | ||
849 | |||
850 | ------------------------------------------------------------------------------ | ||
851 | |||
852 | -- Pseudo-opcode for (primitive) type definitions (map to C types). | ||
853 | map_op[".type_3"] = function(params, nparams) | ||
854 | if not params then | ||
855 | return nparams == 2 and "name, ctype" or "name, ctype, reg" | ||
856 | end | ||
857 | local name, ctype, reg = params[1], params[2], params[3] | ||
858 | if not match(name, "^[%a_][%w_]*$") then | ||
859 | werror("bad type name `"..name.."'") | ||
860 | end | ||
861 | local tp = map_type[name] | ||
862 | if tp then | ||
863 | werror("duplicate type `"..name.."'") | ||
864 | end | ||
865 | -- Add #type to defines. A bit unclean to put it in map_archdef. | ||
866 | map_archdef["#"..name] = "sizeof("..ctype..")" | ||
867 | -- Add new type and emit shortcut define. | ||
868 | local num = ctypenum + 1 | ||
869 | map_type[name] = { | ||
870 | ctype = ctype, | ||
871 | ctypefmt = format("Dt%X(%%s)", num), | ||
872 | reg = reg, | ||
873 | } | ||
874 | wline(format("#define Dt%X(_V) (int)(ptrdiff_t)&(((%s *)0)_V)", num, ctype)) | ||
875 | ctypenum = num | ||
876 | end | ||
877 | map_op[".type_2"] = map_op[".type_3"] | ||
878 | |||
879 | -- Dump type definitions. | ||
880 | local function dumptypes(out, lvl) | ||
881 | local t = {} | ||
882 | for name in pairs(map_type) do t[#t+1] = name end | ||
883 | sort(t) | ||
884 | out:write("Type definitions:\n") | ||
885 | for _,name in ipairs(t) do | ||
886 | local tp = map_type[name] | ||
887 | local reg = tp.reg or "" | ||
888 | out:write(format(" %-20s %-20s %s\n", name, tp.ctype, reg)) | ||
889 | end | ||
890 | out:write("\n") | ||
891 | end | ||
892 | |||
893 | ------------------------------------------------------------------------------ | ||
894 | |||
895 | -- Set the current section. | ||
896 | function _M.section(num) | ||
897 | waction("SECTION", num) | ||
898 | wflush(true) -- SECTION is a terminal action. | ||
899 | end | ||
900 | |||
901 | ------------------------------------------------------------------------------ | ||
902 | |||
903 | -- Dump architecture description. | ||
904 | function _M.dumparch(out) | ||
905 | out:write(format("DynASM %s version %s, released %s\n\n", | ||
906 | _info.arch, _info.version, _info.release)) | ||
907 | dumpactions(out) | ||
908 | end | ||
909 | |||
910 | -- Dump all user defined elements. | ||
911 | function _M.dumpdef(out, lvl) | ||
912 | dumptypes(out, lvl) | ||
913 | dumpglobals(out, lvl) | ||
914 | dumpexterns(out, lvl) | ||
915 | end | ||
916 | |||
917 | ------------------------------------------------------------------------------ | ||
918 | |||
919 | -- Pass callbacks from/to the DynASM core. | ||
920 | function _M.passcb(wl, we, wf, ww) | ||
921 | wline, werror, wfatal, wwarn = wl, we, wf, ww | ||
922 | return wflush | ||
923 | end | ||
924 | |||
925 | -- Setup the arch-specific module. | ||
926 | function _M.setup(arch, opt) | ||
927 | g_arch, g_opt = arch, opt | ||
928 | end | ||
929 | |||
930 | -- Merge the core maps and the arch-specific maps. | ||
931 | function _M.mergemaps(map_coreop, map_def) | ||
932 | setmetatable(map_op, { __index = function(t, k) | ||
933 | local v = map_coreop[k] | ||
934 | if v then return v end | ||
935 | local cc = sub(k, -4, -3) | ||
936 | local cv = map_cond[cc] | ||
937 | if cv then | ||
938 | local v = rawget(t, sub(k, 1, -5)..sub(k, -2)) | ||
939 | if type(v) == "string" then return format("%x%s", cv, sub(v, 2)) end | ||
940 | end | ||
941 | end }) | ||
942 | setmetatable(map_def, { __index = map_archdef }) | ||
943 | return map_op, map_def | ||
944 | end | ||
945 | |||
946 | return _M | ||
947 | |||
948 | ------------------------------------------------------------------------------ | ||
949 | |||
diff --git a/libraries/luajit-2.0/dynasm/dasm_mips.h b/libraries/luajit-2.0/dynasm/dasm_mips.h new file mode 100644 index 0000000..832f9f2 --- /dev/null +++ b/libraries/luajit-2.0/dynasm/dasm_mips.h | |||
@@ -0,0 +1,415 @@ | |||
1 | /* | ||
2 | ** DynASM MIPS encoding engine. | ||
3 | ** Copyright (C) 2005-2011 Mike Pall. All rights reserved. | ||
4 | ** Released under the MIT license. See dynasm.lua for full copyright notice. | ||
5 | */ | ||
6 | |||
7 | #include <stddef.h> | ||
8 | #include <stdarg.h> | ||
9 | #include <string.h> | ||
10 | #include <stdlib.h> | ||
11 | |||
12 | #define DASM_ARCH "mips" | ||
13 | |||
14 | #ifndef DASM_EXTERN | ||
15 | #define DASM_EXTERN(a,b,c,d) 0 | ||
16 | #endif | ||
17 | |||
18 | /* Action definitions. */ | ||
19 | enum { | ||
20 | DASM_STOP, DASM_SECTION, DASM_ESC, DASM_REL_EXT, | ||
21 | /* The following actions need a buffer position. */ | ||
22 | DASM_ALIGN, DASM_REL_LG, DASM_LABEL_LG, | ||
23 | /* The following actions also have an argument. */ | ||
24 | DASM_REL_PC, DASM_LABEL_PC, DASM_IMM, | ||
25 | DASM__MAX | ||
26 | }; | ||
27 | |||
28 | /* Maximum number of section buffer positions for a single dasm_put() call. */ | ||
29 | #define DASM_MAXSECPOS 25 | ||
30 | |||
31 | /* DynASM encoder status codes. Action list offset or number are or'ed in. */ | ||
32 | #define DASM_S_OK 0x00000000 | ||
33 | #define DASM_S_NOMEM 0x01000000 | ||
34 | #define DASM_S_PHASE 0x02000000 | ||
35 | #define DASM_S_MATCH_SEC 0x03000000 | ||
36 | #define DASM_S_RANGE_I 0x11000000 | ||
37 | #define DASM_S_RANGE_SEC 0x12000000 | ||
38 | #define DASM_S_RANGE_LG 0x13000000 | ||
39 | #define DASM_S_RANGE_PC 0x14000000 | ||
40 | #define DASM_S_RANGE_REL 0x15000000 | ||
41 | #define DASM_S_UNDEF_LG 0x21000000 | ||
42 | #define DASM_S_UNDEF_PC 0x22000000 | ||
43 | |||
44 | /* Macros to convert positions (8 bit section + 24 bit index). */ | ||
45 | #define DASM_POS2IDX(pos) ((pos)&0x00ffffff) | ||
46 | #define DASM_POS2BIAS(pos) ((pos)&0xff000000) | ||
47 | #define DASM_SEC2POS(sec) ((sec)<<24) | ||
48 | #define DASM_POS2SEC(pos) ((pos)>>24) | ||
49 | #define DASM_POS2PTR(D, pos) (D->sections[DASM_POS2SEC(pos)].rbuf + (pos)) | ||
50 | |||
51 | /* Action list type. */ | ||
52 | typedef const unsigned int *dasm_ActList; | ||
53 | |||
54 | /* Per-section structure. */ | ||
55 | typedef struct dasm_Section { | ||
56 | int *rbuf; /* Biased buffer pointer (negative section bias). */ | ||
57 | int *buf; /* True buffer pointer. */ | ||
58 | size_t bsize; /* Buffer size in bytes. */ | ||
59 | int pos; /* Biased buffer position. */ | ||
60 | int epos; /* End of biased buffer position - max single put. */ | ||
61 | int ofs; /* Byte offset into section. */ | ||
62 | } dasm_Section; | ||
63 | |||
64 | /* Core structure holding the DynASM encoding state. */ | ||
65 | struct dasm_State { | ||
66 | size_t psize; /* Allocated size of this structure. */ | ||
67 | dasm_ActList actionlist; /* Current actionlist pointer. */ | ||
68 | int *lglabels; /* Local/global chain/pos ptrs. */ | ||
69 | size_t lgsize; | ||
70 | int *pclabels; /* PC label chains/pos ptrs. */ | ||
71 | size_t pcsize; | ||
72 | void **globals; /* Array of globals (bias -10). */ | ||
73 | dasm_Section *section; /* Pointer to active section. */ | ||
74 | size_t codesize; /* Total size of all code sections. */ | ||
75 | int maxsection; /* 0 <= sectionidx < maxsection. */ | ||
76 | int status; /* Status code. */ | ||
77 | dasm_Section sections[1]; /* All sections. Alloc-extended. */ | ||
78 | }; | ||
79 | |||
80 | /* The size of the core structure depends on the max. number of sections. */ | ||
81 | #define DASM_PSZ(ms) (sizeof(dasm_State)+(ms-1)*sizeof(dasm_Section)) | ||
82 | |||
83 | |||
84 | /* Initialize DynASM state. */ | ||
85 | void dasm_init(Dst_DECL, int maxsection) | ||
86 | { | ||
87 | dasm_State *D; | ||
88 | size_t psz = 0; | ||
89 | int i; | ||
90 | Dst_REF = NULL; | ||
91 | DASM_M_GROW(Dst, struct dasm_State, Dst_REF, psz, DASM_PSZ(maxsection)); | ||
92 | D = Dst_REF; | ||
93 | D->psize = psz; | ||
94 | D->lglabels = NULL; | ||
95 | D->lgsize = 0; | ||
96 | D->pclabels = NULL; | ||
97 | D->pcsize = 0; | ||
98 | D->globals = NULL; | ||
99 | D->maxsection = maxsection; | ||
100 | for (i = 0; i < maxsection; i++) { | ||
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 | } | ||
107 | |||
108 | /* Free DynASM state. */ | ||
109 | void dasm_free(Dst_DECL) | ||
110 | { | ||
111 | dasm_State *D = Dst_REF; | ||
112 | int i; | ||
113 | for (i = 0; i < D->maxsection; i++) | ||
114 | if (D->sections[i].buf) | ||
115 | DASM_M_FREE(Dst, D->sections[i].buf, D->sections[i].bsize); | ||
116 | if (D->pclabels) DASM_M_FREE(Dst, D->pclabels, D->pcsize); | ||
117 | if (D->lglabels) DASM_M_FREE(Dst, D->lglabels, D->lgsize); | ||
118 | DASM_M_FREE(Dst, D, D->psize); | ||
119 | } | ||
120 | |||
121 | /* Setup global label array. Must be called before dasm_setup(). */ | ||
122 | void dasm_setupglobal(Dst_DECL, void **gl, unsigned int maxgl) | ||
123 | { | ||
124 | dasm_State *D = Dst_REF; | ||
125 | D->globals = gl - 10; /* Negative bias to compensate for locals. */ | ||
126 | DASM_M_GROW(Dst, int, D->lglabels, D->lgsize, (10+maxgl)*sizeof(int)); | ||
127 | } | ||
128 | |||
129 | /* Grow PC label array. Can be called after dasm_setup(), too. */ | ||
130 | void dasm_growpc(Dst_DECL, unsigned int maxpc) | ||
131 | { | ||
132 | dasm_State *D = Dst_REF; | ||
133 | size_t osz = D->pcsize; | ||
134 | DASM_M_GROW(Dst, int, D->pclabels, D->pcsize, maxpc*sizeof(int)); | ||
135 | memset((void *)(((unsigned char *)D->pclabels)+osz), 0, D->pcsize-osz); | ||
136 | } | ||
137 | |||
138 | /* Setup encoder. */ | ||
139 | void dasm_setup(Dst_DECL, const void *actionlist) | ||
140 | { | ||
141 | dasm_State *D = Dst_REF; | ||
142 | int i; | ||
143 | D->actionlist = (dasm_ActList)actionlist; | ||
144 | D->status = DASM_S_OK; | ||
145 | D->section = &D->sections[0]; | ||
146 | memset((void *)D->lglabels, 0, D->lgsize); | ||
147 | if (D->pclabels) memset((void *)D->pclabels, 0, D->pcsize); | ||
148 | for (i = 0; i < D->maxsection; i++) { | ||
149 | D->sections[i].pos = DASM_SEC2POS(i); | ||
150 | D->sections[i].ofs = 0; | ||
151 | } | ||
152 | } | ||
153 | |||
154 | |||
155 | #ifdef DASM_CHECKS | ||
156 | #define CK(x, st) \ | ||
157 | do { if (!(x)) { \ | ||
158 | D->status = DASM_S_##st|(p-D->actionlist-1); return; } } while (0) | ||
159 | #define CKPL(kind, st) \ | ||
160 | 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) | ||
162 | #else | ||
163 | #define CK(x, st) ((void)0) | ||
164 | #define CKPL(kind, st) ((void)0) | ||
165 | #endif | ||
166 | |||
167 | /* Pass 1: Store actions and args, link branches/labels, estimate offsets. */ | ||
168 | void dasm_put(Dst_DECL, int start, ...) | ||
169 | { | ||
170 | va_list ap; | ||
171 | dasm_State *D = Dst_REF; | ||
172 | dasm_ActList p = D->actionlist + start; | ||
173 | dasm_Section *sec = D->section; | ||
174 | int pos = sec->pos, ofs = sec->ofs; | ||
175 | int *b; | ||
176 | |||
177 | if (pos >= sec->epos) { | ||
178 | DASM_M_GROW(Dst, int, sec->buf, sec->bsize, | ||
179 | sec->bsize + 2*DASM_MAXSECPOS*sizeof(int)); | ||
180 | sec->rbuf = sec->buf - DASM_POS2BIAS(pos); | ||
181 | sec->epos = (int)sec->bsize/sizeof(int) - DASM_MAXSECPOS+DASM_POS2BIAS(pos); | ||
182 | } | ||
183 | |||
184 | b = sec->rbuf; | ||
185 | b[pos++] = start; | ||
186 | |||
187 | va_start(ap, start); | ||
188 | while (1) { | ||
189 | unsigned int ins = *p++; | ||
190 | unsigned int action = (ins >> 16) - 0xff00; | ||
191 | if (action >= DASM__MAX) { | ||
192 | ofs += 4; | ||
193 | } else { | ||
194 | int *pl, n = action >= DASM_REL_PC ? va_arg(ap, int) : 0; | ||
195 | switch (action) { | ||
196 | case DASM_STOP: goto stop; | ||
197 | case DASM_SECTION: | ||
198 | n = (ins & 255); CK(n < D->maxsection, RANGE_SEC); | ||
199 | D->section = &D->sections[n]; goto stop; | ||
200 | case DASM_ESC: p++; ofs += 4; break; | ||
201 | case DASM_REL_EXT: break; | ||
202 | case DASM_ALIGN: ofs += (ins & 255); b[pos++] = ofs; break; | ||
203 | case DASM_REL_LG: | ||
204 | n = (ins & 2047) - 10; pl = D->lglabels + n; | ||
205 | if (n >= 0) { CKPL(lg, LG); goto putrel; } /* Bkwd rel or global. */ | ||
206 | pl += 10; n = *pl; | ||
207 | if (n < 0) n = 0; /* Start new chain for fwd rel if label exists. */ | ||
208 | goto linkrel; | ||
209 | case DASM_REL_PC: | ||
210 | pl = D->pclabels + n; CKPL(pc, PC); | ||
211 | putrel: | ||
212 | n = *pl; | ||
213 | if (n < 0) { /* Label exists. Get label pos and store it. */ | ||
214 | b[pos] = -n; | ||
215 | } else { | ||
216 | linkrel: | ||
217 | b[pos] = n; /* Else link to rel chain, anchored at label. */ | ||
218 | *pl = pos; | ||
219 | } | ||
220 | pos++; | ||
221 | break; | ||
222 | case DASM_LABEL_LG: | ||
223 | pl = D->lglabels + (ins & 2047) - 10; CKPL(lg, LG); goto putlabel; | ||
224 | case DASM_LABEL_PC: | ||
225 | pl = D->pclabels + n; CKPL(pc, PC); | ||
226 | putlabel: | ||
227 | n = *pl; /* n > 0: Collapse rel chain and replace with label pos. */ | ||
228 | while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = pos; | ||
229 | } | ||
230 | *pl = -pos; /* Label exists now. */ | ||
231 | b[pos++] = ofs; /* Store pass1 offset estimate. */ | ||
232 | break; | ||
233 | case DASM_IMM: | ||
234 | #ifdef DASM_CHECKS | ||
235 | CK((n & ((1<<((ins>>10)&31))-1)) == 0, RANGE_I); | ||
236 | #endif | ||
237 | n >>= ((ins>>10)&31); | ||
238 | #ifdef DASM_CHECKS | ||
239 | if (ins & 0x8000) | ||
240 | CK(((n + (1<<(((ins>>5)&31)-1)))>>((ins>>5)&31)) == 0, RANGE_I); | ||
241 | else | ||
242 | CK((n>>((ins>>5)&31)) == 0, RANGE_I); | ||
243 | #endif | ||
244 | b[pos++] = n; | ||
245 | break; | ||
246 | } | ||
247 | } | ||
248 | } | ||
249 | stop: | ||
250 | va_end(ap); | ||
251 | sec->pos = pos; | ||
252 | sec->ofs = ofs; | ||
253 | } | ||
254 | #undef CK | ||
255 | |||
256 | /* Pass 2: Link sections, shrink aligns, fix label offsets. */ | ||
257 | int dasm_link(Dst_DECL, size_t *szp) | ||
258 | { | ||
259 | dasm_State *D = Dst_REF; | ||
260 | int secnum; | ||
261 | int ofs = 0; | ||
262 | |||
263 | #ifdef DASM_CHECKS | ||
264 | *szp = 0; | ||
265 | if (D->status != DASM_S_OK) return D->status; | ||
266 | { | ||
267 | int pc; | ||
268 | for (pc = 0; pc*sizeof(int) < D->pcsize; pc++) | ||
269 | if (D->pclabels[pc] > 0) return DASM_S_UNDEF_PC|pc; | ||
270 | } | ||
271 | #endif | ||
272 | |||
273 | { /* Handle globals not defined in this translation unit. */ | ||
274 | int idx; | ||
275 | for (idx = 20; idx*sizeof(int) < D->lgsize; idx++) { | ||
276 | int n = D->lglabels[idx]; | ||
277 | /* Undefined label: Collapse rel chain and replace with marker (< 0). */ | ||
278 | while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = -idx; } | ||
279 | } | ||
280 | } | ||
281 | |||
282 | /* Combine all code sections. No support for data sections (yet). */ | ||
283 | for (secnum = 0; secnum < D->maxsection; secnum++) { | ||
284 | dasm_Section *sec = D->sections + secnum; | ||
285 | int *b = sec->rbuf; | ||
286 | int pos = DASM_SEC2POS(secnum); | ||
287 | int lastpos = sec->pos; | ||
288 | |||
289 | while (pos != lastpos) { | ||
290 | dasm_ActList p = D->actionlist + b[pos++]; | ||
291 | while (1) { | ||
292 | unsigned int ins = *p++; | ||
293 | unsigned int action = (ins >> 16) - 0xff00; | ||
294 | switch (action) { | ||
295 | case DASM_STOP: case DASM_SECTION: goto stop; | ||
296 | case DASM_ESC: p++; break; | ||
297 | case DASM_REL_EXT: break; | ||
298 | case DASM_ALIGN: ofs -= (b[pos++] + ofs) & (ins & 255); break; | ||
299 | case DASM_REL_LG: case DASM_REL_PC: pos++; break; | ||
300 | case DASM_LABEL_LG: case DASM_LABEL_PC: b[pos++] += ofs; break; | ||
301 | case DASM_IMM: pos++; break; | ||
302 | } | ||
303 | } | ||
304 | stop: (void)0; | ||
305 | } | ||
306 | ofs += sec->ofs; /* Next section starts right after current section. */ | ||
307 | } | ||
308 | |||
309 | D->codesize = ofs; /* Total size of all code sections */ | ||
310 | *szp = ofs; | ||
311 | return DASM_S_OK; | ||
312 | } | ||
313 | |||
314 | #ifdef DASM_CHECKS | ||
315 | #define CK(x, st) \ | ||
316 | do { if (!(x)) return DASM_S_##st|(p-D->actionlist-1); } while (0) | ||
317 | #else | ||
318 | #define CK(x, st) ((void)0) | ||
319 | #endif | ||
320 | |||
321 | /* Pass 3: Encode sections. */ | ||
322 | int dasm_encode(Dst_DECL, void *buffer) | ||
323 | { | ||
324 | dasm_State *D = Dst_REF; | ||
325 | char *base = (char *)buffer; | ||
326 | unsigned int *cp = (unsigned int *)buffer; | ||
327 | int secnum; | ||
328 | |||
329 | /* Encode all code sections. No support for data sections (yet). */ | ||
330 | for (secnum = 0; secnum < D->maxsection; secnum++) { | ||
331 | dasm_Section *sec = D->sections + secnum; | ||
332 | int *b = sec->buf; | ||
333 | int *endb = sec->rbuf + sec->pos; | ||
334 | |||
335 | while (b != endb) { | ||
336 | dasm_ActList p = D->actionlist + *b++; | ||
337 | while (1) { | ||
338 | unsigned int ins = *p++; | ||
339 | unsigned int action = (ins >> 16) - 0xff00; | ||
340 | int n = (action >= DASM_ALIGN && action < DASM__MAX) ? *b++ : 0; | ||
341 | switch (action) { | ||
342 | case DASM_STOP: case DASM_SECTION: goto stop; | ||
343 | case DASM_ESC: *cp++ = *p++; break; | ||
344 | case DASM_REL_EXT: | ||
345 | n = DASM_EXTERN(Dst, (unsigned char *)cp, (ins & 2047), 1); | ||
346 | goto patchrel; | ||
347 | case DASM_ALIGN: | ||
348 | ins &= 255; while ((((char *)cp - base) & ins)) *cp++ = 0x60000000; | ||
349 | break; | ||
350 | case DASM_REL_LG: | ||
351 | CK(n >= 0, UNDEF_LG); | ||
352 | case DASM_REL_PC: | ||
353 | CK(n >= 0, UNDEF_PC); | ||
354 | n = *DASM_POS2PTR(D, n); | ||
355 | if (ins & 2048) | ||
356 | n = n - (int)((char *)cp - base); | ||
357 | else | ||
358 | n = (n + (int)base) & 0x0fffffff; | ||
359 | patchrel: | ||
360 | CK((n & 3) == 0 && | ||
361 | ((n + ((ins & 2048) ? 0x00020000 : 0)) >> | ||
362 | ((ins & 2048) ? 18 : 28)) == 0, RANGE_REL); | ||
363 | cp[-1] |= ((n>>2) & ((ins & 2048) ? 0x0000ffff: 0x03ffffff)); | ||
364 | break; | ||
365 | case DASM_LABEL_LG: | ||
366 | ins &= 2047; if (ins >= 20) D->globals[ins-10] = (void *)(base + n); | ||
367 | break; | ||
368 | case DASM_LABEL_PC: break; | ||
369 | case DASM_IMM: | ||
370 | cp[-1] |= (n & ((1<<((ins>>5)&31))-1)) << (ins&31); | ||
371 | break; | ||
372 | default: *cp++ = ins; break; | ||
373 | } | ||
374 | } | ||
375 | stop: (void)0; | ||
376 | } | ||
377 | } | ||
378 | |||
379 | if (base + D->codesize != (char *)cp) /* Check for phase errors. */ | ||
380 | return DASM_S_PHASE; | ||
381 | return DASM_S_OK; | ||
382 | } | ||
383 | #undef CK | ||
384 | |||
385 | /* Get PC label offset. */ | ||
386 | int dasm_getpclabel(Dst_DECL, unsigned int pc) | ||
387 | { | ||
388 | dasm_State *D = Dst_REF; | ||
389 | if (pc*sizeof(int) < D->pcsize) { | ||
390 | int pos = D->pclabels[pc]; | ||
391 | if (pos < 0) return *DASM_POS2PTR(D, -pos); | ||
392 | if (pos > 0) return -1; /* Undefined. */ | ||
393 | } | ||
394 | return -2; /* Unused or out of range. */ | ||
395 | } | ||
396 | |||
397 | #ifdef DASM_CHECKS | ||
398 | /* Optional sanity checker to call between isolated encoding steps. */ | ||
399 | int dasm_checkstep(Dst_DECL, int secmatch) | ||
400 | { | ||
401 | dasm_State *D = Dst_REF; | ||
402 | if (D->status == DASM_S_OK) { | ||
403 | int i; | ||
404 | for (i = 1; i <= 9; i++) { | ||
405 | if (D->lglabels[i] > 0) { D->status = DASM_S_UNDEF_LG|i; break; } | ||
406 | D->lglabels[i] = 0; | ||
407 | } | ||
408 | } | ||
409 | if (D->status == DASM_S_OK && secmatch >= 0 && | ||
410 | D->section != &D->sections[secmatch]) | ||
411 | D->status = DASM_S_MATCH_SEC|(D->section-D->sections); | ||
412 | return D->status; | ||
413 | } | ||
414 | #endif | ||
415 | |||
diff --git a/libraries/luajit-2.0/dynasm/dasm_mips.lua b/libraries/luajit-2.0/dynasm/dasm_mips.lua new file mode 100644 index 0000000..5cbae8b --- /dev/null +++ b/libraries/luajit-2.0/dynasm/dasm_mips.lua | |||
@@ -0,0 +1,948 @@ | |||
1 | ------------------------------------------------------------------------------ | ||
2 | -- DynASM MIPS module. | ||
3 | -- | ||
4 | -- Copyright (C) 2005-2011 Mike Pall. All rights reserved. | ||
5 | -- See dynasm.lua for full copyright notice. | ||
6 | ------------------------------------------------------------------------------ | ||
7 | |||
8 | -- Module information: | ||
9 | local _info = { | ||
10 | arch = "mips", | ||
11 | description = "DynASM MIPS module", | ||
12 | version = "1.3.0", | ||
13 | vernum = 10300, | ||
14 | release = "2011-12-16", | ||
15 | author = "Mike Pall", | ||
16 | license = "MIT", | ||
17 | } | ||
18 | |||
19 | -- Exported glue functions for the arch-specific module. | ||
20 | local _M = { _info = _info } | ||
21 | |||
22 | -- Cache library functions. | ||
23 | local type, tonumber, pairs, ipairs = type, tonumber, pairs, ipairs | ||
24 | local assert, setmetatable = assert, setmetatable | ||
25 | local _s = string | ||
26 | local sub, format, byte, char = _s.sub, _s.format, _s.byte, _s.char | ||
27 | local match, gmatch = _s.match, _s.gmatch | ||
28 | local concat, sort = table.concat, table.sort | ||
29 | |||
30 | -- Inherited tables and callbacks. | ||
31 | local g_opt, g_arch | ||
32 | local wline, werror, wfatal, wwarn | ||
33 | |||
34 | -- Action name list. | ||
35 | -- CHECK: Keep this in sync with the C code! | ||
36 | local action_names = { | ||
37 | "STOP", "SECTION", "ESC", "REL_EXT", | ||
38 | "ALIGN", "REL_LG", "LABEL_LG", | ||
39 | "REL_PC", "LABEL_PC", "IMM", | ||
40 | } | ||
41 | |||
42 | -- Maximum number of section buffer positions for dasm_put(). | ||
43 | -- CHECK: Keep this in sync with the C code! | ||
44 | local maxsecpos = 25 -- Keep this low, to avoid excessively long C lines. | ||
45 | |||
46 | -- Action name -> action number. | ||
47 | local map_action = {} | ||
48 | for n,name in ipairs(action_names) do | ||
49 | map_action[name] = n-1 | ||
50 | end | ||
51 | |||
52 | -- Action list buffer. | ||
53 | local actlist = {} | ||
54 | |||
55 | -- Argument list for next dasm_put(). Start with offset 0 into action list. | ||
56 | local actargs = { 0 } | ||
57 | |||
58 | -- Current number of section buffer positions for dasm_put(). | ||
59 | local secpos = 1 | ||
60 | |||
61 | ------------------------------------------------------------------------------ | ||
62 | |||
63 | -- Return 8 digit hex number. | ||
64 | local function tohex(x) | ||
65 | return sub(format("%08x", x), -8) -- Avoid 64 bit portability problem in Lua. | ||
66 | end | ||
67 | |||
68 | -- Dump action names and numbers. | ||
69 | local function dumpactions(out) | ||
70 | out:write("DynASM encoding engine action codes:\n") | ||
71 | for n,name in ipairs(action_names) do | ||
72 | local num = map_action[name] | ||
73 | out:write(format(" %-10s %02X %d\n", name, num, num)) | ||
74 | end | ||
75 | out:write("\n") | ||
76 | end | ||
77 | |||
78 | -- Write action list buffer as a huge static C array. | ||
79 | local function writeactions(out, name) | ||
80 | local nn = #actlist | ||
81 | if nn == 0 then nn = 1; actlist[0] = map_action.STOP end | ||
82 | out:write("static const unsigned int ", name, "[", nn, "] = {\n") | ||
83 | for i = 1,nn-1 do | ||
84 | assert(out:write("0x", tohex(actlist[i]), ",\n")) | ||
85 | end | ||
86 | assert(out:write("0x", tohex(actlist[nn]), "\n};\n\n")) | ||
87 | end | ||
88 | |||
89 | ------------------------------------------------------------------------------ | ||
90 | |||
91 | -- Add word to action list. | ||
92 | local function wputxw(n) | ||
93 | assert(n >= 0 and n <= 0xffffffff and n % 1 == 0, "word out of range") | ||
94 | actlist[#actlist+1] = n | ||
95 | end | ||
96 | |||
97 | -- Add action to list with optional arg. Advance buffer pos, too. | ||
98 | local function waction(action, val, a, num) | ||
99 | local w = assert(map_action[action], "bad action name `"..action.."'") | ||
100 | wputxw(0xff000000 + w * 0x10000 + (val or 0)) | ||
101 | if a then actargs[#actargs+1] = a end | ||
102 | if a or num then secpos = secpos + (num or 1) end | ||
103 | end | ||
104 | |||
105 | -- Flush action list (intervening C code or buffer pos overflow). | ||
106 | local function wflush(term) | ||
107 | if #actlist == actargs[1] then return end -- Nothing to flush. | ||
108 | if not term then waction("STOP") end -- Terminate action list. | ||
109 | wline(format("dasm_put(Dst, %s);", concat(actargs, ", ")), true) | ||
110 | actargs = { #actlist } -- Actionlist offset is 1st arg to next dasm_put(). | ||
111 | secpos = 1 -- The actionlist offset occupies a buffer position, too. | ||
112 | end | ||
113 | |||
114 | -- Put escaped word. | ||
115 | local function wputw(n) | ||
116 | if n >= 0xff000000 then waction("ESC") end | ||
117 | wputxw(n) | ||
118 | end | ||
119 | |||
120 | -- Reserve position for word. | ||
121 | local function wpos() | ||
122 | local pos = #actlist+1 | ||
123 | actlist[pos] = "" | ||
124 | return pos | ||
125 | end | ||
126 | |||
127 | -- Store word to reserved position. | ||
128 | local function wputpos(pos, n) | ||
129 | assert(n >= 0 and n <= 0xffffffff and n % 1 == 0, "word out of range") | ||
130 | actlist[pos] = n | ||
131 | end | ||
132 | |||
133 | ------------------------------------------------------------------------------ | ||
134 | |||
135 | -- Global label name -> global label number. With auto assignment on 1st use. | ||
136 | local next_global = 20 | ||
137 | local map_global = setmetatable({}, { __index = function(t, name) | ||
138 | if not match(name, "^[%a_][%w_]*$") then werror("bad global label") end | ||
139 | local n = next_global | ||
140 | if n > 2047 then werror("too many global labels") end | ||
141 | next_global = n + 1 | ||
142 | t[name] = n | ||
143 | return n | ||
144 | end}) | ||
145 | |||
146 | -- Dump global labels. | ||
147 | local function dumpglobals(out, lvl) | ||
148 | local t = {} | ||
149 | for name, n in pairs(map_global) do t[n] = name end | ||
150 | out:write("Global labels:\n") | ||
151 | for i=20,next_global-1 do | ||
152 | out:write(format(" %s\n", t[i])) | ||
153 | end | ||
154 | out:write("\n") | ||
155 | end | ||
156 | |||
157 | -- Write global label enum. | ||
158 | local function writeglobals(out, prefix) | ||
159 | local t = {} | ||
160 | for name, n in pairs(map_global) do t[n] = name end | ||
161 | out:write("enum {\n") | ||
162 | for i=20,next_global-1 do | ||
163 | out:write(" ", prefix, t[i], ",\n") | ||
164 | end | ||
165 | out:write(" ", prefix, "_MAX\n};\n") | ||
166 | end | ||
167 | |||
168 | -- Write global label names. | ||
169 | local function writeglobalnames(out, name) | ||
170 | local t = {} | ||
171 | for name, n in pairs(map_global) do t[n] = name end | ||
172 | out:write("static const char *const ", name, "[] = {\n") | ||
173 | for i=20,next_global-1 do | ||
174 | out:write(" \"", t[i], "\",\n") | ||
175 | end | ||
176 | out:write(" (const char *)0\n};\n") | ||
177 | end | ||
178 | |||
179 | ------------------------------------------------------------------------------ | ||
180 | |||
181 | -- Extern label name -> extern label number. With auto assignment on 1st use. | ||
182 | local next_extern = 0 | ||
183 | local map_extern_ = {} | ||
184 | local map_extern = setmetatable({}, { __index = function(t, name) | ||
185 | -- No restrictions on the name for now. | ||
186 | local n = next_extern | ||
187 | if n > 2047 then werror("too many extern labels") end | ||
188 | next_extern = n + 1 | ||
189 | t[name] = n | ||
190 | map_extern_[n] = name | ||
191 | return n | ||
192 | end}) | ||
193 | |||
194 | -- Dump extern labels. | ||
195 | local function dumpexterns(out, lvl) | ||
196 | out:write("Extern labels:\n") | ||
197 | for i=0,next_extern-1 do | ||
198 | out:write(format(" %s\n", map_extern_[i])) | ||
199 | end | ||
200 | out:write("\n") | ||
201 | end | ||
202 | |||
203 | -- Write extern label names. | ||
204 | local function writeexternnames(out, name) | ||
205 | out:write("static const char *const ", name, "[] = {\n") | ||
206 | for i=0,next_extern-1 do | ||
207 | out:write(" \"", map_extern_[i], "\",\n") | ||
208 | end | ||
209 | out:write(" (const char *)0\n};\n") | ||
210 | end | ||
211 | |||
212 | ------------------------------------------------------------------------------ | ||
213 | |||
214 | -- Arch-specific maps. | ||
215 | local map_archdef = { sp="r29", ra="r31" } -- Ext. register name -> int. name. | ||
216 | |||
217 | local map_type = {} -- Type name -> { ctype, reg } | ||
218 | local ctypenum = 0 -- Type number (for Dt... macros). | ||
219 | |||
220 | -- Reverse defines for registers. | ||
221 | function _M.revdef(s) | ||
222 | if s == "r29" then return "sp" | ||
223 | elseif s == "r31" then return "ra" end | ||
224 | return s | ||
225 | end | ||
226 | |||
227 | ------------------------------------------------------------------------------ | ||
228 | |||
229 | -- Template strings for MIPS instructions. | ||
230 | local map_op = { | ||
231 | -- First-level opcodes. | ||
232 | j_1 = "08000000J", | ||
233 | jal_1 = "0c000000J", | ||
234 | b_1 = "10000000B", | ||
235 | beqz_2 = "10000000SB", | ||
236 | beq_3 = "10000000STB", | ||
237 | bnez_2 = "14000000SB", | ||
238 | bne_3 = "14000000STB", | ||
239 | blez_2 = "18000000SB", | ||
240 | bgtz_2 = "1c000000SB", | ||
241 | addi_3 = "20000000TSI", | ||
242 | li_2 = "24000000TI", | ||
243 | addiu_3 = "24000000TSI", | ||
244 | slti_3 = "28000000TSI", | ||
245 | sltiu_3 = "2c000000TSI", | ||
246 | andi_3 = "30000000TSU", | ||
247 | lu_2 = "34000000TU", | ||
248 | ori_3 = "34000000TSU", | ||
249 | xori_3 = "38000000TSU", | ||
250 | lui_2 = "3c000000TU", | ||
251 | beqzl_2 = "50000000SB", | ||
252 | beql_3 = "50000000STB", | ||
253 | bnezl_2 = "54000000SB", | ||
254 | bnel_3 = "54000000STB", | ||
255 | blezl_2 = "58000000SB", | ||
256 | bgtzl_2 = "5c000000SB", | ||
257 | lb_2 = "80000000TO", | ||
258 | lh_2 = "84000000TO", | ||
259 | lwl_2 = "88000000TO", | ||
260 | lw_2 = "8c000000TO", | ||
261 | lbu_2 = "90000000TO", | ||
262 | lhu_2 = "94000000TO", | ||
263 | lwr_2 = "98000000TO", | ||
264 | sb_2 = "a0000000TO", | ||
265 | sh_2 = "a4000000TO", | ||
266 | swl_2 = "a8000000TO", | ||
267 | sw_2 = "ac000000TO", | ||
268 | swr_2 = "b8000000TO", | ||
269 | cache_2 = "bc000000NO", | ||
270 | ll_2 = "c0000000TO", | ||
271 | lwc1_2 = "c4000000HO", | ||
272 | pref_2 = "cc000000NO", | ||
273 | ldc1_2 = "d4000000HO", | ||
274 | sc_2 = "e0000000TO", | ||
275 | swc1_2 = "e4000000HO", | ||
276 | sdc1_2 = "f4000000HO", | ||
277 | |||
278 | -- Opcode SPECIAL. | ||
279 | nop_0 = "00000000", | ||
280 | sll_3 = "00000000DTA", | ||
281 | movf_3 = "00000001DSC", | ||
282 | movt_3 = "00010001DSC", | ||
283 | srl_3 = "00000002DTA", | ||
284 | rotr_3 = "00200002DTA", | ||
285 | sra_3 = "00000003DTA", | ||
286 | sllv_3 = "00000004DTS", | ||
287 | srlv_3 = "00000006DTS", | ||
288 | rotrv_3 = "00000046DTS", | ||
289 | srav_3 = "00000007DTS", | ||
290 | jr_1 = "00000008S", | ||
291 | jalr_1 = "0000f809S", | ||
292 | jalr_2 = "00000009DS", | ||
293 | movz_3 = "0000000aDST", | ||
294 | movn_3 = "0000000bDST", | ||
295 | syscall_0 = "0000000c", | ||
296 | syscall_1 = "0000000cY", | ||
297 | break_0 = "0000000d", | ||
298 | break_1 = "0000000dY", | ||
299 | sync_0 = "0000000f", | ||
300 | mfhi_1 = "00000010D", | ||
301 | mthi_1 = "00000011S", | ||
302 | mflo_1 = "00000012D", | ||
303 | mtlo_1 = "00000013S", | ||
304 | mult_2 = "00000018ST", | ||
305 | multu_2 = "00000019ST", | ||
306 | div_2 = "0000001aST", | ||
307 | divu_2 = "0000001bST", | ||
308 | add_3 = "00000020DST", | ||
309 | move_2 = "00000021DS", | ||
310 | addu_3 = "00000021DST", | ||
311 | sub_3 = "00000022DST", | ||
312 | subu_3 = "00000023DST", | ||
313 | and_3 = "00000024DST", | ||
314 | or_3 = "00000025DST", | ||
315 | xor_3 = "00000026DST", | ||
316 | nor_3 = "00000027DST", | ||
317 | slt_3 = "0000002aDST", | ||
318 | sltu_3 = "0000002bDST", | ||
319 | tge_2 = "00000030ST", | ||
320 | tge_3 = "00000030STZ", | ||
321 | tgeu_2 = "00000031ST", | ||
322 | tgeu_3 = "00000031STZ", | ||
323 | tlt_2 = "00000032ST", | ||
324 | tlt_3 = "00000032STZ", | ||
325 | tltu_2 = "00000033ST", | ||
326 | tltu_3 = "00000033STZ", | ||
327 | teq_2 = "00000034ST", | ||
328 | teq_3 = "00000034STZ", | ||
329 | tne_2 = "00000036ST", | ||
330 | tne_3 = "00000036STZ", | ||
331 | |||
332 | -- Opcode REGIMM. | ||
333 | bltz_2 = "04000000SB", | ||
334 | bgez_2 = "04010000SB", | ||
335 | bltzl_2 = "04020000SB", | ||
336 | bgezl_2 = "04030000SB", | ||
337 | tgei_2 = "04080000SI", | ||
338 | tgeiu_2 = "04090000SI", | ||
339 | tlti_2 = "040a0000SI", | ||
340 | tltiu_2 = "040b0000SI", | ||
341 | teqi_2 = "040c0000SI", | ||
342 | tnei_2 = "040e0000SI", | ||
343 | bltzal_2 = "04100000SB", | ||
344 | bgezal_2 = "04110000SB", | ||
345 | bltzall_2 = "04120000SB", | ||
346 | bgezall_2 = "04130000SB", | ||
347 | synci_1 = "041f0000O", | ||
348 | |||
349 | -- Opcode SPECIAL2. | ||
350 | madd_2 = "70000000ST", | ||
351 | maddu_2 = "70000001ST", | ||
352 | mul_3 = "70000002DST", | ||
353 | msub_2 = "70000004ST", | ||
354 | msubu_2 = "70000005ST", | ||
355 | clz_2 = "70000020DS=", | ||
356 | clo_2 = "70000021DS=", | ||
357 | sdbbp_0 = "7000003f", | ||
358 | sdbbp_1 = "7000003fY", | ||
359 | |||
360 | -- Opcode SPECIAL3. | ||
361 | ext_4 = "7c000000TSAM", -- Note: last arg is msbd = size-1 | ||
362 | ins_4 = "7c000004TSAM", -- Note: last arg is msb = pos+size-1 | ||
363 | wsbh_2 = "7c0000a0DT", | ||
364 | seb_2 = "7c000420DT", | ||
365 | seh_2 = "7c000620DT", | ||
366 | rdhwr_2 = "7c00003bTD", | ||
367 | |||
368 | -- Opcode COP0. | ||
369 | mfc0_2 = "40000000TD", | ||
370 | mfc0_3 = "40000000TDW", | ||
371 | mtc0_2 = "40800000TD", | ||
372 | mtc0_3 = "40800000TDW", | ||
373 | rdpgpr_2 = "41400000DT", | ||
374 | di_0 = "41606000", | ||
375 | di_1 = "41606000T", | ||
376 | ei_0 = "41606020", | ||
377 | ei_1 = "41606020T", | ||
378 | wrpgpr_2 = "41c00000DT", | ||
379 | tlbr_0 = "42000001", | ||
380 | tlbwi_0 = "42000002", | ||
381 | tlbwr_0 = "42000006", | ||
382 | tlbp_0 = "42000008", | ||
383 | eret_0 = "42000018", | ||
384 | deret_0 = "4200001f", | ||
385 | wait_0 = "42000020", | ||
386 | |||
387 | -- Opcode COP1. | ||
388 | mfc1_2 = "44000000TG", | ||
389 | cfc1_2 = "44400000TG", | ||
390 | mfhc1_2 = "44600000TG", | ||
391 | mtc1_2 = "44800000TG", | ||
392 | ctc1_2 = "44c00000TG", | ||
393 | mthc1_2 = "44e00000TG", | ||
394 | |||
395 | bc1f_1 = "45000000B", | ||
396 | bc1f_2 = "45000000CB", | ||
397 | bc1t_1 = "45010000B", | ||
398 | bc1t_2 = "45010000CB", | ||
399 | bc1fl_1 = "45020000B", | ||
400 | bc1fl_2 = "45020000CB", | ||
401 | bc1tl_1 = "45030000B", | ||
402 | bc1tl_2 = "45030000CB", | ||
403 | |||
404 | ["add.s_3"] = "46000000FGH", | ||
405 | ["sub.s_3"] = "46000001FGH", | ||
406 | ["mul.s_3"] = "46000002FGH", | ||
407 | ["div.s_3"] = "46000003FGH", | ||
408 | ["sqrt.s_2"] = "46000004FG", | ||
409 | ["abs.s_2"] = "46000005FG", | ||
410 | ["mov.s_2"] = "46000006FG", | ||
411 | ["neg.s_2"] = "46000007FG", | ||
412 | ["round.l.s_2"] = "46000008FG", | ||
413 | ["trunc.l.s_2"] = "46000009FG", | ||
414 | ["ceil.l.s_2"] = "4600000aFG", | ||
415 | ["floor.l.s_2"] = "4600000bFG", | ||
416 | ["round.w.s_2"] = "4600000cFG", | ||
417 | ["trunc.w.s_2"] = "4600000dFG", | ||
418 | ["ceil.w.s_2"] = "4600000eFG", | ||
419 | ["floor.w.s_2"] = "4600000fFG", | ||
420 | ["movf.s_2"] = "46000011FG", | ||
421 | ["movf.s_3"] = "46000011FGC", | ||
422 | ["movt.s_2"] = "46010011FG", | ||
423 | ["movt.s_3"] = "46010011FGC", | ||
424 | ["movz.s_3"] = "46000012FGT", | ||
425 | ["movn.s_3"] = "46000013FGT", | ||
426 | ["recip.s_2"] = "46000015FG", | ||
427 | ["rsqrt.s_2"] = "46000016FG", | ||
428 | ["cvt.d.s_2"] = "46000021FG", | ||
429 | ["cvt.w.s_2"] = "46000024FG", | ||
430 | ["cvt.l.s_2"] = "46000025FG", | ||
431 | ["cvt.ps.s_3"] = "46000026FGH", | ||
432 | ["c.f.s_2"] = "46000030GH", | ||
433 | ["c.f.s_3"] = "46000030VGH", | ||
434 | ["c.un.s_2"] = "46000031GH", | ||
435 | ["c.un.s_3"] = "46000031VGH", | ||
436 | ["c.eq.s_2"] = "46000032GH", | ||
437 | ["c.eq.s_3"] = "46000032VGH", | ||
438 | ["c.ueq.s_2"] = "46000033GH", | ||
439 | ["c.ueq.s_3"] = "46000033VGH", | ||
440 | ["c.olt.s_2"] = "46000034GH", | ||
441 | ["c.olt.s_3"] = "46000034VGH", | ||
442 | ["c.ult.s_2"] = "46000035GH", | ||
443 | ["c.ult.s_3"] = "46000035VGH", | ||
444 | ["c.ole.s_2"] = "46000036GH", | ||
445 | ["c.ole.s_3"] = "46000036VGH", | ||
446 | ["c.ule.s_2"] = "46000037GH", | ||
447 | ["c.ule.s_3"] = "46000037VGH", | ||
448 | ["c.sf.s_2"] = "46000038GH", | ||
449 | ["c.sf.s_3"] = "46000038VGH", | ||
450 | ["c.ngle.s_2"] = "46000039GH", | ||
451 | ["c.ngle.s_3"] = "46000039VGH", | ||
452 | ["c.seq.s_2"] = "4600003aGH", | ||
453 | ["c.seq.s_3"] = "4600003aVGH", | ||
454 | ["c.ngl.s_2"] = "4600003bGH", | ||
455 | ["c.ngl.s_3"] = "4600003bVGH", | ||
456 | ["c.lt.s_2"] = "4600003cGH", | ||
457 | ["c.lt.s_3"] = "4600003cVGH", | ||
458 | ["c.nge.s_2"] = "4600003dGH", | ||
459 | ["c.nge.s_3"] = "4600003dVGH", | ||
460 | ["c.le.s_2"] = "4600003eGH", | ||
461 | ["c.le.s_3"] = "4600003eVGH", | ||
462 | ["c.ngt.s_2"] = "4600003fGH", | ||
463 | ["c.ngt.s_3"] = "4600003fVGH", | ||
464 | |||
465 | ["add.d_3"] = "46200000FGH", | ||
466 | ["sub.d_3"] = "46200001FGH", | ||
467 | ["mul.d_3"] = "46200002FGH", | ||
468 | ["div.d_3"] = "46200003FGH", | ||
469 | ["sqrt.d_2"] = "46200004FG", | ||
470 | ["abs.d_2"] = "46200005FG", | ||
471 | ["mov.d_2"] = "46200006FG", | ||
472 | ["neg.d_2"] = "46200007FG", | ||
473 | ["round.l.d_2"] = "46200008FG", | ||
474 | ["trunc.l.d_2"] = "46200009FG", | ||
475 | ["ceil.l.d_2"] = "4620000aFG", | ||
476 | ["floor.l.d_2"] = "4620000bFG", | ||
477 | ["round.w.d_2"] = "4620000cFG", | ||
478 | ["trunc.w.d_2"] = "4620000dFG", | ||
479 | ["ceil.w.d_2"] = "4620000eFG", | ||
480 | ["floor.w.d_2"] = "4620000fFG", | ||
481 | ["movf.d_2"] = "46200011FG", | ||
482 | ["movf.d_3"] = "46200011FGC", | ||
483 | ["movt.d_2"] = "46210011FG", | ||
484 | ["movt.d_3"] = "46210011FGC", | ||
485 | ["movz.d_3"] = "46200012FGT", | ||
486 | ["movn.d_3"] = "46200013FGT", | ||
487 | ["recip.d_2"] = "46200015FG", | ||
488 | ["rsqrt.d_2"] = "46200016FG", | ||
489 | ["cvt.s.d_2"] = "46200020FG", | ||
490 | ["cvt.w.d_2"] = "46200024FG", | ||
491 | ["cvt.l.d_2"] = "46200025FG", | ||
492 | ["c.f.d_2"] = "46200030GH", | ||
493 | ["c.f.d_3"] = "46200030VGH", | ||
494 | ["c.un.d_2"] = "46200031GH", | ||
495 | ["c.un.d_3"] = "46200031VGH", | ||
496 | ["c.eq.d_2"] = "46200032GH", | ||
497 | ["c.eq.d_3"] = "46200032VGH", | ||
498 | ["c.ueq.d_2"] = "46200033GH", | ||
499 | ["c.ueq.d_3"] = "46200033VGH", | ||
500 | ["c.olt.d_2"] = "46200034GH", | ||
501 | ["c.olt.d_3"] = "46200034VGH", | ||
502 | ["c.ult.d_2"] = "46200035GH", | ||
503 | ["c.ult.d_3"] = "46200035VGH", | ||
504 | ["c.ole.d_2"] = "46200036GH", | ||
505 | ["c.ole.d_3"] = "46200036VGH", | ||
506 | ["c.ule.d_2"] = "46200037GH", | ||
507 | ["c.ule.d_3"] = "46200037VGH", | ||
508 | ["c.sf.d_2"] = "46200038GH", | ||
509 | ["c.sf.d_3"] = "46200038VGH", | ||
510 | ["c.ngle.d_2"] = "46200039GH", | ||
511 | ["c.ngle.d_3"] = "46200039VGH", | ||
512 | ["c.seq.d_2"] = "4620003aGH", | ||
513 | ["c.seq.d_3"] = "4620003aVGH", | ||
514 | ["c.ngl.d_2"] = "4620003bGH", | ||
515 | ["c.ngl.d_3"] = "4620003bVGH", | ||
516 | ["c.lt.d_2"] = "4620003cGH", | ||
517 | ["c.lt.d_3"] = "4620003cVGH", | ||
518 | ["c.nge.d_2"] = "4620003dGH", | ||
519 | ["c.nge.d_3"] = "4620003dVGH", | ||
520 | ["c.le.d_2"] = "4620003eGH", | ||
521 | ["c.le.d_3"] = "4620003eVGH", | ||
522 | ["c.ngt.d_2"] = "4620003fGH", | ||
523 | ["c.ngt.d_3"] = "4620003fVGH", | ||
524 | |||
525 | ["add.ps_3"] = "46c00000FGH", | ||
526 | ["sub.ps_3"] = "46c00001FGH", | ||
527 | ["mul.ps_3"] = "46c00002FGH", | ||
528 | ["abs.ps_2"] = "46c00005FG", | ||
529 | ["mov.ps_2"] = "46c00006FG", | ||
530 | ["neg.ps_2"] = "46c00007FG", | ||
531 | ["movf.ps_2"] = "46c00011FG", | ||
532 | ["movf.ps_3"] = "46c00011FGC", | ||
533 | ["movt.ps_2"] = "46c10011FG", | ||
534 | ["movt.ps_3"] = "46c10011FGC", | ||
535 | ["movz.ps_3"] = "46c00012FGT", | ||
536 | ["movn.ps_3"] = "46c00013FGT", | ||
537 | ["cvt.s.pu_2"] = "46c00020FG", | ||
538 | ["cvt.s.pl_2"] = "46c00028FG", | ||
539 | ["pll.ps_3"] = "46c0002cFGH", | ||
540 | ["plu.ps_3"] = "46c0002dFGH", | ||
541 | ["pul.ps_3"] = "46c0002eFGH", | ||
542 | ["puu.ps_3"] = "46c0002fFGH", | ||
543 | ["c.f.ps_2"] = "46c00030GH", | ||
544 | ["c.f.ps_3"] = "46c00030VGH", | ||
545 | ["c.un.ps_2"] = "46c00031GH", | ||
546 | ["c.un.ps_3"] = "46c00031VGH", | ||
547 | ["c.eq.ps_2"] = "46c00032GH", | ||
548 | ["c.eq.ps_3"] = "46c00032VGH", | ||
549 | ["c.ueq.ps_2"] = "46c00033GH", | ||
550 | ["c.ueq.ps_3"] = "46c00033VGH", | ||
551 | ["c.olt.ps_2"] = "46c00034GH", | ||
552 | ["c.olt.ps_3"] = "46c00034VGH", | ||
553 | ["c.ult.ps_2"] = "46c00035GH", | ||
554 | ["c.ult.ps_3"] = "46c00035VGH", | ||
555 | ["c.ole.ps_2"] = "46c00036GH", | ||
556 | ["c.ole.ps_3"] = "46c00036VGH", | ||
557 | ["c.ule.ps_2"] = "46c00037GH", | ||
558 | ["c.ule.ps_3"] = "46c00037VGH", | ||
559 | ["c.sf.ps_2"] = "46c00038GH", | ||
560 | ["c.sf.ps_3"] = "46c00038VGH", | ||
561 | ["c.ngle.ps_2"] = "46c00039GH", | ||
562 | ["c.ngle.ps_3"] = "46c00039VGH", | ||
563 | ["c.seq.ps_2"] = "46c0003aGH", | ||
564 | ["c.seq.ps_3"] = "46c0003aVGH", | ||
565 | ["c.ngl.ps_2"] = "46c0003bGH", | ||
566 | ["c.ngl.ps_3"] = "46c0003bVGH", | ||
567 | ["c.lt.ps_2"] = "46c0003cGH", | ||
568 | ["c.lt.ps_3"] = "46c0003cVGH", | ||
569 | ["c.nge.ps_2"] = "46c0003dGH", | ||
570 | ["c.nge.ps_3"] = "46c0003dVGH", | ||
571 | ["c.le.ps_2"] = "46c0003eGH", | ||
572 | ["c.le.ps_3"] = "46c0003eVGH", | ||
573 | ["c.ngt.ps_2"] = "46c0003fGH", | ||
574 | ["c.ngt.ps_3"] = "46c0003fVGH", | ||
575 | |||
576 | ["cvt.s.w_2"] = "46800020FG", | ||
577 | ["cvt.d.w_2"] = "46800021FG", | ||
578 | |||
579 | ["cvt.s.l_2"] = "46a00020FG", | ||
580 | ["cvt.d.l_2"] = "46a00021FG", | ||
581 | |||
582 | -- Opcode COP1X. | ||
583 | lwxc1_2 = "4c000000FX", | ||
584 | ldxc1_2 = "4c000001FX", | ||
585 | luxc1_2 = "4c000005FX", | ||
586 | swxc1_2 = "4c000008FX", | ||
587 | sdxc1_2 = "4c000009FX", | ||
588 | suxc1_2 = "4c00000dFX", | ||
589 | prefx_2 = "4c00000fMX", | ||
590 | ["alnv.ps_4"] = "4c00001eFGHS", | ||
591 | ["madd.s_4"] = "4c000020FRGH", | ||
592 | ["madd.d_4"] = "4c000021FRGH", | ||
593 | ["madd.ps_4"] = "4c000026FRGH", | ||
594 | ["msub.s_4"] = "4c000028FRGH", | ||
595 | ["msub.d_4"] = "4c000029FRGH", | ||
596 | ["msub.ps_4"] = "4c00002eFRGH", | ||
597 | ["nmadd.s_4"] = "4c000030FRGH", | ||
598 | ["nmadd.d_4"] = "4c000031FRGH", | ||
599 | ["nmadd.ps_4"] = "4c000036FRGH", | ||
600 | ["nmsub.s_4"] = "4c000038FRGH", | ||
601 | ["nmsub.d_4"] = "4c000039FRGH", | ||
602 | ["nmsub.ps_4"] = "4c00003eFRGH", | ||
603 | } | ||
604 | |||
605 | ------------------------------------------------------------------------------ | ||
606 | |||
607 | local function parse_gpr(expr) | ||
608 | local tname, ovreg = match(expr, "^([%w_]+):(r[1-3]?[0-9])$") | ||
609 | local tp = map_type[tname or expr] | ||
610 | if tp then | ||
611 | local reg = ovreg or tp.reg | ||
612 | if not reg then | ||
613 | werror("type `"..(tname or expr).."' needs a register override") | ||
614 | end | ||
615 | expr = reg | ||
616 | end | ||
617 | local r = match(expr, "^r([1-3]?[0-9])$") | ||
618 | if r then | ||
619 | r = tonumber(r) | ||
620 | if r <= 31 then return r, tp end | ||
621 | end | ||
622 | werror("bad register name `"..expr.."'") | ||
623 | end | ||
624 | |||
625 | local function parse_fpr(expr) | ||
626 | local r = match(expr, "^f([1-3]?[0-9])$") | ||
627 | if r then | ||
628 | r = tonumber(r) | ||
629 | if r <= 31 then return r end | ||
630 | end | ||
631 | werror("bad register name `"..expr.."'") | ||
632 | end | ||
633 | |||
634 | local function parse_imm(imm, bits, shift, scale, signed) | ||
635 | local n = tonumber(imm) | ||
636 | if n then | ||
637 | if n % 2^scale == 0 then | ||
638 | n = n / 2^scale | ||
639 | if signed then | ||
640 | if n >= 0 then | ||
641 | if n < 2^(bits-1) then return n*2^shift end | ||
642 | else | ||
643 | if n >= -(2^(bits-1))-1 then return (n+2^bits)*2^shift end | ||
644 | end | ||
645 | else | ||
646 | if n >= 0 and n <= 2^bits-1 then return n*2^shift end | ||
647 | end | ||
648 | end | ||
649 | werror("out of range immediate `"..imm.."'") | ||
650 | elseif match(imm, "^[rf]([1-3]?[0-9])$") or | ||
651 | match(imm, "^([%w_]+):([rf][1-3]?[0-9])$") then | ||
652 | werror("expected immediate operand, got register") | ||
653 | else | ||
654 | waction("IMM", (signed and 32768 or 0)+scale*1024+bits*32+shift, imm) | ||
655 | return 0 | ||
656 | end | ||
657 | end | ||
658 | |||
659 | local function parse_disp(disp) | ||
660 | local imm, reg = match(disp, "^(.*)%(([%w_:]+)%)$") | ||
661 | if imm then | ||
662 | local r = parse_gpr(reg) | ||
663 | return r*2^21 + parse_imm(imm, 16, 0, 0, true) | ||
664 | end | ||
665 | local reg, tailr = match(disp, "^([%w_:]+)%s*(.*)$") | ||
666 | if reg and tailr ~= "" then | ||
667 | local r, tp = parse_gpr(reg) | ||
668 | if tp then | ||
669 | waction("IMM", 32768+16*32, format(tp.ctypefmt, tailr)) | ||
670 | return r*2^21 | ||
671 | end | ||
672 | end | ||
673 | werror("bad displacement `"..disp.."'") | ||
674 | end | ||
675 | |||
676 | local function parse_index(idx) | ||
677 | local rt, rs = match(idx, "^(.*)%(([%w_:]+)%)$") | ||
678 | if rt then | ||
679 | rt = parse_gpr(rt) | ||
680 | rs = parse_gpr(rs) | ||
681 | return rt*2^16 + rs*2^21 | ||
682 | end | ||
683 | werror("bad index `"..idx.."'") | ||
684 | end | ||
685 | |||
686 | local function parse_label(label, def) | ||
687 | local prefix = sub(label, 1, 2) | ||
688 | -- =>label (pc label reference) | ||
689 | if prefix == "=>" then | ||
690 | return "PC", 0, sub(label, 3) | ||
691 | end | ||
692 | -- ->name (global label reference) | ||
693 | if prefix == "->" then | ||
694 | return "LG", map_global[sub(label, 3)] | ||
695 | end | ||
696 | if def then | ||
697 | -- [1-9] (local label definition) | ||
698 | if match(label, "^[1-9]$") then | ||
699 | return "LG", 10+tonumber(label) | ||
700 | end | ||
701 | else | ||
702 | -- [<>][1-9] (local label reference) | ||
703 | local dir, lnum = match(label, "^([<>])([1-9])$") | ||
704 | if dir then -- Fwd: 1-9, Bkwd: 11-19. | ||
705 | return "LG", lnum + (dir == ">" and 0 or 10) | ||
706 | end | ||
707 | -- extern label (extern label reference) | ||
708 | local extname = match(label, "^extern%s+(%S+)$") | ||
709 | if extname then | ||
710 | return "EXT", map_extern[extname] | ||
711 | end | ||
712 | end | ||
713 | werror("bad label `"..label.."'") | ||
714 | end | ||
715 | |||
716 | ------------------------------------------------------------------------------ | ||
717 | |||
718 | -- Handle opcodes defined with template strings. | ||
719 | map_op[".template__"] = function(params, template, nparams) | ||
720 | if not params then return sub(template, 9) end | ||
721 | local op = tonumber(sub(template, 1, 8), 16) | ||
722 | local n = 1 | ||
723 | |||
724 | -- Limit number of section buffer positions used by a single dasm_put(). | ||
725 | -- A single opcode needs a maximum of 2 positions (ins/ext). | ||
726 | if secpos+2 > maxsecpos then wflush() end | ||
727 | local pos = wpos() | ||
728 | |||
729 | -- Process each character. | ||
730 | for p in gmatch(sub(template, 9), ".") do | ||
731 | if p == "D" then | ||
732 | op = op + parse_gpr(params[n]) * 2^11; n = n + 1 | ||
733 | elseif p == "T" then | ||
734 | op = op + parse_gpr(params[n]) * 2^16; n = n + 1 | ||
735 | elseif p == "S" then | ||
736 | op = op + parse_gpr(params[n]) * 2^21; n = n + 1 | ||
737 | elseif p == "F" then | ||
738 | op = op + parse_fpr(params[n]) * 2^6; n = n + 1 | ||
739 | elseif p == "G" then | ||
740 | op = op + parse_fpr(params[n]) * 2^11; n = n + 1 | ||
741 | elseif p == "H" then | ||
742 | op = op + parse_fpr(params[n]) * 2^16; n = n + 1 | ||
743 | elseif p == "R" then | ||
744 | op = op + parse_fpr(params[n]) * 2^21; n = n + 1 | ||
745 | elseif p == "I" then | ||
746 | op = op + parse_imm(params[n], 16, 0, 0, true); n = n + 1 | ||
747 | elseif p == "U" then | ||
748 | op = op + parse_imm(params[n], 16, 0, 0, false); n = n + 1 | ||
749 | elseif p == "O" then | ||
750 | op = op + parse_disp(params[n]); n = n + 1 | ||
751 | elseif p == "X" then | ||
752 | op = op + parse_index(params[n]); n = n + 1 | ||
753 | elseif p == "B" or p == "J" then | ||
754 | local mode, n, s = parse_label(params[n], false) | ||
755 | if p == "B" then n = n + 2048 end | ||
756 | waction("REL_"..mode, n, s, 1) | ||
757 | n = n + 1 | ||
758 | elseif p == "A" then | ||
759 | op = op + parse_imm(params[n], 5, 6, 0, false); n = n + 1 | ||
760 | elseif p == "M" then | ||
761 | op = op + parse_imm(params[n], 5, 11, 0, false); n = n + 1 | ||
762 | elseif p == "N" then | ||
763 | op = op + parse_imm(params[n], 5, 16, 0, false); n = n + 1 | ||
764 | elseif p == "C" then | ||
765 | op = op + parse_imm(params[n], 3, 18, 0, false); n = n + 1 | ||
766 | elseif p == "V" then | ||
767 | op = op + parse_imm(params[n], 3, 8, 0, false); n = n + 1 | ||
768 | elseif p == "W" then | ||
769 | op = op + parse_imm(params[n], 3, 0, 0, false); n = n + 1 | ||
770 | elseif p == "Y" then | ||
771 | op = op + parse_imm(params[n], 20, 6, 0, false); n = n + 1 | ||
772 | elseif p == "Z" then | ||
773 | op = op + parse_imm(params[n], 10, 6, 0, false); n = n + 1 | ||
774 | elseif p == "=" then | ||
775 | local d = ((op - op % 2^11) / 2^11) % 32 | ||
776 | op = op + d * 2^16 -- Copy D to T for clz, clo. | ||
777 | else | ||
778 | assert(false) | ||
779 | end | ||
780 | end | ||
781 | wputpos(pos, op) | ||
782 | end | ||
783 | |||
784 | ------------------------------------------------------------------------------ | ||
785 | |||
786 | -- Pseudo-opcode to mark the position where the action list is to be emitted. | ||
787 | map_op[".actionlist_1"] = function(params) | ||
788 | if not params then return "cvar" end | ||
789 | local name = params[1] -- No syntax check. You get to keep the pieces. | ||
790 | wline(function(out) writeactions(out, name) end) | ||
791 | end | ||
792 | |||
793 | -- Pseudo-opcode to mark the position where the global enum is to be emitted. | ||
794 | map_op[".globals_1"] = function(params) | ||
795 | if not params then return "prefix" end | ||
796 | local prefix = params[1] -- No syntax check. You get to keep the pieces. | ||
797 | wline(function(out) writeglobals(out, prefix) end) | ||
798 | end | ||
799 | |||
800 | -- Pseudo-opcode to mark the position where the global names are to be emitted. | ||
801 | map_op[".globalnames_1"] = function(params) | ||
802 | if not params then return "cvar" end | ||
803 | local name = params[1] -- No syntax check. You get to keep the pieces. | ||
804 | wline(function(out) writeglobalnames(out, name) end) | ||
805 | end | ||
806 | |||
807 | -- Pseudo-opcode to mark the position where the extern names are to be emitted. | ||
808 | map_op[".externnames_1"] = function(params) | ||
809 | if not params then return "cvar" end | ||
810 | local name = params[1] -- No syntax check. You get to keep the pieces. | ||
811 | wline(function(out) writeexternnames(out, name) end) | ||
812 | end | ||
813 | |||
814 | ------------------------------------------------------------------------------ | ||
815 | |||
816 | -- Label pseudo-opcode (converted from trailing colon form). | ||
817 | map_op[".label_1"] = function(params) | ||
818 | if not params then return "[1-9] | ->global | =>pcexpr" end | ||
819 | if secpos+1 > maxsecpos then wflush() end | ||
820 | local mode, n, s = parse_label(params[1], true) | ||
821 | if mode == "EXT" then werror("bad label definition") end | ||
822 | waction("LABEL_"..mode, n, s, 1) | ||
823 | end | ||
824 | |||
825 | ------------------------------------------------------------------------------ | ||
826 | |||
827 | -- Pseudo-opcodes for data storage. | ||
828 | map_op[".long_*"] = function(params) | ||
829 | if not params then return "imm..." end | ||
830 | for _,p in ipairs(params) do | ||
831 | local n = tonumber(p) | ||
832 | if not n then werror("bad immediate `"..p.."'") end | ||
833 | if n < 0 then n = n + 2^32 end | ||
834 | wputw(n) | ||
835 | if secpos+2 > maxsecpos then wflush() end | ||
836 | end | ||
837 | end | ||
838 | |||
839 | -- Alignment pseudo-opcode. | ||
840 | map_op[".align_1"] = function(params) | ||
841 | if not params then return "numpow2" end | ||
842 | if secpos+1 > maxsecpos then wflush() end | ||
843 | local align = tonumber(params[1]) | ||
844 | if align then | ||
845 | local x = align | ||
846 | -- Must be a power of 2 in the range (2 ... 256). | ||
847 | for i=1,8 do | ||
848 | x = x / 2 | ||
849 | if x == 1 then | ||
850 | waction("ALIGN", align-1, nil, 1) -- Action byte is 2**n-1. | ||
851 | return | ||
852 | end | ||
853 | end | ||
854 | end | ||
855 | werror("bad alignment") | ||
856 | end | ||
857 | |||
858 | ------------------------------------------------------------------------------ | ||
859 | |||
860 | -- Pseudo-opcode for (primitive) type definitions (map to C types). | ||
861 | map_op[".type_3"] = function(params, nparams) | ||
862 | if not params then | ||
863 | return nparams == 2 and "name, ctype" or "name, ctype, reg" | ||
864 | end | ||
865 | local name, ctype, reg = params[1], params[2], params[3] | ||
866 | if not match(name, "^[%a_][%w_]*$") then | ||
867 | werror("bad type name `"..name.."'") | ||
868 | end | ||
869 | local tp = map_type[name] | ||
870 | if tp then | ||
871 | werror("duplicate type `"..name.."'") | ||
872 | end | ||
873 | -- Add #type to defines. A bit unclean to put it in map_archdef. | ||
874 | map_archdef["#"..name] = "sizeof("..ctype..")" | ||
875 | -- Add new type and emit shortcut define. | ||
876 | local num = ctypenum + 1 | ||
877 | map_type[name] = { | ||
878 | ctype = ctype, | ||
879 | ctypefmt = format("Dt%X(%%s)", num), | ||
880 | reg = reg, | ||
881 | } | ||
882 | wline(format("#define Dt%X(_V) (int)(ptrdiff_t)&(((%s *)0)_V)", num, ctype)) | ||
883 | ctypenum = num | ||
884 | end | ||
885 | map_op[".type_2"] = map_op[".type_3"] | ||
886 | |||
887 | -- Dump type definitions. | ||
888 | local function dumptypes(out, lvl) | ||
889 | local t = {} | ||
890 | for name in pairs(map_type) do t[#t+1] = name end | ||
891 | sort(t) | ||
892 | out:write("Type definitions:\n") | ||
893 | for _,name in ipairs(t) do | ||
894 | local tp = map_type[name] | ||
895 | local reg = tp.reg or "" | ||
896 | out:write(format(" %-20s %-20s %s\n", name, tp.ctype, reg)) | ||
897 | end | ||
898 | out:write("\n") | ||
899 | end | ||
900 | |||
901 | ------------------------------------------------------------------------------ | ||
902 | |||
903 | -- Set the current section. | ||
904 | function _M.section(num) | ||
905 | waction("SECTION", num) | ||
906 | wflush(true) -- SECTION is a terminal action. | ||
907 | end | ||
908 | |||
909 | ------------------------------------------------------------------------------ | ||
910 | |||
911 | -- Dump architecture description. | ||
912 | function _M.dumparch(out) | ||
913 | out:write(format("DynASM %s version %s, released %s\n\n", | ||
914 | _info.arch, _info.version, _info.release)) | ||
915 | dumpactions(out) | ||
916 | end | ||
917 | |||
918 | -- Dump all user defined elements. | ||
919 | function _M.dumpdef(out, lvl) | ||
920 | dumptypes(out, lvl) | ||
921 | dumpglobals(out, lvl) | ||
922 | dumpexterns(out, lvl) | ||
923 | end | ||
924 | |||
925 | ------------------------------------------------------------------------------ | ||
926 | |||
927 | -- Pass callbacks from/to the DynASM core. | ||
928 | function _M.passcb(wl, we, wf, ww) | ||
929 | wline, werror, wfatal, wwarn = wl, we, wf, ww | ||
930 | return wflush | ||
931 | end | ||
932 | |||
933 | -- Setup the arch-specific module. | ||
934 | function _M.setup(arch, opt) | ||
935 | g_arch, g_opt = arch, opt | ||
936 | end | ||
937 | |||
938 | -- Merge the core maps and the arch-specific maps. | ||
939 | function _M.mergemaps(map_coreop, map_def) | ||
940 | setmetatable(map_op, { __index = map_coreop }) | ||
941 | setmetatable(map_def, { __index = map_archdef }) | ||
942 | return map_op, map_def | ||
943 | end | ||
944 | |||
945 | return _M | ||
946 | |||
947 | ------------------------------------------------------------------------------ | ||
948 | |||
diff --git a/libraries/luajit-2.0/dynasm/dasm_ppc.h b/libraries/luajit-2.0/dynasm/dasm_ppc.h new file mode 100644 index 0000000..645e060 --- /dev/null +++ b/libraries/luajit-2.0/dynasm/dasm_ppc.h | |||
@@ -0,0 +1,411 @@ | |||
1 | /* | ||
2 | ** DynASM PPC encoding engine. | ||
3 | ** Copyright (C) 2005-2011 Mike Pall. All rights reserved. | ||
4 | ** Released under the MIT license. See dynasm.lua for full copyright notice. | ||
5 | */ | ||
6 | |||
7 | #include <stddef.h> | ||
8 | #include <stdarg.h> | ||
9 | #include <string.h> | ||
10 | #include <stdlib.h> | ||
11 | |||
12 | #define DASM_ARCH "ppc" | ||
13 | |||
14 | #ifndef DASM_EXTERN | ||
15 | #define DASM_EXTERN(a,b,c,d) 0 | ||
16 | #endif | ||
17 | |||
18 | /* Action definitions. */ | ||
19 | enum { | ||
20 | DASM_STOP, DASM_SECTION, DASM_ESC, DASM_REL_EXT, | ||
21 | /* The following actions need a buffer position. */ | ||
22 | DASM_ALIGN, DASM_REL_LG, DASM_LABEL_LG, | ||
23 | /* The following actions also have an argument. */ | ||
24 | DASM_REL_PC, DASM_LABEL_PC, DASM_IMM, | ||
25 | DASM__MAX | ||
26 | }; | ||
27 | |||
28 | /* Maximum number of section buffer positions for a single dasm_put() call. */ | ||
29 | #define DASM_MAXSECPOS 25 | ||
30 | |||
31 | /* DynASM encoder status codes. Action list offset or number are or'ed in. */ | ||
32 | #define DASM_S_OK 0x00000000 | ||
33 | #define DASM_S_NOMEM 0x01000000 | ||
34 | #define DASM_S_PHASE 0x02000000 | ||
35 | #define DASM_S_MATCH_SEC 0x03000000 | ||
36 | #define DASM_S_RANGE_I 0x11000000 | ||
37 | #define DASM_S_RANGE_SEC 0x12000000 | ||
38 | #define DASM_S_RANGE_LG 0x13000000 | ||
39 | #define DASM_S_RANGE_PC 0x14000000 | ||
40 | #define DASM_S_RANGE_REL 0x15000000 | ||
41 | #define DASM_S_UNDEF_LG 0x21000000 | ||
42 | #define DASM_S_UNDEF_PC 0x22000000 | ||
43 | |||
44 | /* Macros to convert positions (8 bit section + 24 bit index). */ | ||
45 | #define DASM_POS2IDX(pos) ((pos)&0x00ffffff) | ||
46 | #define DASM_POS2BIAS(pos) ((pos)&0xff000000) | ||
47 | #define DASM_SEC2POS(sec) ((sec)<<24) | ||
48 | #define DASM_POS2SEC(pos) ((pos)>>24) | ||
49 | #define DASM_POS2PTR(D, pos) (D->sections[DASM_POS2SEC(pos)].rbuf + (pos)) | ||
50 | |||
51 | /* Action list type. */ | ||
52 | typedef const unsigned int *dasm_ActList; | ||
53 | |||
54 | /* Per-section structure. */ | ||
55 | typedef struct dasm_Section { | ||
56 | int *rbuf; /* Biased buffer pointer (negative section bias). */ | ||
57 | int *buf; /* True buffer pointer. */ | ||
58 | size_t bsize; /* Buffer size in bytes. */ | ||
59 | int pos; /* Biased buffer position. */ | ||
60 | int epos; /* End of biased buffer position - max single put. */ | ||
61 | int ofs; /* Byte offset into section. */ | ||
62 | } dasm_Section; | ||
63 | |||
64 | /* Core structure holding the DynASM encoding state. */ | ||
65 | struct dasm_State { | ||
66 | size_t psize; /* Allocated size of this structure. */ | ||
67 | dasm_ActList actionlist; /* Current actionlist pointer. */ | ||
68 | int *lglabels; /* Local/global chain/pos ptrs. */ | ||
69 | size_t lgsize; | ||
70 | int *pclabels; /* PC label chains/pos ptrs. */ | ||
71 | size_t pcsize; | ||
72 | void **globals; /* Array of globals (bias -10). */ | ||
73 | dasm_Section *section; /* Pointer to active section. */ | ||
74 | size_t codesize; /* Total size of all code sections. */ | ||
75 | int maxsection; /* 0 <= sectionidx < maxsection. */ | ||
76 | int status; /* Status code. */ | ||
77 | dasm_Section sections[1]; /* All sections. Alloc-extended. */ | ||
78 | }; | ||
79 | |||
80 | /* The size of the core structure depends on the max. number of sections. */ | ||
81 | #define DASM_PSZ(ms) (sizeof(dasm_State)+(ms-1)*sizeof(dasm_Section)) | ||
82 | |||
83 | |||
84 | /* Initialize DynASM state. */ | ||
85 | void dasm_init(Dst_DECL, int maxsection) | ||
86 | { | ||
87 | dasm_State *D; | ||
88 | size_t psz = 0; | ||
89 | int i; | ||
90 | Dst_REF = NULL; | ||
91 | DASM_M_GROW(Dst, struct dasm_State, Dst_REF, psz, DASM_PSZ(maxsection)); | ||
92 | D = Dst_REF; | ||
93 | D->psize = psz; | ||
94 | D->lglabels = NULL; | ||
95 | D->lgsize = 0; | ||
96 | D->pclabels = NULL; | ||
97 | D->pcsize = 0; | ||
98 | D->globals = NULL; | ||
99 | D->maxsection = maxsection; | ||
100 | for (i = 0; i < maxsection; i++) { | ||
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 | } | ||
107 | |||
108 | /* Free DynASM state. */ | ||
109 | void dasm_free(Dst_DECL) | ||
110 | { | ||
111 | dasm_State *D = Dst_REF; | ||
112 | int i; | ||
113 | for (i = 0; i < D->maxsection; i++) | ||
114 | if (D->sections[i].buf) | ||
115 | DASM_M_FREE(Dst, D->sections[i].buf, D->sections[i].bsize); | ||
116 | if (D->pclabels) DASM_M_FREE(Dst, D->pclabels, D->pcsize); | ||
117 | if (D->lglabels) DASM_M_FREE(Dst, D->lglabels, D->lgsize); | ||
118 | DASM_M_FREE(Dst, D, D->psize); | ||
119 | } | ||
120 | |||
121 | /* Setup global label array. Must be called before dasm_setup(). */ | ||
122 | void dasm_setupglobal(Dst_DECL, void **gl, unsigned int maxgl) | ||
123 | { | ||
124 | dasm_State *D = Dst_REF; | ||
125 | D->globals = gl - 10; /* Negative bias to compensate for locals. */ | ||
126 | DASM_M_GROW(Dst, int, D->lglabels, D->lgsize, (10+maxgl)*sizeof(int)); | ||
127 | } | ||
128 | |||
129 | /* Grow PC label array. Can be called after dasm_setup(), too. */ | ||
130 | void dasm_growpc(Dst_DECL, unsigned int maxpc) | ||
131 | { | ||
132 | dasm_State *D = Dst_REF; | ||
133 | size_t osz = D->pcsize; | ||
134 | DASM_M_GROW(Dst, int, D->pclabels, D->pcsize, maxpc*sizeof(int)); | ||
135 | memset((void *)(((unsigned char *)D->pclabels)+osz), 0, D->pcsize-osz); | ||
136 | } | ||
137 | |||
138 | /* Setup encoder. */ | ||
139 | void dasm_setup(Dst_DECL, const void *actionlist) | ||
140 | { | ||
141 | dasm_State *D = Dst_REF; | ||
142 | int i; | ||
143 | D->actionlist = (dasm_ActList)actionlist; | ||
144 | D->status = DASM_S_OK; | ||
145 | D->section = &D->sections[0]; | ||
146 | memset((void *)D->lglabels, 0, D->lgsize); | ||
147 | if (D->pclabels) memset((void *)D->pclabels, 0, D->pcsize); | ||
148 | for (i = 0; i < D->maxsection; i++) { | ||
149 | D->sections[i].pos = DASM_SEC2POS(i); | ||
150 | D->sections[i].ofs = 0; | ||
151 | } | ||
152 | } | ||
153 | |||
154 | |||
155 | #ifdef DASM_CHECKS | ||
156 | #define CK(x, st) \ | ||
157 | do { if (!(x)) { \ | ||
158 | D->status = DASM_S_##st|(p-D->actionlist-1); return; } } while (0) | ||
159 | #define CKPL(kind, st) \ | ||
160 | 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) | ||
162 | #else | ||
163 | #define CK(x, st) ((void)0) | ||
164 | #define CKPL(kind, st) ((void)0) | ||
165 | #endif | ||
166 | |||
167 | /* Pass 1: Store actions and args, link branches/labels, estimate offsets. */ | ||
168 | void dasm_put(Dst_DECL, int start, ...) | ||
169 | { | ||
170 | va_list ap; | ||
171 | dasm_State *D = Dst_REF; | ||
172 | dasm_ActList p = D->actionlist + start; | ||
173 | dasm_Section *sec = D->section; | ||
174 | int pos = sec->pos, ofs = sec->ofs; | ||
175 | int *b; | ||
176 | |||
177 | if (pos >= sec->epos) { | ||
178 | DASM_M_GROW(Dst, int, sec->buf, sec->bsize, | ||
179 | sec->bsize + 2*DASM_MAXSECPOS*sizeof(int)); | ||
180 | sec->rbuf = sec->buf - DASM_POS2BIAS(pos); | ||
181 | sec->epos = (int)sec->bsize/sizeof(int) - DASM_MAXSECPOS+DASM_POS2BIAS(pos); | ||
182 | } | ||
183 | |||
184 | b = sec->rbuf; | ||
185 | b[pos++] = start; | ||
186 | |||
187 | va_start(ap, start); | ||
188 | while (1) { | ||
189 | unsigned int ins = *p++; | ||
190 | unsigned int action = (ins >> 16); | ||
191 | if (action >= DASM__MAX) { | ||
192 | ofs += 4; | ||
193 | } else { | ||
194 | int *pl, n = action >= DASM_REL_PC ? va_arg(ap, int) : 0; | ||
195 | switch (action) { | ||
196 | case DASM_STOP: goto stop; | ||
197 | case DASM_SECTION: | ||
198 | n = (ins & 255); CK(n < D->maxsection, RANGE_SEC); | ||
199 | D->section = &D->sections[n]; goto stop; | ||
200 | case DASM_ESC: p++; ofs += 4; break; | ||
201 | case DASM_REL_EXT: break; | ||
202 | case DASM_ALIGN: ofs += (ins & 255); b[pos++] = ofs; break; | ||
203 | case DASM_REL_LG: | ||
204 | n = (ins & 2047) - 10; pl = D->lglabels + n; | ||
205 | if (n >= 0) { CKPL(lg, LG); goto putrel; } /* Bkwd rel or global. */ | ||
206 | pl += 10; n = *pl; | ||
207 | if (n < 0) n = 0; /* Start new chain for fwd rel if label exists. */ | ||
208 | goto linkrel; | ||
209 | case DASM_REL_PC: | ||
210 | pl = D->pclabels + n; CKPL(pc, PC); | ||
211 | putrel: | ||
212 | n = *pl; | ||
213 | if (n < 0) { /* Label exists. Get label pos and store it. */ | ||
214 | b[pos] = -n; | ||
215 | } else { | ||
216 | linkrel: | ||
217 | b[pos] = n; /* Else link to rel chain, anchored at label. */ | ||
218 | *pl = pos; | ||
219 | } | ||
220 | pos++; | ||
221 | break; | ||
222 | case DASM_LABEL_LG: | ||
223 | pl = D->lglabels + (ins & 2047) - 10; CKPL(lg, LG); goto putlabel; | ||
224 | case DASM_LABEL_PC: | ||
225 | pl = D->pclabels + n; CKPL(pc, PC); | ||
226 | putlabel: | ||
227 | n = *pl; /* n > 0: Collapse rel chain and replace with label pos. */ | ||
228 | while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = pos; | ||
229 | } | ||
230 | *pl = -pos; /* Label exists now. */ | ||
231 | b[pos++] = ofs; /* Store pass1 offset estimate. */ | ||
232 | break; | ||
233 | case DASM_IMM: | ||
234 | #ifdef DASM_CHECKS | ||
235 | CK((n & ((1<<((ins>>10)&31))-1)) == 0, RANGE_I); | ||
236 | #endif | ||
237 | n >>= ((ins>>10)&31); | ||
238 | #ifdef DASM_CHECKS | ||
239 | if (ins & 0x8000) | ||
240 | CK(((n + (1<<(((ins>>5)&31)-1)))>>((ins>>5)&31)) == 0, RANGE_I); | ||
241 | else | ||
242 | CK((n>>((ins>>5)&31)) == 0, RANGE_I); | ||
243 | #endif | ||
244 | b[pos++] = n; | ||
245 | break; | ||
246 | } | ||
247 | } | ||
248 | } | ||
249 | stop: | ||
250 | va_end(ap); | ||
251 | sec->pos = pos; | ||
252 | sec->ofs = ofs; | ||
253 | } | ||
254 | #undef CK | ||
255 | |||
256 | /* Pass 2: Link sections, shrink aligns, fix label offsets. */ | ||
257 | int dasm_link(Dst_DECL, size_t *szp) | ||
258 | { | ||
259 | dasm_State *D = Dst_REF; | ||
260 | int secnum; | ||
261 | int ofs = 0; | ||
262 | |||
263 | #ifdef DASM_CHECKS | ||
264 | *szp = 0; | ||
265 | if (D->status != DASM_S_OK) return D->status; | ||
266 | { | ||
267 | int pc; | ||
268 | for (pc = 0; pc*sizeof(int) < D->pcsize; pc++) | ||
269 | if (D->pclabels[pc] > 0) return DASM_S_UNDEF_PC|pc; | ||
270 | } | ||
271 | #endif | ||
272 | |||
273 | { /* Handle globals not defined in this translation unit. */ | ||
274 | int idx; | ||
275 | for (idx = 20; idx*sizeof(int) < D->lgsize; idx++) { | ||
276 | int n = D->lglabels[idx]; | ||
277 | /* Undefined label: Collapse rel chain and replace with marker (< 0). */ | ||
278 | while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = -idx; } | ||
279 | } | ||
280 | } | ||
281 | |||
282 | /* Combine all code sections. No support for data sections (yet). */ | ||
283 | for (secnum = 0; secnum < D->maxsection; secnum++) { | ||
284 | dasm_Section *sec = D->sections + secnum; | ||
285 | int *b = sec->rbuf; | ||
286 | int pos = DASM_SEC2POS(secnum); | ||
287 | int lastpos = sec->pos; | ||
288 | |||
289 | while (pos != lastpos) { | ||
290 | dasm_ActList p = D->actionlist + b[pos++]; | ||
291 | while (1) { | ||
292 | unsigned int ins = *p++; | ||
293 | unsigned int action = (ins >> 16); | ||
294 | switch (action) { | ||
295 | case DASM_STOP: case DASM_SECTION: goto stop; | ||
296 | case DASM_ESC: p++; break; | ||
297 | case DASM_REL_EXT: break; | ||
298 | case DASM_ALIGN: ofs -= (b[pos++] + ofs) & (ins & 255); break; | ||
299 | case DASM_REL_LG: case DASM_REL_PC: pos++; break; | ||
300 | case DASM_LABEL_LG: case DASM_LABEL_PC: b[pos++] += ofs; break; | ||
301 | case DASM_IMM: pos++; break; | ||
302 | } | ||
303 | } | ||
304 | stop: (void)0; | ||
305 | } | ||
306 | ofs += sec->ofs; /* Next section starts right after current section. */ | ||
307 | } | ||
308 | |||
309 | D->codesize = ofs; /* Total size of all code sections */ | ||
310 | *szp = ofs; | ||
311 | return DASM_S_OK; | ||
312 | } | ||
313 | |||
314 | #ifdef DASM_CHECKS | ||
315 | #define CK(x, st) \ | ||
316 | do { if (!(x)) return DASM_S_##st|(p-D->actionlist-1); } while (0) | ||
317 | #else | ||
318 | #define CK(x, st) ((void)0) | ||
319 | #endif | ||
320 | |||
321 | /* Pass 3: Encode sections. */ | ||
322 | int dasm_encode(Dst_DECL, void *buffer) | ||
323 | { | ||
324 | dasm_State *D = Dst_REF; | ||
325 | char *base = (char *)buffer; | ||
326 | unsigned int *cp = (unsigned int *)buffer; | ||
327 | int secnum; | ||
328 | |||
329 | /* Encode all code sections. No support for data sections (yet). */ | ||
330 | for (secnum = 0; secnum < D->maxsection; secnum++) { | ||
331 | dasm_Section *sec = D->sections + secnum; | ||
332 | int *b = sec->buf; | ||
333 | int *endb = sec->rbuf + sec->pos; | ||
334 | |||
335 | while (b != endb) { | ||
336 | dasm_ActList p = D->actionlist + *b++; | ||
337 | while (1) { | ||
338 | unsigned int ins = *p++; | ||
339 | unsigned int action = (ins >> 16); | ||
340 | int n = (action >= DASM_ALIGN && action < DASM__MAX) ? *b++ : 0; | ||
341 | switch (action) { | ||
342 | case DASM_STOP: case DASM_SECTION: goto stop; | ||
343 | case DASM_ESC: *cp++ = *p++; break; | ||
344 | case DASM_REL_EXT: | ||
345 | n = DASM_EXTERN(Dst, (unsigned char *)cp, (ins & 2047), 1) - 4; | ||
346 | goto patchrel; | ||
347 | case DASM_ALIGN: | ||
348 | ins &= 255; while ((((char *)cp - base) & ins)) *cp++ = 0x60000000; | ||
349 | break; | ||
350 | case DASM_REL_LG: | ||
351 | CK(n >= 0, UNDEF_LG); | ||
352 | case DASM_REL_PC: | ||
353 | CK(n >= 0, UNDEF_PC); | ||
354 | n = *DASM_POS2PTR(D, n) - (int)((char *)cp - base); | ||
355 | patchrel: | ||
356 | CK((n & 3) == 0 && | ||
357 | (((n+4) + ((ins & 2048) ? 0x00008000 : 0x02000000)) >> | ||
358 | ((ins & 2048) ? 16 : 26)) == 0, RANGE_REL); | ||
359 | cp[-1] |= ((n+4) & ((ins & 2048) ? 0x0000fffc: 0x03fffffc)); | ||
360 | break; | ||
361 | case DASM_LABEL_LG: | ||
362 | ins &= 2047; if (ins >= 20) D->globals[ins-10] = (void *)(base + n); | ||
363 | break; | ||
364 | case DASM_LABEL_PC: break; | ||
365 | case DASM_IMM: | ||
366 | cp[-1] |= (n & ((1<<((ins>>5)&31))-1)) << (ins&31); | ||
367 | break; | ||
368 | default: *cp++ = ins; break; | ||
369 | } | ||
370 | } | ||
371 | stop: (void)0; | ||
372 | } | ||
373 | } | ||
374 | |||
375 | if (base + D->codesize != (char *)cp) /* Check for phase errors. */ | ||
376 | return DASM_S_PHASE; | ||
377 | return DASM_S_OK; | ||
378 | } | ||
379 | #undef CK | ||
380 | |||
381 | /* Get PC label offset. */ | ||
382 | int dasm_getpclabel(Dst_DECL, unsigned int pc) | ||
383 | { | ||
384 | dasm_State *D = Dst_REF; | ||
385 | if (pc*sizeof(int) < D->pcsize) { | ||
386 | int pos = D->pclabels[pc]; | ||
387 | if (pos < 0) return *DASM_POS2PTR(D, -pos); | ||
388 | if (pos > 0) return -1; /* Undefined. */ | ||
389 | } | ||
390 | return -2; /* Unused or out of range. */ | ||
391 | } | ||
392 | |||
393 | #ifdef DASM_CHECKS | ||
394 | /* Optional sanity checker to call between isolated encoding steps. */ | ||
395 | int dasm_checkstep(Dst_DECL, int secmatch) | ||
396 | { | ||
397 | dasm_State *D = Dst_REF; | ||
398 | if (D->status == DASM_S_OK) { | ||
399 | int i; | ||
400 | for (i = 1; i <= 9; i++) { | ||
401 | if (D->lglabels[i] > 0) { D->status = DASM_S_UNDEF_LG|i; break; } | ||
402 | D->lglabels[i] = 0; | ||
403 | } | ||
404 | } | ||
405 | if (D->status == DASM_S_OK && secmatch >= 0 && | ||
406 | D->section != &D->sections[secmatch]) | ||
407 | D->status = DASM_S_MATCH_SEC|(D->section-D->sections); | ||
408 | return D->status; | ||
409 | } | ||
410 | #endif | ||
411 | |||
diff --git a/libraries/luajit-2.0/dynasm/dasm_ppc.lua b/libraries/luajit-2.0/dynasm/dasm_ppc.lua new file mode 100644 index 0000000..b2bee2c --- /dev/null +++ b/libraries/luajit-2.0/dynasm/dasm_ppc.lua | |||
@@ -0,0 +1,1230 @@ | |||
1 | ------------------------------------------------------------------------------ | ||
2 | -- DynASM PPC module. | ||
3 | -- | ||
4 | -- Copyright (C) 2005-2011 Mike Pall. All rights reserved. | ||
5 | -- See dynasm.lua for full copyright notice. | ||
6 | ------------------------------------------------------------------------------ | ||
7 | |||
8 | -- Module information: | ||
9 | local _info = { | ||
10 | arch = "ppc", | ||
11 | description = "DynASM PPC module", | ||
12 | version = "1.3.0", | ||
13 | vernum = 10300, | ||
14 | release = "2011-05-05", | ||
15 | author = "Mike Pall", | ||
16 | license = "MIT", | ||
17 | } | ||
18 | |||
19 | -- Exported glue functions for the arch-specific module. | ||
20 | local _M = { _info = _info } | ||
21 | |||
22 | -- Cache library functions. | ||
23 | local type, tonumber, pairs, ipairs = type, tonumber, pairs, ipairs | ||
24 | local assert, setmetatable = assert, setmetatable | ||
25 | local _s = string | ||
26 | local sub, format, byte, char = _s.sub, _s.format, _s.byte, _s.char | ||
27 | local match, gmatch = _s.match, _s.gmatch | ||
28 | local concat, sort = table.concat, table.sort | ||
29 | |||
30 | -- Inherited tables and callbacks. | ||
31 | local g_opt, g_arch | ||
32 | local wline, werror, wfatal, wwarn | ||
33 | |||
34 | -- Action name list. | ||
35 | -- CHECK: Keep this in sync with the C code! | ||
36 | local action_names = { | ||
37 | "STOP", "SECTION", "ESC", "REL_EXT", | ||
38 | "ALIGN", "REL_LG", "LABEL_LG", | ||
39 | "REL_PC", "LABEL_PC", "IMM", | ||
40 | } | ||
41 | |||
42 | -- Maximum number of section buffer positions for dasm_put(). | ||
43 | -- CHECK: Keep this in sync with the C code! | ||
44 | local maxsecpos = 25 -- Keep this low, to avoid excessively long C lines. | ||
45 | |||
46 | -- Action name -> action number. | ||
47 | local map_action = {} | ||
48 | for n,name in ipairs(action_names) do | ||
49 | map_action[name] = n-1 | ||
50 | end | ||
51 | |||
52 | -- Action list buffer. | ||
53 | local actlist = {} | ||
54 | |||
55 | -- Argument list for next dasm_put(). Start with offset 0 into action list. | ||
56 | local actargs = { 0 } | ||
57 | |||
58 | -- Current number of section buffer positions for dasm_put(). | ||
59 | local secpos = 1 | ||
60 | |||
61 | ------------------------------------------------------------------------------ | ||
62 | |||
63 | -- Return 8 digit hex number. | ||
64 | local function tohex(x) | ||
65 | return sub(format("%08x", x), -8) -- Avoid 64 bit portability problem in Lua. | ||
66 | end | ||
67 | |||
68 | -- Dump action names and numbers. | ||
69 | local function dumpactions(out) | ||
70 | out:write("DynASM encoding engine action codes:\n") | ||
71 | for n,name in ipairs(action_names) do | ||
72 | local num = map_action[name] | ||
73 | out:write(format(" %-10s %02X %d\n", name, num, num)) | ||
74 | end | ||
75 | out:write("\n") | ||
76 | end | ||
77 | |||
78 | -- Write action list buffer as a huge static C array. | ||
79 | local function writeactions(out, name) | ||
80 | local nn = #actlist | ||
81 | if nn == 0 then nn = 1; actlist[0] = map_action.STOP end | ||
82 | out:write("static const unsigned int ", name, "[", nn, "] = {\n") | ||
83 | for i = 1,nn-1 do | ||
84 | assert(out:write("0x", tohex(actlist[i]), ",\n")) | ||
85 | end | ||
86 | assert(out:write("0x", tohex(actlist[nn]), "\n};\n\n")) | ||
87 | end | ||
88 | |||
89 | ------------------------------------------------------------------------------ | ||
90 | |||
91 | -- Add word to action list. | ||
92 | local function wputxw(n) | ||
93 | assert(n >= 0 and n <= 0xffffffff and n % 1 == 0, "word out of range") | ||
94 | actlist[#actlist+1] = n | ||
95 | end | ||
96 | |||
97 | -- Add action to list with optional arg. Advance buffer pos, too. | ||
98 | local function waction(action, val, a, num) | ||
99 | local w = assert(map_action[action], "bad action name `"..action.."'") | ||
100 | wputxw(w * 0x10000 + (val or 0)) | ||
101 | if a then actargs[#actargs+1] = a end | ||
102 | if a or num then secpos = secpos + (num or 1) end | ||
103 | end | ||
104 | |||
105 | -- Flush action list (intervening C code or buffer pos overflow). | ||
106 | local function wflush(term) | ||
107 | if #actlist == actargs[1] then return end -- Nothing to flush. | ||
108 | if not term then waction("STOP") end -- Terminate action list. | ||
109 | wline(format("dasm_put(Dst, %s);", concat(actargs, ", ")), true) | ||
110 | actargs = { #actlist } -- Actionlist offset is 1st arg to next dasm_put(). | ||
111 | secpos = 1 -- The actionlist offset occupies a buffer position, too. | ||
112 | end | ||
113 | |||
114 | -- Put escaped word. | ||
115 | local function wputw(n) | ||
116 | if n <= 0xffffff then waction("ESC") end | ||
117 | wputxw(n) | ||
118 | end | ||
119 | |||
120 | -- Reserve position for word. | ||
121 | local function wpos() | ||
122 | local pos = #actlist+1 | ||
123 | actlist[pos] = "" | ||
124 | return pos | ||
125 | end | ||
126 | |||
127 | -- Store word to reserved position. | ||
128 | local function wputpos(pos, n) | ||
129 | assert(n >= 0 and n <= 0xffffffff and n % 1 == 0, "word out of range") | ||
130 | actlist[pos] = n | ||
131 | end | ||
132 | |||
133 | ------------------------------------------------------------------------------ | ||
134 | |||
135 | -- Global label name -> global label number. With auto assignment on 1st use. | ||
136 | local next_global = 20 | ||
137 | local map_global = setmetatable({}, { __index = function(t, name) | ||
138 | if not match(name, "^[%a_][%w_]*$") then werror("bad global label") end | ||
139 | local n = next_global | ||
140 | if n > 2047 then werror("too many global labels") end | ||
141 | next_global = n + 1 | ||
142 | t[name] = n | ||
143 | return n | ||
144 | end}) | ||
145 | |||
146 | -- Dump global labels. | ||
147 | local function dumpglobals(out, lvl) | ||
148 | local t = {} | ||
149 | for name, n in pairs(map_global) do t[n] = name end | ||
150 | out:write("Global labels:\n") | ||
151 | for i=20,next_global-1 do | ||
152 | out:write(format(" %s\n", t[i])) | ||
153 | end | ||
154 | out:write("\n") | ||
155 | end | ||
156 | |||
157 | -- Write global label enum. | ||
158 | local function writeglobals(out, prefix) | ||
159 | local t = {} | ||
160 | for name, n in pairs(map_global) do t[n] = name end | ||
161 | out:write("enum {\n") | ||
162 | for i=20,next_global-1 do | ||
163 | out:write(" ", prefix, t[i], ",\n") | ||
164 | end | ||
165 | out:write(" ", prefix, "_MAX\n};\n") | ||
166 | end | ||
167 | |||
168 | -- Write global label names. | ||
169 | local function writeglobalnames(out, name) | ||
170 | local t = {} | ||
171 | for name, n in pairs(map_global) do t[n] = name end | ||
172 | out:write("static const char *const ", name, "[] = {\n") | ||
173 | for i=20,next_global-1 do | ||
174 | out:write(" \"", t[i], "\",\n") | ||
175 | end | ||
176 | out:write(" (const char *)0\n};\n") | ||
177 | end | ||
178 | |||
179 | ------------------------------------------------------------------------------ | ||
180 | |||
181 | -- Extern label name -> extern label number. With auto assignment on 1st use. | ||
182 | local next_extern = 0 | ||
183 | local map_extern_ = {} | ||
184 | local map_extern = setmetatable({}, { __index = function(t, name) | ||
185 | -- No restrictions on the name for now. | ||
186 | local n = next_extern | ||
187 | if n > 2047 then werror("too many extern labels") end | ||
188 | next_extern = n + 1 | ||
189 | t[name] = n | ||
190 | map_extern_[n] = name | ||
191 | return n | ||
192 | end}) | ||
193 | |||
194 | -- Dump extern labels. | ||
195 | local function dumpexterns(out, lvl) | ||
196 | out:write("Extern labels:\n") | ||
197 | for i=0,next_extern-1 do | ||
198 | out:write(format(" %s\n", map_extern_[i])) | ||
199 | end | ||
200 | out:write("\n") | ||
201 | end | ||
202 | |||
203 | -- Write extern label names. | ||
204 | local function writeexternnames(out, name) | ||
205 | out:write("static const char *const ", name, "[] = {\n") | ||
206 | for i=0,next_extern-1 do | ||
207 | out:write(" \"", map_extern_[i], "\",\n") | ||
208 | end | ||
209 | out:write(" (const char *)0\n};\n") | ||
210 | end | ||
211 | |||
212 | ------------------------------------------------------------------------------ | ||
213 | |||
214 | -- Arch-specific maps. | ||
215 | local map_archdef = { sp = "r1" } -- Ext. register name -> int. name. | ||
216 | |||
217 | local map_type = {} -- Type name -> { ctype, reg } | ||
218 | local ctypenum = 0 -- Type number (for Dt... macros). | ||
219 | |||
220 | -- Reverse defines for registers. | ||
221 | function _M.revdef(s) | ||
222 | if s == "r1" then return "sp" end | ||
223 | return s | ||
224 | end | ||
225 | |||
226 | local map_cond = { | ||
227 | lt = 0, gt = 1, eq = 2, so = 3, | ||
228 | ge = 4, le = 5, ne = 6, ns = 7, | ||
229 | } | ||
230 | |||
231 | ------------------------------------------------------------------------------ | ||
232 | |||
233 | -- Template strings for PPC instructions. | ||
234 | local map_op = { | ||
235 | tdi_3 = "08000000ARI", | ||
236 | twi_3 = "0c000000ARI", | ||
237 | mulli_3 = "1c000000RRI", | ||
238 | subfic_3 = "20000000RRI", | ||
239 | cmplwi_3 = "28000000XRU", | ||
240 | cmplwi_2 = "28000000-RU", | ||
241 | cmpldi_3 = "28200000XRU", | ||
242 | cmpldi_2 = "28200000-RU", | ||
243 | cmpwi_3 = "2c000000XRI", | ||
244 | cmpwi_2 = "2c000000-RI", | ||
245 | cmpdi_3 = "2c200000XRI", | ||
246 | cmpdi_2 = "2c200000-RI", | ||
247 | addic_3 = "30000000RRI", | ||
248 | ["addic._3"] = "34000000RRI", | ||
249 | addi_3 = "38000000RR0I", | ||
250 | li_2 = "38000000RI", | ||
251 | la_2 = "38000000RD", | ||
252 | addis_3 = "3c000000RR0I", | ||
253 | lis_2 = "3c000000RI", | ||
254 | lus_2 = "3c000000RU", | ||
255 | bc_3 = "40000000AAK", | ||
256 | bcl_3 = "40000001AAK", | ||
257 | bdnz_1 = "42000000K", | ||
258 | bdz_1 = "42400000K", | ||
259 | sc_0 = "44000000", | ||
260 | b_1 = "48000000J", | ||
261 | bl_1 = "48000001J", | ||
262 | rlwimi_5 = "50000000RR~AAA.", | ||
263 | rlwinm_5 = "54000000RR~AAA.", | ||
264 | rlwnm_5 = "5c000000RR~RAA.", | ||
265 | ori_3 = "60000000RR~U", | ||
266 | nop_0 = "60000000", | ||
267 | oris_3 = "64000000RR~U", | ||
268 | xori_3 = "68000000RR~U", | ||
269 | xoris_3 = "6c000000RR~U", | ||
270 | ["andi._3"] = "70000000RR~U", | ||
271 | ["andis._3"] = "74000000RR~U", | ||
272 | lwz_2 = "80000000RD", | ||
273 | lwzu_2 = "84000000RD", | ||
274 | lbz_2 = "88000000RD", | ||
275 | lbzu_2 = "8c000000RD", | ||
276 | stw_2 = "90000000RD", | ||
277 | stwu_2 = "94000000RD", | ||
278 | stb_2 = "98000000RD", | ||
279 | stbu_2 = "9c000000RD", | ||
280 | lhz_2 = "a0000000RD", | ||
281 | lhzu_2 = "a4000000RD", | ||
282 | lha_2 = "a8000000RD", | ||
283 | lhau_2 = "ac000000RD", | ||
284 | sth_2 = "b0000000RD", | ||
285 | sthu_2 = "b4000000RD", | ||
286 | lmw_2 = "b8000000RD", | ||
287 | stmw_2 = "bc000000RD", | ||
288 | lfs_2 = "c0000000FD", | ||
289 | lfsu_2 = "c4000000FD", | ||
290 | lfd_2 = "c8000000FD", | ||
291 | lfdu_2 = "cc000000FD", | ||
292 | stfs_2 = "d0000000FD", | ||
293 | stfsu_2 = "d4000000FD", | ||
294 | stfd_2 = "d8000000FD", | ||
295 | stfdu_2 = "dc000000FD", | ||
296 | ld_2 = "e8000000RD", -- NYI: displacement must be divisible by 4. | ||
297 | ldu_2 = "e8000001RD", | ||
298 | lwa_2 = "e8000002RD", | ||
299 | std_2 = "f8000000RD", | ||
300 | stdu_2 = "f8000001RD", | ||
301 | |||
302 | -- Primary opcode 19: | ||
303 | mcrf_2 = "4c000000XX", | ||
304 | isync_0 = "4c00012c", | ||
305 | crnor_3 = "4c000042CCC", | ||
306 | crnot_2 = "4c000042CC=", | ||
307 | crandc_3 = "4c000102CCC", | ||
308 | crxor_3 = "4c000182CCC", | ||
309 | crclr_1 = "4c000182C==", | ||
310 | crnand_3 = "4c0001c2CCC", | ||
311 | crand_3 = "4c000202CCC", | ||
312 | creqv_3 = "4c000242CCC", | ||
313 | crset_1 = "4c000242C==", | ||
314 | crorc_3 = "4c000342CCC", | ||
315 | cror_3 = "4c000382CCC", | ||
316 | crmove_2 = "4c000382CC=", | ||
317 | bclr_2 = "4c000020AA", | ||
318 | bclrl_2 = "4c000021AA", | ||
319 | bcctr_2 = "4c000420AA", | ||
320 | bcctrl_2 = "4c000421AA", | ||
321 | blr_0 = "4e800020", | ||
322 | blrl_0 = "4e800021", | ||
323 | bctr_0 = "4e800420", | ||
324 | bctrl_0 = "4e800421", | ||
325 | |||
326 | -- Primary opcode 31: | ||
327 | cmpw_3 = "7c000000XRR", | ||
328 | cmpw_2 = "7c000000-RR", | ||
329 | cmpd_3 = "7c200000XRR", | ||
330 | cmpd_2 = "7c200000-RR", | ||
331 | tw_3 = "7c000008ARR", | ||
332 | subfc_3 = "7c000010RRR.", | ||
333 | subc_3 = "7c000010RRR~.", | ||
334 | mulhdu_3 = "7c000012RRR.", | ||
335 | addc_3 = "7c000014RRR.", | ||
336 | mulhwu_3 = "7c000016RRR.", | ||
337 | isel_4 = "7c00001eRRRC", | ||
338 | isellt_3 = "7c00001eRRR", | ||
339 | iselgt_3 = "7c00005eRRR", | ||
340 | iseleq_3 = "7c00009eRRR", | ||
341 | mfcr_1 = "7c000026R", | ||
342 | mtcrf_2 = "7c000120GR", | ||
343 | -- NYI: mtocrf, mfocrf | ||
344 | lwarx_3 = "7c000028RR0R", | ||
345 | ldx_3 = "7c00002aRR0R", | ||
346 | lwzx_3 = "7c00002eRR0R", | ||
347 | slw_3 = "7c000030RR~R.", | ||
348 | cntlzw_2 = "7c000034RR~", | ||
349 | sld_3 = "7c000036RR~R.", | ||
350 | and_3 = "7c000038RR~R.", | ||
351 | cmplw_3 = "7c000040XRR", | ||
352 | cmplw_2 = "7c000040-RR", | ||
353 | cmpld_3 = "7c200040XRR", | ||
354 | cmpld_2 = "7c200040-RR", | ||
355 | subf_3 = "7c000050RRR.", | ||
356 | sub_3 = "7c000050RRR~.", | ||
357 | ldux_3 = "7c00006aRR0R", | ||
358 | dcbst_2 = "7c00006c-RR", | ||
359 | lwzux_3 = "7c00006eRR0R", | ||
360 | cntlzd_2 = "7c000074RR~", | ||
361 | andc_3 = "7c000078RR~R.", | ||
362 | td_3 = "7c000088ARR", | ||
363 | mulhd_3 = "7c000092RRR.", | ||
364 | mulhw_3 = "7c000096RRR.", | ||
365 | ldarx_3 = "7c0000a8RR0R", | ||
366 | dcbf_2 = "7c0000ac-RR", | ||
367 | lbzx_3 = "7c0000aeRR0R", | ||
368 | neg_2 = "7c0000d0RR.", | ||
369 | lbzux_3 = "7c0000eeRR0R", | ||
370 | popcntb_2 = "7c0000f4RR~", | ||
371 | not_2 = "7c0000f8RR~%.", | ||
372 | nor_3 = "7c0000f8RR~R.", | ||
373 | subfe_3 = "7c000110RRR.", | ||
374 | sube_3 = "7c000110RRR~.", | ||
375 | adde_3 = "7c000114RRR.", | ||
376 | stdx_3 = "7c00012aRR0R", | ||
377 | stwcx_3 = "7c00012cRR0R.", | ||
378 | stwx_3 = "7c00012eRR0R", | ||
379 | prtyw_2 = "7c000134RR~", | ||
380 | stdux_3 = "7c00016aRR0R", | ||
381 | stwux_3 = "7c00016eRR0R", | ||
382 | prtyd_2 = "7c000174RR~", | ||
383 | subfze_2 = "7c000190RR.", | ||
384 | addze_2 = "7c000194RR.", | ||
385 | stdcx_3 = "7c0001acRR0R.", | ||
386 | stbx_3 = "7c0001aeRR0R", | ||
387 | subfme_2 = "7c0001d0RR.", | ||
388 | mulld_3 = "7c0001d2RRR.", | ||
389 | addme_2 = "7c0001d4RR.", | ||
390 | mullw_3 = "7c0001d6RRR.", | ||
391 | dcbtst_2 = "7c0001ec-RR", | ||
392 | stbux_3 = "7c0001eeRR0R", | ||
393 | add_3 = "7c000214RRR.", | ||
394 | dcbt_2 = "7c00022c-RR", | ||
395 | lhzx_3 = "7c00022eRR0R", | ||
396 | eqv_3 = "7c000238RR~R.", | ||
397 | eciwx_3 = "7c00026cRR0R", | ||
398 | lhzux_3 = "7c00026eRR0R", | ||
399 | xor_3 = "7c000278RR~R.", | ||
400 | mfspefscr_1 = "7c0082a6R", | ||
401 | mfxer_1 = "7c0102a6R", | ||
402 | mflr_1 = "7c0802a6R", | ||
403 | mfctr_1 = "7c0902a6R", | ||
404 | lwax_3 = "7c0002aaRR0R", | ||
405 | lhax_3 = "7c0002aeRR0R", | ||
406 | mftb_1 = "7c0c42e6R", | ||
407 | mftbu_1 = "7c0d42e6R", | ||
408 | lwaux_3 = "7c0002eaRR0R", | ||
409 | lhaux_3 = "7c0002eeRR0R", | ||
410 | sthx_3 = "7c00032eRR0R", | ||
411 | orc_3 = "7c000338RR~R.", | ||
412 | ecowx_3 = "7c00036cRR0R", | ||
413 | sthux_3 = "7c00036eRR0R", | ||
414 | or_3 = "7c000378RR~R.", | ||
415 | mr_2 = "7c000378RR~%.", | ||
416 | divdu_3 = "7c000392RRR.", | ||
417 | divwu_3 = "7c000396RRR.", | ||
418 | mtspefscr_1 = "7c0083a6R", | ||
419 | mtxer_1 = "7c0103a6R", | ||
420 | mtlr_1 = "7c0803a6R", | ||
421 | mtctr_1 = "7c0903a6R", | ||
422 | dcbi_2 = "7c0003ac-RR", | ||
423 | nand_3 = "7c0003b8RR~R.", | ||
424 | divd_3 = "7c0003d2RRR.", | ||
425 | divw_3 = "7c0003d6RRR.", | ||
426 | cmpb_3 = "7c0003f8RR~R.", | ||
427 | mcrxr_1 = "7c000400X", | ||
428 | subfco_3 = "7c000410RRR.", | ||
429 | subco_3 = "7c000410RRR~.", | ||
430 | addco_3 = "7c000414RRR.", | ||
431 | ldbrx_3 = "7c000428RR0R", | ||
432 | lswx_3 = "7c00042aRR0R", | ||
433 | lwbrx_3 = "7c00042cRR0R", | ||
434 | lfsx_3 = "7c00042eFR0R", | ||
435 | srw_3 = "7c000430RR~R.", | ||
436 | srd_3 = "7c000436RR~R.", | ||
437 | subfo_3 = "7c000450RRR.", | ||
438 | subo_3 = "7c000450RRR~.", | ||
439 | lfsux_3 = "7c00046eFR0R", | ||
440 | lswi_3 = "7c0004aaRR0A", | ||
441 | sync_0 = "7c0004ac", | ||
442 | lwsync_0 = "7c2004ac", | ||
443 | ptesync_0 = "7c4004ac", | ||
444 | lfdx_3 = "7c0004aeFR0R", | ||
445 | nego_2 = "7c0004d0RR.", | ||
446 | lfdux_3 = "7c0004eeFR0R", | ||
447 | subfeo_3 = "7c000510RRR.", | ||
448 | subeo_3 = "7c000510RRR~.", | ||
449 | addeo_3 = "7c000514RRR.", | ||
450 | stdbrx_3 = "7c000528RR0R", | ||
451 | stswx_3 = "7c00052aRR0R", | ||
452 | stwbrx_3 = "7c00052cRR0R", | ||
453 | stfsx_3 = "7c00052eFR0R", | ||
454 | stfsux_3 = "7c00056eFR0R", | ||
455 | subfzeo_2 = "7c000590RR.", | ||
456 | addzeo_2 = "7c000594RR.", | ||
457 | stswi_3 = "7c0005aaRR0A", | ||
458 | stfdx_3 = "7c0005aeFR0R", | ||
459 | subfmeo_2 = "7c0005d0RR.", | ||
460 | mulldo_3 = "7c0005d2RRR.", | ||
461 | addmeo_2 = "7c0005d4RR.", | ||
462 | mullwo_3 = "7c0005d6RRR.", | ||
463 | dcba_2 = "7c0005ec-RR", | ||
464 | stfdux_3 = "7c0005eeFR0R", | ||
465 | addo_3 = "7c000614RRR.", | ||
466 | lhbrx_3 = "7c00062cRR0R", | ||
467 | sraw_3 = "7c000630RR~R.", | ||
468 | srad_3 = "7c000634RR~R.", | ||
469 | srawi_3 = "7c000670RR~A.", | ||
470 | eieio_0 = "7c0006ac", | ||
471 | lfiwax_3 = "7c0006aeFR0R", | ||
472 | sthbrx_3 = "7c00072cRR0R", | ||
473 | extsh_2 = "7c000734RR~.", | ||
474 | extsb_2 = "7c000774RR~.", | ||
475 | divduo_3 = "7c000792RRR.", | ||
476 | divwou_3 = "7c000796RRR.", | ||
477 | icbi_2 = "7c0007ac-RR", | ||
478 | stfiwx_3 = "7c0007aeFR0R", | ||
479 | extsw_2 = "7c0007b4RR~.", | ||
480 | divdo_3 = "7c0007d2RRR.", | ||
481 | divwo_3 = "7c0007d6RRR.", | ||
482 | dcbz_2 = "7c0007ec-RR", | ||
483 | |||
484 | -- Primary opcode 59: | ||
485 | fdivs_3 = "ec000024FFF.", | ||
486 | fsubs_3 = "ec000028FFF.", | ||
487 | fadds_3 = "ec00002aFFF.", | ||
488 | fsqrts_2 = "ec00002cF-F.", | ||
489 | fres_2 = "ec000030F-F.", | ||
490 | fmuls_3 = "ec000032FF-F.", | ||
491 | frsqrtes_2 = "ec000034F-F.", | ||
492 | fmsubs_4 = "ec000038FFFF~.", | ||
493 | fmadds_4 = "ec00003aFFFF~.", | ||
494 | fnmsubs_4 = "ec00003cFFFF~.", | ||
495 | fnmadds_4 = "ec00003eFFFF~.", | ||
496 | |||
497 | -- Primary opcode 63: | ||
498 | fdiv_3 = "fc000024FFF.", | ||
499 | fsub_3 = "fc000028FFF.", | ||
500 | fadd_3 = "fc00002aFFF.", | ||
501 | fsqrt_2 = "fc00002cF-F.", | ||
502 | fsel_4 = "fc00002eFFFF~.", | ||
503 | fre_2 = "fc000030F-F.", | ||
504 | fmul_3 = "fc000032FF-F.", | ||
505 | frsqrte_2 = "fc000034F-F.", | ||
506 | fmsub_4 = "fc000038FFFF~.", | ||
507 | fmadd_4 = "fc00003aFFFF~.", | ||
508 | fnmsub_4 = "fc00003cFFFF~.", | ||
509 | fnmadd_4 = "fc00003eFFFF~.", | ||
510 | fcmpu_3 = "fc000000XFF", | ||
511 | fcpsgn_3 = "fc000010FFF.", | ||
512 | fcmpo_3 = "fc000040XFF", | ||
513 | mtfsb1_1 = "fc00004cA", | ||
514 | fneg_2 = "fc000050F-F.", | ||
515 | mcrfs_2 = "fc000080XX", | ||
516 | mtfsb0_1 = "fc00008cA", | ||
517 | fmr_2 = "fc000090F-F.", | ||
518 | frsp_2 = "fc000018F-F.", | ||
519 | fctiw_2 = "fc00001cF-F.", | ||
520 | fctiwz_2 = "fc00001eF-F.", | ||
521 | mtfsfi_2 = "fc00010cAA", -- NYI: upshift. | ||
522 | fnabs_2 = "fc000110F-F.", | ||
523 | fabs_2 = "fc000210F-F.", | ||
524 | frin_2 = "fc000310F-F.", | ||
525 | friz_2 = "fc000350F-F.", | ||
526 | frip_2 = "fc000390F-F.", | ||
527 | frim_2 = "fc0003d0F-F.", | ||
528 | mffs_1 = "fc00048eF.", | ||
529 | -- NYI: mtfsf, mtfsb0, mtfsb1. | ||
530 | fctid_2 = "fc00065cF-F.", | ||
531 | fctidz_2 = "fc00065eF-F.", | ||
532 | fcfid_2 = "fc00069cF-F.", | ||
533 | |||
534 | -- Primary opcode 4, SPE APU extension: | ||
535 | evaddw_3 = "10000200RRR", | ||
536 | evaddiw_3 = "10000202RAR~", | ||
537 | evsubw_3 = "10000204RRR~", | ||
538 | evsubiw_3 = "10000206RAR~", | ||
539 | evabs_2 = "10000208RR", | ||
540 | evneg_2 = "10000209RR", | ||
541 | evextsb_2 = "1000020aRR", | ||
542 | evextsh_2 = "1000020bRR", | ||
543 | evrndw_2 = "1000020cRR", | ||
544 | evcntlzw_2 = "1000020dRR", | ||
545 | evcntlsw_2 = "1000020eRR", | ||
546 | brinc_3 = "1000020fRRR", | ||
547 | evand_3 = "10000211RRR", | ||
548 | evandc_3 = "10000212RRR", | ||
549 | evxor_3 = "10000216RRR", | ||
550 | evor_3 = "10000217RRR", | ||
551 | evmr_2 = "10000217RR=", | ||
552 | evnor_3 = "10000218RRR", | ||
553 | evnot_2 = "10000218RR=", | ||
554 | eveqv_3 = "10000219RRR", | ||
555 | evorc_3 = "1000021bRRR", | ||
556 | evnand_3 = "1000021eRRR", | ||
557 | evsrwu_3 = "10000220RRR", | ||
558 | evsrws_3 = "10000221RRR", | ||
559 | evsrwiu_3 = "10000222RRA", | ||
560 | evsrwis_3 = "10000223RRA", | ||
561 | evslw_3 = "10000224RRR", | ||
562 | evslwi_3 = "10000226RRA", | ||
563 | evrlw_3 = "10000228RRR", | ||
564 | evsplati_2 = "10000229RS", | ||
565 | evrlwi_3 = "1000022aRRA", | ||
566 | evsplatfi_2 = "1000022bRS", | ||
567 | evmergehi_3 = "1000022cRRR", | ||
568 | evmergelo_3 = "1000022dRRR", | ||
569 | evcmpgtu_3 = "10000230XRR", | ||
570 | evcmpgtu_2 = "10000230-RR", | ||
571 | evcmpgts_3 = "10000231XRR", | ||
572 | evcmpgts_2 = "10000231-RR", | ||
573 | evcmpltu_3 = "10000232XRR", | ||
574 | evcmpltu_2 = "10000232-RR", | ||
575 | evcmplts_3 = "10000233XRR", | ||
576 | evcmplts_2 = "10000233-RR", | ||
577 | evcmpeq_3 = "10000234XRR", | ||
578 | evcmpeq_2 = "10000234-RR", | ||
579 | evsel_4 = "10000278RRRW", | ||
580 | evsel_3 = "10000278RRR", | ||
581 | evfsadd_3 = "10000280RRR", | ||
582 | evfssub_3 = "10000281RRR", | ||
583 | evfsabs_2 = "10000284RR", | ||
584 | evfsnabs_2 = "10000285RR", | ||
585 | evfsneg_2 = "10000286RR", | ||
586 | evfsmul_3 = "10000288RRR", | ||
587 | evfsdiv_3 = "10000289RRR", | ||
588 | evfscmpgt_3 = "1000028cXRR", | ||
589 | evfscmpgt_2 = "1000028c-RR", | ||
590 | evfscmplt_3 = "1000028dXRR", | ||
591 | evfscmplt_2 = "1000028d-RR", | ||
592 | evfscmpeq_3 = "1000028eXRR", | ||
593 | evfscmpeq_2 = "1000028e-RR", | ||
594 | evfscfui_2 = "10000290R-R", | ||
595 | evfscfsi_2 = "10000291R-R", | ||
596 | evfscfuf_2 = "10000292R-R", | ||
597 | evfscfsf_2 = "10000293R-R", | ||
598 | evfsctui_2 = "10000294R-R", | ||
599 | evfsctsi_2 = "10000295R-R", | ||
600 | evfsctuf_2 = "10000296R-R", | ||
601 | evfsctsf_2 = "10000297R-R", | ||
602 | evfsctuiz_2 = "10000298R-R", | ||
603 | evfsctsiz_2 = "1000029aR-R", | ||
604 | evfststgt_3 = "1000029cXRR", | ||
605 | evfststgt_2 = "1000029c-RR", | ||
606 | evfststlt_3 = "1000029dXRR", | ||
607 | evfststlt_2 = "1000029d-RR", | ||
608 | evfststeq_3 = "1000029eXRR", | ||
609 | evfststeq_2 = "1000029e-RR", | ||
610 | efsadd_3 = "100002c0RRR", | ||
611 | efssub_3 = "100002c1RRR", | ||
612 | efsabs_2 = "100002c4RR", | ||
613 | efsnabs_2 = "100002c5RR", | ||
614 | efsneg_2 = "100002c6RR", | ||
615 | efsmul_3 = "100002c8RRR", | ||
616 | efsdiv_3 = "100002c9RRR", | ||
617 | efscmpgt_3 = "100002ccXRR", | ||
618 | efscmpgt_2 = "100002cc-RR", | ||
619 | efscmplt_3 = "100002cdXRR", | ||
620 | efscmplt_2 = "100002cd-RR", | ||
621 | efscmpeq_3 = "100002ceXRR", | ||
622 | efscmpeq_2 = "100002ce-RR", | ||
623 | efscfd_2 = "100002cfR-R", | ||
624 | efscfui_2 = "100002d0R-R", | ||
625 | efscfsi_2 = "100002d1R-R", | ||
626 | efscfuf_2 = "100002d2R-R", | ||
627 | efscfsf_2 = "100002d3R-R", | ||
628 | efsctui_2 = "100002d4R-R", | ||
629 | efsctsi_2 = "100002d5R-R", | ||
630 | efsctuf_2 = "100002d6R-R", | ||
631 | efsctsf_2 = "100002d7R-R", | ||
632 | efsctuiz_2 = "100002d8R-R", | ||
633 | efsctsiz_2 = "100002daR-R", | ||
634 | efststgt_3 = "100002dcXRR", | ||
635 | efststgt_2 = "100002dc-RR", | ||
636 | efststlt_3 = "100002ddXRR", | ||
637 | efststlt_2 = "100002dd-RR", | ||
638 | efststeq_3 = "100002deXRR", | ||
639 | efststeq_2 = "100002de-RR", | ||
640 | efdadd_3 = "100002e0RRR", | ||
641 | efdsub_3 = "100002e1RRR", | ||
642 | efdcfuid_2 = "100002e2R-R", | ||
643 | efdcfsid_2 = "100002e3R-R", | ||
644 | efdabs_2 = "100002e4RR", | ||
645 | efdnabs_2 = "100002e5RR", | ||
646 | efdneg_2 = "100002e6RR", | ||
647 | efdmul_3 = "100002e8RRR", | ||
648 | efddiv_3 = "100002e9RRR", | ||
649 | efdctuidz_2 = "100002eaR-R", | ||
650 | efdctsidz_2 = "100002ebR-R", | ||
651 | efdcmpgt_3 = "100002ecXRR", | ||
652 | efdcmpgt_2 = "100002ec-RR", | ||
653 | efdcmplt_3 = "100002edXRR", | ||
654 | efdcmplt_2 = "100002ed-RR", | ||
655 | efdcmpeq_3 = "100002eeXRR", | ||
656 | efdcmpeq_2 = "100002ee-RR", | ||
657 | efdcfs_2 = "100002efR-R", | ||
658 | efdcfui_2 = "100002f0R-R", | ||
659 | efdcfsi_2 = "100002f1R-R", | ||
660 | efdcfuf_2 = "100002f2R-R", | ||
661 | efdcfsf_2 = "100002f3R-R", | ||
662 | efdctui_2 = "100002f4R-R", | ||
663 | efdctsi_2 = "100002f5R-R", | ||
664 | efdctuf_2 = "100002f6R-R", | ||
665 | efdctsf_2 = "100002f7R-R", | ||
666 | efdctuiz_2 = "100002f8R-R", | ||
667 | efdctsiz_2 = "100002faR-R", | ||
668 | efdtstgt_3 = "100002fcXRR", | ||
669 | efdtstgt_2 = "100002fc-RR", | ||
670 | efdtstlt_3 = "100002fdXRR", | ||
671 | efdtstlt_2 = "100002fd-RR", | ||
672 | efdtsteq_3 = "100002feXRR", | ||
673 | efdtsteq_2 = "100002fe-RR", | ||
674 | evlddx_3 = "10000300RR0R", | ||
675 | evldd_2 = "10000301R8", | ||
676 | evldwx_3 = "10000302RR0R", | ||
677 | evldw_2 = "10000303R8", | ||
678 | evldhx_3 = "10000304RR0R", | ||
679 | evldh_2 = "10000305R8", | ||
680 | evlwhex_3 = "10000310RR0R", | ||
681 | evlwhe_2 = "10000311R4", | ||
682 | evlwhoux_3 = "10000314RR0R", | ||
683 | evlwhou_2 = "10000315R4", | ||
684 | evlwhosx_3 = "10000316RR0R", | ||
685 | evlwhos_2 = "10000317R4", | ||
686 | evstddx_3 = "10000320RR0R", | ||
687 | evstdd_2 = "10000321R8", | ||
688 | evstdwx_3 = "10000322RR0R", | ||
689 | evstdw_2 = "10000323R8", | ||
690 | evstdhx_3 = "10000324RR0R", | ||
691 | evstdh_2 = "10000325R8", | ||
692 | evstwhex_3 = "10000330RR0R", | ||
693 | evstwhe_2 = "10000331R4", | ||
694 | evstwhox_3 = "10000334RR0R", | ||
695 | evstwho_2 = "10000335R4", | ||
696 | evstwwex_3 = "10000338RR0R", | ||
697 | evstwwe_2 = "10000339R4", | ||
698 | evstwwox_3 = "1000033cRR0R", | ||
699 | evstwwo_2 = "1000033dR4", | ||
700 | evmhessf_3 = "10000403RRR", | ||
701 | evmhossf_3 = "10000407RRR", | ||
702 | evmheumi_3 = "10000408RRR", | ||
703 | evmhesmi_3 = "10000409RRR", | ||
704 | evmhesmf_3 = "1000040bRRR", | ||
705 | evmhoumi_3 = "1000040cRRR", | ||
706 | evmhosmi_3 = "1000040dRRR", | ||
707 | evmhosmf_3 = "1000040fRRR", | ||
708 | evmhessfa_3 = "10000423RRR", | ||
709 | evmhossfa_3 = "10000427RRR", | ||
710 | evmheumia_3 = "10000428RRR", | ||
711 | evmhesmia_3 = "10000429RRR", | ||
712 | evmhesmfa_3 = "1000042bRRR", | ||
713 | evmhoumia_3 = "1000042cRRR", | ||
714 | evmhosmia_3 = "1000042dRRR", | ||
715 | evmhosmfa_3 = "1000042fRRR", | ||
716 | evmwhssf_3 = "10000447RRR", | ||
717 | evmwlumi_3 = "10000448RRR", | ||
718 | evmwhumi_3 = "1000044cRRR", | ||
719 | evmwhsmi_3 = "1000044dRRR", | ||
720 | evmwhsmf_3 = "1000044fRRR", | ||
721 | evmwssf_3 = "10000453RRR", | ||
722 | evmwumi_3 = "10000458RRR", | ||
723 | evmwsmi_3 = "10000459RRR", | ||
724 | evmwsmf_3 = "1000045bRRR", | ||
725 | evmwhssfa_3 = "10000467RRR", | ||
726 | evmwlumia_3 = "10000468RRR", | ||
727 | evmwhumia_3 = "1000046cRRR", | ||
728 | evmwhsmia_3 = "1000046dRRR", | ||
729 | evmwhsmfa_3 = "1000046fRRR", | ||
730 | evmwssfa_3 = "10000473RRR", | ||
731 | evmwumia_3 = "10000478RRR", | ||
732 | evmwsmia_3 = "10000479RRR", | ||
733 | evmwsmfa_3 = "1000047bRRR", | ||
734 | evmra_2 = "100004c4RR", | ||
735 | evdivws_3 = "100004c6RRR", | ||
736 | evdivwu_3 = "100004c7RRR", | ||
737 | evmwssfaa_3 = "10000553RRR", | ||
738 | evmwumiaa_3 = "10000558RRR", | ||
739 | evmwsmiaa_3 = "10000559RRR", | ||
740 | evmwsmfaa_3 = "1000055bRRR", | ||
741 | evmwssfan_3 = "100005d3RRR", | ||
742 | evmwumian_3 = "100005d8RRR", | ||
743 | evmwsmian_3 = "100005d9RRR", | ||
744 | evmwsmfan_3 = "100005dbRRR", | ||
745 | evmergehilo_3 = "1000022eRRR", | ||
746 | evmergelohi_3 = "1000022fRRR", | ||
747 | evlhhesplatx_3 = "10000308RR0R", | ||
748 | evlhhesplat_2 = "10000309R2", | ||
749 | evlhhousplatx_3 = "1000030cRR0R", | ||
750 | evlhhousplat_2 = "1000030dR2", | ||
751 | evlhhossplatx_3 = "1000030eRR0R", | ||
752 | evlhhossplat_2 = "1000030fR2", | ||
753 | evlwwsplatx_3 = "10000318RR0R", | ||
754 | evlwwsplat_2 = "10000319R4", | ||
755 | evlwhsplatx_3 = "1000031cRR0R", | ||
756 | evlwhsplat_2 = "1000031dR4", | ||
757 | evaddusiaaw_2 = "100004c0RR", | ||
758 | evaddssiaaw_2 = "100004c1RR", | ||
759 | evsubfusiaaw_2 = "100004c2RR", | ||
760 | evsubfssiaaw_2 = "100004c3RR", | ||
761 | evaddumiaaw_2 = "100004c8RR", | ||
762 | evaddsmiaaw_2 = "100004c9RR", | ||
763 | evsubfumiaaw_2 = "100004caRR", | ||
764 | evsubfsmiaaw_2 = "100004cbRR", | ||
765 | evmheusiaaw_3 = "10000500RRR", | ||
766 | evmhessiaaw_3 = "10000501RRR", | ||
767 | evmhessfaaw_3 = "10000503RRR", | ||
768 | evmhousiaaw_3 = "10000504RRR", | ||
769 | evmhossiaaw_3 = "10000505RRR", | ||
770 | evmhossfaaw_3 = "10000507RRR", | ||
771 | evmheumiaaw_3 = "10000508RRR", | ||
772 | evmhesmiaaw_3 = "10000509RRR", | ||
773 | evmhesmfaaw_3 = "1000050bRRR", | ||
774 | evmhoumiaaw_3 = "1000050cRRR", | ||
775 | evmhosmiaaw_3 = "1000050dRRR", | ||
776 | evmhosmfaaw_3 = "1000050fRRR", | ||
777 | evmhegumiaa_3 = "10000528RRR", | ||
778 | evmhegsmiaa_3 = "10000529RRR", | ||
779 | evmhegsmfaa_3 = "1000052bRRR", | ||
780 | evmhogumiaa_3 = "1000052cRRR", | ||
781 | evmhogsmiaa_3 = "1000052dRRR", | ||
782 | evmhogsmfaa_3 = "1000052fRRR", | ||
783 | evmwlusiaaw_3 = "10000540RRR", | ||
784 | evmwlssiaaw_3 = "10000541RRR", | ||
785 | evmwlumiaaw_3 = "10000548RRR", | ||
786 | evmwlsmiaaw_3 = "10000549RRR", | ||
787 | evmheusianw_3 = "10000580RRR", | ||
788 | evmhessianw_3 = "10000581RRR", | ||
789 | evmhessfanw_3 = "10000583RRR", | ||
790 | evmhousianw_3 = "10000584RRR", | ||
791 | evmhossianw_3 = "10000585RRR", | ||
792 | evmhossfanw_3 = "10000587RRR", | ||
793 | evmheumianw_3 = "10000588RRR", | ||
794 | evmhesmianw_3 = "10000589RRR", | ||
795 | evmhesmfanw_3 = "1000058bRRR", | ||
796 | evmhoumianw_3 = "1000058cRRR", | ||
797 | evmhosmianw_3 = "1000058dRRR", | ||
798 | evmhosmfanw_3 = "1000058fRRR", | ||
799 | evmhegumian_3 = "100005a8RRR", | ||
800 | evmhegsmian_3 = "100005a9RRR", | ||
801 | evmhegsmfan_3 = "100005abRRR", | ||
802 | evmhogumian_3 = "100005acRRR", | ||
803 | evmhogsmian_3 = "100005adRRR", | ||
804 | evmhogsmfan_3 = "100005afRRR", | ||
805 | evmwlusianw_3 = "100005c0RRR", | ||
806 | evmwlssianw_3 = "100005c1RRR", | ||
807 | evmwlumianw_3 = "100005c8RRR", | ||
808 | evmwlsmianw_3 = "100005c9RRR", | ||
809 | |||
810 | -- NYI: some 64 bit PowerPC and Book E instructions: | ||
811 | -- rldicl, rldicr, rldic, rldimi, rldcl, rldcr, sradi, 64 bit ext. add/sub, | ||
812 | -- extended addressing branches, cache management, loads and stores | ||
813 | } | ||
814 | |||
815 | -- Add mnemonics for "." variants. | ||
816 | do | ||
817 | local t = {} | ||
818 | for k,v in pairs(map_op) do | ||
819 | if sub(v, -1) == "." then | ||
820 | local v2 = sub(v, 1, 7)..char(byte(v, 8)+1)..sub(v, 9, -2) | ||
821 | t[sub(k, 1, -3).."."..sub(k, -2)] = v2 | ||
822 | end | ||
823 | end | ||
824 | for k,v in pairs(t) do | ||
825 | map_op[k] = v | ||
826 | end | ||
827 | end | ||
828 | |||
829 | -- Add more branch mnemonics. | ||
830 | for cond,c in pairs(map_cond) do | ||
831 | local b1 = "b"..cond | ||
832 | local c1 = (c%4)*0x00010000 + (c < 4 and 0x01000000 or 0) | ||
833 | -- bX[l] | ||
834 | map_op[b1.."_1"] = tohex(0x40800000 + c1).."K" | ||
835 | map_op[b1.."y_1"] = tohex(0x40a00000 + c1).."K" | ||
836 | map_op[b1.."l_1"] = tohex(0x40800001 + c1).."K" | ||
837 | map_op[b1.."_2"] = tohex(0x40800000 + c1).."-XK" | ||
838 | map_op[b1.."y_2"] = tohex(0x40a00000 + c1).."-XK" | ||
839 | map_op[b1.."l_2"] = tohex(0x40800001 + c1).."-XK" | ||
840 | -- bXlr[l] | ||
841 | map_op[b1.."lr_0"] = tohex(0x4c800020 + c1) | ||
842 | map_op[b1.."lrl_0"] = tohex(0x4c800021 + c1) | ||
843 | map_op[b1.."ctr_0"] = tohex(0x4c800420 + c1) | ||
844 | map_op[b1.."ctrl_0"] = tohex(0x4c800421 + c1) | ||
845 | -- bXctr[l] | ||
846 | map_op[b1.."lr_1"] = tohex(0x4c800020 + c1).."-X" | ||
847 | map_op[b1.."lrl_1"] = tohex(0x4c800021 + c1).."-X" | ||
848 | map_op[b1.."ctr_1"] = tohex(0x4c800420 + c1).."-X" | ||
849 | map_op[b1.."ctrl_1"] = tohex(0x4c800421 + c1).."-X" | ||
850 | end | ||
851 | |||
852 | ------------------------------------------------------------------------------ | ||
853 | |||
854 | local function parse_gpr(expr) | ||
855 | local tname, ovreg = match(expr, "^([%w_]+):(r[1-3]?[0-9])$") | ||
856 | local tp = map_type[tname or expr] | ||
857 | if tp then | ||
858 | local reg = ovreg or tp.reg | ||
859 | if not reg then | ||
860 | werror("type `"..(tname or expr).."' needs a register override") | ||
861 | end | ||
862 | expr = reg | ||
863 | end | ||
864 | local r = match(expr, "^r([1-3]?[0-9])$") | ||
865 | if r then | ||
866 | r = tonumber(r) | ||
867 | if r <= 31 then return r, tp end | ||
868 | end | ||
869 | werror("bad register name `"..expr.."'") | ||
870 | end | ||
871 | |||
872 | local function parse_fpr(expr) | ||
873 | local r = match(expr, "^f([1-3]?[0-9])$") | ||
874 | if r then | ||
875 | r = tonumber(r) | ||
876 | if r <= 31 then return r end | ||
877 | end | ||
878 | werror("bad register name `"..expr.."'") | ||
879 | end | ||
880 | |||
881 | local function parse_cr(expr) | ||
882 | local r = match(expr, "^cr([0-7])$") | ||
883 | if r then return tonumber(r) end | ||
884 | werror("bad condition register name `"..expr.."'") | ||
885 | end | ||
886 | |||
887 | local function parse_cond(expr) | ||
888 | local r, cond = match(expr, "^4%*cr([0-7])%+(%w%w)$") | ||
889 | if r then | ||
890 | r = tonumber(r) | ||
891 | local c = map_cond[cond] | ||
892 | if c and c < 4 then return r*4+c end | ||
893 | end | ||
894 | werror("bad condition bit name `"..expr.."'") | ||
895 | end | ||
896 | |||
897 | local function parse_imm(imm, bits, shift, scale, signed) | ||
898 | local n = tonumber(imm) | ||
899 | if n then | ||
900 | if n % 2^scale == 0 then | ||
901 | n = n / 2^scale | ||
902 | if signed then | ||
903 | if n >= 0 then | ||
904 | if n < 2^(bits-1) then return n*2^shift end | ||
905 | else | ||
906 | if n >= -(2^(bits-1))-1 then return (n+2^bits)*2^shift end | ||
907 | end | ||
908 | else | ||
909 | if n >= 0 and n <= 2^bits-1 then return n*2^shift end | ||
910 | end | ||
911 | end | ||
912 | werror("out of range immediate `"..imm.."'") | ||
913 | elseif match(imm, "^r([1-3]?[0-9])$") or | ||
914 | match(imm, "^([%w_]+):(r[1-3]?[0-9])$") then | ||
915 | werror("expected immediate operand, got register") | ||
916 | else | ||
917 | waction("IMM", (signed and 32768 or 0)+scale*1024+bits*32+shift, imm) | ||
918 | return 0 | ||
919 | end | ||
920 | end | ||
921 | |||
922 | local function parse_disp(disp) | ||
923 | local imm, reg = match(disp, "^(.*)%(([%w_:]+)%)$") | ||
924 | if imm then | ||
925 | local r = parse_gpr(reg) | ||
926 | if r == 0 then werror("cannot use r0 in displacement") end | ||
927 | return r*65536 + parse_imm(imm, 16, 0, 0, true) | ||
928 | end | ||
929 | local reg, tailr = match(disp, "^([%w_:]+)%s*(.*)$") | ||
930 | if reg and tailr ~= "" then | ||
931 | local r, tp = parse_gpr(reg) | ||
932 | if r == 0 then werror("cannot use r0 in displacement") end | ||
933 | if tp then | ||
934 | waction("IMM", 32768+16*32, format(tp.ctypefmt, tailr)) | ||
935 | return r*65536 | ||
936 | end | ||
937 | end | ||
938 | werror("bad displacement `"..disp.."'") | ||
939 | end | ||
940 | |||
941 | local function parse_u5disp(disp, scale) | ||
942 | local imm, reg = match(disp, "^(.*)%(([%w_:]+)%)$") | ||
943 | if imm then | ||
944 | local r = parse_gpr(reg) | ||
945 | if r == 0 then werror("cannot use r0 in displacement") end | ||
946 | return r*65536 + parse_imm(imm, 5, 11, scale, false) | ||
947 | end | ||
948 | local reg, tailr = match(disp, "^([%w_:]+)%s*(.*)$") | ||
949 | if reg and tailr ~= "" then | ||
950 | local r, tp = parse_gpr(reg) | ||
951 | if r == 0 then werror("cannot use r0 in displacement") end | ||
952 | if tp then | ||
953 | waction("IMM", scale*1024+5*32+11, format(tp.ctypefmt, tailr)) | ||
954 | return r*65536 | ||
955 | end | ||
956 | end | ||
957 | werror("bad displacement `"..disp.."'") | ||
958 | end | ||
959 | |||
960 | local function parse_label(label, def) | ||
961 | local prefix = sub(label, 1, 2) | ||
962 | -- =>label (pc label reference) | ||
963 | if prefix == "=>" then | ||
964 | return "PC", 0, sub(label, 3) | ||
965 | end | ||
966 | -- ->name (global label reference) | ||
967 | if prefix == "->" then | ||
968 | return "LG", map_global[sub(label, 3)] | ||
969 | end | ||
970 | if def then | ||
971 | -- [1-9] (local label definition) | ||
972 | if match(label, "^[1-9]$") then | ||
973 | return "LG", 10+tonumber(label) | ||
974 | end | ||
975 | else | ||
976 | -- [<>][1-9] (local label reference) | ||
977 | local dir, lnum = match(label, "^([<>])([1-9])$") | ||
978 | if dir then -- Fwd: 1-9, Bkwd: 11-19. | ||
979 | return "LG", lnum + (dir == ">" and 0 or 10) | ||
980 | end | ||
981 | -- extern label (extern label reference) | ||
982 | local extname = match(label, "^extern%s+(%S+)$") | ||
983 | if extname then | ||
984 | return "EXT", map_extern[extname] | ||
985 | end | ||
986 | end | ||
987 | werror("bad label `"..label.."'") | ||
988 | end | ||
989 | |||
990 | ------------------------------------------------------------------------------ | ||
991 | |||
992 | -- Handle opcodes defined with template strings. | ||
993 | map_op[".template__"] = function(params, template, nparams) | ||
994 | if not params then return sub(template, 9) end | ||
995 | local op = tonumber(sub(template, 1, 8), 16) | ||
996 | local n, rs = 1, 26 | ||
997 | |||
998 | -- Limit number of section buffer positions used by a single dasm_put(). | ||
999 | -- A single opcode needs a maximum of 3 positions (rlwinm). | ||
1000 | if secpos+3 > maxsecpos then wflush() end | ||
1001 | local pos = wpos() | ||
1002 | |||
1003 | -- Process each character. | ||
1004 | for p in gmatch(sub(template, 9), ".") do | ||
1005 | if p == "R" then | ||
1006 | rs = rs - 5; op = op + parse_gpr(params[n]) * 2^rs; n = n + 1 | ||
1007 | elseif p == "F" then | ||
1008 | rs = rs - 5; op = op + parse_fpr(params[n]) * 2^rs; n = n + 1 | ||
1009 | elseif p == "A" then | ||
1010 | rs = rs - 5; op = op + parse_imm(params[n], 5, rs, 0, false); n = n + 1 | ||
1011 | elseif p == "S" then | ||
1012 | rs = rs - 5; op = op + parse_imm(params[n], 5, rs, 0, true); n = n + 1 | ||
1013 | elseif p == "I" then | ||
1014 | op = op + parse_imm(params[n], 16, 0, 0, true); n = n + 1 | ||
1015 | elseif p == "U" then | ||
1016 | op = op + parse_imm(params[n], 16, 0, 0, false); n = n + 1 | ||
1017 | elseif p == "D" then | ||
1018 | op = op + parse_disp(params[n]); n = n + 1 | ||
1019 | elseif p == "2" then | ||
1020 | op = op + parse_u5disp(params[n], 1); n = n + 1 | ||
1021 | elseif p == "4" then | ||
1022 | op = op + parse_u5disp(params[n], 2); n = n + 1 | ||
1023 | elseif p == "8" then | ||
1024 | op = op + parse_u5disp(params[n], 3); n = n + 1 | ||
1025 | elseif p == "C" then | ||
1026 | rs = rs - 5; op = op + parse_cond(params[n]) * 2^rs; n = n + 1 | ||
1027 | elseif p == "X" then | ||
1028 | rs = rs - 5; op = op + parse_cr(params[n]) * 2^(rs+2); n = n + 1 | ||
1029 | elseif p == "W" then | ||
1030 | op = op + parse_cr(params[n]); n = n + 1 | ||
1031 | elseif p == "G" then | ||
1032 | op = op + parse_imm(params[n], 8, 12, 0, false); n = n + 1 | ||
1033 | elseif p == "J" or p == "K" then | ||
1034 | local mode, n, s = parse_label(params[n], false) | ||
1035 | if p == "K" then n = n + 2048 end | ||
1036 | waction("REL_"..mode, n, s, 1) | ||
1037 | n = n + 1 | ||
1038 | elseif p == "0" then | ||
1039 | local mm = 2^rs | ||
1040 | local t = op % mm | ||
1041 | if ((op - t) / mm) % 32 == 0 then werror("cannot use r0") end | ||
1042 | elseif p == "=" or p == "%" then | ||
1043 | local mm = 2^(rs + (p == "%" and 5 or 0)) | ||
1044 | local t = ((op - op % mm) / mm) % 32 | ||
1045 | rs = rs - 5 | ||
1046 | op = op + t * 2^rs | ||
1047 | elseif p == "~" then | ||
1048 | local mm = 2^rs | ||
1049 | local t1l = op % mm | ||
1050 | local t1h = (op - t1l) / mm | ||
1051 | local t2l = t1h % 32 | ||
1052 | local t2h = (t1h - t2l) / 32 | ||
1053 | local t3l = t2h % 32 | ||
1054 | op = ((t2h - t3l + t2l)*32 + t3l)*mm + t1l | ||
1055 | elseif p == "-" then | ||
1056 | rs = rs - 5 | ||
1057 | elseif p == "." then | ||
1058 | -- Ignored. | ||
1059 | else | ||
1060 | assert(false) | ||
1061 | end | ||
1062 | end | ||
1063 | wputpos(pos, op) | ||
1064 | end | ||
1065 | |||
1066 | ------------------------------------------------------------------------------ | ||
1067 | |||
1068 | -- Pseudo-opcode to mark the position where the action list is to be emitted. | ||
1069 | map_op[".actionlist_1"] = function(params) | ||
1070 | if not params then return "cvar" end | ||
1071 | local name = params[1] -- No syntax check. You get to keep the pieces. | ||
1072 | wline(function(out) writeactions(out, name) end) | ||
1073 | end | ||
1074 | |||
1075 | -- Pseudo-opcode to mark the position where the global enum is to be emitted. | ||
1076 | map_op[".globals_1"] = function(params) | ||
1077 | if not params then return "prefix" end | ||
1078 | local prefix = params[1] -- No syntax check. You get to keep the pieces. | ||
1079 | wline(function(out) writeglobals(out, prefix) end) | ||
1080 | end | ||
1081 | |||
1082 | -- Pseudo-opcode to mark the position where the global names are to be emitted. | ||
1083 | map_op[".globalnames_1"] = function(params) | ||
1084 | if not params then return "cvar" end | ||
1085 | local name = params[1] -- No syntax check. You get to keep the pieces. | ||
1086 | wline(function(out) writeglobalnames(out, name) end) | ||
1087 | end | ||
1088 | |||
1089 | -- Pseudo-opcode to mark the position where the extern names are to be emitted. | ||
1090 | map_op[".externnames_1"] = function(params) | ||
1091 | if not params then return "cvar" end | ||
1092 | local name = params[1] -- No syntax check. You get to keep the pieces. | ||
1093 | wline(function(out) writeexternnames(out, name) end) | ||
1094 | end | ||
1095 | |||
1096 | ------------------------------------------------------------------------------ | ||
1097 | |||
1098 | -- Label pseudo-opcode (converted from trailing colon form). | ||
1099 | map_op[".label_1"] = function(params) | ||
1100 | if not params then return "[1-9] | ->global | =>pcexpr" end | ||
1101 | if secpos+1 > maxsecpos then wflush() end | ||
1102 | local mode, n, s = parse_label(params[1], true) | ||
1103 | if mode == "EXT" then werror("bad label definition") end | ||
1104 | waction("LABEL_"..mode, n, s, 1) | ||
1105 | end | ||
1106 | |||
1107 | ------------------------------------------------------------------------------ | ||
1108 | |||
1109 | -- Pseudo-opcodes for data storage. | ||
1110 | map_op[".long_*"] = function(params) | ||
1111 | if not params then return "imm..." end | ||
1112 | for _,p in ipairs(params) do | ||
1113 | local n = tonumber(p) | ||
1114 | if not n then werror("bad immediate `"..p.."'") end | ||
1115 | if n < 0 then n = n + 2^32 end | ||
1116 | wputw(n) | ||
1117 | if secpos+2 > maxsecpos then wflush() end | ||
1118 | end | ||
1119 | end | ||
1120 | |||
1121 | -- Alignment pseudo-opcode. | ||
1122 | map_op[".align_1"] = function(params) | ||
1123 | if not params then return "numpow2" end | ||
1124 | if secpos+1 > maxsecpos then wflush() end | ||
1125 | local align = tonumber(params[1]) | ||
1126 | if align then | ||
1127 | local x = align | ||
1128 | -- Must be a power of 2 in the range (2 ... 256). | ||
1129 | for i=1,8 do | ||
1130 | x = x / 2 | ||
1131 | if x == 1 then | ||
1132 | waction("ALIGN", align-1, nil, 1) -- Action byte is 2**n-1. | ||
1133 | return | ||
1134 | end | ||
1135 | end | ||
1136 | end | ||
1137 | werror("bad alignment") | ||
1138 | end | ||
1139 | |||
1140 | ------------------------------------------------------------------------------ | ||
1141 | |||
1142 | -- Pseudo-opcode for (primitive) type definitions (map to C types). | ||
1143 | map_op[".type_3"] = function(params, nparams) | ||
1144 | if not params then | ||
1145 | return nparams == 2 and "name, ctype" or "name, ctype, reg" | ||
1146 | end | ||
1147 | local name, ctype, reg = params[1], params[2], params[3] | ||
1148 | if not match(name, "^[%a_][%w_]*$") then | ||
1149 | werror("bad type name `"..name.."'") | ||
1150 | end | ||
1151 | local tp = map_type[name] | ||
1152 | if tp then | ||
1153 | werror("duplicate type `"..name.."'") | ||
1154 | end | ||
1155 | -- Add #type to defines. A bit unclean to put it in map_archdef. | ||
1156 | map_archdef["#"..name] = "sizeof("..ctype..")" | ||
1157 | -- Add new type and emit shortcut define. | ||
1158 | local num = ctypenum + 1 | ||
1159 | map_type[name] = { | ||
1160 | ctype = ctype, | ||
1161 | ctypefmt = format("Dt%X(%%s)", num), | ||
1162 | reg = reg, | ||
1163 | } | ||
1164 | wline(format("#define Dt%X(_V) (int)(ptrdiff_t)&(((%s *)0)_V)", num, ctype)) | ||
1165 | ctypenum = num | ||
1166 | end | ||
1167 | map_op[".type_2"] = map_op[".type_3"] | ||
1168 | |||
1169 | -- Dump type definitions. | ||
1170 | local function dumptypes(out, lvl) | ||
1171 | local t = {} | ||
1172 | for name in pairs(map_type) do t[#t+1] = name end | ||
1173 | sort(t) | ||
1174 | out:write("Type definitions:\n") | ||
1175 | for _,name in ipairs(t) do | ||
1176 | local tp = map_type[name] | ||
1177 | local reg = tp.reg or "" | ||
1178 | out:write(format(" %-20s %-20s %s\n", name, tp.ctype, reg)) | ||
1179 | end | ||
1180 | out:write("\n") | ||
1181 | end | ||
1182 | |||
1183 | ------------------------------------------------------------------------------ | ||
1184 | |||
1185 | -- Set the current section. | ||
1186 | function _M.section(num) | ||
1187 | waction("SECTION", num) | ||
1188 | wflush(true) -- SECTION is a terminal action. | ||
1189 | end | ||
1190 | |||
1191 | ------------------------------------------------------------------------------ | ||
1192 | |||
1193 | -- Dump architecture description. | ||
1194 | function _M.dumparch(out) | ||
1195 | out:write(format("DynASM %s version %s, released %s\n\n", | ||
1196 | _info.arch, _info.version, _info.release)) | ||
1197 | dumpactions(out) | ||
1198 | end | ||
1199 | |||
1200 | -- Dump all user defined elements. | ||
1201 | function _M.dumpdef(out, lvl) | ||
1202 | dumptypes(out, lvl) | ||
1203 | dumpglobals(out, lvl) | ||
1204 | dumpexterns(out, lvl) | ||
1205 | end | ||
1206 | |||
1207 | ------------------------------------------------------------------------------ | ||
1208 | |||
1209 | -- Pass callbacks from/to the DynASM core. | ||
1210 | function _M.passcb(wl, we, wf, ww) | ||
1211 | wline, werror, wfatal, wwarn = wl, we, wf, ww | ||
1212 | return wflush | ||
1213 | end | ||
1214 | |||
1215 | -- Setup the arch-specific module. | ||
1216 | function _M.setup(arch, opt) | ||
1217 | g_arch, g_opt = arch, opt | ||
1218 | end | ||
1219 | |||
1220 | -- Merge the core maps and the arch-specific maps. | ||
1221 | function _M.mergemaps(map_coreop, map_def) | ||
1222 | setmetatable(map_op, { __index = map_coreop }) | ||
1223 | setmetatable(map_def, { __index = map_archdef }) | ||
1224 | return map_op, map_def | ||
1225 | end | ||
1226 | |||
1227 | return _M | ||
1228 | |||
1229 | ------------------------------------------------------------------------------ | ||
1230 | |||
diff --git a/libraries/luajit-2.0/dynasm/dasm_proto.h b/libraries/luajit-2.0/dynasm/dasm_proto.h new file mode 100644 index 0000000..3cc3af2 --- /dev/null +++ b/libraries/luajit-2.0/dynasm/dasm_proto.h | |||
@@ -0,0 +1,83 @@ | |||
1 | /* | ||
2 | ** DynASM encoding engine prototypes. | ||
3 | ** Copyright (C) 2005-2011 Mike Pall. All rights reserved. | ||
4 | ** Released under the MIT license. See dynasm.lua for full copyright notice. | ||
5 | */ | ||
6 | |||
7 | #ifndef _DASM_PROTO_H | ||
8 | #define _DASM_PROTO_H | ||
9 | |||
10 | #include <stddef.h> | ||
11 | #include <stdarg.h> | ||
12 | |||
13 | #define DASM_IDENT "DynASM 1.3.0" | ||
14 | #define DASM_VERSION 10300 /* 1.3.0 */ | ||
15 | |||
16 | #ifndef Dst_DECL | ||
17 | #define Dst_DECL dasm_State **Dst | ||
18 | #endif | ||
19 | |||
20 | #ifndef Dst_REF | ||
21 | #define Dst_REF (*Dst) | ||
22 | #endif | ||
23 | |||
24 | #ifndef DASM_FDEF | ||
25 | #define DASM_FDEF extern | ||
26 | #endif | ||
27 | |||
28 | #ifndef DASM_M_GROW | ||
29 | #define DASM_M_GROW(ctx, t, p, sz, need) \ | ||
30 | do { \ | ||
31 | size_t _sz = (sz), _need = (need); \ | ||
32 | if (_sz < _need) { \ | ||
33 | if (_sz < 16) _sz = 16; \ | ||
34 | while (_sz < _need) _sz += _sz; \ | ||
35 | (p) = (t *)realloc((p), _sz); \ | ||
36 | if ((p) == NULL) exit(1); \ | ||
37 | (sz) = _sz; \ | ||
38 | } \ | ||
39 | } while(0) | ||
40 | #endif | ||
41 | |||
42 | #ifndef DASM_M_FREE | ||
43 | #define DASM_M_FREE(ctx, p, sz) free(p) | ||
44 | #endif | ||
45 | |||
46 | /* Internal DynASM encoder state. */ | ||
47 | typedef struct dasm_State dasm_State; | ||
48 | |||
49 | |||
50 | /* Initialize and free DynASM state. */ | ||
51 | DASM_FDEF void dasm_init(Dst_DECL, int maxsection); | ||
52 | DASM_FDEF void dasm_free(Dst_DECL); | ||
53 | |||
54 | /* Setup global array. Must be called before dasm_setup(). */ | ||
55 | DASM_FDEF void dasm_setupglobal(Dst_DECL, void **gl, unsigned int maxgl); | ||
56 | |||
57 | /* Grow PC label array. Can be called after dasm_setup(), too. */ | ||
58 | DASM_FDEF void dasm_growpc(Dst_DECL, unsigned int maxpc); | ||
59 | |||
60 | /* Setup encoder. */ | ||
61 | DASM_FDEF void dasm_setup(Dst_DECL, const void *actionlist); | ||
62 | |||
63 | /* Feed encoder with actions. Calls are generated by pre-processor. */ | ||
64 | DASM_FDEF void dasm_put(Dst_DECL, int start, ...); | ||
65 | |||
66 | /* Link sections and return the resulting size. */ | ||
67 | DASM_FDEF int dasm_link(Dst_DECL, size_t *szp); | ||
68 | |||
69 | /* Encode sections into buffer. */ | ||
70 | DASM_FDEF int dasm_encode(Dst_DECL, void *buffer); | ||
71 | |||
72 | /* Get PC label offset. */ | ||
73 | DASM_FDEF int dasm_getpclabel(Dst_DECL, unsigned int pc); | ||
74 | |||
75 | #ifdef DASM_CHECKS | ||
76 | /* Optional sanity checker to call between isolated encoding steps. */ | ||
77 | DASM_FDEF int dasm_checkstep(Dst_DECL, int secmatch); | ||
78 | #else | ||
79 | #define dasm_checkstep(a, b) 0 | ||
80 | #endif | ||
81 | |||
82 | |||
83 | #endif /* _DASM_PROTO_H */ | ||
diff --git a/libraries/luajit-2.0/dynasm/dasm_x64.lua b/libraries/luajit-2.0/dynasm/dasm_x64.lua new file mode 100644 index 0000000..73e01e9 --- /dev/null +++ b/libraries/luajit-2.0/dynasm/dasm_x64.lua | |||
@@ -0,0 +1,12 @@ | |||
1 | ------------------------------------------------------------------------------ | ||
2 | -- DynASM x64 module. | ||
3 | -- | ||
4 | -- Copyright (C) 2005-2011 Mike Pall. All rights reserved. | ||
5 | -- See dynasm.lua for full copyright notice. | ||
6 | ------------------------------------------------------------------------------ | ||
7 | -- This module just sets 64 bit mode for the combined x86/x64 module. | ||
8 | -- All the interesting stuff is there. | ||
9 | ------------------------------------------------------------------------------ | ||
10 | |||
11 | x64 = true -- Using a global is an ugly, but effective solution. | ||
12 | return require("dasm_x86") | ||
diff --git a/libraries/luajit-2.0/dynasm/dasm_x86.h b/libraries/luajit-2.0/dynasm/dasm_x86.h new file mode 100644 index 0000000..8f2dd1c --- /dev/null +++ b/libraries/luajit-2.0/dynasm/dasm_x86.h | |||
@@ -0,0 +1,470 @@ | |||
1 | /* | ||
2 | ** DynASM x86 encoding engine. | ||
3 | ** Copyright (C) 2005-2011 Mike Pall. All rights reserved. | ||
4 | ** Released under the MIT license. See dynasm.lua for full copyright notice. | ||
5 | */ | ||
6 | |||
7 | #include <stddef.h> | ||
8 | #include <stdarg.h> | ||
9 | #include <string.h> | ||
10 | #include <stdlib.h> | ||
11 | |||
12 | #define DASM_ARCH "x86" | ||
13 | |||
14 | #ifndef DASM_EXTERN | ||
15 | #define DASM_EXTERN(a,b,c,d) 0 | ||
16 | #endif | ||
17 | |||
18 | /* Action definitions. DASM_STOP must be 255. */ | ||
19 | enum { | ||
20 | DASM_DISP = 233, | ||
21 | DASM_IMM_S, DASM_IMM_B, DASM_IMM_W, DASM_IMM_D, DASM_IMM_WB, DASM_IMM_DB, | ||
22 | DASM_VREG, DASM_SPACE, DASM_SETLABEL, DASM_REL_A, DASM_REL_LG, DASM_REL_PC, | ||
23 | DASM_IMM_LG, DASM_IMM_PC, DASM_LABEL_LG, DASM_LABEL_PC, DASM_ALIGN, | ||
24 | DASM_EXTERN, DASM_ESC, DASM_MARK, DASM_SECTION, DASM_STOP | ||
25 | }; | ||
26 | |||
27 | /* Maximum number of section buffer positions for a single dasm_put() call. */ | ||
28 | #define DASM_MAXSECPOS 25 | ||
29 | |||
30 | /* DynASM encoder status codes. Action list offset or number are or'ed in. */ | ||
31 | #define DASM_S_OK 0x00000000 | ||
32 | #define DASM_S_NOMEM 0x01000000 | ||
33 | #define DASM_S_PHASE 0x02000000 | ||
34 | #define DASM_S_MATCH_SEC 0x03000000 | ||
35 | #define DASM_S_RANGE_I 0x11000000 | ||
36 | #define DASM_S_RANGE_SEC 0x12000000 | ||
37 | #define DASM_S_RANGE_LG 0x13000000 | ||
38 | #define DASM_S_RANGE_PC 0x14000000 | ||
39 | #define DASM_S_RANGE_VREG 0x15000000 | ||
40 | #define DASM_S_UNDEF_L 0x21000000 | ||
41 | #define DASM_S_UNDEF_PC 0x22000000 | ||
42 | |||
43 | /* Macros to convert positions (8 bit section + 24 bit index). */ | ||
44 | #define DASM_POS2IDX(pos) ((pos)&0x00ffffff) | ||
45 | #define DASM_POS2BIAS(pos) ((pos)&0xff000000) | ||
46 | #define DASM_SEC2POS(sec) ((sec)<<24) | ||
47 | #define DASM_POS2SEC(pos) ((pos)>>24) | ||
48 | #define DASM_POS2PTR(D, pos) (D->sections[DASM_POS2SEC(pos)].rbuf + (pos)) | ||
49 | |||
50 | /* Action list type. */ | ||
51 | typedef const unsigned char *dasm_ActList; | ||
52 | |||
53 | /* Per-section structure. */ | ||
54 | typedef struct dasm_Section { | ||
55 | int *rbuf; /* Biased buffer pointer (negative section bias). */ | ||
56 | int *buf; /* True buffer pointer. */ | ||
57 | size_t bsize; /* Buffer size in bytes. */ | ||
58 | int pos; /* Biased buffer position. */ | ||
59 | int epos; /* End of biased buffer position - max single put. */ | ||
60 | int ofs; /* Byte offset into section. */ | ||
61 | } dasm_Section; | ||
62 | |||
63 | /* Core structure holding the DynASM encoding state. */ | ||
64 | struct dasm_State { | ||
65 | size_t psize; /* Allocated size of this structure. */ | ||
66 | dasm_ActList actionlist; /* Current actionlist pointer. */ | ||
67 | int *lglabels; /* Local/global chain/pos ptrs. */ | ||
68 | size_t lgsize; | ||
69 | int *pclabels; /* PC label chains/pos ptrs. */ | ||
70 | size_t pcsize; | ||
71 | void **globals; /* Array of globals (bias -10). */ | ||
72 | dasm_Section *section; /* Pointer to active section. */ | ||
73 | size_t codesize; /* Total size of all code sections. */ | ||
74 | int maxsection; /* 0 <= sectionidx < maxsection. */ | ||
75 | int status; /* Status code. */ | ||
76 | dasm_Section sections[1]; /* All sections. Alloc-extended. */ | ||
77 | }; | ||
78 | |||
79 | /* The size of the core structure depends on the max. number of sections. */ | ||
80 | #define DASM_PSZ(ms) (sizeof(dasm_State)+(ms-1)*sizeof(dasm_Section)) | ||
81 | |||
82 | |||
83 | /* Initialize DynASM state. */ | ||
84 | void dasm_init(Dst_DECL, int maxsection) | ||
85 | { | ||
86 | dasm_State *D; | ||
87 | size_t psz = 0; | ||
88 | int i; | ||
89 | Dst_REF = NULL; | ||
90 | DASM_M_GROW(Dst, struct dasm_State, Dst_REF, psz, DASM_PSZ(maxsection)); | ||
91 | D = Dst_REF; | ||
92 | D->psize = psz; | ||
93 | D->lglabels = NULL; | ||
94 | D->lgsize = 0; | ||
95 | D->pclabels = NULL; | ||
96 | D->pcsize = 0; | ||
97 | D->globals = NULL; | ||
98 | D->maxsection = maxsection; | ||
99 | for (i = 0; i < maxsection; i++) { | ||
100 | D->sections[i].buf = NULL; /* Need this for pass3. */ | ||
101 | D->sections[i].rbuf = D->sections[i].buf - DASM_SEC2POS(i); | ||
102 | D->sections[i].bsize = 0; | ||
103 | D->sections[i].epos = 0; /* Wrong, but is recalculated after resize. */ | ||
104 | } | ||
105 | } | ||
106 | |||
107 | /* Free DynASM state. */ | ||
108 | void dasm_free(Dst_DECL) | ||
109 | { | ||
110 | dasm_State *D = Dst_REF; | ||
111 | int i; | ||
112 | for (i = 0; i < D->maxsection; i++) | ||
113 | if (D->sections[i].buf) | ||
114 | DASM_M_FREE(Dst, D->sections[i].buf, D->sections[i].bsize); | ||
115 | if (D->pclabels) DASM_M_FREE(Dst, D->pclabels, D->pcsize); | ||
116 | if (D->lglabels) DASM_M_FREE(Dst, D->lglabels, D->lgsize); | ||
117 | DASM_M_FREE(Dst, D, D->psize); | ||
118 | } | ||
119 | |||
120 | /* Setup global label array. Must be called before dasm_setup(). */ | ||
121 | void dasm_setupglobal(Dst_DECL, void **gl, unsigned int maxgl) | ||
122 | { | ||
123 | dasm_State *D = Dst_REF; | ||
124 | D->globals = gl - 10; /* Negative bias to compensate for locals. */ | ||
125 | DASM_M_GROW(Dst, int, D->lglabels, D->lgsize, (10+maxgl)*sizeof(int)); | ||
126 | } | ||
127 | |||
128 | /* Grow PC label array. Can be called after dasm_setup(), too. */ | ||
129 | void dasm_growpc(Dst_DECL, unsigned int maxpc) | ||
130 | { | ||
131 | dasm_State *D = Dst_REF; | ||
132 | size_t osz = D->pcsize; | ||
133 | DASM_M_GROW(Dst, int, D->pclabels, D->pcsize, maxpc*sizeof(int)); | ||
134 | memset((void *)(((unsigned char *)D->pclabels)+osz), 0, D->pcsize-osz); | ||
135 | } | ||
136 | |||
137 | /* Setup encoder. */ | ||
138 | void dasm_setup(Dst_DECL, const void *actionlist) | ||
139 | { | ||
140 | dasm_State *D = Dst_REF; | ||
141 | int i; | ||
142 | D->actionlist = (dasm_ActList)actionlist; | ||
143 | D->status = DASM_S_OK; | ||
144 | D->section = &D->sections[0]; | ||
145 | memset((void *)D->lglabels, 0, D->lgsize); | ||
146 | if (D->pclabels) memset((void *)D->pclabels, 0, D->pcsize); | ||
147 | for (i = 0; i < D->maxsection; i++) { | ||
148 | D->sections[i].pos = DASM_SEC2POS(i); | ||
149 | D->sections[i].ofs = 0; | ||
150 | } | ||
151 | } | ||
152 | |||
153 | |||
154 | #ifdef DASM_CHECKS | ||
155 | #define CK(x, st) \ | ||
156 | do { if (!(x)) { \ | ||
157 | D->status = DASM_S_##st|(int)(p-D->actionlist-1); return; } } while (0) | ||
158 | #define CKPL(kind, st) \ | ||
159 | do { if ((size_t)((char *)pl-(char *)D->kind##labels) >= D->kind##size) { \ | ||
160 | D->status=DASM_S_RANGE_##st|(int)(p-D->actionlist-1); return; } } while (0) | ||
161 | #else | ||
162 | #define CK(x, st) ((void)0) | ||
163 | #define CKPL(kind, st) ((void)0) | ||
164 | #endif | ||
165 | |||
166 | /* Pass 1: Store actions and args, link branches/labels, estimate offsets. */ | ||
167 | void dasm_put(Dst_DECL, int start, ...) | ||
168 | { | ||
169 | va_list ap; | ||
170 | dasm_State *D = Dst_REF; | ||
171 | dasm_ActList p = D->actionlist + start; | ||
172 | dasm_Section *sec = D->section; | ||
173 | int pos = sec->pos, ofs = sec->ofs, mrm = 4; | ||
174 | int *b; | ||
175 | |||
176 | if (pos >= sec->epos) { | ||
177 | DASM_M_GROW(Dst, int, sec->buf, sec->bsize, | ||
178 | sec->bsize + 2*DASM_MAXSECPOS*sizeof(int)); | ||
179 | sec->rbuf = sec->buf - DASM_POS2BIAS(pos); | ||
180 | sec->epos = (int)sec->bsize/sizeof(int) - DASM_MAXSECPOS+DASM_POS2BIAS(pos); | ||
181 | } | ||
182 | |||
183 | b = sec->rbuf; | ||
184 | b[pos++] = start; | ||
185 | |||
186 | va_start(ap, start); | ||
187 | while (1) { | ||
188 | int action = *p++; | ||
189 | if (action < DASM_DISP) { | ||
190 | ofs++; | ||
191 | } else if (action <= DASM_REL_A) { | ||
192 | int n = va_arg(ap, int); | ||
193 | b[pos++] = n; | ||
194 | switch (action) { | ||
195 | case DASM_DISP: | ||
196 | if (n == 0) { if ((mrm&7) == 4) mrm = p[-2]; if ((mrm&7) != 5) break; } | ||
197 | case DASM_IMM_DB: if (((n+128)&-256) == 0) goto ob; | ||
198 | case DASM_REL_A: /* Assumes ptrdiff_t is int. !x64 */ | ||
199 | case DASM_IMM_D: ofs += 4; break; | ||
200 | case DASM_IMM_S: CK(((n+128)&-256) == 0, RANGE_I); goto ob; | ||
201 | case DASM_IMM_B: CK((n&-256) == 0, RANGE_I); ob: ofs++; break; | ||
202 | case DASM_IMM_WB: if (((n+128)&-256) == 0) goto ob; | ||
203 | case DASM_IMM_W: CK((n&-65536) == 0, RANGE_I); ofs += 2; break; | ||
204 | case DASM_SPACE: p++; ofs += n; break; | ||
205 | case DASM_SETLABEL: b[pos-2] = -0x40000000; break; /* Neg. label ofs. */ | ||
206 | case DASM_VREG: CK((n&-8) == 0 && (n != 4 || (*p&1) == 0), RANGE_VREG); | ||
207 | if (*p++ == 1 && *p == DASM_DISP) mrm = n; continue; | ||
208 | } | ||
209 | mrm = 4; | ||
210 | } else { | ||
211 | int *pl, n; | ||
212 | switch (action) { | ||
213 | case DASM_REL_LG: | ||
214 | case DASM_IMM_LG: | ||
215 | n = *p++; pl = D->lglabels + n; | ||
216 | if (n <= 246) { CKPL(lg, LG); goto putrel; } /* Bkwd rel or global. */ | ||
217 | pl -= 246; n = *pl; | ||
218 | if (n < 0) n = 0; /* Start new chain for fwd rel if label exists. */ | ||
219 | goto linkrel; | ||
220 | case DASM_REL_PC: | ||
221 | case DASM_IMM_PC: pl = D->pclabels + va_arg(ap, int); CKPL(pc, PC); | ||
222 | putrel: | ||
223 | n = *pl; | ||
224 | if (n < 0) { /* Label exists. Get label pos and store it. */ | ||
225 | b[pos] = -n; | ||
226 | } else { | ||
227 | linkrel: | ||
228 | b[pos] = n; /* Else link to rel chain, anchored at label. */ | ||
229 | *pl = pos; | ||
230 | } | ||
231 | pos++; | ||
232 | ofs += 4; /* Maximum offset needed. */ | ||
233 | if (action == DASM_REL_LG || action == DASM_REL_PC) | ||
234 | b[pos++] = ofs; /* Store pass1 offset estimate. */ | ||
235 | break; | ||
236 | case DASM_LABEL_LG: pl = D->lglabels + *p++; CKPL(lg, LG); goto putlabel; | ||
237 | case DASM_LABEL_PC: pl = D->pclabels + va_arg(ap, int); CKPL(pc, PC); | ||
238 | putlabel: | ||
239 | n = *pl; /* n > 0: Collapse rel chain and replace with label pos. */ | ||
240 | while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = pos; } | ||
241 | *pl = -pos; /* Label exists now. */ | ||
242 | b[pos++] = ofs; /* Store pass1 offset estimate. */ | ||
243 | break; | ||
244 | case DASM_ALIGN: | ||
245 | ofs += *p++; /* Maximum alignment needed (arg is 2**n-1). */ | ||
246 | b[pos++] = ofs; /* Store pass1 offset estimate. */ | ||
247 | break; | ||
248 | case DASM_EXTERN: p += 2; ofs += 4; break; | ||
249 | case DASM_ESC: p++; ofs++; break; | ||
250 | case DASM_MARK: mrm = p[-2]; break; | ||
251 | case DASM_SECTION: | ||
252 | n = *p; CK(n < D->maxsection, RANGE_SEC); D->section = &D->sections[n]; | ||
253 | case DASM_STOP: goto stop; | ||
254 | } | ||
255 | } | ||
256 | } | ||
257 | stop: | ||
258 | va_end(ap); | ||
259 | sec->pos = pos; | ||
260 | sec->ofs = ofs; | ||
261 | } | ||
262 | #undef CK | ||
263 | |||
264 | /* Pass 2: Link sections, shrink branches/aligns, fix label offsets. */ | ||
265 | int dasm_link(Dst_DECL, size_t *szp) | ||
266 | { | ||
267 | dasm_State *D = Dst_REF; | ||
268 | int secnum; | ||
269 | int ofs = 0; | ||
270 | |||
271 | #ifdef DASM_CHECKS | ||
272 | *szp = 0; | ||
273 | if (D->status != DASM_S_OK) return D->status; | ||
274 | { | ||
275 | int pc; | ||
276 | for (pc = 0; pc*sizeof(int) < D->pcsize; pc++) | ||
277 | if (D->pclabels[pc] > 0) return DASM_S_UNDEF_PC|pc; | ||
278 | } | ||
279 | #endif | ||
280 | |||
281 | { /* Handle globals not defined in this translation unit. */ | ||
282 | int idx; | ||
283 | for (idx = 10; idx*sizeof(int) < D->lgsize; idx++) { | ||
284 | int n = D->lglabels[idx]; | ||
285 | /* Undefined label: Collapse rel chain and replace with marker (< 0). */ | ||
286 | while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = -idx; } | ||
287 | } | ||
288 | } | ||
289 | |||
290 | /* Combine all code sections. No support for data sections (yet). */ | ||
291 | for (secnum = 0; secnum < D->maxsection; secnum++) { | ||
292 | dasm_Section *sec = D->sections + secnum; | ||
293 | int *b = sec->rbuf; | ||
294 | int pos = DASM_SEC2POS(secnum); | ||
295 | int lastpos = sec->pos; | ||
296 | |||
297 | while (pos != lastpos) { | ||
298 | dasm_ActList p = D->actionlist + b[pos++]; | ||
299 | while (1) { | ||
300 | int op, action = *p++; | ||
301 | switch (action) { | ||
302 | case DASM_REL_LG: p++; op = p[-3]; goto rel_pc; | ||
303 | case DASM_REL_PC: op = p[-2]; rel_pc: { | ||
304 | int shrink = op == 0xe9 ? 3 : ((op&0xf0) == 0x80 ? 4 : 0); | ||
305 | if (shrink) { /* Shrinkable branch opcode? */ | ||
306 | int lofs, lpos = b[pos]; | ||
307 | if (lpos < 0) goto noshrink; /* Ext global? */ | ||
308 | lofs = *DASM_POS2PTR(D, lpos); | ||
309 | if (lpos > pos) { /* Fwd label: add cumulative section offsets. */ | ||
310 | int i; | ||
311 | for (i = secnum; i < DASM_POS2SEC(lpos); i++) | ||
312 | lofs += D->sections[i].ofs; | ||
313 | } else { | ||
314 | lofs -= ofs; /* Bkwd label: unfix offset. */ | ||
315 | } | ||
316 | lofs -= b[pos+1]; /* Short branch ok? */ | ||
317 | if (lofs >= -128-shrink && lofs <= 127) ofs -= shrink; /* Yes. */ | ||
318 | else { noshrink: shrink = 0; } /* No, cannot shrink op. */ | ||
319 | } | ||
320 | b[pos+1] = shrink; | ||
321 | pos += 2; | ||
322 | break; | ||
323 | } | ||
324 | case DASM_SPACE: case DASM_IMM_LG: case DASM_VREG: p++; | ||
325 | case DASM_DISP: case DASM_IMM_S: case DASM_IMM_B: case DASM_IMM_W: | ||
326 | case DASM_IMM_D: case DASM_IMM_WB: case DASM_IMM_DB: | ||
327 | case DASM_SETLABEL: case DASM_REL_A: case DASM_IMM_PC: pos++; break; | ||
328 | case DASM_LABEL_LG: p++; | ||
329 | case DASM_LABEL_PC: b[pos++] += ofs; break; /* Fix label offset. */ | ||
330 | case DASM_ALIGN: ofs -= (b[pos++]+ofs)&*p++; break; /* Adjust ofs. */ | ||
331 | case DASM_EXTERN: p += 2; break; | ||
332 | case DASM_ESC: p++; break; | ||
333 | case DASM_MARK: break; | ||
334 | case DASM_SECTION: case DASM_STOP: goto stop; | ||
335 | } | ||
336 | } | ||
337 | stop: (void)0; | ||
338 | } | ||
339 | ofs += sec->ofs; /* Next section starts right after current section. */ | ||
340 | } | ||
341 | |||
342 | D->codesize = ofs; /* Total size of all code sections */ | ||
343 | *szp = ofs; | ||
344 | return DASM_S_OK; | ||
345 | } | ||
346 | |||
347 | #define dasmb(x) *cp++ = (unsigned char)(x) | ||
348 | #ifndef DASM_ALIGNED_WRITES | ||
349 | #define dasmw(x) \ | ||
350 | do { *((unsigned short *)cp) = (unsigned short)(x); cp+=2; } while (0) | ||
351 | #define dasmd(x) \ | ||
352 | do { *((unsigned int *)cp) = (unsigned int)(x); cp+=4; } while (0) | ||
353 | #else | ||
354 | #define dasmw(x) do { dasmb(x); dasmb((x)>>8); } while (0) | ||
355 | #define dasmd(x) do { dasmw(x); dasmw((x)>>16); } while (0) | ||
356 | #endif | ||
357 | |||
358 | /* Pass 3: Encode sections. */ | ||
359 | int dasm_encode(Dst_DECL, void *buffer) | ||
360 | { | ||
361 | dasm_State *D = Dst_REF; | ||
362 | unsigned char *base = (unsigned char *)buffer; | ||
363 | unsigned char *cp = base; | ||
364 | int secnum; | ||
365 | |||
366 | /* Encode all code sections. No support for data sections (yet). */ | ||
367 | for (secnum = 0; secnum < D->maxsection; secnum++) { | ||
368 | dasm_Section *sec = D->sections + secnum; | ||
369 | int *b = sec->buf; | ||
370 | int *endb = sec->rbuf + sec->pos; | ||
371 | |||
372 | while (b != endb) { | ||
373 | dasm_ActList p = D->actionlist + *b++; | ||
374 | unsigned char *mark = NULL; | ||
375 | while (1) { | ||
376 | int action = *p++; | ||
377 | int n = (action >= DASM_DISP && action <= DASM_ALIGN) ? *b++ : 0; | ||
378 | switch (action) { | ||
379 | case DASM_DISP: if (!mark) mark = cp; { | ||
380 | unsigned char *mm = mark; | ||
381 | if (*p != DASM_IMM_DB && *p != DASM_IMM_WB) mark = NULL; | ||
382 | if (n == 0) { int mrm = mm[-1]&7; if (mrm == 4) mrm = mm[0]&7; | ||
383 | if (mrm != 5) { mm[-1] -= 0x80; break; } } | ||
384 | if (((n+128) & -256) != 0) goto wd; else mm[-1] -= 0x40; | ||
385 | } | ||
386 | case DASM_IMM_S: case DASM_IMM_B: wb: dasmb(n); break; | ||
387 | case DASM_IMM_DB: if (((n+128)&-256) == 0) { | ||
388 | db: if (!mark) mark = cp; mark[-2] += 2; mark = NULL; goto wb; | ||
389 | } else mark = NULL; | ||
390 | case DASM_IMM_D: wd: dasmd(n); break; | ||
391 | case DASM_IMM_WB: if (((n+128)&-256) == 0) goto db; else mark = NULL; | ||
392 | case DASM_IMM_W: dasmw(n); break; | ||
393 | case DASM_VREG: { int t = *p++; if (t >= 2) n<<=3; cp[-1] |= n; break; } | ||
394 | case DASM_REL_LG: p++; if (n >= 0) goto rel_pc; | ||
395 | b++; n = (int)(ptrdiff_t)D->globals[-n]; | ||
396 | case DASM_REL_A: rel_a: n -= (int)(ptrdiff_t)(cp+4); goto wd; /* !x64 */ | ||
397 | case DASM_REL_PC: rel_pc: { | ||
398 | int shrink = *b++; | ||
399 | int *pb = DASM_POS2PTR(D, n); if (*pb < 0) { n = pb[1]; goto rel_a; } | ||
400 | n = *pb - ((int)(cp-base) + 4-shrink); | ||
401 | if (shrink == 0) goto wd; | ||
402 | if (shrink == 4) { cp--; cp[-1] = *cp-0x10; } else cp[-1] = 0xeb; | ||
403 | goto wb; | ||
404 | } | ||
405 | case DASM_IMM_LG: | ||
406 | p++; if (n < 0) { n = (int)(ptrdiff_t)D->globals[-n]; goto wd; } | ||
407 | case DASM_IMM_PC: { | ||
408 | int *pb = DASM_POS2PTR(D, n); | ||
409 | n = *pb < 0 ? pb[1] : (*pb + (int)(ptrdiff_t)base); | ||
410 | goto wd; | ||
411 | } | ||
412 | case DASM_LABEL_LG: { | ||
413 | int idx = *p++; | ||
414 | if (idx >= 10) | ||
415 | D->globals[idx] = (void *)(base + (*p == DASM_SETLABEL ? *b : n)); | ||
416 | break; | ||
417 | } | ||
418 | case DASM_LABEL_PC: case DASM_SETLABEL: break; | ||
419 | case DASM_SPACE: { int fill = *p++; while (n--) *cp++ = fill; break; } | ||
420 | case DASM_ALIGN: | ||
421 | n = *p++; | ||
422 | while (((cp-base) & n)) *cp++ = 0x90; /* nop */ | ||
423 | break; | ||
424 | case DASM_EXTERN: n = DASM_EXTERN(Dst, cp, p[1], *p); p += 2; goto wd; | ||
425 | case DASM_MARK: mark = cp; break; | ||
426 | case DASM_ESC: action = *p++; | ||
427 | default: *cp++ = action; break; | ||
428 | case DASM_SECTION: case DASM_STOP: goto stop; | ||
429 | } | ||
430 | } | ||
431 | stop: (void)0; | ||
432 | } | ||
433 | } | ||
434 | |||
435 | if (base + D->codesize != cp) /* Check for phase errors. */ | ||
436 | return DASM_S_PHASE; | ||
437 | return DASM_S_OK; | ||
438 | } | ||
439 | |||
440 | /* Get PC label offset. */ | ||
441 | int dasm_getpclabel(Dst_DECL, unsigned int pc) | ||
442 | { | ||
443 | dasm_State *D = Dst_REF; | ||
444 | if (pc*sizeof(int) < D->pcsize) { | ||
445 | int pos = D->pclabels[pc]; | ||
446 | if (pos < 0) return *DASM_POS2PTR(D, -pos); | ||
447 | if (pos > 0) return -1; /* Undefined. */ | ||
448 | } | ||
449 | return -2; /* Unused or out of range. */ | ||
450 | } | ||
451 | |||
452 | #ifdef DASM_CHECKS | ||
453 | /* Optional sanity checker to call between isolated encoding steps. */ | ||
454 | int dasm_checkstep(Dst_DECL, int secmatch) | ||
455 | { | ||
456 | dasm_State *D = Dst_REF; | ||
457 | if (D->status == DASM_S_OK) { | ||
458 | int i; | ||
459 | for (i = 1; i <= 9; i++) { | ||
460 | if (D->lglabels[i] > 0) { D->status = DASM_S_UNDEF_L|i; break; } | ||
461 | D->lglabels[i] = 0; | ||
462 | } | ||
463 | } | ||
464 | if (D->status == DASM_S_OK && secmatch >= 0 && | ||
465 | D->section != &D->sections[secmatch]) | ||
466 | D->status = DASM_S_MATCH_SEC|(int)(D->section-D->sections); | ||
467 | return D->status; | ||
468 | } | ||
469 | #endif | ||
470 | |||
diff --git a/libraries/luajit-2.0/dynasm/dasm_x86.lua b/libraries/luajit-2.0/dynasm/dasm_x86.lua new file mode 100644 index 0000000..5571f93 --- /dev/null +++ b/libraries/luajit-2.0/dynasm/dasm_x86.lua | |||
@@ -0,0 +1,1931 @@ | |||
1 | ------------------------------------------------------------------------------ | ||
2 | -- DynASM x86/x64 module. | ||
3 | -- | ||
4 | -- Copyright (C) 2005-2011 Mike Pall. All rights reserved. | ||
5 | -- See dynasm.lua for full copyright notice. | ||
6 | ------------------------------------------------------------------------------ | ||
7 | |||
8 | local x64 = x64 | ||
9 | |||
10 | -- Module information: | ||
11 | local _info = { | ||
12 | arch = x64 and "x64" or "x86", | ||
13 | description = "DynASM x86/x64 module", | ||
14 | version = "1.3.0", | ||
15 | vernum = 10300, | ||
16 | release = "2011-05-05", | ||
17 | author = "Mike Pall", | ||
18 | license = "MIT", | ||
19 | } | ||
20 | |||
21 | -- Exported glue functions for the arch-specific module. | ||
22 | local _M = { _info = _info } | ||
23 | |||
24 | -- Cache library functions. | ||
25 | local type, tonumber, pairs, ipairs = type, tonumber, pairs, ipairs | ||
26 | local assert, unpack, setmetatable = assert, unpack, setmetatable | ||
27 | local _s = string | ||
28 | local sub, format, byte, char = _s.sub, _s.format, _s.byte, _s.char | ||
29 | local find, match, gmatch, gsub = _s.find, _s.match, _s.gmatch, _s.gsub | ||
30 | local concat, sort = table.concat, table.sort | ||
31 | |||
32 | -- Inherited tables and callbacks. | ||
33 | local g_opt, g_arch | ||
34 | local wline, werror, wfatal, wwarn | ||
35 | |||
36 | -- Action name list. | ||
37 | -- CHECK: Keep this in sync with the C code! | ||
38 | local action_names = { | ||
39 | -- int arg, 1 buffer pos: | ||
40 | "DISP", "IMM_S", "IMM_B", "IMM_W", "IMM_D", "IMM_WB", "IMM_DB", | ||
41 | -- action arg (1 byte), int arg, 1 buffer pos (reg/num): | ||
42 | "VREG", "SPACE", -- !x64: VREG support NYI. | ||
43 | -- ptrdiff_t arg, 1 buffer pos (address): !x64 | ||
44 | "SETLABEL", "REL_A", | ||
45 | -- action arg (1 byte) or int arg, 2 buffer pos (link, offset): | ||
46 | "REL_LG", "REL_PC", | ||
47 | -- action arg (1 byte) or int arg, 1 buffer pos (link): | ||
48 | "IMM_LG", "IMM_PC", | ||
49 | -- action arg (1 byte) or int arg, 1 buffer pos (offset): | ||
50 | "LABEL_LG", "LABEL_PC", | ||
51 | -- action arg (1 byte), 1 buffer pos (offset): | ||
52 | "ALIGN", | ||
53 | -- action args (2 bytes), no buffer pos. | ||
54 | "EXTERN", | ||
55 | -- action arg (1 byte), no buffer pos. | ||
56 | "ESC", | ||
57 | -- no action arg, no buffer pos. | ||
58 | "MARK", | ||
59 | -- action arg (1 byte), no buffer pos, terminal action: | ||
60 | "SECTION", | ||
61 | -- no args, no buffer pos, terminal action: | ||
62 | "STOP" | ||
63 | } | ||
64 | |||
65 | -- Maximum number of section buffer positions for dasm_put(). | ||
66 | -- CHECK: Keep this in sync with the C code! | ||
67 | local maxsecpos = 25 -- Keep this low, to avoid excessively long C lines. | ||
68 | |||
69 | -- Action name -> action number (dynamically generated below). | ||
70 | local map_action = {} | ||
71 | -- First action number. Everything below does not need to be escaped. | ||
72 | local actfirst = 256-#action_names | ||
73 | |||
74 | -- Action list buffer and string (only used to remove dupes). | ||
75 | local actlist = {} | ||
76 | local actstr = "" | ||
77 | |||
78 | -- Argument list for next dasm_put(). Start with offset 0 into action list. | ||
79 | local actargs = { 0 } | ||
80 | |||
81 | -- Current number of section buffer positions for dasm_put(). | ||
82 | local secpos = 1 | ||
83 | |||
84 | ------------------------------------------------------------------------------ | ||
85 | |||
86 | -- Compute action numbers for action names. | ||
87 | for n,name in ipairs(action_names) do | ||
88 | local num = actfirst + n - 1 | ||
89 | map_action[name] = num | ||
90 | end | ||
91 | |||
92 | -- Dump action names and numbers. | ||
93 | local function dumpactions(out) | ||
94 | out:write("DynASM encoding engine action codes:\n") | ||
95 | for n,name in ipairs(action_names) do | ||
96 | local num = map_action[name] | ||
97 | out:write(format(" %-10s %02X %d\n", name, num, num)) | ||
98 | end | ||
99 | out:write("\n") | ||
100 | end | ||
101 | |||
102 | -- Write action list buffer as a huge static C array. | ||
103 | local function writeactions(out, name) | ||
104 | local nn = #actlist | ||
105 | local last = actlist[nn] or 255 | ||
106 | actlist[nn] = nil -- Remove last byte. | ||
107 | if nn == 0 then nn = 1 end | ||
108 | out:write("static const unsigned char ", name, "[", nn, "] = {\n") | ||
109 | local s = " " | ||
110 | for n,b in ipairs(actlist) do | ||
111 | s = s..b.."," | ||
112 | if #s >= 75 then | ||
113 | assert(out:write(s, "\n")) | ||
114 | s = " " | ||
115 | end | ||
116 | end | ||
117 | out:write(s, last, "\n};\n\n") -- Add last byte back. | ||
118 | end | ||
119 | |||
120 | ------------------------------------------------------------------------------ | ||
121 | |||
122 | -- Add byte to action list. | ||
123 | local function wputxb(n) | ||
124 | assert(n >= 0 and n <= 255 and n % 1 == 0, "byte out of range") | ||
125 | actlist[#actlist+1] = n | ||
126 | end | ||
127 | |||
128 | -- Add action to list with optional arg. Advance buffer pos, too. | ||
129 | local function waction(action, a, num) | ||
130 | wputxb(assert(map_action[action], "bad action name `"..action.."'")) | ||
131 | if a then actargs[#actargs+1] = a end | ||
132 | if a or num then secpos = secpos + (num or 1) end | ||
133 | end | ||
134 | |||
135 | -- Add call to embedded DynASM C code. | ||
136 | local function wcall(func, args) | ||
137 | wline(format("dasm_%s(Dst, %s);", func, concat(args, ", ")), true) | ||
138 | end | ||
139 | |||
140 | -- Delete duplicate action list chunks. A tad slow, but so what. | ||
141 | local function dedupechunk(offset) | ||
142 | local al, as = actlist, actstr | ||
143 | local chunk = char(unpack(al, offset+1, #al)) | ||
144 | local orig = find(as, chunk, 1, true) | ||
145 | if orig then | ||
146 | actargs[1] = orig-1 -- Replace with original offset. | ||
147 | for i=offset+1,#al do al[i] = nil end -- Kill dupe. | ||
148 | else | ||
149 | actstr = as..chunk | ||
150 | end | ||
151 | end | ||
152 | |||
153 | -- Flush action list (intervening C code or buffer pos overflow). | ||
154 | local function wflush(term) | ||
155 | local offset = actargs[1] | ||
156 | if #actlist == offset then return end -- Nothing to flush. | ||
157 | if not term then waction("STOP") end -- Terminate action list. | ||
158 | dedupechunk(offset) | ||
159 | wcall("put", actargs) -- Add call to dasm_put(). | ||
160 | actargs = { #actlist } -- Actionlist offset is 1st arg to next dasm_put(). | ||
161 | secpos = 1 -- The actionlist offset occupies a buffer position, too. | ||
162 | end | ||
163 | |||
164 | -- Put escaped byte. | ||
165 | local function wputb(n) | ||
166 | if n >= actfirst then waction("ESC") end -- Need to escape byte. | ||
167 | wputxb(n) | ||
168 | end | ||
169 | |||
170 | ------------------------------------------------------------------------------ | ||
171 | |||
172 | -- Global label name -> global label number. With auto assignment on 1st use. | ||
173 | local next_global = 10 | ||
174 | local map_global = setmetatable({}, { __index = function(t, name) | ||
175 | if not match(name, "^[%a_][%w_@]*$") then werror("bad global label") end | ||
176 | local n = next_global | ||
177 | if n > 246 then werror("too many global labels") end | ||
178 | next_global = n + 1 | ||
179 | t[name] = n | ||
180 | return n | ||
181 | end}) | ||
182 | |||
183 | -- Dump global labels. | ||
184 | local function dumpglobals(out, lvl) | ||
185 | local t = {} | ||
186 | for name, n in pairs(map_global) do t[n] = name end | ||
187 | out:write("Global labels:\n") | ||
188 | for i=10,next_global-1 do | ||
189 | out:write(format(" %s\n", t[i])) | ||
190 | end | ||
191 | out:write("\n") | ||
192 | end | ||
193 | |||
194 | -- Write global label enum. | ||
195 | local function writeglobals(out, prefix) | ||
196 | local t = {} | ||
197 | for name, n in pairs(map_global) do t[n] = name end | ||
198 | out:write("enum {\n") | ||
199 | for i=10,next_global-1 do | ||
200 | out:write(" ", prefix, gsub(t[i], "@.*", ""), ",\n") | ||
201 | end | ||
202 | out:write(" ", prefix, "_MAX\n};\n") | ||
203 | end | ||
204 | |||
205 | -- Write global label names. | ||
206 | local function writeglobalnames(out, name) | ||
207 | local t = {} | ||
208 | for name, n in pairs(map_global) do t[n] = name end | ||
209 | out:write("static const char *const ", name, "[] = {\n") | ||
210 | for i=10,next_global-1 do | ||
211 | out:write(" \"", t[i], "\",\n") | ||
212 | end | ||
213 | out:write(" (const char *)0\n};\n") | ||
214 | end | ||
215 | |||
216 | ------------------------------------------------------------------------------ | ||
217 | |||
218 | -- Extern label name -> extern label number. With auto assignment on 1st use. | ||
219 | local next_extern = -1 | ||
220 | local map_extern = setmetatable({}, { __index = function(t, name) | ||
221 | -- No restrictions on the name for now. | ||
222 | local n = next_extern | ||
223 | if n < -256 then werror("too many extern labels") end | ||
224 | next_extern = n - 1 | ||
225 | t[name] = n | ||
226 | return n | ||
227 | end}) | ||
228 | |||
229 | -- Dump extern labels. | ||
230 | local function dumpexterns(out, lvl) | ||
231 | local t = {} | ||
232 | for name, n in pairs(map_extern) do t[-n] = name end | ||
233 | out:write("Extern labels:\n") | ||
234 | for i=1,-next_extern-1 do | ||
235 | out:write(format(" %s\n", t[i])) | ||
236 | end | ||
237 | out:write("\n") | ||
238 | end | ||
239 | |||
240 | -- Write extern label names. | ||
241 | local function writeexternnames(out, name) | ||
242 | local t = {} | ||
243 | for name, n in pairs(map_extern) do t[-n] = name end | ||
244 | out:write("static const char *const ", name, "[] = {\n") | ||
245 | for i=1,-next_extern-1 do | ||
246 | out:write(" \"", t[i], "\",\n") | ||
247 | end | ||
248 | out:write(" (const char *)0\n};\n") | ||
249 | end | ||
250 | |||
251 | ------------------------------------------------------------------------------ | ||
252 | |||
253 | -- Arch-specific maps. | ||
254 | local map_archdef = {} -- Ext. register name -> int. name. | ||
255 | local map_reg_rev = {} -- Int. register name -> ext. name. | ||
256 | local map_reg_num = {} -- Int. register name -> register number. | ||
257 | local map_reg_opsize = {} -- Int. register name -> operand size. | ||
258 | local map_reg_valid_base = {} -- Int. register name -> valid base register? | ||
259 | local map_reg_valid_index = {} -- Int. register name -> valid index register? | ||
260 | local map_reg_needrex = {} -- Int. register name -> need rex vs. no rex. | ||
261 | local reg_list = {} -- Canonical list of int. register names. | ||
262 | |||
263 | local map_type = {} -- Type name -> { ctype, reg } | ||
264 | local ctypenum = 0 -- Type number (for _PTx macros). | ||
265 | |||
266 | local addrsize = x64 and "q" or "d" -- Size for address operands. | ||
267 | |||
268 | -- Helper functions to fill register maps. | ||
269 | local function mkrmap(sz, cl, names) | ||
270 | local cname = format("@%s", sz) | ||
271 | reg_list[#reg_list+1] = cname | ||
272 | map_archdef[cl] = cname | ||
273 | map_reg_rev[cname] = cl | ||
274 | map_reg_num[cname] = -1 | ||
275 | map_reg_opsize[cname] = sz | ||
276 | if sz == addrsize or sz == "d" then | ||
277 | map_reg_valid_base[cname] = true | ||
278 | map_reg_valid_index[cname] = true | ||
279 | end | ||
280 | if names then | ||
281 | for n,name in ipairs(names) do | ||
282 | local iname = format("@%s%x", sz, n-1) | ||
283 | reg_list[#reg_list+1] = iname | ||
284 | map_archdef[name] = iname | ||
285 | map_reg_rev[iname] = name | ||
286 | map_reg_num[iname] = n-1 | ||
287 | map_reg_opsize[iname] = sz | ||
288 | if sz == "b" and n > 4 then map_reg_needrex[iname] = false end | ||
289 | if sz == addrsize or sz == "d" then | ||
290 | map_reg_valid_base[iname] = true | ||
291 | map_reg_valid_index[iname] = true | ||
292 | end | ||
293 | end | ||
294 | end | ||
295 | for i=0,(x64 and sz ~= "f") and 15 or 7 do | ||
296 | local needrex = sz == "b" and i > 3 | ||
297 | local iname = format("@%s%x%s", sz, i, needrex and "R" or "") | ||
298 | if needrex then map_reg_needrex[iname] = true end | ||
299 | local name | ||
300 | if sz == "o" then name = format("xmm%d", i) | ||
301 | elseif sz == "f" then name = format("st%d", i) | ||
302 | else name = format("r%d%s", i, sz == addrsize and "" or sz) end | ||
303 | map_archdef[name] = iname | ||
304 | if not map_reg_rev[iname] then | ||
305 | reg_list[#reg_list+1] = iname | ||
306 | map_reg_rev[iname] = name | ||
307 | map_reg_num[iname] = i | ||
308 | map_reg_opsize[iname] = sz | ||
309 | if sz == addrsize or sz == "d" then | ||
310 | map_reg_valid_base[iname] = true | ||
311 | map_reg_valid_index[iname] = true | ||
312 | end | ||
313 | end | ||
314 | end | ||
315 | reg_list[#reg_list+1] = "" | ||
316 | end | ||
317 | |||
318 | -- Integer registers (qword, dword, word and byte sized). | ||
319 | if x64 then | ||
320 | mkrmap("q", "Rq", {"rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi"}) | ||
321 | end | ||
322 | mkrmap("d", "Rd", {"eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"}) | ||
323 | mkrmap("w", "Rw", {"ax", "cx", "dx", "bx", "sp", "bp", "si", "di"}) | ||
324 | mkrmap("b", "Rb", {"al", "cl", "dl", "bl", "ah", "ch", "dh", "bh"}) | ||
325 | map_reg_valid_index[map_archdef.esp] = false | ||
326 | if x64 then map_reg_valid_index[map_archdef.rsp] = false end | ||
327 | map_archdef["Ra"] = "@"..addrsize | ||
328 | |||
329 | -- FP registers (internally tword sized, but use "f" as operand size). | ||
330 | mkrmap("f", "Rf") | ||
331 | |||
332 | -- SSE registers (oword sized, but qword and dword accessible). | ||
333 | mkrmap("o", "xmm") | ||
334 | |||
335 | -- Operand size prefixes to codes. | ||
336 | local map_opsize = { | ||
337 | byte = "b", word = "w", dword = "d", qword = "q", oword = "o", tword = "t", | ||
338 | aword = addrsize, | ||
339 | } | ||
340 | |||
341 | -- Operand size code to number. | ||
342 | local map_opsizenum = { | ||
343 | b = 1, w = 2, d = 4, q = 8, o = 16, t = 10, | ||
344 | } | ||
345 | |||
346 | -- Operand size code to name. | ||
347 | local map_opsizename = { | ||
348 | b = "byte", w = "word", d = "dword", q = "qword", o = "oword", t = "tword", | ||
349 | f = "fpword", | ||
350 | } | ||
351 | |||
352 | -- Valid index register scale factors. | ||
353 | local map_xsc = { | ||
354 | ["1"] = 0, ["2"] = 1, ["4"] = 2, ["8"] = 3, | ||
355 | } | ||
356 | |||
357 | -- Condition codes. | ||
358 | local map_cc = { | ||
359 | o = 0, no = 1, b = 2, nb = 3, e = 4, ne = 5, be = 6, nbe = 7, | ||
360 | s = 8, ns = 9, p = 10, np = 11, l = 12, nl = 13, le = 14, nle = 15, | ||
361 | c = 2, nae = 2, nc = 3, ae = 3, z = 4, nz = 5, na = 6, a = 7, | ||
362 | pe = 10, po = 11, nge = 12, ge = 13, ng = 14, g = 15, | ||
363 | } | ||
364 | |||
365 | |||
366 | -- Reverse defines for registers. | ||
367 | function _M.revdef(s) | ||
368 | return gsub(s, "@%w+", map_reg_rev) | ||
369 | end | ||
370 | |||
371 | -- Dump register names and numbers | ||
372 | local function dumpregs(out) | ||
373 | out:write("Register names, sizes and internal numbers:\n") | ||
374 | for _,reg in ipairs(reg_list) do | ||
375 | if reg == "" then | ||
376 | out:write("\n") | ||
377 | else | ||
378 | local name = map_reg_rev[reg] | ||
379 | local num = map_reg_num[reg] | ||
380 | local opsize = map_opsizename[map_reg_opsize[reg]] | ||
381 | out:write(format(" %-5s %-8s %s\n", name, opsize, | ||
382 | num < 0 and "(variable)" or num)) | ||
383 | end | ||
384 | end | ||
385 | end | ||
386 | |||
387 | ------------------------------------------------------------------------------ | ||
388 | |||
389 | -- Put action for label arg (IMM_LG, IMM_PC, REL_LG, REL_PC). | ||
390 | local function wputlabel(aprefix, imm, num) | ||
391 | if type(imm) == "number" then | ||
392 | if imm < 0 then | ||
393 | waction("EXTERN") | ||
394 | wputxb(aprefix == "IMM_" and 0 or 1) | ||
395 | imm = -imm-1 | ||
396 | else | ||
397 | waction(aprefix.."LG", nil, num); | ||
398 | end | ||
399 | wputxb(imm) | ||
400 | else | ||
401 | waction(aprefix.."PC", imm, num) | ||
402 | end | ||
403 | end | ||
404 | |||
405 | -- Put signed byte or arg. | ||
406 | local function wputsbarg(n) | ||
407 | if type(n) == "number" then | ||
408 | if n < -128 or n > 127 then | ||
409 | werror("signed immediate byte out of range") | ||
410 | end | ||
411 | if n < 0 then n = n + 256 end | ||
412 | wputb(n) | ||
413 | else waction("IMM_S", n) end | ||
414 | end | ||
415 | |||
416 | -- Put unsigned byte or arg. | ||
417 | local function wputbarg(n) | ||
418 | if type(n) == "number" then | ||
419 | if n < 0 or n > 255 then | ||
420 | werror("unsigned immediate byte out of range") | ||
421 | end | ||
422 | wputb(n) | ||
423 | else waction("IMM_B", n) end | ||
424 | end | ||
425 | |||
426 | -- Put unsigned word or arg. | ||
427 | local function wputwarg(n) | ||
428 | if type(n) == "number" then | ||
429 | if n < 0 or n > 65535 then | ||
430 | werror("unsigned immediate word out of range") | ||
431 | end | ||
432 | local r = n%256; n = (n-r)/256; wputb(r); wputb(n); | ||
433 | else waction("IMM_W", n) end | ||
434 | end | ||
435 | |||
436 | -- Put signed or unsigned dword or arg. | ||
437 | local function wputdarg(n) | ||
438 | local tn = type(n) | ||
439 | if tn == "number" then | ||
440 | if n < 0 then n = n + 4294967296 end | ||
441 | local r = n%256; n = (n-r)/256; wputb(r); | ||
442 | r = n%256; n = (n-r)/256; wputb(r); | ||
443 | r = n%256; n = (n-r)/256; wputb(r); wputb(n); | ||
444 | elseif tn == "table" then | ||
445 | wputlabel("IMM_", n[1], 1) | ||
446 | else | ||
447 | waction("IMM_D", n) | ||
448 | end | ||
449 | end | ||
450 | |||
451 | -- Put operand-size dependent number or arg (defaults to dword). | ||
452 | local function wputszarg(sz, n) | ||
453 | if not sz or sz == "d" or sz == "q" then wputdarg(n) | ||
454 | elseif sz == "w" then wputwarg(n) | ||
455 | elseif sz == "b" then wputbarg(n) | ||
456 | elseif sz == "s" then wputsbarg(n) | ||
457 | else werror("bad operand size") end | ||
458 | end | ||
459 | |||
460 | -- Put multi-byte opcode with operand-size dependent modifications. | ||
461 | local function wputop(sz, op, rex) | ||
462 | local r | ||
463 | if rex ~= 0 and not x64 then werror("bad operand size") end | ||
464 | if sz == "w" then wputb(102) end | ||
465 | -- Needs >32 bit numbers, but only for crc32 eax, word [ebx] | ||
466 | if op >= 4294967296 then r = op%4294967296 wputb((op-r)/4294967296) op = r end | ||
467 | if op >= 16777216 then r = op % 16777216 wputb((op-r) / 16777216) op = r end | ||
468 | if op >= 65536 then | ||
469 | if rex ~= 0 then | ||
470 | local opc3 = op - op % 256 | ||
471 | if opc3 == 0x0f3a00 or opc3 == 0x0f3800 then | ||
472 | wputb(64 + rex % 16); rex = 0 | ||
473 | end | ||
474 | end | ||
475 | r = op % 65536 wputb((op-r) / 65536) op = r | ||
476 | end | ||
477 | if op >= 256 then | ||
478 | r = op % 256 | ||
479 | local b = (op-r) / 256 | ||
480 | if b == 15 and rex ~= 0 then wputb(64 + rex % 16); rex = 0 end | ||
481 | wputb(b) | ||
482 | op = r | ||
483 | end | ||
484 | if rex ~= 0 then wputb(64 + rex % 16) end | ||
485 | if sz == "b" then op = op - 1 end | ||
486 | wputb(op) | ||
487 | end | ||
488 | |||
489 | -- Put ModRM or SIB formatted byte. | ||
490 | local function wputmodrm(m, s, rm, vs, vrm) | ||
491 | assert(m < 4 and s < 16 and rm < 16, "bad modrm operands") | ||
492 | wputb(64*m + 8*(s%8) + (rm%8)) | ||
493 | end | ||
494 | |||
495 | -- Put ModRM/SIB plus optional displacement. | ||
496 | local function wputmrmsib(t, imark, s, vsreg) | ||
497 | local vreg, vxreg | ||
498 | local reg, xreg = t.reg, t.xreg | ||
499 | if reg and reg < 0 then reg = 0; vreg = t.vreg end | ||
500 | if xreg and xreg < 0 then xreg = 0; vxreg = t.vxreg end | ||
501 | if s < 0 then s = 0 end | ||
502 | |||
503 | -- Register mode. | ||
504 | if sub(t.mode, 1, 1) == "r" then | ||
505 | wputmodrm(3, s, reg) | ||
506 | if vsreg then waction("VREG", vsreg); wputxb(2) end | ||
507 | if vreg then waction("VREG", vreg); wputxb(0) end | ||
508 | return | ||
509 | end | ||
510 | |||
511 | local disp = t.disp | ||
512 | local tdisp = type(disp) | ||
513 | -- No base register? | ||
514 | if not reg then | ||
515 | local riprel = false | ||
516 | if xreg then | ||
517 | -- Indexed mode with index register only. | ||
518 | -- [xreg*xsc+disp] -> (0, s, esp) (xsc, xreg, ebp) | ||
519 | wputmodrm(0, s, 4) | ||
520 | if imark == "I" then waction("MARK") end | ||
521 | if vsreg then waction("VREG", vsreg); wputxb(2) end | ||
522 | wputmodrm(t.xsc, xreg, 5) | ||
523 | if vxreg then waction("VREG", vxreg); wputxb(3) end | ||
524 | else | ||
525 | -- Pure 32 bit displacement. | ||
526 | if x64 and tdisp ~= "table" then | ||
527 | wputmodrm(0, s, 4) -- [disp] -> (0, s, esp) (0, esp, ebp) | ||
528 | if imark == "I" then waction("MARK") end | ||
529 | wputmodrm(0, 4, 5) | ||
530 | else | ||
531 | riprel = x64 | ||
532 | wputmodrm(0, s, 5) -- [disp|rip-label] -> (0, s, ebp) | ||
533 | if imark == "I" then waction("MARK") end | ||
534 | end | ||
535 | if vsreg then waction("VREG", vsreg); wputxb(2) end | ||
536 | end | ||
537 | if riprel then -- Emit rip-relative displacement. | ||
538 | if match("UWSiI", imark) then | ||
539 | werror("NYI: rip-relative displacement followed by immediate") | ||
540 | end | ||
541 | -- The previous byte in the action buffer cannot be 0xe9 or 0x80-0x8f. | ||
542 | wputlabel("REL_", disp[1], 2) | ||
543 | else | ||
544 | wputdarg(disp) | ||
545 | end | ||
546 | return | ||
547 | end | ||
548 | |||
549 | local m | ||
550 | if tdisp == "number" then -- Check displacement size at assembly time. | ||
551 | if disp == 0 and (reg%8) ~= 5 then -- [ebp] -> [ebp+0] (in SIB, too) | ||
552 | if not vreg then m = 0 end -- Force DISP to allow [Rd(5)] -> [ebp+0] | ||
553 | elseif disp >= -128 and disp <= 127 then m = 1 | ||
554 | else m = 2 end | ||
555 | elseif tdisp == "table" then | ||
556 | m = 2 | ||
557 | end | ||
558 | |||
559 | -- Index register present or esp as base register: need SIB encoding. | ||
560 | if xreg or (reg%8) == 4 then | ||
561 | wputmodrm(m or 2, s, 4) -- ModRM. | ||
562 | if m == nil or imark == "I" then waction("MARK") end | ||
563 | if vsreg then waction("VREG", vsreg); wputxb(2) end | ||
564 | wputmodrm(t.xsc or 0, xreg or 4, reg) -- SIB. | ||
565 | if vxreg then waction("VREG", vxreg); wputxb(3) end | ||
566 | if vreg then waction("VREG", vreg); wputxb(1) end | ||
567 | else | ||
568 | wputmodrm(m or 2, s, reg) -- ModRM. | ||
569 | if (imark == "I" and (m == 1 or m == 2)) or | ||
570 | (m == nil and (vsreg or vreg)) then waction("MARK") end | ||
571 | if vsreg then waction("VREG", vsreg); wputxb(2) end | ||
572 | if vreg then waction("VREG", vreg); wputxb(1) end | ||
573 | end | ||
574 | |||
575 | -- Put displacement. | ||
576 | if m == 1 then wputsbarg(disp) | ||
577 | elseif m == 2 then wputdarg(disp) | ||
578 | elseif m == nil then waction("DISP", disp) end | ||
579 | end | ||
580 | |||
581 | ------------------------------------------------------------------------------ | ||
582 | |||
583 | -- Return human-readable operand mode string. | ||
584 | local function opmodestr(op, args) | ||
585 | local m = {} | ||
586 | for i=1,#args do | ||
587 | local a = args[i] | ||
588 | m[#m+1] = sub(a.mode, 1, 1)..(a.opsize or "?") | ||
589 | end | ||
590 | return op.." "..concat(m, ",") | ||
591 | end | ||
592 | |||
593 | -- Convert number to valid integer or nil. | ||
594 | local function toint(expr) | ||
595 | local n = tonumber(expr) | ||
596 | if n then | ||
597 | if n % 1 ~= 0 or n < -2147483648 or n > 4294967295 then | ||
598 | werror("bad integer number `"..expr.."'") | ||
599 | end | ||
600 | return n | ||
601 | end | ||
602 | end | ||
603 | |||
604 | -- Parse immediate expression. | ||
605 | local function immexpr(expr) | ||
606 | -- &expr (pointer) | ||
607 | if sub(expr, 1, 1) == "&" then | ||
608 | return "iPJ", format("(ptrdiff_t)(%s)", sub(expr,2)) | ||
609 | end | ||
610 | |||
611 | local prefix = sub(expr, 1, 2) | ||
612 | -- =>expr (pc label reference) | ||
613 | if prefix == "=>" then | ||
614 | return "iJ", sub(expr, 3) | ||
615 | end | ||
616 | -- ->name (global label reference) | ||
617 | if prefix == "->" then | ||
618 | return "iJ", map_global[sub(expr, 3)] | ||
619 | end | ||
620 | |||
621 | -- [<>][1-9] (local label reference) | ||
622 | local dir, lnum = match(expr, "^([<>])([1-9])$") | ||
623 | if dir then -- Fwd: 247-255, Bkwd: 1-9. | ||
624 | return "iJ", lnum + (dir == ">" and 246 or 0) | ||
625 | end | ||
626 | |||
627 | local extname = match(expr, "^extern%s+(%S+)$") | ||
628 | if extname then | ||
629 | return "iJ", map_extern[extname] | ||
630 | end | ||
631 | |||
632 | -- expr (interpreted as immediate) | ||
633 | return "iI", expr | ||
634 | end | ||
635 | |||
636 | -- Parse displacement expression: +-num, +-expr, +-opsize*num | ||
637 | local function dispexpr(expr) | ||
638 | local disp = expr == "" and 0 or toint(expr) | ||
639 | if disp then return disp end | ||
640 | local c, dispt = match(expr, "^([+-])%s*(.+)$") | ||
641 | if c == "+" then | ||
642 | expr = dispt | ||
643 | elseif not c then | ||
644 | werror("bad displacement expression `"..expr.."'") | ||
645 | end | ||
646 | local opsize, tailops = match(dispt, "^(%w+)%s*%*%s*(.+)$") | ||
647 | local ops, imm = map_opsize[opsize], toint(tailops) | ||
648 | if ops and imm then | ||
649 | if c == "-" then imm = -imm end | ||
650 | return imm*map_opsizenum[ops] | ||
651 | end | ||
652 | local mode, iexpr = immexpr(dispt) | ||
653 | if mode == "iJ" then | ||
654 | if c == "-" then werror("cannot invert label reference") end | ||
655 | return { iexpr } | ||
656 | end | ||
657 | return expr -- Need to return original signed expression. | ||
658 | end | ||
659 | |||
660 | -- Parse register or type expression. | ||
661 | local function rtexpr(expr) | ||
662 | if not expr then return end | ||
663 | local tname, ovreg = match(expr, "^([%w_]+):(@[%w_]+)$") | ||
664 | local tp = map_type[tname or expr] | ||
665 | if tp then | ||
666 | local reg = ovreg or tp.reg | ||
667 | local rnum = map_reg_num[reg] | ||
668 | if not rnum then | ||
669 | werror("type `"..(tname or expr).."' needs a register override") | ||
670 | end | ||
671 | if not map_reg_valid_base[reg] then | ||
672 | werror("bad base register override `"..(map_reg_rev[reg] or reg).."'") | ||
673 | end | ||
674 | return reg, rnum, tp | ||
675 | end | ||
676 | return expr, map_reg_num[expr] | ||
677 | end | ||
678 | |||
679 | -- Parse operand and return { mode, opsize, reg, xreg, xsc, disp, imm }. | ||
680 | local function parseoperand(param) | ||
681 | local t = {} | ||
682 | |||
683 | local expr = param | ||
684 | local opsize, tailops = match(param, "^(%w+)%s*(.+)$") | ||
685 | if opsize then | ||
686 | t.opsize = map_opsize[opsize] | ||
687 | if t.opsize then expr = tailops end | ||
688 | end | ||
689 | |||
690 | local br = match(expr, "^%[%s*(.-)%s*%]$") | ||
691 | repeat | ||
692 | if br then | ||
693 | t.mode = "xm" | ||
694 | |||
695 | -- [disp] | ||
696 | t.disp = toint(br) | ||
697 | if t.disp then | ||
698 | t.mode = x64 and "xm" or "xmO" | ||
699 | break | ||
700 | end | ||
701 | |||
702 | -- [reg...] | ||
703 | local tp | ||
704 | local reg, tailr = match(br, "^([@%w_:]+)%s*(.*)$") | ||
705 | reg, t.reg, tp = rtexpr(reg) | ||
706 | if not t.reg then | ||
707 | -- [expr] | ||
708 | t.mode = x64 and "xm" or "xmO" | ||
709 | t.disp = dispexpr("+"..br) | ||
710 | break | ||
711 | end | ||
712 | |||
713 | if t.reg == -1 then | ||
714 | t.vreg, tailr = match(tailr, "^(%b())(.*)$") | ||
715 | if not t.vreg then werror("bad variable register expression") end | ||
716 | end | ||
717 | |||
718 | -- [xreg*xsc] or [xreg*xsc+-disp] or [xreg*xsc+-expr] | ||
719 | local xsc, tailsc = match(tailr, "^%*%s*([1248])%s*(.*)$") | ||
720 | if xsc then | ||
721 | if not map_reg_valid_index[reg] then | ||
722 | werror("bad index register `"..map_reg_rev[reg].."'") | ||
723 | end | ||
724 | t.xsc = map_xsc[xsc] | ||
725 | t.xreg = t.reg | ||
726 | t.vxreg = t.vreg | ||
727 | t.reg = nil | ||
728 | t.vreg = nil | ||
729 | t.disp = dispexpr(tailsc) | ||
730 | break | ||
731 | end | ||
732 | if not map_reg_valid_base[reg] then | ||
733 | werror("bad base register `"..map_reg_rev[reg].."'") | ||
734 | end | ||
735 | |||
736 | -- [reg] or [reg+-disp] | ||
737 | t.disp = toint(tailr) or (tailr == "" and 0) | ||
738 | if t.disp then break end | ||
739 | |||
740 | -- [reg+xreg...] | ||
741 | local xreg, tailx = match(tailr, "^+%s*([@%w_:]+)%s*(.*)$") | ||
742 | xreg, t.xreg, tp = rtexpr(xreg) | ||
743 | if not t.xreg then | ||
744 | -- [reg+-expr] | ||
745 | t.disp = dispexpr(tailr) | ||
746 | break | ||
747 | end | ||
748 | if not map_reg_valid_index[xreg] then | ||
749 | werror("bad index register `"..map_reg_rev[xreg].."'") | ||
750 | end | ||
751 | |||
752 | if t.xreg == -1 then | ||
753 | t.vxreg, tailx = match(tailx, "^(%b())(.*)$") | ||
754 | if not t.vxreg then werror("bad variable register expression") end | ||
755 | end | ||
756 | |||
757 | -- [reg+xreg*xsc...] | ||
758 | local xsc, tailsc = match(tailx, "^%*%s*([1248])%s*(.*)$") | ||
759 | if xsc then | ||
760 | t.xsc = map_xsc[xsc] | ||
761 | tailx = tailsc | ||
762 | end | ||
763 | |||
764 | -- [...] or [...+-disp] or [...+-expr] | ||
765 | t.disp = dispexpr(tailx) | ||
766 | else | ||
767 | -- imm or opsize*imm | ||
768 | local imm = toint(expr) | ||
769 | if not imm and sub(expr, 1, 1) == "*" and t.opsize then | ||
770 | imm = toint(sub(expr, 2)) | ||
771 | if imm then | ||
772 | imm = imm * map_opsizenum[t.opsize] | ||
773 | t.opsize = nil | ||
774 | end | ||
775 | end | ||
776 | if imm then | ||
777 | if t.opsize then werror("bad operand size override") end | ||
778 | local m = "i" | ||
779 | if imm == 1 then m = m.."1" end | ||
780 | if imm >= 4294967168 and imm <= 4294967295 then imm = imm-4294967296 end | ||
781 | if imm >= -128 and imm <= 127 then m = m.."S" end | ||
782 | t.imm = imm | ||
783 | t.mode = m | ||
784 | break | ||
785 | end | ||
786 | |||
787 | local tp | ||
788 | local reg, tailr = match(expr, "^([@%w_:]+)%s*(.*)$") | ||
789 | reg, t.reg, tp = rtexpr(reg) | ||
790 | if t.reg then | ||
791 | if t.reg == -1 then | ||
792 | t.vreg, tailr = match(tailr, "^(%b())(.*)$") | ||
793 | if not t.vreg then werror("bad variable register expression") end | ||
794 | end | ||
795 | -- reg | ||
796 | if tailr == "" then | ||
797 | if t.opsize then werror("bad operand size override") end | ||
798 | t.opsize = map_reg_opsize[reg] | ||
799 | if t.opsize == "f" then | ||
800 | t.mode = t.reg == 0 and "fF" or "f" | ||
801 | else | ||
802 | if reg == "@w4" or (x64 and reg == "@d4") then | ||
803 | wwarn("bad idea, try again with `"..(x64 and "rsp'" or "esp'")) | ||
804 | end | ||
805 | t.mode = t.reg == 0 and "rmR" or (reg == "@b1" and "rmC" or "rm") | ||
806 | end | ||
807 | t.needrex = map_reg_needrex[reg] | ||
808 | break | ||
809 | end | ||
810 | |||
811 | -- type[idx], type[idx].field, type->field -> [reg+offset_expr] | ||
812 | if not tp then werror("bad operand `"..param.."'") end | ||
813 | t.mode = "xm" | ||
814 | t.disp = format(tp.ctypefmt, tailr) | ||
815 | else | ||
816 | t.mode, t.imm = immexpr(expr) | ||
817 | if sub(t.mode, -1) == "J" then | ||
818 | if t.opsize and t.opsize ~= addrsize then | ||
819 | werror("bad operand size override") | ||
820 | end | ||
821 | t.opsize = addrsize | ||
822 | end | ||
823 | end | ||
824 | end | ||
825 | until true | ||
826 | return t | ||
827 | end | ||
828 | |||
829 | ------------------------------------------------------------------------------ | ||
830 | -- x86 Template String Description | ||
831 | -- =============================== | ||
832 | -- | ||
833 | -- Each template string is a list of [match:]pattern pairs, | ||
834 | -- separated by "|". The first match wins. No match means a | ||
835 | -- bad or unsupported combination of operand modes or sizes. | ||
836 | -- | ||
837 | -- The match part and the ":" is omitted if the operation has | ||
838 | -- no operands. Otherwise the first N characters are matched | ||
839 | -- against the mode strings of each of the N operands. | ||
840 | -- | ||
841 | -- The mode string for each operand type is (see parseoperand()): | ||
842 | -- Integer register: "rm", +"R" for eax, ax, al, +"C" for cl | ||
843 | -- FP register: "f", +"F" for st0 | ||
844 | -- Index operand: "xm", +"O" for [disp] (pure offset) | ||
845 | -- Immediate: "i", +"S" for signed 8 bit, +"1" for 1, | ||
846 | -- +"I" for arg, +"P" for pointer | ||
847 | -- Any: +"J" for valid jump targets | ||
848 | -- | ||
849 | -- So a match character "m" (mixed) matches both an integer register | ||
850 | -- and an index operand (to be encoded with the ModRM/SIB scheme). | ||
851 | -- But "r" matches only a register and "x" only an index operand | ||
852 | -- (e.g. for FP memory access operations). | ||
853 | -- | ||
854 | -- The operand size match string starts right after the mode match | ||
855 | -- characters and ends before the ":". "dwb" or "qdwb" is assumed, if empty. | ||
856 | -- The effective data size of the operation is matched against this list. | ||
857 | -- | ||
858 | -- If only the regular "b", "w", "d", "q", "t" operand sizes are | ||
859 | -- present, then all operands must be the same size. Unspecified sizes | ||
860 | -- are ignored, but at least one operand must have a size or the pattern | ||
861 | -- won't match (use the "byte", "word", "dword", "qword", "tword" | ||
862 | -- operand size overrides. E.g.: mov dword [eax], 1). | ||
863 | -- | ||
864 | -- If the list has a "1" or "2" prefix, the operand size is taken | ||
865 | -- from the respective operand and any other operand sizes are ignored. | ||
866 | -- If the list contains only ".", all operand sizes are ignored. | ||
867 | -- If the list has a "/" prefix, the concatenated (mixed) operand sizes | ||
868 | -- are compared to the match. | ||
869 | -- | ||
870 | -- E.g. "rrdw" matches for either two dword registers or two word | ||
871 | -- registers. "Fx2dq" matches an st0 operand plus an index operand | ||
872 | -- pointing to a dword (float) or qword (double). | ||
873 | -- | ||
874 | -- Every character after the ":" is part of the pattern string: | ||
875 | -- Hex chars are accumulated to form the opcode (left to right). | ||
876 | -- "n" disables the standard opcode mods | ||
877 | -- (otherwise: -1 for "b", o16 prefix for "w", rex.w for "q") | ||
878 | -- "X" Force REX.W. | ||
879 | -- "r"/"R" adds the reg. number from the 1st/2nd operand to the opcode. | ||
880 | -- "m"/"M" generates ModRM/SIB from the 1st/2nd operand. | ||
881 | -- The spare 3 bits are either filled with the last hex digit or | ||
882 | -- the result from a previous "r"/"R". The opcode is restored. | ||
883 | -- | ||
884 | -- All of the following characters force a flush of the opcode: | ||
885 | -- "o"/"O" stores a pure 32 bit disp (offset) from the 1st/2nd operand. | ||
886 | -- "S" stores a signed 8 bit immediate from the last operand. | ||
887 | -- "U" stores an unsigned 8 bit immediate from the last operand. | ||
888 | -- "W" stores an unsigned 16 bit immediate from the last operand. | ||
889 | -- "i" stores an operand sized immediate from the last operand. | ||
890 | -- "I" dito, but generates an action code to optionally modify | ||
891 | -- the opcode (+2) for a signed 8 bit immediate. | ||
892 | -- "J" generates one of the REL action codes from the last operand. | ||
893 | -- | ||
894 | ------------------------------------------------------------------------------ | ||
895 | |||
896 | -- Template strings for x86 instructions. Ordered by first opcode byte. | ||
897 | -- Unimplemented opcodes (deliberate omissions) are marked with *. | ||
898 | local map_op = { | ||
899 | -- 00-05: add... | ||
900 | -- 06: *push es | ||
901 | -- 07: *pop es | ||
902 | -- 08-0D: or... | ||
903 | -- 0E: *push cs | ||
904 | -- 0F: two byte opcode prefix | ||
905 | -- 10-15: adc... | ||
906 | -- 16: *push ss | ||
907 | -- 17: *pop ss | ||
908 | -- 18-1D: sbb... | ||
909 | -- 1E: *push ds | ||
910 | -- 1F: *pop ds | ||
911 | -- 20-25: and... | ||
912 | es_0 = "26", | ||
913 | -- 27: *daa | ||
914 | -- 28-2D: sub... | ||
915 | cs_0 = "2E", | ||
916 | -- 2F: *das | ||
917 | -- 30-35: xor... | ||
918 | ss_0 = "36", | ||
919 | -- 37: *aaa | ||
920 | -- 38-3D: cmp... | ||
921 | ds_0 = "3E", | ||
922 | -- 3F: *aas | ||
923 | inc_1 = x64 and "m:FF0m" or "rdw:40r|m:FF0m", | ||
924 | dec_1 = x64 and "m:FF1m" or "rdw:48r|m:FF1m", | ||
925 | push_1 = (x64 and "rq:n50r|rw:50r|mq:nFF6m|mw:FF6m" or | ||
926 | "rdw:50r|mdw:FF6m").."|S.:6AS|ib:n6Ai|i.:68i", | ||
927 | pop_1 = x64 and "rq:n58r|rw:58r|mq:n8F0m|mw:8F0m" or "rdw:58r|mdw:8F0m", | ||
928 | -- 60: *pusha, *pushad, *pushaw | ||
929 | -- 61: *popa, *popad, *popaw | ||
930 | -- 62: *bound rdw,x | ||
931 | -- 63: x86: *arpl mw,rw | ||
932 | movsxd_2 = x64 and "rm/qd:63rM", | ||
933 | fs_0 = "64", | ||
934 | gs_0 = "65", | ||
935 | o16_0 = "66", | ||
936 | a16_0 = not x64 and "67" or nil, | ||
937 | a32_0 = x64 and "67", | ||
938 | -- 68: push idw | ||
939 | -- 69: imul rdw,mdw,idw | ||
940 | -- 6A: push ib | ||
941 | -- 6B: imul rdw,mdw,S | ||
942 | -- 6C: *insb | ||
943 | -- 6D: *insd, *insw | ||
944 | -- 6E: *outsb | ||
945 | -- 6F: *outsd, *outsw | ||
946 | -- 70-7F: jcc lb | ||
947 | -- 80: add... mb,i | ||
948 | -- 81: add... mdw,i | ||
949 | -- 82: *undefined | ||
950 | -- 83: add... mdw,S | ||
951 | test_2 = "mr:85Rm|rm:85rM|Ri:A9ri|mi:F70mi", | ||
952 | -- 86: xchg rb,mb | ||
953 | -- 87: xchg rdw,mdw | ||
954 | -- 88: mov mb,r | ||
955 | -- 89: mov mdw,r | ||
956 | -- 8A: mov r,mb | ||
957 | -- 8B: mov r,mdw | ||
958 | -- 8C: *mov mdw,seg | ||
959 | lea_2 = "rx1dq:8DrM", | ||
960 | -- 8E: *mov seg,mdw | ||
961 | -- 8F: pop mdw | ||
962 | nop_0 = "90", | ||
963 | xchg_2 = "Rrqdw:90R|rRqdw:90r|rm:87rM|mr:87Rm", | ||
964 | cbw_0 = "6698", | ||
965 | cwde_0 = "98", | ||
966 | cdqe_0 = "4898", | ||
967 | cwd_0 = "6699", | ||
968 | cdq_0 = "99", | ||
969 | cqo_0 = "4899", | ||
970 | -- 9A: *call iw:idw | ||
971 | wait_0 = "9B", | ||
972 | fwait_0 = "9B", | ||
973 | pushf_0 = "9C", | ||
974 | pushfd_0 = not x64 and "9C", | ||
975 | pushfq_0 = x64 and "9C", | ||
976 | popf_0 = "9D", | ||
977 | popfd_0 = not x64 and "9D", | ||
978 | popfq_0 = x64 and "9D", | ||
979 | sahf_0 = "9E", | ||
980 | lahf_0 = "9F", | ||
981 | mov_2 = "OR:A3o|RO:A1O|mr:89Rm|rm:8BrM|rib:nB0ri|ridw:B8ri|mi:C70mi", | ||
982 | movsb_0 = "A4", | ||
983 | movsw_0 = "66A5", | ||
984 | movsd_0 = "A5", | ||
985 | cmpsb_0 = "A6", | ||
986 | cmpsw_0 = "66A7", | ||
987 | cmpsd_0 = "A7", | ||
988 | -- A8: test Rb,i | ||
989 | -- A9: test Rdw,i | ||
990 | stosb_0 = "AA", | ||
991 | stosw_0 = "66AB", | ||
992 | stosd_0 = "AB", | ||
993 | lodsb_0 = "AC", | ||
994 | lodsw_0 = "66AD", | ||
995 | lodsd_0 = "AD", | ||
996 | scasb_0 = "AE", | ||
997 | scasw_0 = "66AF", | ||
998 | scasd_0 = "AF", | ||
999 | -- B0-B7: mov rb,i | ||
1000 | -- B8-BF: mov rdw,i | ||
1001 | -- C0: rol... mb,i | ||
1002 | -- C1: rol... mdw,i | ||
1003 | ret_1 = "i.:nC2W", | ||
1004 | ret_0 = "C3", | ||
1005 | -- C4: *les rdw,mq | ||
1006 | -- C5: *lds rdw,mq | ||
1007 | -- C6: mov mb,i | ||
1008 | -- C7: mov mdw,i | ||
1009 | -- C8: *enter iw,ib | ||
1010 | leave_0 = "C9", | ||
1011 | -- CA: *retf iw | ||
1012 | -- CB: *retf | ||
1013 | int3_0 = "CC", | ||
1014 | int_1 = "i.:nCDU", | ||
1015 | into_0 = "CE", | ||
1016 | -- CF: *iret | ||
1017 | -- D0: rol... mb,1 | ||
1018 | -- D1: rol... mdw,1 | ||
1019 | -- D2: rol... mb,cl | ||
1020 | -- D3: rol... mb,cl | ||
1021 | -- D4: *aam ib | ||
1022 | -- D5: *aad ib | ||
1023 | -- D6: *salc | ||
1024 | -- D7: *xlat | ||
1025 | -- D8-DF: floating point ops | ||
1026 | -- E0: *loopne | ||
1027 | -- E1: *loope | ||
1028 | -- E2: *loop | ||
1029 | -- E3: *jcxz, *jecxz | ||
1030 | -- E4: *in Rb,ib | ||
1031 | -- E5: *in Rdw,ib | ||
1032 | -- E6: *out ib,Rb | ||
1033 | -- E7: *out ib,Rdw | ||
1034 | call_1 = x64 and "mq:nFF2m|J.:E8nJ" or "md:FF2m|J.:E8J", | ||
1035 | jmp_1 = x64 and "mq:nFF4m|J.:E9nJ" or "md:FF4m|J.:E9J", -- short: EB | ||
1036 | -- EA: *jmp iw:idw | ||
1037 | -- EB: jmp ib | ||
1038 | -- EC: *in Rb,dx | ||
1039 | -- ED: *in Rdw,dx | ||
1040 | -- EE: *out dx,Rb | ||
1041 | -- EF: *out dx,Rdw | ||
1042 | -- F0: *lock | ||
1043 | int1_0 = "F1", | ||
1044 | repne_0 = "F2", | ||
1045 | repnz_0 = "F2", | ||
1046 | rep_0 = "F3", | ||
1047 | repe_0 = "F3", | ||
1048 | repz_0 = "F3", | ||
1049 | -- F4: *hlt | ||
1050 | cmc_0 = "F5", | ||
1051 | -- F6: test... mb,i; div... mb | ||
1052 | -- F7: test... mdw,i; div... mdw | ||
1053 | clc_0 = "F8", | ||
1054 | stc_0 = "F9", | ||
1055 | -- FA: *cli | ||
1056 | cld_0 = "FC", | ||
1057 | std_0 = "FD", | ||
1058 | -- FE: inc... mb | ||
1059 | -- FF: inc... mdw | ||
1060 | |||
1061 | -- misc ops | ||
1062 | not_1 = "m:F72m", | ||
1063 | neg_1 = "m:F73m", | ||
1064 | mul_1 = "m:F74m", | ||
1065 | imul_1 = "m:F75m", | ||
1066 | div_1 = "m:F76m", | ||
1067 | idiv_1 = "m:F77m", | ||
1068 | |||
1069 | imul_2 = "rmqdw:0FAFrM|rIqdw:69rmI|rSqdw:6BrmS|riqdw:69rmi", | ||
1070 | imul_3 = "rmIqdw:69rMI|rmSqdw:6BrMS|rmiqdw:69rMi", | ||
1071 | |||
1072 | movzx_2 = "rm/db:0FB6rM|rm/qb:|rm/wb:0FB6rM|rm/dw:0FB7rM|rm/qw:", | ||
1073 | movsx_2 = "rm/db:0FBErM|rm/qb:|rm/wb:0FBErM|rm/dw:0FBFrM|rm/qw:", | ||
1074 | |||
1075 | bswap_1 = "rqd:0FC8r", | ||
1076 | bsf_2 = "rmqdw:0FBCrM", | ||
1077 | bsr_2 = "rmqdw:0FBDrM", | ||
1078 | bt_2 = "mrqdw:0FA3Rm|miqdw:0FBA4mU", | ||
1079 | btc_2 = "mrqdw:0FBBRm|miqdw:0FBA7mU", | ||
1080 | btr_2 = "mrqdw:0FB3Rm|miqdw:0FBA6mU", | ||
1081 | bts_2 = "mrqdw:0FABRm|miqdw:0FBA5mU", | ||
1082 | |||
1083 | rdtsc_0 = "0F31", -- P1+ | ||
1084 | cpuid_0 = "0FA2", -- P1+ | ||
1085 | |||
1086 | -- floating point ops | ||
1087 | fst_1 = "ff:DDD0r|xd:D92m|xq:nDD2m", | ||
1088 | fstp_1 = "ff:DDD8r|xd:D93m|xq:nDD3m|xt:DB7m", | ||
1089 | fld_1 = "ff:D9C0r|xd:D90m|xq:nDD0m|xt:DB5m", | ||
1090 | |||
1091 | fpop_0 = "DDD8", -- Alias for fstp st0. | ||
1092 | |||
1093 | fist_1 = "xw:nDF2m|xd:DB2m", | ||
1094 | fistp_1 = "xw:nDF3m|xd:DB3m|xq:nDF7m", | ||
1095 | fild_1 = "xw:nDF0m|xd:DB0m|xq:nDF5m", | ||
1096 | |||
1097 | fxch_0 = "D9C9", | ||
1098 | fxch_1 = "ff:D9C8r", | ||
1099 | fxch_2 = "fFf:D9C8r|Fff:D9C8R", | ||
1100 | |||
1101 | fucom_1 = "ff:DDE0r", | ||
1102 | fucom_2 = "Fff:DDE0R", | ||
1103 | fucomp_1 = "ff:DDE8r", | ||
1104 | fucomp_2 = "Fff:DDE8R", | ||
1105 | fucomi_1 = "ff:DBE8r", -- P6+ | ||
1106 | fucomi_2 = "Fff:DBE8R", -- P6+ | ||
1107 | fucomip_1 = "ff:DFE8r", -- P6+ | ||
1108 | fucomip_2 = "Fff:DFE8R", -- P6+ | ||
1109 | fcomi_1 = "ff:DBF0r", -- P6+ | ||
1110 | fcomi_2 = "Fff:DBF0R", -- P6+ | ||
1111 | fcomip_1 = "ff:DFF0r", -- P6+ | ||
1112 | fcomip_2 = "Fff:DFF0R", -- P6+ | ||
1113 | fucompp_0 = "DAE9", | ||
1114 | fcompp_0 = "DED9", | ||
1115 | |||
1116 | fldcw_1 = "xw:nD95m", | ||
1117 | fstcw_1 = "xw:n9BD97m", | ||
1118 | fnstcw_1 = "xw:nD97m", | ||
1119 | fstsw_1 = "Rw:n9BDFE0|xw:n9BDD7m", | ||
1120 | fnstsw_1 = "Rw:nDFE0|xw:nDD7m", | ||
1121 | fclex_0 = "9BDBE2", | ||
1122 | fnclex_0 = "DBE2", | ||
1123 | |||
1124 | fnop_0 = "D9D0", | ||
1125 | -- D9D1-D9DF: unassigned | ||
1126 | |||
1127 | fchs_0 = "D9E0", | ||
1128 | fabs_0 = "D9E1", | ||
1129 | -- D9E2: unassigned | ||
1130 | -- D9E3: unassigned | ||
1131 | ftst_0 = "D9E4", | ||
1132 | fxam_0 = "D9E5", | ||
1133 | -- D9E6: unassigned | ||
1134 | -- D9E7: unassigned | ||
1135 | fld1_0 = "D9E8", | ||
1136 | fldl2t_0 = "D9E9", | ||
1137 | fldl2e_0 = "D9EA", | ||
1138 | fldpi_0 = "D9EB", | ||
1139 | fldlg2_0 = "D9EC", | ||
1140 | fldln2_0 = "D9ED", | ||
1141 | fldz_0 = "D9EE", | ||
1142 | -- D9EF: unassigned | ||
1143 | |||
1144 | f2xm1_0 = "D9F0", | ||
1145 | fyl2x_0 = "D9F1", | ||
1146 | fptan_0 = "D9F2", | ||
1147 | fpatan_0 = "D9F3", | ||
1148 | fxtract_0 = "D9F4", | ||
1149 | fprem1_0 = "D9F5", | ||
1150 | fdecstp_0 = "D9F6", | ||
1151 | fincstp_0 = "D9F7", | ||
1152 | fprem_0 = "D9F8", | ||
1153 | fyl2xp1_0 = "D9F9", | ||
1154 | fsqrt_0 = "D9FA", | ||
1155 | fsincos_0 = "D9FB", | ||
1156 | frndint_0 = "D9FC", | ||
1157 | fscale_0 = "D9FD", | ||
1158 | fsin_0 = "D9FE", | ||
1159 | fcos_0 = "D9FF", | ||
1160 | |||
1161 | -- SSE, SSE2 | ||
1162 | andnpd_2 = "rmo:660F55rM", | ||
1163 | andnps_2 = "rmo:0F55rM", | ||
1164 | andpd_2 = "rmo:660F54rM", | ||
1165 | andps_2 = "rmo:0F54rM", | ||
1166 | clflush_1 = "x.:0FAE7m", | ||
1167 | cmppd_3 = "rmio:660FC2rMU", | ||
1168 | cmpps_3 = "rmio:0FC2rMU", | ||
1169 | cmpsd_3 = "rrio:F20FC2rMU|rxi/oq:", | ||
1170 | cmpss_3 = "rrio:F30FC2rMU|rxi/od:", | ||
1171 | comisd_2 = "rro:660F2FrM|rx/oq:", | ||
1172 | comiss_2 = "rro:0F2FrM|rx/od:", | ||
1173 | cvtdq2pd_2 = "rro:F30FE6rM|rx/oq:", | ||
1174 | cvtdq2ps_2 = "rmo:0F5BrM", | ||
1175 | cvtpd2dq_2 = "rmo:F20FE6rM", | ||
1176 | cvtpd2ps_2 = "rmo:660F5ArM", | ||
1177 | cvtpi2pd_2 = "rx/oq:660F2ArM", | ||
1178 | cvtpi2ps_2 = "rx/oq:0F2ArM", | ||
1179 | cvtps2dq_2 = "rmo:660F5BrM", | ||
1180 | cvtps2pd_2 = "rro:0F5ArM|rx/oq:", | ||
1181 | cvtsd2si_2 = "rr/do:F20F2DrM|rr/qo:|rx/dq:|rxq:", | ||
1182 | cvtsd2ss_2 = "rro:F20F5ArM|rx/oq:", | ||
1183 | cvtsi2sd_2 = "rm/od:F20F2ArM|rm/oq:F20F2ArXM", | ||
1184 | cvtsi2ss_2 = "rm/od:F30F2ArM|rm/oq:F30F2ArXM", | ||
1185 | cvtss2sd_2 = "rro:F30F5ArM|rx/od:", | ||
1186 | cvtss2si_2 = "rr/do:F20F2CrM|rr/qo:|rxd:|rx/qd:", | ||
1187 | cvttpd2dq_2 = "rmo:660FE6rM", | ||
1188 | cvttps2dq_2 = "rmo:F30F5BrM", | ||
1189 | cvttsd2si_2 = "rr/do:F20F2CrM|rr/qo:|rx/dq:|rxq:", | ||
1190 | cvttss2si_2 = "rr/do:F30F2CrM|rr/qo:|rxd:|rx/qd:", | ||
1191 | ldmxcsr_1 = "xd:0FAE2m", | ||
1192 | lfence_0 = "0FAEE8", | ||
1193 | maskmovdqu_2 = "rro:660FF7rM", | ||
1194 | mfence_0 = "0FAEF0", | ||
1195 | movapd_2 = "rmo:660F28rM|mro:660F29Rm", | ||
1196 | movaps_2 = "rmo:0F28rM|mro:0F29Rm", | ||
1197 | movd_2 = "rm/od:660F6ErM|rm/oq:660F6ErXM|mr/do:660F7ERm|mr/qo:", | ||
1198 | movdqa_2 = "rmo:660F6FrM|mro:660F7FRm", | ||
1199 | movdqu_2 = "rmo:F30F6FrM|mro:F30F7FRm", | ||
1200 | movhlps_2 = "rro:0F12rM", | ||
1201 | movhpd_2 = "rx/oq:660F16rM|xr/qo:n660F17Rm", | ||
1202 | movhps_2 = "rx/oq:0F16rM|xr/qo:n0F17Rm", | ||
1203 | movlhps_2 = "rro:0F16rM", | ||
1204 | movlpd_2 = "rx/oq:660F12rM|xr/qo:n660F13Rm", | ||
1205 | movlps_2 = "rx/oq:0F12rM|xr/qo:n0F13Rm", | ||
1206 | movmskpd_2 = "rr/do:660F50rM", | ||
1207 | movmskps_2 = "rr/do:0F50rM", | ||
1208 | movntdq_2 = "xro:660FE7Rm", | ||
1209 | movnti_2 = "xrqd:0FC3Rm", | ||
1210 | movntpd_2 = "xro:660F2BRm", | ||
1211 | movntps_2 = "xro:0F2BRm", | ||
1212 | movq_2 = "rro:F30F7ErM|rx/oq:|xr/qo:n660FD6Rm", | ||
1213 | movsd_2 = "rro:F20F10rM|rx/oq:|xr/qo:nF20F11Rm", | ||
1214 | movss_2 = "rro:F30F10rM|rx/od:|xr/do:F30F11Rm", | ||
1215 | movupd_2 = "rmo:660F10rM|mro:660F11Rm", | ||
1216 | movups_2 = "rmo:0F10rM|mro:0F11Rm", | ||
1217 | orpd_2 = "rmo:660F56rM", | ||
1218 | orps_2 = "rmo:0F56rM", | ||
1219 | packssdw_2 = "rmo:660F6BrM", | ||
1220 | packsswb_2 = "rmo:660F63rM", | ||
1221 | packuswb_2 = "rmo:660F67rM", | ||
1222 | paddb_2 = "rmo:660FFCrM", | ||
1223 | paddd_2 = "rmo:660FFErM", | ||
1224 | paddq_2 = "rmo:660FD4rM", | ||
1225 | paddsb_2 = "rmo:660FECrM", | ||
1226 | paddsw_2 = "rmo:660FEDrM", | ||
1227 | paddusb_2 = "rmo:660FDCrM", | ||
1228 | paddusw_2 = "rmo:660FDDrM", | ||
1229 | paddw_2 = "rmo:660FFDrM", | ||
1230 | pand_2 = "rmo:660FDBrM", | ||
1231 | pandn_2 = "rmo:660FDFrM", | ||
1232 | pause_0 = "F390", | ||
1233 | pavgb_2 = "rmo:660FE0rM", | ||
1234 | pavgw_2 = "rmo:660FE3rM", | ||
1235 | pcmpeqb_2 = "rmo:660F74rM", | ||
1236 | pcmpeqd_2 = "rmo:660F76rM", | ||
1237 | pcmpeqw_2 = "rmo:660F75rM", | ||
1238 | pcmpgtb_2 = "rmo:660F64rM", | ||
1239 | pcmpgtd_2 = "rmo:660F66rM", | ||
1240 | pcmpgtw_2 = "rmo:660F65rM", | ||
1241 | pextrw_3 = "rri/do:660FC5rMU|xri/wo:660F3A15nrMU", -- Mem op: SSE4.1 only. | ||
1242 | pinsrw_3 = "rri/od:660FC4rMU|rxi/ow:", | ||
1243 | pmaddwd_2 = "rmo:660FF5rM", | ||
1244 | pmaxsw_2 = "rmo:660FEErM", | ||
1245 | pmaxub_2 = "rmo:660FDErM", | ||
1246 | pminsw_2 = "rmo:660FEArM", | ||
1247 | pminub_2 = "rmo:660FDArM", | ||
1248 | pmovmskb_2 = "rr/do:660FD7rM", | ||
1249 | pmulhuw_2 = "rmo:660FE4rM", | ||
1250 | pmulhw_2 = "rmo:660FE5rM", | ||
1251 | pmullw_2 = "rmo:660FD5rM", | ||
1252 | pmuludq_2 = "rmo:660FF4rM", | ||
1253 | por_2 = "rmo:660FEBrM", | ||
1254 | prefetchnta_1 = "xb:n0F180m", | ||
1255 | prefetcht0_1 = "xb:n0F181m", | ||
1256 | prefetcht1_1 = "xb:n0F182m", | ||
1257 | prefetcht2_1 = "xb:n0F183m", | ||
1258 | psadbw_2 = "rmo:660FF6rM", | ||
1259 | pshufd_3 = "rmio:660F70rMU", | ||
1260 | pshufhw_3 = "rmio:F30F70rMU", | ||
1261 | pshuflw_3 = "rmio:F20F70rMU", | ||
1262 | pslld_2 = "rmo:660FF2rM|rio:660F726mU", | ||
1263 | pslldq_2 = "rio:660F737mU", | ||
1264 | psllq_2 = "rmo:660FF3rM|rio:660F736mU", | ||
1265 | psllw_2 = "rmo:660FF1rM|rio:660F716mU", | ||
1266 | psrad_2 = "rmo:660FE2rM|rio:660F724mU", | ||
1267 | psraw_2 = "rmo:660FE1rM|rio:660F714mU", | ||
1268 | psrld_2 = "rmo:660FD2rM|rio:660F722mU", | ||
1269 | psrldq_2 = "rio:660F733mU", | ||
1270 | psrlq_2 = "rmo:660FD3rM|rio:660F732mU", | ||
1271 | psrlw_2 = "rmo:660FD1rM|rio:660F712mU", | ||
1272 | psubb_2 = "rmo:660FF8rM", | ||
1273 | psubd_2 = "rmo:660FFArM", | ||
1274 | psubq_2 = "rmo:660FFBrM", | ||
1275 | psubsb_2 = "rmo:660FE8rM", | ||
1276 | psubsw_2 = "rmo:660FE9rM", | ||
1277 | psubusb_2 = "rmo:660FD8rM", | ||
1278 | psubusw_2 = "rmo:660FD9rM", | ||
1279 | psubw_2 = "rmo:660FF9rM", | ||
1280 | punpckhbw_2 = "rmo:660F68rM", | ||
1281 | punpckhdq_2 = "rmo:660F6ArM", | ||
1282 | punpckhqdq_2 = "rmo:660F6DrM", | ||
1283 | punpckhwd_2 = "rmo:660F69rM", | ||
1284 | punpcklbw_2 = "rmo:660F60rM", | ||
1285 | punpckldq_2 = "rmo:660F62rM", | ||
1286 | punpcklqdq_2 = "rmo:660F6CrM", | ||
1287 | punpcklwd_2 = "rmo:660F61rM", | ||
1288 | pxor_2 = "rmo:660FEFrM", | ||
1289 | rcpps_2 = "rmo:0F53rM", | ||
1290 | rcpss_2 = "rro:F30F53rM|rx/od:", | ||
1291 | rsqrtps_2 = "rmo:0F52rM", | ||
1292 | rsqrtss_2 = "rmo:F30F52rM", | ||
1293 | sfence_0 = "0FAEF8", | ||
1294 | shufpd_3 = "rmio:660FC6rMU", | ||
1295 | shufps_3 = "rmio:0FC6rMU", | ||
1296 | stmxcsr_1 = "xd:0FAE3m", | ||
1297 | ucomisd_2 = "rro:660F2ErM|rx/oq:", | ||
1298 | ucomiss_2 = "rro:0F2ErM|rx/od:", | ||
1299 | unpckhpd_2 = "rmo:660F15rM", | ||
1300 | unpckhps_2 = "rmo:0F15rM", | ||
1301 | unpcklpd_2 = "rmo:660F14rM", | ||
1302 | unpcklps_2 = "rmo:0F14rM", | ||
1303 | xorpd_2 = "rmo:660F57rM", | ||
1304 | xorps_2 = "rmo:0F57rM", | ||
1305 | |||
1306 | -- SSE3 ops | ||
1307 | fisttp_1 = "xw:nDF1m|xd:DB1m|xq:nDD1m", | ||
1308 | addsubpd_2 = "rmo:660FD0rM", | ||
1309 | addsubps_2 = "rmo:F20FD0rM", | ||
1310 | haddpd_2 = "rmo:660F7CrM", | ||
1311 | haddps_2 = "rmo:F20F7CrM", | ||
1312 | hsubpd_2 = "rmo:660F7DrM", | ||
1313 | hsubps_2 = "rmo:F20F7DrM", | ||
1314 | lddqu_2 = "rxo:F20FF0rM", | ||
1315 | movddup_2 = "rmo:F20F12rM", | ||
1316 | movshdup_2 = "rmo:F30F16rM", | ||
1317 | movsldup_2 = "rmo:F30F12rM", | ||
1318 | |||
1319 | -- SSSE3 ops | ||
1320 | pabsb_2 = "rmo:660F381CrM", | ||
1321 | pabsd_2 = "rmo:660F381ErM", | ||
1322 | pabsw_2 = "rmo:660F381DrM", | ||
1323 | palignr_3 = "rmio:660F3A0FrMU", | ||
1324 | phaddd_2 = "rmo:660F3802rM", | ||
1325 | phaddsw_2 = "rmo:660F3803rM", | ||
1326 | phaddw_2 = "rmo:660F3801rM", | ||
1327 | phsubd_2 = "rmo:660F3806rM", | ||
1328 | phsubsw_2 = "rmo:660F3807rM", | ||
1329 | phsubw_2 = "rmo:660F3805rM", | ||
1330 | pmaddubsw_2 = "rmo:660F3804rM", | ||
1331 | pmulhrsw_2 = "rmo:660F380BrM", | ||
1332 | pshufb_2 = "rmo:660F3800rM", | ||
1333 | psignb_2 = "rmo:660F3808rM", | ||
1334 | psignd_2 = "rmo:660F380ArM", | ||
1335 | psignw_2 = "rmo:660F3809rM", | ||
1336 | |||
1337 | -- SSE4.1 ops | ||
1338 | blendpd_3 = "rmio:660F3A0DrMU", | ||
1339 | blendps_3 = "rmio:660F3A0CrMU", | ||
1340 | blendvpd_3 = "rmRo:660F3815rM", | ||
1341 | blendvps_3 = "rmRo:660F3814rM", | ||
1342 | dppd_3 = "rmio:660F3A41rMU", | ||
1343 | dpps_3 = "rmio:660F3A40rMU", | ||
1344 | extractps_3 = "mri/do:660F3A17RmU|rri/qo:660F3A17RXmU", | ||
1345 | insertps_3 = "rrio:660F3A41rMU|rxi/od:", | ||
1346 | movntdqa_2 = "rmo:660F382ArM", | ||
1347 | mpsadbw_3 = "rmio:660F3A42rMU", | ||
1348 | packusdw_2 = "rmo:660F382BrM", | ||
1349 | pblendvb_3 = "rmRo:660F3810rM", | ||
1350 | pblendw_3 = "rmio:660F3A0ErMU", | ||
1351 | pcmpeqq_2 = "rmo:660F3829rM", | ||
1352 | pextrb_3 = "rri/do:660F3A14nRmU|rri/qo:|xri/bo:", | ||
1353 | pextrd_3 = "mri/do:660F3A16RmU", | ||
1354 | pextrq_3 = "mri/qo:660F3A16RmU", | ||
1355 | -- pextrw is SSE2, mem operand is SSE4.1 only | ||
1356 | phminposuw_2 = "rmo:660F3841rM", | ||
1357 | pinsrb_3 = "rri/od:660F3A20nrMU|rxi/ob:", | ||
1358 | pinsrd_3 = "rmi/od:660F3A22rMU", | ||
1359 | pinsrq_3 = "rmi/oq:660F3A22rXMU", | ||
1360 | pmaxsb_2 = "rmo:660F383CrM", | ||
1361 | pmaxsd_2 = "rmo:660F383DrM", | ||
1362 | pmaxud_2 = "rmo:660F383FrM", | ||
1363 | pmaxuw_2 = "rmo:660F383ErM", | ||
1364 | pminsb_2 = "rmo:660F3838rM", | ||
1365 | pminsd_2 = "rmo:660F3839rM", | ||
1366 | pminud_2 = "rmo:660F383BrM", | ||
1367 | pminuw_2 = "rmo:660F383ArM", | ||
1368 | pmovsxbd_2 = "rro:660F3821rM|rx/od:", | ||
1369 | pmovsxbq_2 = "rro:660F3822rM|rx/ow:", | ||
1370 | pmovsxbw_2 = "rro:660F3820rM|rx/oq:", | ||
1371 | pmovsxdq_2 = "rro:660F3825rM|rx/oq:", | ||
1372 | pmovsxwd_2 = "rro:660F3823rM|rx/oq:", | ||
1373 | pmovsxwq_2 = "rro:660F3824rM|rx/od:", | ||
1374 | pmovzxbd_2 = "rro:660F3831rM|rx/od:", | ||
1375 | pmovzxbq_2 = "rro:660F3832rM|rx/ow:", | ||
1376 | pmovzxbw_2 = "rro:660F3830rM|rx/oq:", | ||
1377 | pmovzxdq_2 = "rro:660F3835rM|rx/oq:", | ||
1378 | pmovzxwd_2 = "rro:660F3833rM|rx/oq:", | ||
1379 | pmovzxwq_2 = "rro:660F3834rM|rx/od:", | ||
1380 | pmuldq_2 = "rmo:660F3828rM", | ||
1381 | pmulld_2 = "rmo:660F3840rM", | ||
1382 | ptest_2 = "rmo:660F3817rM", | ||
1383 | roundpd_3 = "rmio:660F3A09rMU", | ||
1384 | roundps_3 = "rmio:660F3A08rMU", | ||
1385 | roundsd_3 = "rrio:660F3A0BrMU|rxi/oq:", | ||
1386 | roundss_3 = "rrio:660F3A0ArMU|rxi/od:", | ||
1387 | |||
1388 | -- SSE4.2 ops | ||
1389 | crc32_2 = "rmqd:F20F38F1rM|rm/dw:66F20F38F1rM|rm/db:F20F38F0rM|rm/qb:", | ||
1390 | pcmpestri_3 = "rmio:660F3A61rMU", | ||
1391 | pcmpestrm_3 = "rmio:660F3A60rMU", | ||
1392 | pcmpgtq_2 = "rmo:660F3837rM", | ||
1393 | pcmpistri_3 = "rmio:660F3A63rMU", | ||
1394 | pcmpistrm_3 = "rmio:660F3A62rMU", | ||
1395 | popcnt_2 = "rmqdw:F30FB8rM", | ||
1396 | |||
1397 | -- SSE4a | ||
1398 | extrq_2 = "rro:660F79rM", | ||
1399 | extrq_3 = "riio:660F780mUU", | ||
1400 | insertq_2 = "rro:F20F79rM", | ||
1401 | insertq_4 = "rriio:F20F78rMUU", | ||
1402 | lzcnt_2 = "rmqdw:F30FBDrM", | ||
1403 | movntsd_2 = "xr/qo:nF20F2BRm", | ||
1404 | movntss_2 = "xr/do:F30F2BRm", | ||
1405 | -- popcnt is also in SSE4.2 | ||
1406 | } | ||
1407 | |||
1408 | ------------------------------------------------------------------------------ | ||
1409 | |||
1410 | -- Arithmetic ops. | ||
1411 | for name,n in pairs{ add = 0, ["or"] = 1, adc = 2, sbb = 3, | ||
1412 | ["and"] = 4, sub = 5, xor = 6, cmp = 7 } do | ||
1413 | local n8 = n * 8 | ||
1414 | map_op[name.."_2"] = format( | ||
1415 | "mr:%02XRm|rm:%02XrM|mI1qdw:81%XmI|mS1qdw:83%XmS|Ri1qdwb:%02Xri|mi1qdwb:81%Xmi", | ||
1416 | 1+n8, 3+n8, n, n, 5+n8, n) | ||
1417 | end | ||
1418 | |||
1419 | -- Shift ops. | ||
1420 | for name,n in pairs{ rol = 0, ror = 1, rcl = 2, rcr = 3, | ||
1421 | shl = 4, shr = 5, sar = 7, sal = 4 } do | ||
1422 | map_op[name.."_2"] = format("m1:D1%Xm|mC1qdwb:D3%Xm|mi:C1%XmU", n, n, n) | ||
1423 | end | ||
1424 | |||
1425 | -- Conditional ops. | ||
1426 | for cc,n in pairs(map_cc) do | ||
1427 | map_op["j"..cc.."_1"] = format("J.:n0F8%XJ", n) -- short: 7%X | ||
1428 | map_op["set"..cc.."_1"] = format("mb:n0F9%X2m", n) | ||
1429 | map_op["cmov"..cc.."_2"] = format("rmqdw:0F4%XrM", n) -- P6+ | ||
1430 | end | ||
1431 | |||
1432 | -- FP arithmetic ops. | ||
1433 | for name,n in pairs{ add = 0, mul = 1, com = 2, comp = 3, | ||
1434 | sub = 4, subr = 5, div = 6, divr = 7 } do | ||
1435 | local nc = 192 + n * 8 | ||
1436 | local nr = nc + (n < 4 and 0 or (n % 2 == 0 and 8 or -8)) | ||
1437 | local fn = "f"..name | ||
1438 | map_op[fn.."_1"] = format("ff:D8%02Xr|xd:D8%Xm|xq:nDC%Xm", nc, n, n) | ||
1439 | if n == 2 or n == 3 then | ||
1440 | map_op[fn.."_2"] = format("Fff:D8%02XR|Fx2d:D8%XM|Fx2q:nDC%XM", nc, n, n) | ||
1441 | else | ||
1442 | map_op[fn.."_2"] = format("Fff:D8%02XR|fFf:DC%02Xr|Fx2d:D8%XM|Fx2q:nDC%XM", nc, nr, n, n) | ||
1443 | map_op[fn.."p_1"] = format("ff:DE%02Xr", nr) | ||
1444 | map_op[fn.."p_2"] = format("fFf:DE%02Xr", nr) | ||
1445 | end | ||
1446 | map_op["fi"..name.."_1"] = format("xd:DA%Xm|xw:nDE%Xm", n, n) | ||
1447 | end | ||
1448 | |||
1449 | -- FP conditional moves. | ||
1450 | for cc,n in pairs{ b=0, e=1, be=2, u=3, nb=4, ne=5, nbe=6, nu=7 } do | ||
1451 | local n4 = n % 4 | ||
1452 | local nc = 56000 + n4 * 8 + (n-n4) * 64 | ||
1453 | map_op["fcmov"..cc.."_1"] = format("ff:%04Xr", nc) -- P6+ | ||
1454 | map_op["fcmov"..cc.."_2"] = format("Fff:%04XR", nc) -- P6+ | ||
1455 | end | ||
1456 | |||
1457 | -- SSE FP arithmetic ops. | ||
1458 | for name,n in pairs{ sqrt = 1, add = 8, mul = 9, | ||
1459 | sub = 12, min = 13, div = 14, max = 15 } do | ||
1460 | map_op[name.."ps_2"] = format("rmo:0F5%XrM", n) | ||
1461 | map_op[name.."ss_2"] = format("rro:F30F5%XrM|rx/od:", n) | ||
1462 | map_op[name.."pd_2"] = format("rmo:660F5%XrM", n) | ||
1463 | map_op[name.."sd_2"] = format("rro:F20F5%XrM|rx/oq:", n) | ||
1464 | end | ||
1465 | |||
1466 | ------------------------------------------------------------------------------ | ||
1467 | |||
1468 | -- Process pattern string. | ||
1469 | local function dopattern(pat, args, sz, op, needrex) | ||
1470 | local digit, addin | ||
1471 | local opcode = 0 | ||
1472 | local szov = sz | ||
1473 | local narg = 1 | ||
1474 | local rex = 0 | ||
1475 | |||
1476 | -- Limit number of section buffer positions used by a single dasm_put(). | ||
1477 | -- A single opcode needs a maximum of 5 positions. | ||
1478 | if secpos+5 > maxsecpos then wflush() end | ||
1479 | |||
1480 | -- Process each character. | ||
1481 | for c in gmatch(pat.."|", ".") do | ||
1482 | if match(c, "%x") then -- Hex digit. | ||
1483 | digit = byte(c) - 48 | ||
1484 | if digit > 48 then digit = digit - 39 | ||
1485 | elseif digit > 16 then digit = digit - 7 end | ||
1486 | opcode = opcode*16 + digit | ||
1487 | addin = nil | ||
1488 | elseif c == "n" then -- Disable operand size mods for opcode. | ||
1489 | szov = nil | ||
1490 | elseif c == "X" then -- Force REX.W. | ||
1491 | rex = 8 | ||
1492 | elseif c == "r" then -- Merge 1st operand regno. into opcode. | ||
1493 | addin = args[1]; opcode = opcode + (addin.reg % 8) | ||
1494 | if narg < 2 then narg = 2 end | ||
1495 | elseif c == "R" then -- Merge 2nd operand regno. into opcode. | ||
1496 | addin = args[2]; opcode = opcode + (addin.reg % 8) | ||
1497 | narg = 3 | ||
1498 | elseif c == "m" or c == "M" then -- Encode ModRM/SIB. | ||
1499 | local s | ||
1500 | if addin then | ||
1501 | s = addin.reg | ||
1502 | opcode = opcode - (s%8) -- Undo regno opcode merge. | ||
1503 | else | ||
1504 | s = opcode % 16 -- Undo last digit. | ||
1505 | opcode = (opcode - s) / 16 | ||
1506 | end | ||
1507 | local nn = c == "m" and 1 or 2 | ||
1508 | local t = args[nn] | ||
1509 | if narg <= nn then narg = nn + 1 end | ||
1510 | if szov == "q" and rex == 0 then rex = rex + 8 end | ||
1511 | if t.reg and t.reg > 7 then rex = rex + 1 end | ||
1512 | if t.xreg and t.xreg > 7 then rex = rex + 2 end | ||
1513 | if s > 7 then rex = rex + 4 end | ||
1514 | if needrex then rex = rex + 16 end | ||
1515 | wputop(szov, opcode, rex); opcode = nil | ||
1516 | local imark = sub(pat, -1) -- Force a mark (ugly). | ||
1517 | -- Put ModRM/SIB with regno/last digit as spare. | ||
1518 | wputmrmsib(t, imark, s, addin and addin.vreg) | ||
1519 | addin = nil | ||
1520 | else | ||
1521 | if opcode then -- Flush opcode. | ||
1522 | if szov == "q" and rex == 0 then rex = rex + 8 end | ||
1523 | if needrex then rex = rex + 16 end | ||
1524 | if addin and addin.reg == -1 then | ||
1525 | wputop(szov, opcode - 7, rex) | ||
1526 | waction("VREG", addin.vreg); wputxb(0) | ||
1527 | else | ||
1528 | if addin and addin.reg > 7 then rex = rex + 1 end | ||
1529 | wputop(szov, opcode, rex) | ||
1530 | end | ||
1531 | opcode = nil | ||
1532 | end | ||
1533 | if c == "|" then break end | ||
1534 | if c == "o" then -- Offset (pure 32 bit displacement). | ||
1535 | wputdarg(args[1].disp); if narg < 2 then narg = 2 end | ||
1536 | elseif c == "O" then | ||
1537 | wputdarg(args[2].disp); narg = 3 | ||
1538 | else | ||
1539 | -- Anything else is an immediate operand. | ||
1540 | local a = args[narg] | ||
1541 | narg = narg + 1 | ||
1542 | local mode, imm = a.mode, a.imm | ||
1543 | if mode == "iJ" and not match("iIJ", c) then | ||
1544 | werror("bad operand size for label") | ||
1545 | end | ||
1546 | if c == "S" then | ||
1547 | wputsbarg(imm) | ||
1548 | elseif c == "U" then | ||
1549 | wputbarg(imm) | ||
1550 | elseif c == "W" then | ||
1551 | wputwarg(imm) | ||
1552 | elseif c == "i" or c == "I" then | ||
1553 | if mode == "iJ" then | ||
1554 | wputlabel("IMM_", imm, 1) | ||
1555 | elseif mode == "iI" and c == "I" then | ||
1556 | waction(sz == "w" and "IMM_WB" or "IMM_DB", imm) | ||
1557 | else | ||
1558 | wputszarg(sz, imm) | ||
1559 | end | ||
1560 | elseif c == "J" then | ||
1561 | if mode == "iPJ" then | ||
1562 | waction("REL_A", imm) -- !x64 (secpos) | ||
1563 | else | ||
1564 | wputlabel("REL_", imm, 2) | ||
1565 | end | ||
1566 | else | ||
1567 | werror("bad char `"..c.."' in pattern `"..pat.."' for `"..op.."'") | ||
1568 | end | ||
1569 | end | ||
1570 | end | ||
1571 | end | ||
1572 | end | ||
1573 | |||
1574 | ------------------------------------------------------------------------------ | ||
1575 | |||
1576 | -- Mapping of operand modes to short names. Suppress output with '#'. | ||
1577 | local map_modename = { | ||
1578 | r = "reg", R = "eax", C = "cl", x = "mem", m = "mrm", i = "imm", | ||
1579 | f = "stx", F = "st0", J = "lbl", ["1"] = "1", | ||
1580 | I = "#", S = "#", O = "#", | ||
1581 | } | ||
1582 | |||
1583 | -- Return a table/string showing all possible operand modes. | ||
1584 | local function templatehelp(template, nparams) | ||
1585 | if nparams == 0 then return "" end | ||
1586 | local t = {} | ||
1587 | for tm in gmatch(template, "[^%|]+") do | ||
1588 | local s = map_modename[sub(tm, 1, 1)] | ||
1589 | s = s..gsub(sub(tm, 2, nparams), ".", function(c) | ||
1590 | return ", "..map_modename[c] | ||
1591 | end) | ||
1592 | if not match(s, "#") then t[#t+1] = s end | ||
1593 | end | ||
1594 | return t | ||
1595 | end | ||
1596 | |||
1597 | -- Match operand modes against mode match part of template. | ||
1598 | local function matchtm(tm, args) | ||
1599 | for i=1,#args do | ||
1600 | if not match(args[i].mode, sub(tm, i, i)) then return end | ||
1601 | end | ||
1602 | return true | ||
1603 | end | ||
1604 | |||
1605 | -- Handle opcodes defined with template strings. | ||
1606 | map_op[".template__"] = function(params, template, nparams) | ||
1607 | if not params then return templatehelp(template, nparams) end | ||
1608 | local args = {} | ||
1609 | |||
1610 | -- Zero-operand opcodes have no match part. | ||
1611 | if #params == 0 then | ||
1612 | dopattern(template, args, "d", params.op, nil) | ||
1613 | return | ||
1614 | end | ||
1615 | |||
1616 | -- Determine common operand size (coerce undefined size) or flag as mixed. | ||
1617 | local sz, szmix, needrex | ||
1618 | for i,p in ipairs(params) do | ||
1619 | args[i] = parseoperand(p) | ||
1620 | local nsz = args[i].opsize | ||
1621 | if nsz then | ||
1622 | if sz and sz ~= nsz then szmix = true else sz = nsz end | ||
1623 | end | ||
1624 | local nrex = args[i].needrex | ||
1625 | if nrex ~= nil then | ||
1626 | if needrex == nil then | ||
1627 | needrex = nrex | ||
1628 | elseif needrex ~= nrex then | ||
1629 | werror("bad mix of byte-addressable registers") | ||
1630 | end | ||
1631 | end | ||
1632 | end | ||
1633 | |||
1634 | -- Try all match:pattern pairs (separated by '|'). | ||
1635 | local gotmatch, lastpat | ||
1636 | for tm in gmatch(template, "[^%|]+") do | ||
1637 | -- Split off size match (starts after mode match) and pattern string. | ||
1638 | local szm, pat = match(tm, "^(.-):(.*)$", #args+1) | ||
1639 | if pat == "" then pat = lastpat else lastpat = pat end | ||
1640 | if matchtm(tm, args) then | ||
1641 | local prefix = sub(szm, 1, 1) | ||
1642 | if prefix == "/" then -- Match both operand sizes. | ||
1643 | if args[1].opsize == sub(szm, 2, 2) and | ||
1644 | args[2].opsize == sub(szm, 3, 3) then | ||
1645 | dopattern(pat, args, sz, params.op, needrex) -- Process pattern. | ||
1646 | return | ||
1647 | end | ||
1648 | else -- Match common operand size. | ||
1649 | local szp = sz | ||
1650 | if szm == "" then szm = x64 and "qdwb" or "dwb" end -- Default sizes. | ||
1651 | if prefix == "1" then szp = args[1].opsize; szmix = nil | ||
1652 | elseif prefix == "2" then szp = args[2].opsize; szmix = nil end | ||
1653 | if not szmix and (prefix == "." or match(szm, szp or "#")) then | ||
1654 | dopattern(pat, args, szp, params.op, needrex) -- Process pattern. | ||
1655 | return | ||
1656 | end | ||
1657 | end | ||
1658 | gotmatch = true | ||
1659 | end | ||
1660 | end | ||
1661 | |||
1662 | local msg = "bad operand mode" | ||
1663 | if gotmatch then | ||
1664 | if szmix then | ||
1665 | msg = "mixed operand size" | ||
1666 | else | ||
1667 | msg = sz and "bad operand size" or "missing operand size" | ||
1668 | end | ||
1669 | end | ||
1670 | |||
1671 | werror(msg.." in `"..opmodestr(params.op, args).."'") | ||
1672 | end | ||
1673 | |||
1674 | ------------------------------------------------------------------------------ | ||
1675 | |||
1676 | -- x64-specific opcode for 64 bit immediates and displacements. | ||
1677 | if x64 then | ||
1678 | function map_op.mov64_2(params) | ||
1679 | if not params then return { "reg, imm", "reg, [disp]", "[disp], reg" } end | ||
1680 | if secpos+2 > maxsecpos then wflush() end | ||
1681 | local opcode, op64, sz, rex | ||
1682 | local op64 = match(params[1], "^%[%s*(.-)%s*%]$") | ||
1683 | if op64 then | ||
1684 | local a = parseoperand(params[2]) | ||
1685 | if a.mode ~= "rmR" then werror("bad operand mode") end | ||
1686 | sz = a.opsize | ||
1687 | rex = sz == "q" and 8 or 0 | ||
1688 | opcode = 0xa3 | ||
1689 | else | ||
1690 | op64 = match(params[2], "^%[%s*(.-)%s*%]$") | ||
1691 | local a = parseoperand(params[1]) | ||
1692 | if op64 then | ||
1693 | if a.mode ~= "rmR" then werror("bad operand mode") end | ||
1694 | sz = a.opsize | ||
1695 | rex = sz == "q" and 8 or 0 | ||
1696 | opcode = 0xa1 | ||
1697 | else | ||
1698 | if sub(a.mode, 1, 1) ~= "r" or a.opsize ~= "q" then | ||
1699 | werror("bad operand mode") | ||
1700 | end | ||
1701 | op64 = params[2] | ||
1702 | opcode = 0xb8 + (a.reg%8) -- !x64: no VREG support. | ||
1703 | rex = a.reg > 7 and 9 or 8 | ||
1704 | end | ||
1705 | end | ||
1706 | wputop(sz, opcode, rex) | ||
1707 | waction("IMM_D", format("(unsigned int)(%s)", op64)) | ||
1708 | waction("IMM_D", format("(unsigned int)((%s)>>32)", op64)) | ||
1709 | end | ||
1710 | end | ||
1711 | |||
1712 | ------------------------------------------------------------------------------ | ||
1713 | |||
1714 | -- Pseudo-opcodes for data storage. | ||
1715 | local function op_data(params) | ||
1716 | if not params then return "imm..." end | ||
1717 | local sz = sub(params.op, 2, 2) | ||
1718 | if sz == "a" then sz = addrsize end | ||
1719 | for _,p in ipairs(params) do | ||
1720 | local a = parseoperand(p) | ||
1721 | if sub(a.mode, 1, 1) ~= "i" or (a.opsize and a.opsize ~= sz) then | ||
1722 | werror("bad mode or size in `"..p.."'") | ||
1723 | end | ||
1724 | if a.mode == "iJ" then | ||
1725 | wputlabel("IMM_", a.imm, 1) | ||
1726 | else | ||
1727 | wputszarg(sz, a.imm) | ||
1728 | end | ||
1729 | if secpos+2 > maxsecpos then wflush() end | ||
1730 | end | ||
1731 | end | ||
1732 | |||
1733 | map_op[".byte_*"] = op_data | ||
1734 | map_op[".sbyte_*"] = op_data | ||
1735 | map_op[".word_*"] = op_data | ||
1736 | map_op[".dword_*"] = op_data | ||
1737 | map_op[".aword_*"] = op_data | ||
1738 | |||
1739 | ------------------------------------------------------------------------------ | ||
1740 | |||
1741 | -- Pseudo-opcode to mark the position where the action list is to be emitted. | ||
1742 | map_op[".actionlist_1"] = function(params) | ||
1743 | if not params then return "cvar" end | ||
1744 | local name = params[1] -- No syntax check. You get to keep the pieces. | ||
1745 | wline(function(out) writeactions(out, name) end) | ||
1746 | end | ||
1747 | |||
1748 | -- Pseudo-opcode to mark the position where the global enum is to be emitted. | ||
1749 | map_op[".globals_1"] = function(params) | ||
1750 | if not params then return "prefix" end | ||
1751 | local prefix = params[1] -- No syntax check. You get to keep the pieces. | ||
1752 | wline(function(out) writeglobals(out, prefix) end) | ||
1753 | end | ||
1754 | |||
1755 | -- Pseudo-opcode to mark the position where the global names are to be emitted. | ||
1756 | map_op[".globalnames_1"] = function(params) | ||
1757 | if not params then return "cvar" end | ||
1758 | local name = params[1] -- No syntax check. You get to keep the pieces. | ||
1759 | wline(function(out) writeglobalnames(out, name) end) | ||
1760 | end | ||
1761 | |||
1762 | -- Pseudo-opcode to mark the position where the extern names are to be emitted. | ||
1763 | map_op[".externnames_1"] = function(params) | ||
1764 | if not params then return "cvar" end | ||
1765 | local name = params[1] -- No syntax check. You get to keep the pieces. | ||
1766 | wline(function(out) writeexternnames(out, name) end) | ||
1767 | end | ||
1768 | |||
1769 | ------------------------------------------------------------------------------ | ||
1770 | |||
1771 | -- Label pseudo-opcode (converted from trailing colon form). | ||
1772 | map_op[".label_2"] = function(params) | ||
1773 | if not params then return "[1-9] | ->global | =>pcexpr [, addr]" end | ||
1774 | if secpos+2 > maxsecpos then wflush() end | ||
1775 | local a = parseoperand(params[1]) | ||
1776 | local mode, imm = a.mode, a.imm | ||
1777 | if type(imm) == "number" and (mode == "iJ" or (imm >= 1 and imm <= 9)) then | ||
1778 | -- Local label (1: ... 9:) or global label (->global:). | ||
1779 | waction("LABEL_LG", nil, 1) | ||
1780 | wputxb(imm) | ||
1781 | elseif mode == "iJ" then | ||
1782 | -- PC label (=>pcexpr:). | ||
1783 | waction("LABEL_PC", imm) | ||
1784 | else | ||
1785 | werror("bad label definition") | ||
1786 | end | ||
1787 | -- SETLABEL must immediately follow LABEL_LG/LABEL_PC. | ||
1788 | local addr = params[2] | ||
1789 | if addr then | ||
1790 | local a = parseoperand(addr) | ||
1791 | if a.mode == "iPJ" then | ||
1792 | waction("SETLABEL", a.imm) | ||
1793 | else | ||
1794 | werror("bad label assignment") | ||
1795 | end | ||
1796 | end | ||
1797 | end | ||
1798 | map_op[".label_1"] = map_op[".label_2"] | ||
1799 | |||
1800 | ------------------------------------------------------------------------------ | ||
1801 | |||
1802 | -- Alignment pseudo-opcode. | ||
1803 | map_op[".align_1"] = function(params) | ||
1804 | if not params then return "numpow2" end | ||
1805 | if secpos+1 > maxsecpos then wflush() end | ||
1806 | local align = tonumber(params[1]) or map_opsizenum[map_opsize[params[1]]] | ||
1807 | if align then | ||
1808 | local x = align | ||
1809 | -- Must be a power of 2 in the range (2 ... 256). | ||
1810 | for i=1,8 do | ||
1811 | x = x / 2 | ||
1812 | if x == 1 then | ||
1813 | waction("ALIGN", nil, 1) | ||
1814 | wputxb(align-1) -- Action byte is 2**n-1. | ||
1815 | return | ||
1816 | end | ||
1817 | end | ||
1818 | end | ||
1819 | werror("bad alignment") | ||
1820 | end | ||
1821 | |||
1822 | -- Spacing pseudo-opcode. | ||
1823 | map_op[".space_2"] = function(params) | ||
1824 | if not params then return "num [, filler]" end | ||
1825 | if secpos+1 > maxsecpos then wflush() end | ||
1826 | waction("SPACE", params[1]) | ||
1827 | local fill = params[2] | ||
1828 | if fill then | ||
1829 | fill = tonumber(fill) | ||
1830 | if not fill or fill < 0 or fill > 255 then werror("bad filler") end | ||
1831 | end | ||
1832 | wputxb(fill or 0) | ||
1833 | end | ||
1834 | map_op[".space_1"] = map_op[".space_2"] | ||
1835 | |||
1836 | ------------------------------------------------------------------------------ | ||
1837 | |||
1838 | -- Pseudo-opcode for (primitive) type definitions (map to C types). | ||
1839 | map_op[".type_3"] = function(params, nparams) | ||
1840 | if not params then | ||
1841 | return nparams == 2 and "name, ctype" or "name, ctype, reg" | ||
1842 | end | ||
1843 | local name, ctype, reg = params[1], params[2], params[3] | ||
1844 | if not match(name, "^[%a_][%w_]*$") then | ||
1845 | werror("bad type name `"..name.."'") | ||
1846 | end | ||
1847 | local tp = map_type[name] | ||
1848 | if tp then | ||
1849 | werror("duplicate type `"..name.."'") | ||
1850 | end | ||
1851 | if reg and not map_reg_valid_base[reg] then | ||
1852 | werror("bad base register `"..(map_reg_rev[reg] or reg).."'") | ||
1853 | end | ||
1854 | -- Add #type to defines. A bit unclean to put it in map_archdef. | ||
1855 | map_archdef["#"..name] = "sizeof("..ctype..")" | ||
1856 | -- Add new type and emit shortcut define. | ||
1857 | local num = ctypenum + 1 | ||
1858 | map_type[name] = { | ||
1859 | ctype = ctype, | ||
1860 | ctypefmt = format("Dt%X(%%s)", num), | ||
1861 | reg = reg, | ||
1862 | } | ||
1863 | wline(format("#define Dt%X(_V) (int)(ptrdiff_t)&(((%s *)0)_V)", num, ctype)) | ||
1864 | ctypenum = num | ||
1865 | end | ||
1866 | map_op[".type_2"] = map_op[".type_3"] | ||
1867 | |||
1868 | -- Dump type definitions. | ||
1869 | local function dumptypes(out, lvl) | ||
1870 | local t = {} | ||
1871 | for name in pairs(map_type) do t[#t+1] = name end | ||
1872 | sort(t) | ||
1873 | out:write("Type definitions:\n") | ||
1874 | for _,name in ipairs(t) do | ||
1875 | local tp = map_type[name] | ||
1876 | local reg = tp.reg and map_reg_rev[tp.reg] or "" | ||
1877 | out:write(format(" %-20s %-20s %s\n", name, tp.ctype, reg)) | ||
1878 | end | ||
1879 | out:write("\n") | ||
1880 | end | ||
1881 | |||
1882 | ------------------------------------------------------------------------------ | ||
1883 | |||
1884 | -- Set the current section. | ||
1885 | function _M.section(num) | ||
1886 | waction("SECTION") | ||
1887 | wputxb(num) | ||
1888 | wflush(true) -- SECTION is a terminal action. | ||
1889 | end | ||
1890 | |||
1891 | ------------------------------------------------------------------------------ | ||
1892 | |||
1893 | -- Dump architecture description. | ||
1894 | function _M.dumparch(out) | ||
1895 | out:write(format("DynASM %s version %s, released %s\n\n", | ||
1896 | _info.arch, _info.version, _info.release)) | ||
1897 | dumpregs(out) | ||
1898 | dumpactions(out) | ||
1899 | end | ||
1900 | |||
1901 | -- Dump all user defined elements. | ||
1902 | function _M.dumpdef(out, lvl) | ||
1903 | dumptypes(out, lvl) | ||
1904 | dumpglobals(out, lvl) | ||
1905 | dumpexterns(out, lvl) | ||
1906 | end | ||
1907 | |||
1908 | ------------------------------------------------------------------------------ | ||
1909 | |||
1910 | -- Pass callbacks from/to the DynASM core. | ||
1911 | function _M.passcb(wl, we, wf, ww) | ||
1912 | wline, werror, wfatal, wwarn = wl, we, wf, ww | ||
1913 | return wflush | ||
1914 | end | ||
1915 | |||
1916 | -- Setup the arch-specific module. | ||
1917 | function _M.setup(arch, opt) | ||
1918 | g_arch, g_opt = arch, opt | ||
1919 | end | ||
1920 | |||
1921 | -- Merge the core maps and the arch-specific maps. | ||
1922 | function _M.mergemaps(map_coreop, map_def) | ||
1923 | setmetatable(map_op, { __index = map_coreop }) | ||
1924 | setmetatable(map_def, { __index = map_archdef }) | ||
1925 | return map_op, map_def | ||
1926 | end | ||
1927 | |||
1928 | return _M | ||
1929 | |||
1930 | ------------------------------------------------------------------------------ | ||
1931 | |||
diff --git a/libraries/luajit-2.0/dynasm/dynasm.lua b/libraries/luajit-2.0/dynasm/dynasm.lua new file mode 100644 index 0000000..8ff9851 --- /dev/null +++ b/libraries/luajit-2.0/dynasm/dynasm.lua | |||
@@ -0,0 +1,1076 @@ | |||
1 | ------------------------------------------------------------------------------ | ||
2 | -- DynASM. A dynamic assembler for code generation engines. | ||
3 | -- Originally designed and implemented for LuaJIT. | ||
4 | -- | ||
5 | -- Copyright (C) 2005-2011 Mike Pall. All rights reserved. | ||
6 | -- See below for full copyright notice. | ||
7 | ------------------------------------------------------------------------------ | ||
8 | |||
9 | -- Application information. | ||
10 | local _info = { | ||
11 | name = "DynASM", | ||
12 | description = "A dynamic assembler for code generation engines", | ||
13 | version = "1.3.0", | ||
14 | vernum = 10300, | ||
15 | release = "2011-05-05", | ||
16 | author = "Mike Pall", | ||
17 | url = "http://luajit.org/dynasm.html", | ||
18 | license = "MIT", | ||
19 | copyright = [[ | ||
20 | Copyright (C) 2005-2011 Mike Pall. All rights reserved. | ||
21 | |||
22 | Permission is hereby granted, free of charge, to any person obtaining | ||
23 | a copy of this software and associated documentation files (the | ||
24 | "Software"), to deal in the Software without restriction, including | ||
25 | without limitation the rights to use, copy, modify, merge, publish, | ||
26 | distribute, sublicense, and/or sell copies of the Software, and to | ||
27 | permit persons to whom the Software is furnished to do so, subject to | ||
28 | the following conditions: | ||
29 | |||
30 | The above copyright notice and this permission notice shall be | ||
31 | included in all copies or substantial portions of the Software. | ||
32 | |||
33 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
34 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
35 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | ||
36 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | ||
37 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||
38 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||
39 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
40 | |||
41 | [ MIT license: http://www.opensource.org/licenses/mit-license.php ] | ||
42 | ]], | ||
43 | } | ||
44 | |||
45 | -- Cache library functions. | ||
46 | local type, pairs, ipairs = type, pairs, ipairs | ||
47 | local pcall, error, assert = pcall, error, assert | ||
48 | local _s = string | ||
49 | local sub, match, gmatch, gsub = _s.sub, _s.match, _s.gmatch, _s.gsub | ||
50 | local format, rep, upper = _s.format, _s.rep, _s.upper | ||
51 | local _t = table | ||
52 | local insert, remove, concat, sort = _t.insert, _t.remove, _t.concat, _t.sort | ||
53 | local exit = os.exit | ||
54 | local io = io | ||
55 | local stdin, stdout, stderr = io.stdin, io.stdout, io.stderr | ||
56 | |||
57 | ------------------------------------------------------------------------------ | ||
58 | |||
59 | -- Program options. | ||
60 | local g_opt = {} | ||
61 | |||
62 | -- Global state for current file. | ||
63 | local g_fname, g_curline, g_indent, g_lineno, g_synclineno, g_arch | ||
64 | local g_errcount = 0 | ||
65 | |||
66 | -- Write buffer for output file. | ||
67 | local g_wbuffer, g_capbuffer | ||
68 | |||
69 | ------------------------------------------------------------------------------ | ||
70 | |||
71 | -- Write an output line (or callback function) to the buffer. | ||
72 | local function wline(line, needindent) | ||
73 | local buf = g_capbuffer or g_wbuffer | ||
74 | buf[#buf+1] = needindent and g_indent..line or line | ||
75 | g_synclineno = g_synclineno + 1 | ||
76 | end | ||
77 | |||
78 | -- Write assembler line as a comment, if requestd. | ||
79 | local function wcomment(aline) | ||
80 | if g_opt.comment then | ||
81 | wline(g_opt.comment..aline..g_opt.endcomment, true) | ||
82 | end | ||
83 | end | ||
84 | |||
85 | -- Resync CPP line numbers. | ||
86 | local function wsync() | ||
87 | if g_synclineno ~= g_lineno and g_opt.cpp then | ||
88 | wline("# "..g_lineno..' "'..g_fname..'"') | ||
89 | g_synclineno = g_lineno | ||
90 | end | ||
91 | end | ||
92 | |||
93 | -- Dummy action flush function. Replaced with arch-specific function later. | ||
94 | local function wflush(term) | ||
95 | end | ||
96 | |||
97 | -- Dump all buffered output lines. | ||
98 | local function wdumplines(out, buf) | ||
99 | for _,line in ipairs(buf) do | ||
100 | if type(line) == "string" then | ||
101 | assert(out:write(line, "\n")) | ||
102 | else | ||
103 | -- Special callback to dynamically insert lines after end of processing. | ||
104 | line(out) | ||
105 | end | ||
106 | end | ||
107 | end | ||
108 | |||
109 | ------------------------------------------------------------------------------ | ||
110 | |||
111 | -- Emit an error. Processing continues with next statement. | ||
112 | local function werror(msg) | ||
113 | error(format("%s:%s: error: %s:\n%s", g_fname, g_lineno, msg, g_curline), 0) | ||
114 | end | ||
115 | |||
116 | -- Emit a fatal error. Processing stops. | ||
117 | local function wfatal(msg) | ||
118 | g_errcount = "fatal" | ||
119 | werror(msg) | ||
120 | end | ||
121 | |||
122 | -- Print a warning. Processing continues. | ||
123 | local function wwarn(msg) | ||
124 | stderr:write(format("%s:%s: warning: %s:\n%s\n", | ||
125 | g_fname, g_lineno, msg, g_curline)) | ||
126 | end | ||
127 | |||
128 | -- Print caught error message. But suppress excessive errors. | ||
129 | local function wprinterr(...) | ||
130 | if type(g_errcount) == "number" then | ||
131 | -- Regular error. | ||
132 | g_errcount = g_errcount + 1 | ||
133 | if g_errcount < 21 then -- Seems to be a reasonable limit. | ||
134 | stderr:write(...) | ||
135 | elseif g_errcount == 21 then | ||
136 | stderr:write(g_fname, | ||
137 | ":*: warning: too many errors (suppressed further messages).\n") | ||
138 | end | ||
139 | else | ||
140 | -- Fatal error. | ||
141 | stderr:write(...) | ||
142 | return true -- Stop processing. | ||
143 | end | ||
144 | end | ||
145 | |||
146 | ------------------------------------------------------------------------------ | ||
147 | |||
148 | -- Map holding all option handlers. | ||
149 | local opt_map = {} | ||
150 | local opt_current | ||
151 | |||
152 | -- Print error and exit with error status. | ||
153 | local function opterror(...) | ||
154 | stderr:write("dynasm.lua: ERROR: ", ...) | ||
155 | stderr:write("\n") | ||
156 | exit(1) | ||
157 | end | ||
158 | |||
159 | -- Get option parameter. | ||
160 | local function optparam(args) | ||
161 | local argn = args.argn | ||
162 | local p = args[argn] | ||
163 | if not p then | ||
164 | opterror("missing parameter for option `", opt_current, "'.") | ||
165 | end | ||
166 | args.argn = argn + 1 | ||
167 | return p | ||
168 | end | ||
169 | |||
170 | ------------------------------------------------------------------------------ | ||
171 | |||
172 | -- Core pseudo-opcodes. | ||
173 | local map_coreop = {} | ||
174 | -- Dummy opcode map. Replaced by arch-specific map. | ||
175 | local map_op = {} | ||
176 | |||
177 | -- Forward declarations. | ||
178 | local dostmt | ||
179 | local readfile | ||
180 | |||
181 | ------------------------------------------------------------------------------ | ||
182 | |||
183 | -- Map for defines (initially empty, chains to arch-specific map). | ||
184 | local map_def = {} | ||
185 | |||
186 | -- Pseudo-opcode to define a substitution. | ||
187 | map_coreop[".define_2"] = function(params, nparams) | ||
188 | if not params then return nparams == 1 and "name" or "name, subst" end | ||
189 | local name, def = params[1], params[2] or "1" | ||
190 | if not match(name, "^[%a_][%w_]*$") then werror("bad or duplicate define") end | ||
191 | map_def[name] = def | ||
192 | end | ||
193 | map_coreop[".define_1"] = map_coreop[".define_2"] | ||
194 | |||
195 | -- Define a substitution on the command line. | ||
196 | function opt_map.D(args) | ||
197 | local namesubst = optparam(args) | ||
198 | local name, subst = match(namesubst, "^([%a_][%w_]*)=(.*)$") | ||
199 | if name then | ||
200 | map_def[name] = subst | ||
201 | elseif match(namesubst, "^[%a_][%w_]*$") then | ||
202 | map_def[namesubst] = "1" | ||
203 | else | ||
204 | opterror("bad define") | ||
205 | end | ||
206 | end | ||
207 | |||
208 | -- Undefine a substitution on the command line. | ||
209 | function opt_map.U(args) | ||
210 | local name = optparam(args) | ||
211 | if match(name, "^[%a_][%w_]*$") then | ||
212 | map_def[name] = nil | ||
213 | else | ||
214 | opterror("bad define") | ||
215 | end | ||
216 | end | ||
217 | |||
218 | -- Helper for definesubst. | ||
219 | local gotsubst | ||
220 | |||
221 | local function definesubst_one(word) | ||
222 | local subst = map_def[word] | ||
223 | if subst then gotsubst = word; return subst else return word end | ||
224 | end | ||
225 | |||
226 | -- Iteratively substitute defines. | ||
227 | local function definesubst(stmt) | ||
228 | -- Limit number of iterations. | ||
229 | for i=1,100 do | ||
230 | gotsubst = false | ||
231 | stmt = gsub(stmt, "#?[%w_]+", definesubst_one) | ||
232 | if not gotsubst then break end | ||
233 | end | ||
234 | if gotsubst then wfatal("recursive define involving `"..gotsubst.."'") end | ||
235 | return stmt | ||
236 | end | ||
237 | |||
238 | -- Dump all defines. | ||
239 | local function dumpdefines(out, lvl) | ||
240 | local t = {} | ||
241 | for name in pairs(map_def) do | ||
242 | t[#t+1] = name | ||
243 | end | ||
244 | sort(t) | ||
245 | out:write("Defines:\n") | ||
246 | for _,name in ipairs(t) do | ||
247 | local subst = map_def[name] | ||
248 | if g_arch then subst = g_arch.revdef(subst) end | ||
249 | out:write(format(" %-20s %s\n", name, subst)) | ||
250 | end | ||
251 | out:write("\n") | ||
252 | end | ||
253 | |||
254 | ------------------------------------------------------------------------------ | ||
255 | |||
256 | -- Support variables for conditional assembly. | ||
257 | local condlevel = 0 | ||
258 | local condstack = {} | ||
259 | |||
260 | -- Evaluate condition with a Lua expression. Substitutions already performed. | ||
261 | local function cond_eval(cond) | ||
262 | local func, err = loadstring("return "..cond) | ||
263 | if func then | ||
264 | setfenv(func, {}) -- No globals. All unknown identifiers evaluate to nil. | ||
265 | local ok, res = pcall(func) | ||
266 | if ok then | ||
267 | if res == 0 then return false end -- Oh well. | ||
268 | return not not res | ||
269 | end | ||
270 | err = res | ||
271 | end | ||
272 | wfatal("bad condition: "..err) | ||
273 | end | ||
274 | |||
275 | -- Skip statements until next conditional pseudo-opcode at the same level. | ||
276 | local function stmtskip() | ||
277 | local dostmt_save = dostmt | ||
278 | local lvl = 0 | ||
279 | dostmt = function(stmt) | ||
280 | local op = match(stmt, "^%s*(%S+)") | ||
281 | if op == ".if" then | ||
282 | lvl = lvl + 1 | ||
283 | elseif lvl ~= 0 then | ||
284 | if op == ".endif" then lvl = lvl - 1 end | ||
285 | elseif op == ".elif" or op == ".else" or op == ".endif" then | ||
286 | dostmt = dostmt_save | ||
287 | dostmt(stmt) | ||
288 | end | ||
289 | end | ||
290 | end | ||
291 | |||
292 | -- Pseudo-opcodes for conditional assembly. | ||
293 | map_coreop[".if_1"] = function(params) | ||
294 | if not params then return "condition" end | ||
295 | local lvl = condlevel + 1 | ||
296 | local res = cond_eval(params[1]) | ||
297 | condlevel = lvl | ||
298 | condstack[lvl] = res | ||
299 | if not res then stmtskip() end | ||
300 | end | ||
301 | |||
302 | map_coreop[".elif_1"] = function(params) | ||
303 | if not params then return "condition" end | ||
304 | if condlevel == 0 then wfatal(".elif without .if") end | ||
305 | local lvl = condlevel | ||
306 | local res = condstack[lvl] | ||
307 | if res then | ||
308 | if res == "else" then wfatal(".elif after .else") end | ||
309 | else | ||
310 | res = cond_eval(params[1]) | ||
311 | if res then | ||
312 | condstack[lvl] = res | ||
313 | return | ||
314 | end | ||
315 | end | ||
316 | stmtskip() | ||
317 | end | ||
318 | |||
319 | map_coreop[".else_0"] = function(params) | ||
320 | if condlevel == 0 then wfatal(".else without .if") end | ||
321 | local lvl = condlevel | ||
322 | local res = condstack[lvl] | ||
323 | condstack[lvl] = "else" | ||
324 | if res then | ||
325 | if res == "else" then wfatal(".else after .else") end | ||
326 | stmtskip() | ||
327 | end | ||
328 | end | ||
329 | |||
330 | map_coreop[".endif_0"] = function(params) | ||
331 | local lvl = condlevel | ||
332 | if lvl == 0 then wfatal(".endif without .if") end | ||
333 | condlevel = lvl - 1 | ||
334 | end | ||
335 | |||
336 | -- Check for unfinished conditionals. | ||
337 | local function checkconds() | ||
338 | if g_errcount ~= "fatal" and condlevel ~= 0 then | ||
339 | wprinterr(g_fname, ":*: error: unbalanced conditional\n") | ||
340 | end | ||
341 | end | ||
342 | |||
343 | ------------------------------------------------------------------------------ | ||
344 | |||
345 | -- Search for a file in the given path and open it for reading. | ||
346 | local function pathopen(path, name) | ||
347 | local dirsep = match(package.path, "\\") and "\\" or "/" | ||
348 | for _,p in ipairs(path) do | ||
349 | local fullname = p == "" and name or p..dirsep..name | ||
350 | local fin = io.open(fullname, "r") | ||
351 | if fin then | ||
352 | g_fname = fullname | ||
353 | return fin | ||
354 | end | ||
355 | end | ||
356 | end | ||
357 | |||
358 | -- Include a file. | ||
359 | map_coreop[".include_1"] = function(params) | ||
360 | if not params then return "filename" end | ||
361 | local name = params[1] | ||
362 | -- Save state. Ugly, I know. but upvalues are fast. | ||
363 | local gf, gl, gcl, gi = g_fname, g_lineno, g_curline, g_indent | ||
364 | -- Read the included file. | ||
365 | local fatal = readfile(pathopen(g_opt.include, name) or | ||
366 | wfatal("include file `"..name.."' not found")) | ||
367 | -- Restore state. | ||
368 | g_synclineno = -1 | ||
369 | g_fname, g_lineno, g_curline, g_indent = gf, gl, gcl, gi | ||
370 | if fatal then wfatal("in include file") end | ||
371 | end | ||
372 | |||
373 | -- Make .include and conditionals initially available, too. | ||
374 | map_op[".include_1"] = map_coreop[".include_1"] | ||
375 | map_op[".if_1"] = map_coreop[".if_1"] | ||
376 | map_op[".elif_1"] = map_coreop[".elif_1"] | ||
377 | map_op[".else_0"] = map_coreop[".else_0"] | ||
378 | map_op[".endif_0"] = map_coreop[".endif_0"] | ||
379 | |||
380 | ------------------------------------------------------------------------------ | ||
381 | |||
382 | -- Support variables for macros. | ||
383 | local mac_capture, mac_lineno, mac_name | ||
384 | local mac_active = {} | ||
385 | local mac_list = {} | ||
386 | |||
387 | -- Pseudo-opcode to define a macro. | ||
388 | map_coreop[".macro_*"] = function(mparams) | ||
389 | if not mparams then return "name [, params...]" end | ||
390 | -- Split off and validate macro name. | ||
391 | local name = remove(mparams, 1) | ||
392 | if not name then werror("missing macro name") end | ||
393 | if not (match(name, "^[%a_][%w_%.]*$") or match(name, "^%.[%w_%.]+$")) then | ||
394 | wfatal("bad macro name `"..name.."'") | ||
395 | end | ||
396 | -- Validate macro parameter names. | ||
397 | local mdup = {} | ||
398 | for _,mp in ipairs(mparams) do | ||
399 | if not match(mp, "^[%a_][%w_]*$") then | ||
400 | wfatal("bad macro parameter name `"..mp.."'") | ||
401 | end | ||
402 | if mdup[mp] then wfatal("duplicate macro parameter name `"..mp.."'") end | ||
403 | mdup[mp] = true | ||
404 | end | ||
405 | -- Check for duplicate or recursive macro definitions. | ||
406 | local opname = name.."_"..#mparams | ||
407 | if map_op[opname] or map_op[name.."_*"] then | ||
408 | wfatal("duplicate macro `"..name.."' ("..#mparams.." parameters)") | ||
409 | end | ||
410 | if mac_capture then wfatal("recursive macro definition") end | ||
411 | |||
412 | -- Enable statement capture. | ||
413 | local lines = {} | ||
414 | mac_lineno = g_lineno | ||
415 | mac_name = name | ||
416 | mac_capture = function(stmt) -- Statement capture function. | ||
417 | -- Stop macro definition with .endmacro pseudo-opcode. | ||
418 | if not match(stmt, "^%s*.endmacro%s*$") then | ||
419 | lines[#lines+1] = stmt | ||
420 | return | ||
421 | end | ||
422 | mac_capture = nil | ||
423 | mac_lineno = nil | ||
424 | mac_name = nil | ||
425 | mac_list[#mac_list+1] = opname | ||
426 | -- Add macro-op definition. | ||
427 | map_op[opname] = function(params) | ||
428 | if not params then return mparams, lines end | ||
429 | -- Protect against recursive macro invocation. | ||
430 | if mac_active[opname] then wfatal("recursive macro invocation") end | ||
431 | mac_active[opname] = true | ||
432 | -- Setup substitution map. | ||
433 | local subst = {} | ||
434 | for i,mp in ipairs(mparams) do subst[mp] = params[i] end | ||
435 | local mcom | ||
436 | if g_opt.maccomment and g_opt.comment then | ||
437 | mcom = " MACRO "..name.." ("..#mparams..")" | ||
438 | wcomment("{"..mcom) | ||
439 | end | ||
440 | -- Loop through all captured statements | ||
441 | for _,stmt in ipairs(lines) do | ||
442 | -- Substitute macro parameters. | ||
443 | local st = gsub(stmt, "[%w_]+", subst) | ||
444 | st = definesubst(st) | ||
445 | st = gsub(st, "%s*%.%.%s*", "") -- Token paste a..b. | ||
446 | if mcom and sub(st, 1, 1) ~= "|" then wcomment(st) end | ||
447 | -- Emit statement. Use a protected call for better diagnostics. | ||
448 | local ok, err = pcall(dostmt, st) | ||
449 | if not ok then | ||
450 | -- Add the captured statement to the error. | ||
451 | wprinterr(err, "\n", g_indent, "| ", stmt, | ||
452 | "\t[MACRO ", name, " (", #mparams, ")]\n") | ||
453 | end | ||
454 | end | ||
455 | if mcom then wcomment("}"..mcom) end | ||
456 | mac_active[opname] = nil | ||
457 | end | ||
458 | end | ||
459 | end | ||
460 | |||
461 | -- An .endmacro pseudo-opcode outside of a macro definition is an error. | ||
462 | map_coreop[".endmacro_0"] = function(params) | ||
463 | wfatal(".endmacro without .macro") | ||
464 | end | ||
465 | |||
466 | -- Dump all macros and their contents (with -PP only). | ||
467 | local function dumpmacros(out, lvl) | ||
468 | sort(mac_list) | ||
469 | out:write("Macros:\n") | ||
470 | for _,opname in ipairs(mac_list) do | ||
471 | local name = sub(opname, 1, -3) | ||
472 | local params, lines = map_op[opname]() | ||
473 | out:write(format(" %-20s %s\n", name, concat(params, ", "))) | ||
474 | if lvl > 1 then | ||
475 | for _,line in ipairs(lines) do | ||
476 | out:write(" |", line, "\n") | ||
477 | end | ||
478 | out:write("\n") | ||
479 | end | ||
480 | end | ||
481 | out:write("\n") | ||
482 | end | ||
483 | |||
484 | -- Check for unfinished macro definitions. | ||
485 | local function checkmacros() | ||
486 | if mac_capture then | ||
487 | wprinterr(g_fname, ":", mac_lineno, | ||
488 | ": error: unfinished .macro `", mac_name ,"'\n") | ||
489 | end | ||
490 | end | ||
491 | |||
492 | ------------------------------------------------------------------------------ | ||
493 | |||
494 | -- Support variables for captures. | ||
495 | local cap_lineno, cap_name | ||
496 | local cap_buffers = {} | ||
497 | local cap_used = {} | ||
498 | |||
499 | -- Start a capture. | ||
500 | map_coreop[".capture_1"] = function(params) | ||
501 | if not params then return "name" end | ||
502 | wflush() | ||
503 | local name = params[1] | ||
504 | if not match(name, "^[%a_][%w_]*$") then | ||
505 | wfatal("bad capture name `"..name.."'") | ||
506 | end | ||
507 | if cap_name then | ||
508 | wfatal("already capturing to `"..cap_name.."' since line "..cap_lineno) | ||
509 | end | ||
510 | cap_name = name | ||
511 | cap_lineno = g_lineno | ||
512 | -- Create or continue a capture buffer and start the output line capture. | ||
513 | local buf = cap_buffers[name] | ||
514 | if not buf then buf = {}; cap_buffers[name] = buf end | ||
515 | g_capbuffer = buf | ||
516 | g_synclineno = 0 | ||
517 | end | ||
518 | |||
519 | -- Stop a capture. | ||
520 | map_coreop[".endcapture_0"] = function(params) | ||
521 | wflush() | ||
522 | if not cap_name then wfatal(".endcapture without a valid .capture") end | ||
523 | cap_name = nil | ||
524 | cap_lineno = nil | ||
525 | g_capbuffer = nil | ||
526 | g_synclineno = 0 | ||
527 | end | ||
528 | |||
529 | -- Dump a capture buffer. | ||
530 | map_coreop[".dumpcapture_1"] = function(params) | ||
531 | if not params then return "name" end | ||
532 | wflush() | ||
533 | local name = params[1] | ||
534 | if not match(name, "^[%a_][%w_]*$") then | ||
535 | wfatal("bad capture name `"..name.."'") | ||
536 | end | ||
537 | cap_used[name] = true | ||
538 | wline(function(out) | ||
539 | local buf = cap_buffers[name] | ||
540 | if buf then wdumplines(out, buf) end | ||
541 | end) | ||
542 | g_synclineno = 0 | ||
543 | end | ||
544 | |||
545 | -- Dump all captures and their buffers (with -PP only). | ||
546 | local function dumpcaptures(out, lvl) | ||
547 | out:write("Captures:\n") | ||
548 | for name,buf in pairs(cap_buffers) do | ||
549 | out:write(format(" %-20s %4s)\n", name, "("..#buf)) | ||
550 | if lvl > 1 then | ||
551 | local bar = rep("=", 76) | ||
552 | out:write(" ", bar, "\n") | ||
553 | for _,line in ipairs(buf) do | ||
554 | out:write(" ", line, "\n") | ||
555 | end | ||
556 | out:write(" ", bar, "\n\n") | ||
557 | end | ||
558 | end | ||
559 | out:write("\n") | ||
560 | end | ||
561 | |||
562 | -- Check for unfinished or unused captures. | ||
563 | local function checkcaptures() | ||
564 | if cap_name then | ||
565 | wprinterr(g_fname, ":", cap_lineno, | ||
566 | ": error: unfinished .capture `", cap_name,"'\n") | ||
567 | return | ||
568 | end | ||
569 | for name in pairs(cap_buffers) do | ||
570 | if not cap_used[name] then | ||
571 | wprinterr(g_fname, ":*: error: missing .dumpcapture ", name ,"\n") | ||
572 | end | ||
573 | end | ||
574 | end | ||
575 | |||
576 | ------------------------------------------------------------------------------ | ||
577 | |||
578 | -- Sections names. | ||
579 | local map_sections = {} | ||
580 | |||
581 | -- Pseudo-opcode to define code sections. | ||
582 | -- TODO: Data sections, BSS sections. Needs extra C code and API. | ||
583 | map_coreop[".section_*"] = function(params) | ||
584 | if not params then return "name..." end | ||
585 | if #map_sections > 0 then werror("duplicate section definition") end | ||
586 | wflush() | ||
587 | for sn,name in ipairs(params) do | ||
588 | local opname = "."..name.."_0" | ||
589 | if not match(name, "^[%a][%w_]*$") or | ||
590 | map_op[opname] or map_op["."..name.."_*"] then | ||
591 | werror("bad section name `"..name.."'") | ||
592 | end | ||
593 | map_sections[#map_sections+1] = name | ||
594 | wline(format("#define DASM_SECTION_%s\t%d", upper(name), sn-1)) | ||
595 | map_op[opname] = function(params) g_arch.section(sn-1) end | ||
596 | end | ||
597 | wline(format("#define DASM_MAXSECTION\t\t%d", #map_sections)) | ||
598 | end | ||
599 | |||
600 | -- Dump all sections. | ||
601 | local function dumpsections(out, lvl) | ||
602 | out:write("Sections:\n") | ||
603 | for _,name in ipairs(map_sections) do | ||
604 | out:write(format(" %s\n", name)) | ||
605 | end | ||
606 | out:write("\n") | ||
607 | end | ||
608 | |||
609 | ------------------------------------------------------------------------------ | ||
610 | |||
611 | -- Load architecture-specific module. | ||
612 | local function loadarch(arch) | ||
613 | if not match(arch, "^[%w_]+$") then return "bad arch name" end | ||
614 | local ok, m_arch = pcall(require, "dasm_"..arch) | ||
615 | if not ok then return "cannot load module: "..m_arch end | ||
616 | g_arch = m_arch | ||
617 | wflush = m_arch.passcb(wline, werror, wfatal, wwarn) | ||
618 | m_arch.setup(arch, g_opt) | ||
619 | map_op, map_def = m_arch.mergemaps(map_coreop, map_def) | ||
620 | end | ||
621 | |||
622 | -- Dump architecture description. | ||
623 | function opt_map.dumparch(args) | ||
624 | local name = optparam(args) | ||
625 | if not g_arch then | ||
626 | local err = loadarch(name) | ||
627 | if err then opterror(err) end | ||
628 | end | ||
629 | |||
630 | local t = {} | ||
631 | for name in pairs(map_coreop) do t[#t+1] = name end | ||
632 | for name in pairs(map_op) do t[#t+1] = name end | ||
633 | sort(t) | ||
634 | |||
635 | local out = stdout | ||
636 | local _arch = g_arch._info | ||
637 | out:write(format("%s version %s, released %s, %s\n", | ||
638 | _info.name, _info.version, _info.release, _info.url)) | ||
639 | g_arch.dumparch(out) | ||
640 | |||
641 | local pseudo = true | ||
642 | out:write("Pseudo-Opcodes:\n") | ||
643 | for _,sname in ipairs(t) do | ||
644 | local name, nparam = match(sname, "^(.+)_([0-9%*])$") | ||
645 | if name then | ||
646 | if pseudo and sub(name, 1, 1) ~= "." then | ||
647 | out:write("\nOpcodes:\n") | ||
648 | pseudo = false | ||
649 | end | ||
650 | local f = map_op[sname] | ||
651 | local s | ||
652 | if nparam ~= "*" then nparam = nparam + 0 end | ||
653 | if nparam == 0 then | ||
654 | s = "" | ||
655 | elseif type(f) == "string" then | ||
656 | s = map_op[".template__"](nil, f, nparam) | ||
657 | else | ||
658 | s = f(nil, nparam) | ||
659 | end | ||
660 | if type(s) == "table" then | ||
661 | for _,s2 in ipairs(s) do | ||
662 | out:write(format(" %-12s %s\n", name, s2)) | ||
663 | end | ||
664 | else | ||
665 | out:write(format(" %-12s %s\n", name, s)) | ||
666 | end | ||
667 | end | ||
668 | end | ||
669 | out:write("\n") | ||
670 | exit(0) | ||
671 | end | ||
672 | |||
673 | -- Pseudo-opcode to set the architecture. | ||
674 | -- Only initially available (map_op is replaced when called). | ||
675 | map_op[".arch_1"] = function(params) | ||
676 | if not params then return "name" end | ||
677 | local err = loadarch(params[1]) | ||
678 | if err then wfatal(err) end | ||
679 | end | ||
680 | |||
681 | -- Dummy .arch pseudo-opcode to improve the error report. | ||
682 | map_coreop[".arch_1"] = function(params) | ||
683 | if not params then return "name" end | ||
684 | wfatal("duplicate .arch statement") | ||
685 | end | ||
686 | |||
687 | ------------------------------------------------------------------------------ | ||
688 | |||
689 | -- Dummy pseudo-opcode. Don't confuse '.nop' with 'nop'. | ||
690 | map_coreop[".nop_*"] = function(params) | ||
691 | if not params then return "[ignored...]" end | ||
692 | end | ||
693 | |||
694 | -- Pseudo-opcodes to raise errors. | ||
695 | map_coreop[".error_1"] = function(params) | ||
696 | if not params then return "message" end | ||
697 | werror(params[1]) | ||
698 | end | ||
699 | |||
700 | map_coreop[".fatal_1"] = function(params) | ||
701 | if not params then return "message" end | ||
702 | wfatal(params[1]) | ||
703 | end | ||
704 | |||
705 | -- Dump all user defined elements. | ||
706 | local function dumpdef(out) | ||
707 | local lvl = g_opt.dumpdef | ||
708 | if lvl == 0 then return end | ||
709 | dumpsections(out, lvl) | ||
710 | dumpdefines(out, lvl) | ||
711 | if g_arch then g_arch.dumpdef(out, lvl) end | ||
712 | dumpmacros(out, lvl) | ||
713 | dumpcaptures(out, lvl) | ||
714 | end | ||
715 | |||
716 | ------------------------------------------------------------------------------ | ||
717 | |||
718 | -- Helper for splitstmt. | ||
719 | local splitlvl | ||
720 | |||
721 | local function splitstmt_one(c) | ||
722 | if c == "(" then | ||
723 | splitlvl = ")"..splitlvl | ||
724 | elseif c == "[" then | ||
725 | splitlvl = "]"..splitlvl | ||
726 | elseif c == "{" then | ||
727 | splitlvl = "}"..splitlvl | ||
728 | elseif c == ")" or c == "]" or c == "}" then | ||
729 | if sub(splitlvl, 1, 1) ~= c then werror("unbalanced (), [] or {}") end | ||
730 | splitlvl = sub(splitlvl, 2) | ||
731 | elseif splitlvl == "" then | ||
732 | return " \0 " | ||
733 | end | ||
734 | return c | ||
735 | end | ||
736 | |||
737 | -- Split statement into (pseudo-)opcode and params. | ||
738 | local function splitstmt(stmt) | ||
739 | -- Convert label with trailing-colon into .label statement. | ||
740 | local label = match(stmt, "^%s*(.+):%s*$") | ||
741 | if label then return ".label", {label} end | ||
742 | |||
743 | -- Split at commas and equal signs, but obey parentheses and brackets. | ||
744 | splitlvl = "" | ||
745 | stmt = gsub(stmt, "[,%(%)%[%]{}]", splitstmt_one) | ||
746 | if splitlvl ~= "" then werror("unbalanced () or []") end | ||
747 | |||
748 | -- Split off opcode. | ||
749 | local op, other = match(stmt, "^%s*([^%s%z]+)%s*(.*)$") | ||
750 | if not op then werror("bad statement syntax") end | ||
751 | |||
752 | -- Split parameters. | ||
753 | local params = {} | ||
754 | for p in gmatch(other, "%s*(%Z+)%z?") do | ||
755 | params[#params+1] = gsub(p, "%s+$", "") | ||
756 | end | ||
757 | if #params > 16 then werror("too many parameters") end | ||
758 | |||
759 | params.op = op | ||
760 | return op, params | ||
761 | end | ||
762 | |||
763 | -- Process a single statement. | ||
764 | dostmt = function(stmt) | ||
765 | -- Ignore empty statements. | ||
766 | if match(stmt, "^%s*$") then return end | ||
767 | |||
768 | -- Capture macro defs before substitution. | ||
769 | if mac_capture then return mac_capture(stmt) end | ||
770 | stmt = definesubst(stmt) | ||
771 | |||
772 | -- Emit C code without parsing the line. | ||
773 | if sub(stmt, 1, 1) == "|" then | ||
774 | local tail = sub(stmt, 2) | ||
775 | wflush() | ||
776 | if sub(tail, 1, 2) == "//" then wcomment(tail) else wline(tail, true) end | ||
777 | return | ||
778 | end | ||
779 | |||
780 | -- Split into (pseudo-)opcode and params. | ||
781 | local op, params = splitstmt(stmt) | ||
782 | |||
783 | -- Get opcode handler (matching # of parameters or generic handler). | ||
784 | local f = map_op[op.."_"..#params] or map_op[op.."_*"] | ||
785 | if not f then | ||
786 | if not g_arch then wfatal("first statement must be .arch") end | ||
787 | -- Improve error report. | ||
788 | for i=0,9 do | ||
789 | if map_op[op.."_"..i] then | ||
790 | werror("wrong number of parameters for `"..op.."'") | ||
791 | end | ||
792 | end | ||
793 | werror("unknown statement `"..op.."'") | ||
794 | end | ||
795 | |||
796 | -- Call opcode handler or special handler for template strings. | ||
797 | if type(f) == "string" then | ||
798 | map_op[".template__"](params, f) | ||
799 | else | ||
800 | f(params) | ||
801 | end | ||
802 | end | ||
803 | |||
804 | -- Process a single line. | ||
805 | local function doline(line) | ||
806 | if g_opt.flushline then wflush() end | ||
807 | |||
808 | -- Assembler line? | ||
809 | local indent, aline = match(line, "^(%s*)%|(.*)$") | ||
810 | if not aline then | ||
811 | -- No, plain C code line, need to flush first. | ||
812 | wflush() | ||
813 | wsync() | ||
814 | wline(line, false) | ||
815 | return | ||
816 | end | ||
817 | |||
818 | g_indent = indent -- Remember current line indentation. | ||
819 | |||
820 | -- Emit C code (even from macros). Avoids echo and line parsing. | ||
821 | if sub(aline, 1, 1) == "|" then | ||
822 | if not mac_capture then | ||
823 | wsync() | ||
824 | elseif g_opt.comment then | ||
825 | wsync() | ||
826 | wcomment(aline) | ||
827 | end | ||
828 | dostmt(aline) | ||
829 | return | ||
830 | end | ||
831 | |||
832 | -- Echo assembler line as a comment. | ||
833 | if g_opt.comment then | ||
834 | wsync() | ||
835 | wcomment(aline) | ||
836 | end | ||
837 | |||
838 | -- Strip assembler comments. | ||
839 | aline = gsub(aline, "//.*$", "") | ||
840 | |||
841 | -- Split line into statements at semicolons. | ||
842 | if match(aline, ";") then | ||
843 | for stmt in gmatch(aline, "[^;]+") do dostmt(stmt) end | ||
844 | else | ||
845 | dostmt(aline) | ||
846 | end | ||
847 | end | ||
848 | |||
849 | ------------------------------------------------------------------------------ | ||
850 | |||
851 | -- Write DynASM header. | ||
852 | local function dasmhead(out) | ||
853 | out:write(format([[ | ||
854 | /* | ||
855 | ** This file has been pre-processed with DynASM. | ||
856 | ** %s | ||
857 | ** DynASM version %s, DynASM %s version %s | ||
858 | ** DO NOT EDIT! The original file is in "%s". | ||
859 | */ | ||
860 | |||
861 | #if DASM_VERSION != %d | ||
862 | #error "Version mismatch between DynASM and included encoding engine" | ||
863 | #endif | ||
864 | |||
865 | ]], _info.url, | ||
866 | _info.version, g_arch._info.arch, g_arch._info.version, | ||
867 | g_fname, _info.vernum)) | ||
868 | end | ||
869 | |||
870 | -- Read input file. | ||
871 | readfile = function(fin) | ||
872 | g_indent = "" | ||
873 | g_lineno = 0 | ||
874 | g_synclineno = -1 | ||
875 | |||
876 | -- Process all lines. | ||
877 | for line in fin:lines() do | ||
878 | g_lineno = g_lineno + 1 | ||
879 | g_curline = line | ||
880 | local ok, err = pcall(doline, line) | ||
881 | if not ok and wprinterr(err, "\n") then return true end | ||
882 | end | ||
883 | wflush() | ||
884 | |||
885 | -- Close input file. | ||
886 | assert(fin == stdin or fin:close()) | ||
887 | end | ||
888 | |||
889 | -- Write output file. | ||
890 | local function writefile(outfile) | ||
891 | local fout | ||
892 | |||
893 | -- Open output file. | ||
894 | if outfile == nil or outfile == "-" then | ||
895 | fout = stdout | ||
896 | else | ||
897 | fout = assert(io.open(outfile, "w")) | ||
898 | end | ||
899 | |||
900 | -- Write all buffered lines | ||
901 | wdumplines(fout, g_wbuffer) | ||
902 | |||
903 | -- Close output file. | ||
904 | assert(fout == stdout or fout:close()) | ||
905 | |||
906 | -- Optionally dump definitions. | ||
907 | dumpdef(fout == stdout and stderr or stdout) | ||
908 | end | ||
909 | |||
910 | -- Translate an input file to an output file. | ||
911 | local function translate(infile, outfile) | ||
912 | g_wbuffer = {} | ||
913 | g_indent = "" | ||
914 | g_lineno = 0 | ||
915 | g_synclineno = -1 | ||
916 | |||
917 | -- Put header. | ||
918 | wline(dasmhead) | ||
919 | |||
920 | -- Read input file. | ||
921 | local fin | ||
922 | if infile == "-" then | ||
923 | g_fname = "(stdin)" | ||
924 | fin = stdin | ||
925 | else | ||
926 | g_fname = infile | ||
927 | fin = assert(io.open(infile, "r")) | ||
928 | end | ||
929 | readfile(fin) | ||
930 | |||
931 | -- Check for errors. | ||
932 | if not g_arch then | ||
933 | wprinterr(g_fname, ":*: error: missing .arch directive\n") | ||
934 | end | ||
935 | checkconds() | ||
936 | checkmacros() | ||
937 | checkcaptures() | ||
938 | |||
939 | if g_errcount ~= 0 then | ||
940 | stderr:write(g_fname, ":*: info: ", g_errcount, " error", | ||
941 | (type(g_errcount) == "number" and g_errcount > 1) and "s" or "", | ||
942 | " in input file -- no output file generated.\n") | ||
943 | dumpdef(stderr) | ||
944 | exit(1) | ||
945 | end | ||
946 | |||
947 | -- Write output file. | ||
948 | writefile(outfile) | ||
949 | end | ||
950 | |||
951 | ------------------------------------------------------------------------------ | ||
952 | |||
953 | -- Print help text. | ||
954 | function opt_map.help() | ||
955 | stdout:write("DynASM -- ", _info.description, ".\n") | ||
956 | stdout:write("DynASM ", _info.version, " ", _info.release, " ", _info.url, "\n") | ||
957 | stdout:write[[ | ||
958 | |||
959 | Usage: dynasm [OPTION]... INFILE.dasc|- | ||
960 | |||
961 | -h, --help Display this help text. | ||
962 | -V, --version Display version and copyright information. | ||
963 | |||
964 | -o, --outfile FILE Output file name (default is stdout). | ||
965 | -I, --include DIR Add directory to the include search path. | ||
966 | |||
967 | -c, --ccomment Use /* */ comments for assembler lines. | ||
968 | -C, --cppcomment Use // comments for assembler lines (default). | ||
969 | -N, --nocomment Suppress assembler lines in output. | ||
970 | -M, --maccomment Show macro expansions as comments (default off). | ||
971 | |||
972 | -L, --nolineno Suppress CPP line number information in output. | ||
973 | -F, --flushline Flush action list for every line. | ||
974 | |||
975 | -D NAME[=SUBST] Define a substitution. | ||
976 | -U NAME Undefine a substitution. | ||
977 | |||
978 | -P, --dumpdef Dump defines, macros, etc. Repeat for more output. | ||
979 | -A, --dumparch ARCH Load architecture ARCH and dump description. | ||
980 | ]] | ||
981 | exit(0) | ||
982 | end | ||
983 | |||
984 | -- Print version information. | ||
985 | function opt_map.version() | ||
986 | stdout:write(format("%s version %s, released %s\n%s\n\n%s", | ||
987 | _info.name, _info.version, _info.release, _info.url, _info.copyright)) | ||
988 | exit(0) | ||
989 | end | ||
990 | |||
991 | -- Misc. options. | ||
992 | function opt_map.outfile(args) g_opt.outfile = optparam(args) end | ||
993 | function opt_map.include(args) insert(g_opt.include, 1, optparam(args)) end | ||
994 | function opt_map.ccomment() g_opt.comment = "/*|"; g_opt.endcomment = " */" end | ||
995 | function opt_map.cppcomment() g_opt.comment = "//|"; g_opt.endcomment = "" end | ||
996 | function opt_map.nocomment() g_opt.comment = false end | ||
997 | function opt_map.maccomment() g_opt.maccomment = true end | ||
998 | function opt_map.nolineno() g_opt.cpp = false end | ||
999 | function opt_map.flushline() g_opt.flushline = true end | ||
1000 | function opt_map.dumpdef() g_opt.dumpdef = g_opt.dumpdef + 1 end | ||
1001 | |||
1002 | ------------------------------------------------------------------------------ | ||
1003 | |||
1004 | -- Short aliases for long options. | ||
1005 | local opt_alias = { | ||
1006 | h = "help", ["?"] = "help", V = "version", | ||
1007 | o = "outfile", I = "include", | ||
1008 | c = "ccomment", C = "cppcomment", N = "nocomment", M = "maccomment", | ||
1009 | L = "nolineno", F = "flushline", | ||
1010 | P = "dumpdef", A = "dumparch", | ||
1011 | } | ||
1012 | |||
1013 | -- Parse single option. | ||
1014 | local function parseopt(opt, args) | ||
1015 | opt_current = #opt == 1 and "-"..opt or "--"..opt | ||
1016 | local f = opt_map[opt] or opt_map[opt_alias[opt]] | ||
1017 | if not f then | ||
1018 | opterror("unrecognized option `", opt_current, "'. Try `--help'.\n") | ||
1019 | end | ||
1020 | f(args) | ||
1021 | end | ||
1022 | |||
1023 | -- Parse arguments. | ||
1024 | local function parseargs(args) | ||
1025 | -- Default options. | ||
1026 | g_opt.comment = "//|" | ||
1027 | g_opt.endcomment = "" | ||
1028 | g_opt.cpp = true | ||
1029 | g_opt.dumpdef = 0 | ||
1030 | g_opt.include = { "" } | ||
1031 | |||
1032 | -- Process all option arguments. | ||
1033 | args.argn = 1 | ||
1034 | repeat | ||
1035 | local a = args[args.argn] | ||
1036 | if not a then break end | ||
1037 | local lopt, opt = match(a, "^%-(%-?)(.+)") | ||
1038 | if not opt then break end | ||
1039 | args.argn = args.argn + 1 | ||
1040 | if lopt == "" then | ||
1041 | -- Loop through short options. | ||
1042 | for o in gmatch(opt, ".") do parseopt(o, args) end | ||
1043 | else | ||
1044 | -- Long option. | ||
1045 | parseopt(opt, args) | ||
1046 | end | ||
1047 | until false | ||
1048 | |||
1049 | -- Check for proper number of arguments. | ||
1050 | local nargs = #args - args.argn + 1 | ||
1051 | if nargs ~= 1 then | ||
1052 | if nargs == 0 then | ||
1053 | if g_opt.dumpdef > 0 then return dumpdef(stdout) end | ||
1054 | end | ||
1055 | opt_map.help() | ||
1056 | end | ||
1057 | |||
1058 | -- Translate a single input file to a single output file | ||
1059 | -- TODO: Handle multiple files? | ||
1060 | translate(args[args.argn], g_opt.outfile) | ||
1061 | end | ||
1062 | |||
1063 | ------------------------------------------------------------------------------ | ||
1064 | |||
1065 | -- Add the directory dynasm.lua resides in to the Lua module search path. | ||
1066 | local arg = arg | ||
1067 | if arg and arg[0] then | ||
1068 | local prefix = match(arg[0], "^(.*[/\\])") | ||
1069 | if prefix then package.path = prefix.."?.lua;"..package.path end | ||
1070 | end | ||
1071 | |||
1072 | -- Start DynASM. | ||
1073 | parseargs{...} | ||
1074 | |||
1075 | ------------------------------------------------------------------------------ | ||
1076 | |||