aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/luajit-2.0/dynasm
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/luajit-2.0/dynasm')
-rw-r--r--libraries/luajit-2.0/dynasm/dasm_arm.h448
-rw-r--r--libraries/luajit-2.0/dynasm/dasm_arm.lua949
-rw-r--r--libraries/luajit-2.0/dynasm/dasm_mips.h415
-rw-r--r--libraries/luajit-2.0/dynasm/dasm_mips.lua948
-rw-r--r--libraries/luajit-2.0/dynasm/dasm_ppc.h411
-rw-r--r--libraries/luajit-2.0/dynasm/dasm_ppc.lua1230
-rw-r--r--libraries/luajit-2.0/dynasm/dasm_proto.h83
-rw-r--r--libraries/luajit-2.0/dynasm/dasm_x64.lua12
-rw-r--r--libraries/luajit-2.0/dynasm/dasm_x86.h470
-rw-r--r--libraries/luajit-2.0/dynasm/dasm_x86.lua1931
-rw-r--r--libraries/luajit-2.0/dynasm/dynasm.lua1076
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. */
19enum {
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. */
53typedef const unsigned int *dasm_ActList;
54
55/* Per-section structure. */
56typedef 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. */
66struct 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. */
86void 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. */
110void 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(). */
123void 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. */
131void 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. */
140void 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
168static 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. */
177void 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 }
266stop:
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. */
274int 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. */
340int 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. */
419int 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. */
432int 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:
9local _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.
20local _M = { _info = _info }
21
22-- Cache library functions.
23local type, tonumber, pairs, ipairs = type, tonumber, pairs, ipairs
24local assert, setmetatable, rawget = assert, setmetatable, rawget
25local _s = string
26local sub, format, byte, char = _s.sub, _s.format, _s.byte, _s.char
27local match, gmatch, gsub = _s.match, _s.gmatch, _s.gsub
28local concat, sort, insert = table.concat, table.sort, table.insert
29
30-- Inherited tables and callbacks.
31local g_opt, g_arch
32local wline, werror, wfatal, wwarn
33
34-- Action name list.
35-- CHECK: Keep this in sync with the C code!
36local 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!
44local maxsecpos = 25 -- Keep this low, to avoid excessively long C lines.
45
46-- Action name -> action number.
47local map_action = {}
48for n,name in ipairs(action_names) do
49 map_action[name] = n-1
50end
51
52-- Action list buffer.
53local actlist = {}
54
55-- Argument list for next dasm_put(). Start with offset 0 into action list.
56local actargs = { 0 }
57
58-- Current number of section buffer positions for dasm_put().
59local secpos = 1
60
61------------------------------------------------------------------------------
62
63-- Return 8 digit hex number.
64local function tohex(x)
65 return sub(format("%08x", x), -8) -- Avoid 64 bit portability problem in Lua.
66end
67
68-- Dump action names and numbers.
69local 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")
76end
77
78-- Write action list buffer as a huge static C array.
79local 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"))
87end
88
89------------------------------------------------------------------------------
90
91-- Add word to action list.
92local function wputxw(n)
93 assert(n >= 0 and n <= 0xffffffff and n % 1 == 0, "word out of range")
94 actlist[#actlist+1] = n
95end
96
97-- Add action to list with optional arg. Advance buffer pos, too.
98local 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
103end
104
105-- Flush action list (intervening C code or buffer pos overflow).
106local 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.
112end
113
114-- Put escaped word.
115local function wputw(n)
116 if n <= 0x000fffff then waction("ESC") end
117 wputxw(n)
118end
119
120-- Reserve position for word.
121local function wpos()
122 local pos = #actlist+1
123 actlist[pos] = ""
124 return pos
125end
126
127-- Store word to reserved position.
128local 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
135end
136
137------------------------------------------------------------------------------
138
139-- Global label name -> global label number. With auto assignment on 1st use.
140local next_global = 20
141local 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
148end})
149
150-- Dump global labels.
151local 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")
159end
160
161-- Write global label enum.
162local 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")
170end
171
172-- Write global label names.
173local 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")
181end
182
183------------------------------------------------------------------------------
184
185-- Extern label name -> extern label number. With auto assignment on 1st use.
186local next_extern = 0
187local map_extern_ = {}
188local 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
196end})
197
198-- Dump extern labels.
199local 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")
205end
206
207-- Write extern label names.
208local 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")
214end
215
216------------------------------------------------------------------------------
217
218-- Arch-specific maps.
219
220-- Ext. register name -> int. name.
221local map_archdef = { sp = "r13", lr = "r14", pc = "r15", }
222
223-- Int. register name -> ext. name.
224local map_reg_rev = { r13 = "sp", r14 = "lr", r15 = "pc", }
225
226local map_type = {} -- Type name -> { ctype, reg }
227local ctypenum = 0 -- Type number (for Dt... macros).
228
229-- Reverse defines for registers.
230function _M.revdef(s)
231 return map_reg_rev[s] or s
232end
233
234local map_shift = { lsl = 0, lsr = 1, asr = 2, ror = 3, }
235
236local 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.
245local 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.
443do
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
454end
455
456------------------------------------------------------------------------------
457
458local 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.."'")
474end
475
476local function parse_gpr_pm(expr)
477 local pm, expr2 = match(expr, "^([+-]?)(.*)$")
478 return parse_gpr(expr2), (pm == "-")
479end
480
481local 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
493end
494
495local 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
517end
518
519local 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
533end
534
535local 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
549end
550
551local 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
571end
572
573local 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
587end
588
589local 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.."'")
617end
618
619local 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
689end
690
691------------------------------------------------------------------------------
692
693-- Handle opcodes defined with template strings.
694map_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)
774end
775
776------------------------------------------------------------------------------
777
778-- Pseudo-opcode to mark the position where the action list is to be emitted.
779map_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)
783end
784
785-- Pseudo-opcode to mark the position where the global enum is to be emitted.
786map_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)
790end
791
792-- Pseudo-opcode to mark the position where the global names are to be emitted.
793map_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)
797end
798
799-- Pseudo-opcode to mark the position where the extern names are to be emitted.
800map_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)
804end
805
806------------------------------------------------------------------------------
807
808-- Label pseudo-opcode (converted from trailing colon form).
809map_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)
815end
816
817------------------------------------------------------------------------------
818
819-- Pseudo-opcodes for data storage.
820map_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
829end
830
831-- Alignment pseudo-opcode.
832map_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")
848end
849
850------------------------------------------------------------------------------
851
852-- Pseudo-opcode for (primitive) type definitions (map to C types).
853map_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
876end
877map_op[".type_2"] = map_op[".type_3"]
878
879-- Dump type definitions.
880local 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")
891end
892
893------------------------------------------------------------------------------
894
895-- Set the current section.
896function _M.section(num)
897 waction("SECTION", num)
898 wflush(true) -- SECTION is a terminal action.
899end
900
901------------------------------------------------------------------------------
902
903-- Dump architecture description.
904function _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)
908end
909
910-- Dump all user defined elements.
911function _M.dumpdef(out, lvl)
912 dumptypes(out, lvl)
913 dumpglobals(out, lvl)
914 dumpexterns(out, lvl)
915end
916
917------------------------------------------------------------------------------
918
919-- Pass callbacks from/to the DynASM core.
920function _M.passcb(wl, we, wf, ww)
921 wline, werror, wfatal, wwarn = wl, we, wf, ww
922 return wflush
923end
924
925-- Setup the arch-specific module.
926function _M.setup(arch, opt)
927 g_arch, g_opt = arch, opt
928end
929
930-- Merge the core maps and the arch-specific maps.
931function _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
944end
945
946return _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. */
19enum {
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. */
52typedef const unsigned int *dasm_ActList;
53
54/* Per-section structure. */
55typedef 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. */
65struct 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. */
85void 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. */
109void 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(). */
122void 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. */
130void 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. */
139void 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. */
168void 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 }
249stop:
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. */
257int 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. */
322int 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. */
386int 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. */
399int 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:
9local _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.
20local _M = { _info = _info }
21
22-- Cache library functions.
23local type, tonumber, pairs, ipairs = type, tonumber, pairs, ipairs
24local assert, setmetatable = assert, setmetatable
25local _s = string
26local sub, format, byte, char = _s.sub, _s.format, _s.byte, _s.char
27local match, gmatch = _s.match, _s.gmatch
28local concat, sort = table.concat, table.sort
29
30-- Inherited tables and callbacks.
31local g_opt, g_arch
32local wline, werror, wfatal, wwarn
33
34-- Action name list.
35-- CHECK: Keep this in sync with the C code!
36local 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!
44local maxsecpos = 25 -- Keep this low, to avoid excessively long C lines.
45
46-- Action name -> action number.
47local map_action = {}
48for n,name in ipairs(action_names) do
49 map_action[name] = n-1
50end
51
52-- Action list buffer.
53local actlist = {}
54
55-- Argument list for next dasm_put(). Start with offset 0 into action list.
56local actargs = { 0 }
57
58-- Current number of section buffer positions for dasm_put().
59local secpos = 1
60
61------------------------------------------------------------------------------
62
63-- Return 8 digit hex number.
64local function tohex(x)
65 return sub(format("%08x", x), -8) -- Avoid 64 bit portability problem in Lua.
66end
67
68-- Dump action names and numbers.
69local 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")
76end
77
78-- Write action list buffer as a huge static C array.
79local 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"))
87end
88
89------------------------------------------------------------------------------
90
91-- Add word to action list.
92local function wputxw(n)
93 assert(n >= 0 and n <= 0xffffffff and n % 1 == 0, "word out of range")
94 actlist[#actlist+1] = n
95end
96
97-- Add action to list with optional arg. Advance buffer pos, too.
98local 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
103end
104
105-- Flush action list (intervening C code or buffer pos overflow).
106local 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.
112end
113
114-- Put escaped word.
115local function wputw(n)
116 if n >= 0xff000000 then waction("ESC") end
117 wputxw(n)
118end
119
120-- Reserve position for word.
121local function wpos()
122 local pos = #actlist+1
123 actlist[pos] = ""
124 return pos
125end
126
127-- Store word to reserved position.
128local function wputpos(pos, n)
129 assert(n >= 0 and n <= 0xffffffff and n % 1 == 0, "word out of range")
130 actlist[pos] = n
131end
132
133------------------------------------------------------------------------------
134
135-- Global label name -> global label number. With auto assignment on 1st use.
136local next_global = 20
137local 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
144end})
145
146-- Dump global labels.
147local 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")
155end
156
157-- Write global label enum.
158local 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")
166end
167
168-- Write global label names.
169local 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")
177end
178
179------------------------------------------------------------------------------
180
181-- Extern label name -> extern label number. With auto assignment on 1st use.
182local next_extern = 0
183local map_extern_ = {}
184local 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
192end})
193
194-- Dump extern labels.
195local 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")
201end
202
203-- Write extern label names.
204local 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")
210end
211
212------------------------------------------------------------------------------
213
214-- Arch-specific maps.
215local map_archdef = { sp="r29", ra="r31" } -- Ext. register name -> int. name.
216
217local map_type = {} -- Type name -> { ctype, reg }
218local ctypenum = 0 -- Type number (for Dt... macros).
219
220-- Reverse defines for registers.
221function _M.revdef(s)
222 if s == "r29" then return "sp"
223 elseif s == "r31" then return "ra" end
224 return s
225end
226
227------------------------------------------------------------------------------
228
229-- Template strings for MIPS instructions.
230local 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
607local 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.."'")
623end
624
625local 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.."'")
632end
633
634local 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
657end
658
659local 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.."'")
674end
675
676local 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.."'")
684end
685
686local 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.."'")
714end
715
716------------------------------------------------------------------------------
717
718-- Handle opcodes defined with template strings.
719map_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)
782end
783
784------------------------------------------------------------------------------
785
786-- Pseudo-opcode to mark the position where the action list is to be emitted.
787map_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)
791end
792
793-- Pseudo-opcode to mark the position where the global enum is to be emitted.
794map_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)
798end
799
800-- Pseudo-opcode to mark the position where the global names are to be emitted.
801map_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)
805end
806
807-- Pseudo-opcode to mark the position where the extern names are to be emitted.
808map_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)
812end
813
814------------------------------------------------------------------------------
815
816-- Label pseudo-opcode (converted from trailing colon form).
817map_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)
823end
824
825------------------------------------------------------------------------------
826
827-- Pseudo-opcodes for data storage.
828map_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
837end
838
839-- Alignment pseudo-opcode.
840map_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")
856end
857
858------------------------------------------------------------------------------
859
860-- Pseudo-opcode for (primitive) type definitions (map to C types).
861map_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
884end
885map_op[".type_2"] = map_op[".type_3"]
886
887-- Dump type definitions.
888local 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")
899end
900
901------------------------------------------------------------------------------
902
903-- Set the current section.
904function _M.section(num)
905 waction("SECTION", num)
906 wflush(true) -- SECTION is a terminal action.
907end
908
909------------------------------------------------------------------------------
910
911-- Dump architecture description.
912function _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)
916end
917
918-- Dump all user defined elements.
919function _M.dumpdef(out, lvl)
920 dumptypes(out, lvl)
921 dumpglobals(out, lvl)
922 dumpexterns(out, lvl)
923end
924
925------------------------------------------------------------------------------
926
927-- Pass callbacks from/to the DynASM core.
928function _M.passcb(wl, we, wf, ww)
929 wline, werror, wfatal, wwarn = wl, we, wf, ww
930 return wflush
931end
932
933-- Setup the arch-specific module.
934function _M.setup(arch, opt)
935 g_arch, g_opt = arch, opt
936end
937
938-- Merge the core maps and the arch-specific maps.
939function _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
943end
944
945return _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. */
19enum {
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. */
52typedef const unsigned int *dasm_ActList;
53
54/* Per-section structure. */
55typedef 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. */
65struct 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. */
85void 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. */
109void 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(). */
122void 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. */
130void 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. */
139void 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. */
168void 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 }
249stop:
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. */
257int 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. */
322int 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. */
382int 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. */
395int 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:
9local _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.
20local _M = { _info = _info }
21
22-- Cache library functions.
23local type, tonumber, pairs, ipairs = type, tonumber, pairs, ipairs
24local assert, setmetatable = assert, setmetatable
25local _s = string
26local sub, format, byte, char = _s.sub, _s.format, _s.byte, _s.char
27local match, gmatch = _s.match, _s.gmatch
28local concat, sort = table.concat, table.sort
29
30-- Inherited tables and callbacks.
31local g_opt, g_arch
32local wline, werror, wfatal, wwarn
33
34-- Action name list.
35-- CHECK: Keep this in sync with the C code!
36local 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!
44local maxsecpos = 25 -- Keep this low, to avoid excessively long C lines.
45
46-- Action name -> action number.
47local map_action = {}
48for n,name in ipairs(action_names) do
49 map_action[name] = n-1
50end
51
52-- Action list buffer.
53local actlist = {}
54
55-- Argument list for next dasm_put(). Start with offset 0 into action list.
56local actargs = { 0 }
57
58-- Current number of section buffer positions for dasm_put().
59local secpos = 1
60
61------------------------------------------------------------------------------
62
63-- Return 8 digit hex number.
64local function tohex(x)
65 return sub(format("%08x", x), -8) -- Avoid 64 bit portability problem in Lua.
66end
67
68-- Dump action names and numbers.
69local 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")
76end
77
78-- Write action list buffer as a huge static C array.
79local 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"))
87end
88
89------------------------------------------------------------------------------
90
91-- Add word to action list.
92local function wputxw(n)
93 assert(n >= 0 and n <= 0xffffffff and n % 1 == 0, "word out of range")
94 actlist[#actlist+1] = n
95end
96
97-- Add action to list with optional arg. Advance buffer pos, too.
98local 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
103end
104
105-- Flush action list (intervening C code or buffer pos overflow).
106local 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.
112end
113
114-- Put escaped word.
115local function wputw(n)
116 if n <= 0xffffff then waction("ESC") end
117 wputxw(n)
118end
119
120-- Reserve position for word.
121local function wpos()
122 local pos = #actlist+1
123 actlist[pos] = ""
124 return pos
125end
126
127-- Store word to reserved position.
128local function wputpos(pos, n)
129 assert(n >= 0 and n <= 0xffffffff and n % 1 == 0, "word out of range")
130 actlist[pos] = n
131end
132
133------------------------------------------------------------------------------
134
135-- Global label name -> global label number. With auto assignment on 1st use.
136local next_global = 20
137local 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
144end})
145
146-- Dump global labels.
147local 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")
155end
156
157-- Write global label enum.
158local 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")
166end
167
168-- Write global label names.
169local 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")
177end
178
179------------------------------------------------------------------------------
180
181-- Extern label name -> extern label number. With auto assignment on 1st use.
182local next_extern = 0
183local map_extern_ = {}
184local 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
192end})
193
194-- Dump extern labels.
195local 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")
201end
202
203-- Write extern label names.
204local 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")
210end
211
212------------------------------------------------------------------------------
213
214-- Arch-specific maps.
215local map_archdef = { sp = "r1" } -- Ext. register name -> int. name.
216
217local map_type = {} -- Type name -> { ctype, reg }
218local ctypenum = 0 -- Type number (for Dt... macros).
219
220-- Reverse defines for registers.
221function _M.revdef(s)
222 if s == "r1" then return "sp" end
223 return s
224end
225
226local 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.
234local 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.
816do
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
827end
828
829-- Add more branch mnemonics.
830for 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"
850end
851
852------------------------------------------------------------------------------
853
854local 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.."'")
870end
871
872local 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.."'")
879end
880
881local 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.."'")
885end
886
887local 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.."'")
895end
896
897local 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
920end
921
922local 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.."'")
939end
940
941local 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.."'")
958end
959
960local 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.."'")
988end
989
990------------------------------------------------------------------------------
991
992-- Handle opcodes defined with template strings.
993map_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)
1064end
1065
1066------------------------------------------------------------------------------
1067
1068-- Pseudo-opcode to mark the position where the action list is to be emitted.
1069map_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)
1073end
1074
1075-- Pseudo-opcode to mark the position where the global enum is to be emitted.
1076map_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)
1080end
1081
1082-- Pseudo-opcode to mark the position where the global names are to be emitted.
1083map_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)
1087end
1088
1089-- Pseudo-opcode to mark the position where the extern names are to be emitted.
1090map_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)
1094end
1095
1096------------------------------------------------------------------------------
1097
1098-- Label pseudo-opcode (converted from trailing colon form).
1099map_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)
1105end
1106
1107------------------------------------------------------------------------------
1108
1109-- Pseudo-opcodes for data storage.
1110map_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
1119end
1120
1121-- Alignment pseudo-opcode.
1122map_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")
1138end
1139
1140------------------------------------------------------------------------------
1141
1142-- Pseudo-opcode for (primitive) type definitions (map to C types).
1143map_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
1166end
1167map_op[".type_2"] = map_op[".type_3"]
1168
1169-- Dump type definitions.
1170local 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")
1181end
1182
1183------------------------------------------------------------------------------
1184
1185-- Set the current section.
1186function _M.section(num)
1187 waction("SECTION", num)
1188 wflush(true) -- SECTION is a terminal action.
1189end
1190
1191------------------------------------------------------------------------------
1192
1193-- Dump architecture description.
1194function _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)
1198end
1199
1200-- Dump all user defined elements.
1201function _M.dumpdef(out, lvl)
1202 dumptypes(out, lvl)
1203 dumpglobals(out, lvl)
1204 dumpexterns(out, lvl)
1205end
1206
1207------------------------------------------------------------------------------
1208
1209-- Pass callbacks from/to the DynASM core.
1210function _M.passcb(wl, we, wf, ww)
1211 wline, werror, wfatal, wwarn = wl, we, wf, ww
1212 return wflush
1213end
1214
1215-- Setup the arch-specific module.
1216function _M.setup(arch, opt)
1217 g_arch, g_opt = arch, opt
1218end
1219
1220-- Merge the core maps and the arch-specific maps.
1221function _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
1225end
1226
1227return _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. */
47typedef struct dasm_State dasm_State;
48
49
50/* Initialize and free DynASM state. */
51DASM_FDEF void dasm_init(Dst_DECL, int maxsection);
52DASM_FDEF void dasm_free(Dst_DECL);
53
54/* Setup global array. Must be called before dasm_setup(). */
55DASM_FDEF void dasm_setupglobal(Dst_DECL, void **gl, unsigned int maxgl);
56
57/* Grow PC label array. Can be called after dasm_setup(), too. */
58DASM_FDEF void dasm_growpc(Dst_DECL, unsigned int maxpc);
59
60/* Setup encoder. */
61DASM_FDEF void dasm_setup(Dst_DECL, const void *actionlist);
62
63/* Feed encoder with actions. Calls are generated by pre-processor. */
64DASM_FDEF void dasm_put(Dst_DECL, int start, ...);
65
66/* Link sections and return the resulting size. */
67DASM_FDEF int dasm_link(Dst_DECL, size_t *szp);
68
69/* Encode sections into buffer. */
70DASM_FDEF int dasm_encode(Dst_DECL, void *buffer);
71
72/* Get PC label offset. */
73DASM_FDEF int dasm_getpclabel(Dst_DECL, unsigned int pc);
74
75#ifdef DASM_CHECKS
76/* Optional sanity checker to call between isolated encoding steps. */
77DASM_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
11x64 = true -- Using a global is an ugly, but effective solution.
12return 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. */
19enum {
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. */
51typedef const unsigned char *dasm_ActList;
52
53/* Per-section structure. */
54typedef 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. */
64struct 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. */
84void 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. */
108void 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(). */
121void 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. */
129void 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. */
138void 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. */
167void 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 }
257stop:
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. */
265int 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. */
359int 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. */
441int 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. */
454int 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
8local x64 = x64
9
10-- Module information:
11local _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.
22local _M = { _info = _info }
23
24-- Cache library functions.
25local type, tonumber, pairs, ipairs = type, tonumber, pairs, ipairs
26local assert, unpack, setmetatable = assert, unpack, setmetatable
27local _s = string
28local sub, format, byte, char = _s.sub, _s.format, _s.byte, _s.char
29local find, match, gmatch, gsub = _s.find, _s.match, _s.gmatch, _s.gsub
30local concat, sort = table.concat, table.sort
31
32-- Inherited tables and callbacks.
33local g_opt, g_arch
34local wline, werror, wfatal, wwarn
35
36-- Action name list.
37-- CHECK: Keep this in sync with the C code!
38local 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!
67local maxsecpos = 25 -- Keep this low, to avoid excessively long C lines.
68
69-- Action name -> action number (dynamically generated below).
70local map_action = {}
71-- First action number. Everything below does not need to be escaped.
72local actfirst = 256-#action_names
73
74-- Action list buffer and string (only used to remove dupes).
75local actlist = {}
76local actstr = ""
77
78-- Argument list for next dasm_put(). Start with offset 0 into action list.
79local actargs = { 0 }
80
81-- Current number of section buffer positions for dasm_put().
82local secpos = 1
83
84------------------------------------------------------------------------------
85
86-- Compute action numbers for action names.
87for n,name in ipairs(action_names) do
88 local num = actfirst + n - 1
89 map_action[name] = num
90end
91
92-- Dump action names and numbers.
93local 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")
100end
101
102-- Write action list buffer as a huge static C array.
103local 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.
118end
119
120------------------------------------------------------------------------------
121
122-- Add byte to action list.
123local function wputxb(n)
124 assert(n >= 0 and n <= 255 and n % 1 == 0, "byte out of range")
125 actlist[#actlist+1] = n
126end
127
128-- Add action to list with optional arg. Advance buffer pos, too.
129local 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
133end
134
135-- Add call to embedded DynASM C code.
136local function wcall(func, args)
137 wline(format("dasm_%s(Dst, %s);", func, concat(args, ", ")), true)
138end
139
140-- Delete duplicate action list chunks. A tad slow, but so what.
141local 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
151end
152
153-- Flush action list (intervening C code or buffer pos overflow).
154local 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.
162end
163
164-- Put escaped byte.
165local function wputb(n)
166 if n >= actfirst then waction("ESC") end -- Need to escape byte.
167 wputxb(n)
168end
169
170------------------------------------------------------------------------------
171
172-- Global label name -> global label number. With auto assignment on 1st use.
173local next_global = 10
174local 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
181end})
182
183-- Dump global labels.
184local 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")
192end
193
194-- Write global label enum.
195local 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")
203end
204
205-- Write global label names.
206local 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")
214end
215
216------------------------------------------------------------------------------
217
218-- Extern label name -> extern label number. With auto assignment on 1st use.
219local next_extern = -1
220local 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
227end})
228
229-- Dump extern labels.
230local 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")
238end
239
240-- Write extern label names.
241local 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")
249end
250
251------------------------------------------------------------------------------
252
253-- Arch-specific maps.
254local map_archdef = {} -- Ext. register name -> int. name.
255local map_reg_rev = {} -- Int. register name -> ext. name.
256local map_reg_num = {} -- Int. register name -> register number.
257local map_reg_opsize = {} -- Int. register name -> operand size.
258local map_reg_valid_base = {} -- Int. register name -> valid base register?
259local map_reg_valid_index = {} -- Int. register name -> valid index register?
260local map_reg_needrex = {} -- Int. register name -> need rex vs. no rex.
261local reg_list = {} -- Canonical list of int. register names.
262
263local map_type = {} -- Type name -> { ctype, reg }
264local ctypenum = 0 -- Type number (for _PTx macros).
265
266local addrsize = x64 and "q" or "d" -- Size for address operands.
267
268-- Helper functions to fill register maps.
269local 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] = ""
316end
317
318-- Integer registers (qword, dword, word and byte sized).
319if x64 then
320 mkrmap("q", "Rq", {"rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi"})
321end
322mkrmap("d", "Rd", {"eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"})
323mkrmap("w", "Rw", {"ax", "cx", "dx", "bx", "sp", "bp", "si", "di"})
324mkrmap("b", "Rb", {"al", "cl", "dl", "bl", "ah", "ch", "dh", "bh"})
325map_reg_valid_index[map_archdef.esp] = false
326if x64 then map_reg_valid_index[map_archdef.rsp] = false end
327map_archdef["Ra"] = "@"..addrsize
328
329-- FP registers (internally tword sized, but use "f" as operand size).
330mkrmap("f", "Rf")
331
332-- SSE registers (oword sized, but qword and dword accessible).
333mkrmap("o", "xmm")
334
335-- Operand size prefixes to codes.
336local 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.
342local map_opsizenum = {
343 b = 1, w = 2, d = 4, q = 8, o = 16, t = 10,
344}
345
346-- Operand size code to name.
347local 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.
353local map_xsc = {
354 ["1"] = 0, ["2"] = 1, ["4"] = 2, ["8"] = 3,
355}
356
357-- Condition codes.
358local 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.
367function _M.revdef(s)
368 return gsub(s, "@%w+", map_reg_rev)
369end
370
371-- Dump register names and numbers
372local 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
385end
386
387------------------------------------------------------------------------------
388
389-- Put action for label arg (IMM_LG, IMM_PC, REL_LG, REL_PC).
390local 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
403end
404
405-- Put signed byte or arg.
406local 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
414end
415
416-- Put unsigned byte or arg.
417local 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
424end
425
426-- Put unsigned word or arg.
427local 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
434end
435
436-- Put signed or unsigned dword or arg.
437local 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
449end
450
451-- Put operand-size dependent number or arg (defaults to dword).
452local 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
458end
459
460-- Put multi-byte opcode with operand-size dependent modifications.
461local 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)
487end
488
489-- Put ModRM or SIB formatted byte.
490local 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))
493end
494
495-- Put ModRM/SIB plus optional displacement.
496local 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
579end
580
581------------------------------------------------------------------------------
582
583-- Return human-readable operand mode string.
584local 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, ",")
591end
592
593-- Convert number to valid integer or nil.
594local 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
602end
603
604-- Parse immediate expression.
605local 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
634end
635
636-- Parse displacement expression: +-num, +-expr, +-opsize*num
637local 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.
658end
659
660-- Parse register or type expression.
661local 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]
677end
678
679-- Parse operand and return { mode, opsize, reg, xreg, xsc, disp, imm }.
680local 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
827end
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 *.
898local 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.
1411for 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)
1417end
1418
1419-- Shift ops.
1420for 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)
1423end
1424
1425-- Conditional ops.
1426for 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+
1430end
1431
1432-- FP arithmetic ops.
1433for 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)
1447end
1448
1449-- FP conditional moves.
1450for 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+
1455end
1456
1457-- SSE FP arithmetic ops.
1458for 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)
1464end
1465
1466------------------------------------------------------------------------------
1467
1468-- Process pattern string.
1469local 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
1572end
1573
1574------------------------------------------------------------------------------
1575
1576-- Mapping of operand modes to short names. Suppress output with '#'.
1577local 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.
1584local 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
1595end
1596
1597-- Match operand modes against mode match part of template.
1598local 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
1603end
1604
1605-- Handle opcodes defined with template strings.
1606map_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).."'")
1672end
1673
1674------------------------------------------------------------------------------
1675
1676-- x64-specific opcode for 64 bit immediates and displacements.
1677if 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
1710end
1711
1712------------------------------------------------------------------------------
1713
1714-- Pseudo-opcodes for data storage.
1715local 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
1731end
1732
1733map_op[".byte_*"] = op_data
1734map_op[".sbyte_*"] = op_data
1735map_op[".word_*"] = op_data
1736map_op[".dword_*"] = op_data
1737map_op[".aword_*"] = op_data
1738
1739------------------------------------------------------------------------------
1740
1741-- Pseudo-opcode to mark the position where the action list is to be emitted.
1742map_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)
1746end
1747
1748-- Pseudo-opcode to mark the position where the global enum is to be emitted.
1749map_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)
1753end
1754
1755-- Pseudo-opcode to mark the position where the global names are to be emitted.
1756map_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)
1760end
1761
1762-- Pseudo-opcode to mark the position where the extern names are to be emitted.
1763map_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)
1767end
1768
1769------------------------------------------------------------------------------
1770
1771-- Label pseudo-opcode (converted from trailing colon form).
1772map_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
1797end
1798map_op[".label_1"] = map_op[".label_2"]
1799
1800------------------------------------------------------------------------------
1801
1802-- Alignment pseudo-opcode.
1803map_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")
1820end
1821
1822-- Spacing pseudo-opcode.
1823map_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)
1833end
1834map_op[".space_1"] = map_op[".space_2"]
1835
1836------------------------------------------------------------------------------
1837
1838-- Pseudo-opcode for (primitive) type definitions (map to C types).
1839map_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
1865end
1866map_op[".type_2"] = map_op[".type_3"]
1867
1868-- Dump type definitions.
1869local 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")
1880end
1881
1882------------------------------------------------------------------------------
1883
1884-- Set the current section.
1885function _M.section(num)
1886 waction("SECTION")
1887 wputxb(num)
1888 wflush(true) -- SECTION is a terminal action.
1889end
1890
1891------------------------------------------------------------------------------
1892
1893-- Dump architecture description.
1894function _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)
1899end
1900
1901-- Dump all user defined elements.
1902function _M.dumpdef(out, lvl)
1903 dumptypes(out, lvl)
1904 dumpglobals(out, lvl)
1905 dumpexterns(out, lvl)
1906end
1907
1908------------------------------------------------------------------------------
1909
1910-- Pass callbacks from/to the DynASM core.
1911function _M.passcb(wl, we, wf, ww)
1912 wline, werror, wfatal, wwarn = wl, we, wf, ww
1913 return wflush
1914end
1915
1916-- Setup the arch-specific module.
1917function _M.setup(arch, opt)
1918 g_arch, g_opt = arch, opt
1919end
1920
1921-- Merge the core maps and the arch-specific maps.
1922function _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
1926end
1927
1928return _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.
10local _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 = [[
20Copyright (C) 2005-2011 Mike Pall. All rights reserved.
21
22Permission is hereby granted, free of charge, to any person obtaining
23a copy of this software and associated documentation files (the
24"Software"), to deal in the Software without restriction, including
25without limitation the rights to use, copy, modify, merge, publish,
26distribute, sublicense, and/or sell copies of the Software, and to
27permit persons to whom the Software is furnished to do so, subject to
28the following conditions:
29
30The above copyright notice and this permission notice shall be
31included in all copies or substantial portions of the Software.
32
33THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
34EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
35MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
36IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
37CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
38TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
39SOFTWARE 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.
46local type, pairs, ipairs = type, pairs, ipairs
47local pcall, error, assert = pcall, error, assert
48local _s = string
49local sub, match, gmatch, gsub = _s.sub, _s.match, _s.gmatch, _s.gsub
50local format, rep, upper = _s.format, _s.rep, _s.upper
51local _t = table
52local insert, remove, concat, sort = _t.insert, _t.remove, _t.concat, _t.sort
53local exit = os.exit
54local io = io
55local stdin, stdout, stderr = io.stdin, io.stdout, io.stderr
56
57------------------------------------------------------------------------------
58
59-- Program options.
60local g_opt = {}
61
62-- Global state for current file.
63local g_fname, g_curline, g_indent, g_lineno, g_synclineno, g_arch
64local g_errcount = 0
65
66-- Write buffer for output file.
67local g_wbuffer, g_capbuffer
68
69------------------------------------------------------------------------------
70
71-- Write an output line (or callback function) to the buffer.
72local 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
76end
77
78-- Write assembler line as a comment, if requestd.
79local function wcomment(aline)
80 if g_opt.comment then
81 wline(g_opt.comment..aline..g_opt.endcomment, true)
82 end
83end
84
85-- Resync CPP line numbers.
86local 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
91end
92
93-- Dummy action flush function. Replaced with arch-specific function later.
94local function wflush(term)
95end
96
97-- Dump all buffered output lines.
98local 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
107end
108
109------------------------------------------------------------------------------
110
111-- Emit an error. Processing continues with next statement.
112local function werror(msg)
113 error(format("%s:%s: error: %s:\n%s", g_fname, g_lineno, msg, g_curline), 0)
114end
115
116-- Emit a fatal error. Processing stops.
117local function wfatal(msg)
118 g_errcount = "fatal"
119 werror(msg)
120end
121
122-- Print a warning. Processing continues.
123local function wwarn(msg)
124 stderr:write(format("%s:%s: warning: %s:\n%s\n",
125 g_fname, g_lineno, msg, g_curline))
126end
127
128-- Print caught error message. But suppress excessive errors.
129local 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
144end
145
146------------------------------------------------------------------------------
147
148-- Map holding all option handlers.
149local opt_map = {}
150local opt_current
151
152-- Print error and exit with error status.
153local function opterror(...)
154 stderr:write("dynasm.lua: ERROR: ", ...)
155 stderr:write("\n")
156 exit(1)
157end
158
159-- Get option parameter.
160local 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
168end
169
170------------------------------------------------------------------------------
171
172-- Core pseudo-opcodes.
173local map_coreop = {}
174-- Dummy opcode map. Replaced by arch-specific map.
175local map_op = {}
176
177-- Forward declarations.
178local dostmt
179local readfile
180
181------------------------------------------------------------------------------
182
183-- Map for defines (initially empty, chains to arch-specific map).
184local map_def = {}
185
186-- Pseudo-opcode to define a substitution.
187map_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
192end
193map_coreop[".define_1"] = map_coreop[".define_2"]
194
195-- Define a substitution on the command line.
196function 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
206end
207
208-- Undefine a substitution on the command line.
209function 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
216end
217
218-- Helper for definesubst.
219local gotsubst
220
221local function definesubst_one(word)
222 local subst = map_def[word]
223 if subst then gotsubst = word; return subst else return word end
224end
225
226-- Iteratively substitute defines.
227local 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
236end
237
238-- Dump all defines.
239local 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")
252end
253
254------------------------------------------------------------------------------
255
256-- Support variables for conditional assembly.
257local condlevel = 0
258local condstack = {}
259
260-- Evaluate condition with a Lua expression. Substitutions already performed.
261local 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)
273end
274
275-- Skip statements until next conditional pseudo-opcode at the same level.
276local 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
290end
291
292-- Pseudo-opcodes for conditional assembly.
293map_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
300end
301
302map_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()
317end
318
319map_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
328end
329
330map_coreop[".endif_0"] = function(params)
331 local lvl = condlevel
332 if lvl == 0 then wfatal(".endif without .if") end
333 condlevel = lvl - 1
334end
335
336-- Check for unfinished conditionals.
337local function checkconds()
338 if g_errcount ~= "fatal" and condlevel ~= 0 then
339 wprinterr(g_fname, ":*: error: unbalanced conditional\n")
340 end
341end
342
343------------------------------------------------------------------------------
344
345-- Search for a file in the given path and open it for reading.
346local 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
356end
357
358-- Include a file.
359map_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
371end
372
373-- Make .include and conditionals initially available, too.
374map_op[".include_1"] = map_coreop[".include_1"]
375map_op[".if_1"] = map_coreop[".if_1"]
376map_op[".elif_1"] = map_coreop[".elif_1"]
377map_op[".else_0"] = map_coreop[".else_0"]
378map_op[".endif_0"] = map_coreop[".endif_0"]
379
380------------------------------------------------------------------------------
381
382-- Support variables for macros.
383local mac_capture, mac_lineno, mac_name
384local mac_active = {}
385local mac_list = {}
386
387-- Pseudo-opcode to define a macro.
388map_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
459end
460
461-- An .endmacro pseudo-opcode outside of a macro definition is an error.
462map_coreop[".endmacro_0"] = function(params)
463 wfatal(".endmacro without .macro")
464end
465
466-- Dump all macros and their contents (with -PP only).
467local 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")
482end
483
484-- Check for unfinished macro definitions.
485local function checkmacros()
486 if mac_capture then
487 wprinterr(g_fname, ":", mac_lineno,
488 ": error: unfinished .macro `", mac_name ,"'\n")
489 end
490end
491
492------------------------------------------------------------------------------
493
494-- Support variables for captures.
495local cap_lineno, cap_name
496local cap_buffers = {}
497local cap_used = {}
498
499-- Start a capture.
500map_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
517end
518
519-- Stop a capture.
520map_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
527end
528
529-- Dump a capture buffer.
530map_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
543end
544
545-- Dump all captures and their buffers (with -PP only).
546local 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")
560end
561
562-- Check for unfinished or unused captures.
563local 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
574end
575
576------------------------------------------------------------------------------
577
578-- Sections names.
579local map_sections = {}
580
581-- Pseudo-opcode to define code sections.
582-- TODO: Data sections, BSS sections. Needs extra C code and API.
583map_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))
598end
599
600-- Dump all sections.
601local 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")
607end
608
609------------------------------------------------------------------------------
610
611-- Load architecture-specific module.
612local 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)
620end
621
622-- Dump architecture description.
623function 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)
671end
672
673-- Pseudo-opcode to set the architecture.
674-- Only initially available (map_op is replaced when called).
675map_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
679end
680
681-- Dummy .arch pseudo-opcode to improve the error report.
682map_coreop[".arch_1"] = function(params)
683 if not params then return "name" end
684 wfatal("duplicate .arch statement")
685end
686
687------------------------------------------------------------------------------
688
689-- Dummy pseudo-opcode. Don't confuse '.nop' with 'nop'.
690map_coreop[".nop_*"] = function(params)
691 if not params then return "[ignored...]" end
692end
693
694-- Pseudo-opcodes to raise errors.
695map_coreop[".error_1"] = function(params)
696 if not params then return "message" end
697 werror(params[1])
698end
699
700map_coreop[".fatal_1"] = function(params)
701 if not params then return "message" end
702 wfatal(params[1])
703end
704
705-- Dump all user defined elements.
706local 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)
714end
715
716------------------------------------------------------------------------------
717
718-- Helper for splitstmt.
719local splitlvl
720
721local 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
735end
736
737-- Split statement into (pseudo-)opcode and params.
738local 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
761end
762
763-- Process a single statement.
764dostmt = 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
802end
803
804-- Process a single line.
805local 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
847end
848
849------------------------------------------------------------------------------
850
851-- Write DynASM header.
852local 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))
868end
869
870-- Read input file.
871readfile = 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())
887end
888
889-- Write output file.
890local 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)
908end
909
910-- Translate an input file to an output file.
911local 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)
949end
950
951------------------------------------------------------------------------------
952
953-- Print help text.
954function 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
959Usage: 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)
982end
983
984-- Print version information.
985function 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)
989end
990
991-- Misc. options.
992function opt_map.outfile(args) g_opt.outfile = optparam(args) end
993function opt_map.include(args) insert(g_opt.include, 1, optparam(args)) end
994function opt_map.ccomment() g_opt.comment = "/*|"; g_opt.endcomment = " */" end
995function opt_map.cppcomment() g_opt.comment = "//|"; g_opt.endcomment = "" end
996function opt_map.nocomment() g_opt.comment = false end
997function opt_map.maccomment() g_opt.maccomment = true end
998function opt_map.nolineno() g_opt.cpp = false end
999function opt_map.flushline() g_opt.flushline = true end
1000function opt_map.dumpdef() g_opt.dumpdef = g_opt.dumpdef + 1 end
1001
1002------------------------------------------------------------------------------
1003
1004-- Short aliases for long options.
1005local 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.
1014local 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)
1021end
1022
1023-- Parse arguments.
1024local 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)
1061end
1062
1063------------------------------------------------------------------------------
1064
1065-- Add the directory dynasm.lua resides in to the Lua module search path.
1066local arg = arg
1067if arg and arg[0] then
1068 local prefix = match(arg[0], "^(.*[/\\])")
1069 if prefix then package.path = prefix.."?.lua;"..package.path end
1070end
1071
1072-- Start DynASM.
1073parseargs{...}
1074
1075------------------------------------------------------------------------------
1076