aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/LuaJIT-1.1.7/dynasm
diff options
context:
space:
mode:
authorDavid Walter Seikel2012-01-23 23:36:30 +1000
committerDavid Walter Seikel2012-01-23 23:36:30 +1000
commit6523585c66c04cea54df50013df8886b589847d8 (patch)
tree0b22aee7064166d88595eda260ca2d17c0773da5 /libraries/LuaJIT-1.1.7/dynasm
parentUpdate the EFL to what I'm actually using, coz I'm using some stuff not yet r... (diff)
downloadSledjHamr-6523585c66c04cea54df50013df8886b589847d8.zip
SledjHamr-6523585c66c04cea54df50013df8886b589847d8.tar.gz
SledjHamr-6523585c66c04cea54df50013df8886b589847d8.tar.bz2
SledjHamr-6523585c66c04cea54df50013df8886b589847d8.tar.xz
Add luaproc and LuaJIT libraries.
Two versions of LuaJIT, the stable release, and the dev version. Try the dev version first, until ih fails badly.
Diffstat (limited to '')
-rw-r--r--libraries/LuaJIT-1.1.7/dynasm/dasm_proto.h68
-rw-r--r--libraries/LuaJIT-1.1.7/dynasm/dasm_x86.h455
-rw-r--r--libraries/LuaJIT-1.1.7/dynasm/dasm_x86.lua1581
-rw-r--r--libraries/LuaJIT-1.1.7/dynasm/dynasm.lua1070
4 files changed, 3174 insertions, 0 deletions
diff --git a/libraries/LuaJIT-1.1.7/dynasm/dasm_proto.h b/libraries/LuaJIT-1.1.7/dynasm/dasm_proto.h
new file mode 100644
index 0000000..c194cba
--- /dev/null
+++ b/libraries/LuaJIT-1.1.7/dynasm/dasm_proto.h
@@ -0,0 +1,68 @@
1/*
2** DynASM encoding engine prototypes.
3** Copyright (C) 2005-2008 Mike Pall. All rights reserved.
4** Released under the MIT/X 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_VERSION 10104 /* 1.1.4 */
14
15#ifndef Dst_DECL
16#define Dst_DECL dasm_State *Dst
17#endif
18
19#ifndef Dst_GET
20#define Dst_GET (Dst)
21#endif
22
23#ifndef DASM_FDEF
24#define DASM_FDEF extern
25#endif
26
27
28/* Internal DynASM encoder state. */
29typedef struct dasm_State dasm_State;
30
31/* Action list type. */
32typedef const unsigned char *dasm_ActList;
33
34
35/* Initialize and free DynASM state. */
36DASM_FDEF void dasm_init(Dst_DECL, int maxsection);
37DASM_FDEF void dasm_free(Dst_DECL);
38
39/* Setup global array. Must be called before dasm_setup(). */
40DASM_FDEF void dasm_setupglobal(Dst_DECL, void **gl, unsigned int maxgl);
41
42/* Grow PC label array. Can be called after dasm_setup(), too. */
43DASM_FDEF void dasm_growpc(Dst_DECL, unsigned int maxpc);
44
45/* Setup encoder. */
46DASM_FDEF void dasm_setup(Dst_DECL, dasm_ActList actionlist);
47
48/* Feed encoder with actions. Calls are generated by pre-processor. */
49DASM_FDEF void dasm_put(Dst_DECL, int start, ...);
50
51/* Link sections and return the resulting size. */
52DASM_FDEF int dasm_link(Dst_DECL, size_t *szp);
53
54/* Encode sections into buffer. */
55DASM_FDEF int dasm_encode(Dst_DECL, void *buffer);
56
57/* Get PC label offset. */
58DASM_FDEF int dasm_getpclabel(Dst_DECL, unsigned int pc);
59
60#ifdef DASM_CHECKS
61/* Optional sanity checker to call between isolated encoding steps. */
62DASM_FDEF int dasm_checkstep(Dst_DECL, int secmatch);
63#else
64#define dasm_checkstep(a, b) 0
65#endif
66
67
68#endif /* _DASM_PROTO_H */
diff --git a/libraries/LuaJIT-1.1.7/dynasm/dasm_x86.h b/libraries/LuaJIT-1.1.7/dynasm/dasm_x86.h
new file mode 100644
index 0000000..2d4fb26
--- /dev/null
+++ b/libraries/LuaJIT-1.1.7/dynasm/dasm_x86.h
@@ -0,0 +1,455 @@
1/*
2** DynASM x86 encoding engine.
3** Copyright (C) 2005-2008 Mike Pall. All rights reserved.
4** Released under the MIT/X 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/* Action definitions. DASM_STOP must be 255. */
15enum {
16 DASM_DISP = 235,
17 DASM_IMM_S, DASM_IMM_B, DASM_IMM_W, DASM_IMM_D, DASM_IMM_WB, DASM_IMM_DB,
18 DASM_SPACE, DASM_SETLABEL, DASM_REL_A, DASM_REL_LG, DASM_REL_PC, DASM_IMM_LG,
19 DASM_IMM_PC, DASM_LABEL_LG, DASM_LABEL_PC, DASM_ALIGN, DASM_ESC, DASM_MARK,
20 DASM_SECTION, DASM_STOP
21};
22
23/* Maximum number of section buffer positions for a single dasm_put() call. */
24#define DASM_MAXSECPOS 25
25
26/* DynASM encoder status codes. Action list offset or number are or'ed in. */
27#define DASM_S_OK 0x00000000
28#define DASM_S_NOMEM 0x01000000
29#define DASM_S_PHASE 0x02000000
30#define DASM_S_MATCH_SEC 0x03000000
31#define DASM_S_RANGE_I 0x11000000
32#define DASM_S_RANGE_SEC 0x12000000
33#define DASM_S_RANGE_LG 0x13000000
34#define DASM_S_RANGE_PC 0x14000000
35#define DASM_S_UNDEF_L 0x21000000
36#define DASM_S_UNDEF_PC 0x22000000
37
38/* Macros to convert positions (8 bit section + 24 bit index). */
39#define DASM_POS2IDX(pos) ((pos)&0x00ffffff)
40#define DASM_POS2BIAS(pos) ((pos)&0xff000000)
41#define DASM_SEC2POS(sec) ((sec)<<24)
42#define DASM_POS2SEC(pos) ((pos)>>24)
43#define DASM_POS2PTR(D, pos) (D->sections[DASM_POS2SEC(pos)].rbuf + (pos))
44
45/* Per-section structure. */
46typedef struct dasm_Section {
47 int *rbuf; /* Biased buffer pointer (negative section bias). */
48 int *buf; /* True buffer pointer. */
49 size_t bsize; /* Buffer size in bytes. */
50 int pos; /* Biased buffer position. */
51 int epos; /* End of biased buffer position - max single put. */
52 int ofs; /* Byte offset into section. */
53} dasm_Section;
54
55/* Core structure holding the DynASM encoding state. */
56struct dasm_State {
57 size_t psize; /* Allocated size of this structure. */
58 dasm_ActList actionlist; /* Current actionlist pointer. */
59 int *lglabels; /* Local/global chain/pos ptrs. */
60 size_t lgsize;
61 int *pclabels; /* PC label chains/pos ptrs. */
62 size_t pcsize;
63 void **globals; /* Array of globals (bias -10). */
64 dasm_Section *section; /* Pointer to active section. */
65 size_t codesize; /* Total size of all code sections. */
66 int maxsection; /* 0 <= sectionidx < maxsection. */
67 int status; /* Status code. */
68 dasm_Section sections[1]; /* All sections. Alloc-extended. */
69};
70
71/* The size of the core structure depends on the max. number of sections. */
72#define DASM_PSZ(ms) (sizeof(dasm_State)+(ms-1)*sizeof(dasm_Section))
73
74
75/* Initialize DynASM state. */
76void dasm_init(Dst_DECL, int maxsection)
77{
78 dasm_State *D;
79 size_t psz = 0;
80 int i;
81 Dst_REF = NULL;
82 DASM_M_GROW(Dst, struct dasm_State, Dst_REF, psz, DASM_PSZ(maxsection));
83 D = Dst_REF;
84 D->psize = psz;
85 D->lglabels = NULL;
86 D->lgsize = 0;
87 D->pclabels = NULL;
88 D->pcsize = 0;
89 D->globals = NULL;
90 D->maxsection = maxsection;
91 for (i = 0; i < maxsection; i++) {
92 D->sections[i].buf = NULL; /* Need this for pass3. */
93 D->sections[i].rbuf = D->sections[i].buf - DASM_SEC2POS(i);
94 D->sections[i].bsize = 0;
95 D->sections[i].epos = 0; /* Wrong, but is recalculated after resize. */
96 }
97}
98
99/* Free DynASM state. */
100void dasm_free(Dst_DECL)
101{
102 dasm_State *D = Dst_REF;
103 int i;
104 for (i = 0; i < D->maxsection; i++)
105 if (D->sections[i].buf)
106 DASM_M_FREE(Dst, D->sections[i].buf, D->sections[i].bsize);
107 if (D->pclabels) DASM_M_FREE(Dst, D->pclabels, D->pcsize);
108 if (D->lglabels) DASM_M_FREE(Dst, D->lglabels, D->lgsize);
109 DASM_M_FREE(Dst, D, D->psize);
110}
111
112/* Setup global label array. Must be called before dasm_setup(). */
113void dasm_setupglobal(Dst_DECL, void **gl, unsigned int maxgl)
114{
115 dasm_State *D = Dst_REF;
116 D->globals = gl - 10; /* Negative bias to compensate for locals. */
117 DASM_M_GROW(Dst, int, D->lglabels, D->lgsize, (10+maxgl)*sizeof(int));
118}
119
120/* Grow PC label array. Can be called after dasm_setup(), too. */
121void dasm_growpc(Dst_DECL, unsigned int maxpc)
122{
123 dasm_State *D = Dst_REF;
124 size_t osz = D->pcsize;
125 DASM_M_GROW(Dst, int, D->pclabels, D->pcsize, maxpc*sizeof(int));
126 memset((void *)(((unsigned char *)D->pclabels)+osz), 0, D->pcsize-osz);
127}
128
129/* Setup encoder. */
130void dasm_setup(Dst_DECL, dasm_ActList actionlist)
131{
132 dasm_State *D = Dst_REF;
133 int i;
134 D->actionlist = actionlist;
135 D->status = DASM_S_OK;
136 D->section = &D->sections[0];
137 memset((void *)D->lglabels, 0, D->lgsize);
138 if (D->pclabels) memset((void *)D->pclabels, 0, D->pcsize);
139 for (i = 0; i < D->maxsection; i++) {
140 D->sections[i].pos = DASM_SEC2POS(i);
141 D->sections[i].ofs = 0;
142 }
143}
144
145
146#ifdef DASM_CHECKS
147#define CK(x, st) \
148 do { if (!(x)) { \
149 D->status = DASM_S_##st|(p-D->actionlist-1); return; } } while (0)
150#define CKPL(kind, st) \
151 do { if ((size_t)((char *)pl-(char *)D->kind##labels) >= D->kind##size) { \
152 D->status = DASM_S_RANGE_##st|(p-D->actionlist-1); return; } } while (0)
153#else
154#define CK(x, st) ((void)0)
155#define CKPL(kind, st) ((void)0)
156#endif
157
158/* Pass 1: Store actions and args, link branches/labels, estimate offsets. */
159void dasm_put(Dst_DECL, int start, ...)
160{
161 va_list ap;
162 dasm_State *D = Dst_REF;
163 dasm_ActList p = D->actionlist + start;
164 dasm_Section *sec = D->section;
165 int pos = sec->pos, ofs = sec->ofs, mrm = 4;
166 int *b;
167
168 if (pos >= sec->epos) {
169 DASM_M_GROW(Dst, int, sec->buf, sec->bsize,
170 sec->bsize + 2*DASM_MAXSECPOS*sizeof(int));
171 sec->rbuf = sec->buf - DASM_POS2BIAS(pos);
172 sec->epos = sec->bsize/sizeof(int) - DASM_MAXSECPOS + DASM_POS2BIAS(pos);
173 }
174
175 b = sec->rbuf;
176 b[pos++] = start;
177
178 va_start(ap, start);
179 while (1) {
180 int action = *p++;
181 if (action < DASM_DISP) {
182 ofs++;
183 } else if (action <= DASM_REL_A) {
184 int n = va_arg(ap, int);
185 b[pos++] = n;
186 switch (action) {
187 case DASM_DISP:
188 if (n == 0) { if ((mrm&7) == 4) mrm = p[-2]; if ((mrm&7) != 5) break; }
189 case DASM_IMM_DB: if (((n+128)&-256) == 0) goto ob;
190 case DASM_REL_A: /* Assumes ptrdiff_t is int. !x64 */
191 case DASM_IMM_D: ofs += 4; break;
192 case DASM_IMM_S: CK(((n+128)&-256) == 0, RANGE_I); goto ob;
193 case DASM_IMM_B: CK((n&-256) == 0, RANGE_I); ob: ofs++; break;
194 case DASM_IMM_WB: if (((n+128)&-256) == 0) goto ob;
195 case DASM_IMM_W: CK((n&-65536) == 0, RANGE_I); ofs += 2; break;
196 case DASM_SPACE: p++; ofs += n; break;
197 case DASM_SETLABEL: b[pos-2] = -0x40000000; break; /* Neg. label ofs. */
198 }
199 mrm = 4;
200 } else {
201 int *pl, n;
202 switch (action) {
203 case DASM_REL_LG:
204 case DASM_IMM_LG:
205 n = *p++; pl = D->lglabels + n;
206 if (n <= 246) { CKPL(lg, LG); goto putrel; } /* Bkwd rel or global. */
207 pl -= 246; n = *pl;
208 if (n < 0) n = 0; /* Start new chain for fwd rel if label exists. */
209 goto linkrel;
210 case DASM_REL_PC:
211 case DASM_IMM_PC: pl = D->pclabels + va_arg(ap, int); CKPL(pc, PC);
212 putrel:
213 n = *pl;
214 if (n < 0) { /* Label exists. Get label pos and store it. */
215 b[pos] = -n;
216 } else {
217 linkrel:
218 b[pos] = n; /* Else link to rel chain, anchored at label. */
219 *pl = pos;
220 }
221 pos++;
222 ofs += 4; /* Maximum offset needed. */
223 if (action == DASM_REL_LG || action == DASM_REL_PC)
224 b[pos++] = ofs; /* Store pass1 offset estimate. */
225 break;
226 case DASM_LABEL_LG: pl = D->lglabels + *p++; CKPL(lg, LG); goto putlabel;
227 case DASM_LABEL_PC: pl = D->pclabels + va_arg(ap, int); CKPL(pc, PC);
228 putlabel:
229 n = *pl; /* n > 0: Collapse rel chain and replace with label pos. */
230 while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = pos; }
231 *pl = -pos; /* Label exists now. */
232 b[pos++] = ofs; /* Store pass1 offset estimate. */
233 break;
234 case DASM_ALIGN:
235 ofs += *p++; /* Maximum alignment needed (arg is 2**n-1). */
236 b[pos++] = ofs; /* Store pass1 offset estimate. */
237 break;
238 case DASM_ESC: p++; ofs++; break;
239 case DASM_MARK: mrm = p[-2]; break;
240 case DASM_SECTION:
241 n = *p; CK(n < D->maxsection, RANGE_SEC); D->section = &D->sections[n];
242 case DASM_STOP: goto stop;
243 }
244 }
245 }
246stop:
247 va_end(ap);
248 sec->pos = pos;
249 sec->ofs = ofs;
250}
251#undef CK
252
253/* Pass 2: Link sections, shrink branches/aligns, fix label offsets. */
254int dasm_link(Dst_DECL, size_t *szp)
255{
256 dasm_State *D = Dst_REF;
257 int secnum;
258 int ofs = 0;
259
260#ifdef DASM_CHECKS
261 *szp = 0;
262 if (D->status != DASM_S_OK) return D->status;
263 {
264 int pc;
265 for (pc = 0; pc*sizeof(int) < D->pcsize; pc++)
266 if (D->pclabels[pc] > 0) return DASM_S_UNDEF_PC|pc;
267 }
268#endif
269
270 { /* Handle globals not defined in this translation unit. */
271 int idx;
272 for (idx = 10; idx*sizeof(int) < D->lgsize; idx++) {
273 int n = D->lglabels[idx];
274 /* Undefined label: Collapse rel chain and replace with marker (< 0). */
275 while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = -idx; }
276 }
277 }
278
279 /* Combine all code sections. No support for data sections (yet). */
280 for (secnum = 0; secnum < D->maxsection; secnum++) {
281 dasm_Section *sec = D->sections + secnum;
282 int *b = sec->rbuf;
283 int pos = DASM_SEC2POS(secnum);
284 int lastpos = sec->pos;
285
286 while (pos != lastpos) {
287 dasm_ActList p = D->actionlist + b[pos++];
288 while (1) {
289 int op, action = *p++;
290 switch (action) {
291 case DASM_REL_LG: p++; op = p[-3]; goto rel_pc;
292 case DASM_REL_PC: op = p[-2]; rel_pc: {
293 int shrink = op == 0xe9 ? 3 : ((op&0xf0) == 0x80 ? 4 : 0);
294 if (shrink) { /* Shrinkable branch opcode? */
295 int lofs, lpos = b[pos];
296 if (lpos < 0) goto noshrink; /* Ext global? */
297 lofs = *DASM_POS2PTR(D, lpos);
298 if (lpos > pos) { /* Fwd label: add cumulative section offsets. */
299 int i;
300 for (i = secnum; i < DASM_POS2SEC(lpos); i++)
301 lofs += D->sections[i].ofs;
302 } else {
303 lofs -= ofs; /* Bkwd label: unfix offset. */
304 }
305 lofs -= b[pos+1]; /* Short branch ok? */
306 if (lofs >= -128-shrink && lofs <= 127) ofs -= shrink; /* Yes. */
307 else { noshrink: shrink = 0; } /* No, cannot shrink op. */
308 }
309 b[pos+1] = shrink;
310 pos += 2;
311 break;
312 }
313 case DASM_SPACE: case DASM_IMM_LG: p++;
314 case DASM_DISP: case DASM_IMM_S: case DASM_IMM_B: case DASM_IMM_W:
315 case DASM_IMM_D: case DASM_IMM_WB: case DASM_IMM_DB:
316 case DASM_SETLABEL: case DASM_REL_A: case DASM_IMM_PC: pos++; break;
317 case DASM_LABEL_LG: p++;
318 case DASM_LABEL_PC: b[pos++] += ofs; break; /* Fix label offset. */
319 case DASM_ALIGN: ofs -= (b[pos++]+ofs)&*p++; break; /* Adjust ofs. */
320 case DASM_ESC: p++;
321 case DASM_MARK: break;
322 case DASM_SECTION: case DASM_STOP: goto stop;
323 }
324 }
325 stop: (void)0;
326 }
327 ofs += sec->ofs; /* Next section starts right after current section. */
328 }
329
330 D->codesize = ofs; /* Total size of all code sections */
331 *szp = ofs;
332 return DASM_S_OK;
333}
334
335#define dasmb(x) *cp++ = (unsigned char)(x)
336#ifndef DASM_ALIGNED_WRITES
337#define dasmw(x) \
338 do { *((unsigned short *)cp) = (unsigned short)(x); cp+=2; } while (0)
339#define dasmd(x) \
340 do { *((unsigned int *)cp) = (unsigned int)(x); cp+=4; } while (0)
341#else
342#define dasmw(x) do { dasmb(x); dasmb((x)>>8); } while (0)
343#define dasmd(x) do { dasmw(x); dasmw((x)>>16); } while (0)
344#endif
345
346/* Pass 3: Encode sections. */
347int dasm_encode(Dst_DECL, void *buffer)
348{
349 dasm_State *D = Dst_REF;
350 unsigned char *base = (unsigned char *)buffer;
351 unsigned char *cp = base;
352 int secnum;
353
354 /* Encode all code sections. No support for data sections (yet). */
355 for (secnum = 0; secnum < D->maxsection; secnum++) {
356 dasm_Section *sec = D->sections + secnum;
357 int *b = sec->buf;
358 int *endb = sec->rbuf + sec->pos;
359
360 while (b != endb) {
361 dasm_ActList p = D->actionlist + *b++;
362 unsigned char *mark = NULL;
363 while (1) {
364 int action = *p++;
365 int n = (action >= DASM_DISP && action <= DASM_ALIGN) ? *b++ : 0;
366 switch (action) {
367 case DASM_DISP: if (!mark) mark = cp; {
368 unsigned char *mm = mark;
369 if (*p != DASM_IMM_DB && *p != DASM_IMM_WB) mark = NULL;
370 if (n == 0) { int mrm = mm[-1]&7; if (mrm == 4) mrm = mm[0]&7;
371 if (mrm != 5) { mm[-1] -= 0x80; break; } }
372 if (((n+128) & -256) != 0) goto wd; else mm[-1] -= 0x40;
373 }
374 case DASM_IMM_S: case DASM_IMM_B: wb: dasmb(n); break;
375 case DASM_IMM_DB: if (((n+128)&-256) == 0) {
376 db: if (!mark) mark = cp; mark[-2] += 2; mark = NULL; goto wb;
377 } else mark = NULL;
378 case DASM_IMM_D: wd: dasmd(n); break;
379 case DASM_IMM_WB: if (((n+128)&-256) == 0) goto db; else mark = NULL;
380 case DASM_IMM_W: dasmw(n); break;
381 case DASM_REL_LG: p++; if (n >= 0) goto rel_pc;
382 b++; n = (int)D->globals[-n];
383 case DASM_REL_A: rel_a: n -= (int)(cp+4); goto wd; /* !x64 */
384 case DASM_REL_PC: rel_pc: {
385 int shrink = *b++;
386 int *pb = DASM_POS2PTR(D, n); if (*pb < 0) { n = pb[1]; goto rel_a; }
387 n = *pb - ((cp-base) + 4-shrink);
388 if (shrink == 0) goto wd;
389 if (shrink == 4) { cp--; cp[-1] = *cp-0x10; } else cp[-1] = 0xeb;
390 goto wb;
391 }
392 case DASM_IMM_LG: p++; if (n < 0) { n = (int)D->globals[-n]; goto wd; }
393 case DASM_IMM_PC: {
394 int *pb = DASM_POS2PTR(D, n);
395 n = *pb < 0 ? pb[1] : (*pb + (ptrdiff_t)base);
396 goto wd;
397 }
398 case DASM_LABEL_LG: {
399 int idx = *p++;
400 if (idx >= 10)
401 D->globals[idx] = (void *)(base + (*p == DASM_SETLABEL ? *b : n));
402 break;
403 }
404 case DASM_LABEL_PC: case DASM_SETLABEL: break;
405 case DASM_SPACE: { int fill = *p++; while (n--) *cp++ = fill; break; }
406 case DASM_ALIGN:
407 n = *p++;
408 while (((cp-base) & n)) *cp++ = 0x90; /* nop */
409 break;
410 case DASM_MARK: mark = cp; break;
411 case DASM_ESC: action = *p++;
412 default: *cp++ = action; break;
413 case DASM_SECTION: case DASM_STOP: goto stop;
414 }
415 }
416 stop: (void)0;
417 }
418 }
419
420 if (base + D->codesize != cp) /* Check for phase errors. */
421 return DASM_S_PHASE;
422 return DASM_S_OK;
423}
424
425/* Get PC label offset. */
426int dasm_getpclabel(Dst_DECL, unsigned int pc)
427{
428 dasm_State *D = Dst_REF;
429 if (pc*sizeof(int) < D->pcsize) {
430 int pos = D->pclabels[pc];
431 if (pos < 0) return *DASM_POS2PTR(D, -pos);
432 if (pos > 0) return -1; /* Undefined. */
433 }
434 return -2; /* Unused or out of range. */
435}
436
437#ifdef DASM_CHECKS
438/* Optional sanity checker to call between isolated encoding steps. */
439int dasm_checkstep(Dst_DECL, int secmatch)
440{
441 dasm_State *D = Dst_REF;
442 if (D->status == DASM_S_OK) {
443 int i;
444 for (i = 1; i <= 9; i++) {
445 if (D->lglabels[i] > 0) { D->status = DASM_S_UNDEF_L|i; break; }
446 D->lglabels[i] = 0;
447 }
448 }
449 if (D->status == DASM_S_OK && secmatch >= 0 &&
450 D->section != &D->sections[secmatch])
451 D->status = DASM_S_MATCH_SEC|(D->section-D->sections);
452 return D->status;
453}
454#endif
455
diff --git a/libraries/LuaJIT-1.1.7/dynasm/dasm_x86.lua b/libraries/LuaJIT-1.1.7/dynasm/dasm_x86.lua
new file mode 100644
index 0000000..026c3b0
--- /dev/null
+++ b/libraries/LuaJIT-1.1.7/dynasm/dasm_x86.lua
@@ -0,0 +1,1581 @@
1------------------------------------------------------------------------------
2-- DynASM x86 module.
3--
4-- Copyright (C) 2005-2008 Mike Pall. All rights reserved.
5-- See dynasm.lua for full copyright notice.
6------------------------------------------------------------------------------
7
8-- Module information:
9local _info = {
10 arch = "x86",
11 description = "DynASM x86 (i386) module",
12 version = "1.1.4",
13 vernum = 10104,
14 release = "2008-01-29",
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, unpack = assert, unpack
25local _s = string
26local sub, format, byte, char = _s.sub, _s.format, _s.byte, _s.char
27local find, match, gmatch, gsub = _s.find, _s.match, _s.gmatch, _s.gsub
28local concat, sort = table.concat, table.sort
29local char, unpack = string.char, unpack
30
31-- Inherited tables and callbacks.
32local g_opt, g_arch
33local wline, werror, wfatal, wwarn
34
35-- Action name list.
36-- CHECK: Keep this in sync with the C code!
37local action_names = {
38 -- int arg, 1 buffer pos:
39 "DISP", "IMM_S", "IMM_B", "IMM_W", "IMM_D", "IMM_WB", "IMM_DB",
40 -- action arg (1 byte), int arg, 1 buffer pos (num):
41 "SPACE",
42 -- ptrdiff_t arg, 1 buffer pos (address): !x64
43 "SETLABEL", "REL_A",
44 -- action arg (1 byte) or int arg, 2 buffer pos (link, offset):
45 "REL_LG", "REL_PC",
46 -- action arg (1 byte) or int arg, 1 buffer pos (link):
47 "IMM_LG", "IMM_PC",
48 -- action arg (1 byte) or int arg, 1 buffer pos (offset):
49 "LABEL_LG", "LABEL_PC",
50 -- action arg (1 byte), 1 buffer pos (offset):
51 "ALIGN",
52 -- action arg (1 byte), no buffer pos.
53 "ESC",
54 -- no action arg, no buffer pos.
55 "MARK",
56 -- action arg (1 byte), no buffer pos, terminal action:
57 "SECTION",
58 -- no args, no buffer pos, terminal action:
59 "STOP"
60}
61
62-- Maximum number of section buffer positions for dasm_put().
63-- CHECK: Keep this in sync with the C code!
64local maxsecpos = 25 -- Keep this low, to avoid excessively long C lines.
65
66-- Action name -> action number (dynamically generated below).
67local map_action = {}
68-- First action number. Everything below does not need to be escaped.
69local actfirst = 256-#action_names
70
71-- Action list buffer and string (only used to remove dupes).
72local actlist = {}
73local actstr = ""
74
75-- Argument list for next dasm_put(). Start with offset 0 into action list.
76local actargs = { 0 }
77
78-- Current number of section buffer positions for dasm_put().
79local secpos = 1
80
81------------------------------------------------------------------------------
82
83-- Compute action numbers for action names.
84for n,name in ipairs(action_names) do
85 local num = actfirst + n - 1
86 map_action[name] = num
87end
88
89-- Dump action names and numbers.
90local function dumpactions(out)
91 out:write("DynASM encoding engine action codes:\n")
92 for n,name in ipairs(action_names) do
93 local num = map_action[name]
94 out:write(format(" %-10s %02X %d\n", name, num, num))
95 end
96 out:write("\n")
97end
98
99-- Write action list buffer as a huge static C array.
100local function writeactions(out, name)
101 local nn = #actlist
102 local last = actlist[nn] or 255
103 actlist[nn] = nil -- Remove last byte.
104 if nn == 0 then nn = 1 end
105 out:write("static const unsigned char ", name, "[", nn, "] = {\n")
106 local s = " "
107 for n,b in ipairs(actlist) do
108 s = s..b..","
109 if #s >= 75 then
110 assert(out:write(s, "\n"))
111 s = " "
112 end
113 end
114 out:write(s, last, "\n};\n\n") -- Add last byte back.
115end
116
117------------------------------------------------------------------------------
118
119-- Add byte to action list.
120local function wputxb(n)
121 assert(n >= 0 and n <= 255 and n % 1 == 0, "byte out of range")
122 actlist[#actlist+1] = n
123end
124
125-- Add action to list with optional arg. Advance buffer pos, too.
126local function waction(action, a, num)
127 wputxb(assert(map_action[action], "bad action name `"..action.."'"))
128 if a then actargs[#actargs+1] = a end
129 if a or num then secpos = secpos + (num or 1) end
130end
131
132-- Add call to embedded DynASM C code.
133local function wcall(func, args)
134 wline(format("dasm_%s(Dst, %s);", func, concat(args, ", ")), true)
135end
136
137-- Delete duplicate action list chunks. A tad slow, but so what.
138local function dedupechunk(offset)
139 local al, as = actlist, actstr
140 local chunk = char(unpack(al, offset+1, #al))
141 local orig = find(as, chunk, 1, true)
142 if orig then
143 actargs[1] = orig-1 -- Replace with original offset.
144 for i=offset+1,#al do al[i] = nil end -- Kill dupe.
145 else
146 actstr = as..chunk
147 end
148end
149
150-- Flush action list (intervening C code or buffer pos overflow).
151local function wflush(term)
152 local offset = actargs[1]
153 if #actlist == offset then return end -- Nothing to flush.
154 if not term then waction("STOP") end -- Terminate action list.
155 dedupechunk(offset)
156 wcall("put", actargs) -- Add call to dasm_put().
157 actargs = { #actlist } -- Actionlist offset is 1st arg to next dasm_put().
158 secpos = 1 -- The actionlist offset occupies a buffer position, too.
159end
160
161-- Put escaped byte.
162local function wputb(n)
163 if n >= actfirst then waction("ESC") end -- Need to escape byte.
164 wputxb(n)
165end
166
167------------------------------------------------------------------------------
168
169-- Global label name -> global label number. With auto assignment on 1st use.
170local next_global = 10
171local map_global = setmetatable({}, { __index = function(t, name)
172 if not match(name, "^[%a_][%w_]*$") then werror("bad global label") end
173 local n = next_global
174 if n > 246 then werror("too many global labels") end
175 next_global = n + 1
176 t[name] = n
177 return n
178end})
179
180-- Dump global labels.
181local function dumpglobals(out, lvl)
182 local t = {}
183 for name, n in pairs(map_global) do t[n] = name end
184 out:write("Global labels:\n")
185 for i=10,next_global-1 do
186 out:write(format(" %s\n", t[i]))
187 end
188 out:write("\n")
189end
190
191-- Write global label enum.
192local function writeglobals(out, prefix)
193 local t = {}
194 for name, n in pairs(map_global) do t[n] = name end
195 out:write("enum {\n")
196 for i=10,next_global-1 do
197 out:write(" ", prefix, t[i], ",\n")
198 end
199 out:write(" ", prefix, "_MAX\n};\n")
200end
201
202------------------------------------------------------------------------------
203
204-- Arch-specific maps.
205local map_archdef = {} -- Ext. register name -> int. name.
206local map_reg_rev = {} -- Int. register name -> ext. name.
207local map_reg_num = {} -- Int. register name -> register number.
208local map_reg_opsize = {} -- Int. register name -> operand size.
209local map_reg_valid_base = {} -- Int. register name -> valid base register?
210local map_reg_valid_index = {} -- Int. register name -> valid index register?
211local reg_list = {} -- Canonical list of int. register names.
212
213local map_type = {} -- Type name -> { ctype, reg }
214local ctypenum = 0 -- Type number (for _PTx macros).
215
216local addrsize = "d" -- Size for address operands. !x64
217
218-- Helper function to fill register maps.
219local function mkrmap(sz, names)
220 for n,name in ipairs(names) do
221 local iname = format("@%s%x", sz, n-1)
222 reg_list[#reg_list+1] = iname
223 map_archdef[name] = iname
224 map_reg_rev[iname] = name
225 map_reg_num[iname] = n-1
226 map_reg_opsize[iname] = sz
227 if sz == addrsize then
228 map_reg_valid_base[iname] = true
229 map_reg_valid_index[iname] = true
230 end
231 end
232 reg_list[#reg_list+1] = ""
233end
234
235-- Integer registers (dword, word and byte sized).
236mkrmap("d", {"eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"})
237map_reg_valid_index[map_archdef.esp] = nil
238mkrmap("w", {"ax", "cx", "dx", "bx", "sp", "bp", "si", "di"})
239mkrmap("b", {"al", "cl", "dl", "bl", "ah", "ch", "dh", "bh"})
240
241-- FP registers (internally tword sized, but use "f" as operand size).
242mkrmap("f", {"st0", "st1", "st2", "st3", "st4", "st5", "st6", "st7"})
243
244-- SSE registers (oword sized, but qword and dword accessible).
245mkrmap("o", {"xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7"})
246
247-- Operand size prefixes to codes.
248local map_opsize = {
249 byte = "b", word = "w", dword = "d", qword = "q", oword = "o", tword = "t",
250 aword = addrsize,
251}
252
253-- Operand size code to number.
254local map_opsizenum = {
255 b = 1, w = 2, d = 4, q = 8, o = 16, t = 10,
256}
257
258-- Operand size code to name.
259local map_opsizename = {
260 b = "byte", w = "word", d = "dword", q = "qword", o = "oword", t = "tword",
261 f = "fpword",
262}
263
264-- Valid index register scale factors.
265local map_xsc = {
266 ["1"] = 0, ["2"] = 1, ["4"] = 2, ["8"] = 3,
267}
268
269-- Condition codes.
270local map_cc = {
271 o = 0, no = 1, b = 2, nb = 3, e = 4, ne = 5, be = 6, nbe = 7,
272 s = 8, ns = 9, p = 10, np = 11, l = 12, nl = 13, le = 14, nle = 15,
273 c = 2, nae = 2, nc = 3, ae = 3, z = 4, nz = 5, na = 6, a = 7,
274 nge = 12, ge = 13, ng = 14, g = 15,
275}
276
277
278-- Reverse defines for registers.
279function _M.revdef(s)
280 return gsub(s, "@%w+", map_reg_rev)
281end
282
283-- Dump register names and numbers
284local function dumpregs(out)
285 out:write("Register names, sizes and internal numbers:\n")
286 for _,reg in ipairs(reg_list) do
287 if reg == "" then
288 out:write("\n")
289 else
290 local name = map_reg_rev[reg]
291 local num = map_reg_num[reg]
292 local opsize = map_opsizename[map_reg_opsize[reg]]
293 out:write(format(" %-5s %-8s %d\n", name, opsize, num))
294 end
295 end
296end
297
298------------------------------------------------------------------------------
299
300-- Put action for label arg (IMM_LG, IMM_PC, REL_LG, REL_PC).
301local function wputlabel(aprefix, imm, num)
302 if type(imm) == "number" then
303 waction(aprefix.."LG", nil, num);
304 wputxb(imm)
305 else
306 waction(aprefix.."PC", imm, num)
307 end
308end
309
310-- Put signed byte or arg.
311local function wputsbarg(n)
312 if type(n) == "number" then
313 if n < -128 or n > 127 then
314 werror("signed immediate byte out of range")
315 end
316 if n < 0 then n = n + 256 end
317 wputb(n)
318 else waction("IMM_S", n) end
319end
320
321-- Put unsigned byte or arg.
322local function wputbarg(n)
323 if type(n) == "number" then
324 if n < 0 or n > 255 then
325 werror("unsigned immediate byte out of range")
326 end
327 wputb(n)
328 else waction("IMM_B", n) end
329end
330
331-- Put unsigned word or arg.
332local function wputwarg(n)
333 if type(n) == "number" then
334 if n < 0 or n > 65535 then
335 werror("unsigned immediate word out of range")
336 end
337 local r = n%256; n = (n-r)/256; wputb(r); wputb(n);
338 else waction("IMM_W", n) end
339end
340
341-- Put signed or unsigned dword or arg.
342local function wputdarg(n)
343 local tn = type(n)
344 if tn == "number" then
345 if n < 0 then n = n + 4294967296 end
346 local r = n%256; n = (n-r)/256; wputb(r);
347 r = n%256; n = (n-r)/256; wputb(r);
348 r = n%256; n = (n-r)/256; wputb(r); wputb(n);
349 elseif tn == "table" then
350 wputlabel("IMM_", n[1], 1)
351 else
352 waction("IMM_D", n)
353 end
354end
355
356-- Put operand-size dependent number or arg (defaults to dword).
357local function wputszarg(sz, n)
358 if not sz or sz == "d" then wputdarg(n)
359 elseif sz == "w" then wputwarg(n)
360 elseif sz == "b" then wputbarg(n)
361 elseif sz == "s" then wputsbarg(n)
362 else werror("bad operand size") end
363end
364
365-- Put multi-byte opcode with operand-size dependent modifications.
366local function wputop(sz, op)
367 local r
368 if sz == "w" then wputb(102) end
369 if op >= 16777216 then r = op % 16777216 wputb((op-r) / 16777216) op = r end
370 if op >= 65536 then r = op % 65536 wputb((op-r) / 65536) op = r end
371 if op >= 256 then r = op % 256 wputb((op-r) / 256) op = r end
372 if sz == "b" then op = op - 1 end
373 wputb(op)
374end
375
376-- Put ModRM or SIB formatted byte.
377local function wputmodrm(m, s, rm)
378 assert(m < 4 and s < 8 and rm < 8, "bad modrm operands")
379 wputb(64*m + 8*s + rm)
380end
381
382-- Put ModRM/SIB plus optional displacement.
383local function wputmrmsib(t, s, imark)
384 -- Register mode.
385 if sub(t.mode, 1, 1) == "r" then
386 wputmodrm(3, s, t.reg)
387 return
388 end
389
390 local disp = t.disp
391 local tdisp = type(disp)
392 -- No base register?
393 if not t.reg then
394 if t.xreg then
395 -- Indexed mode with index register only.
396 wputmodrm(0, s, 4) -- [xreg*xsc+disp] -> (0, s, esp) (xsc, xreg, ebp)
397 wputmodrm(t.xsc, t.xreg, 5)
398 else
399 -- Pure displacement.
400 wputmodrm(0, s, 5) -- [disp] -> (0, s, ebp)
401 end
402 wputdarg(disp)
403 return
404 end
405
406 local m
407 if tdisp == "number" then -- Check displacement size at assembly time.
408 if disp == 0 and t.reg ~= 5 then m = 0 -- [ebp] -> [ebp+0] (in SIB, too)
409 elseif disp >= -128 and disp <= 127 then m = 1
410 else m = 2 end
411 elseif tdisp == "table" then
412 m = 2
413 end
414
415 -- Index register present or esp as base register: need SIB encoding.
416 if t.xreg or t.reg == 4 then
417 wputmodrm(m or 2, s, 4) -- ModRM.
418 if (m == nil or imark) and tdisp ~= "table" then waction("MARK") end
419 wputmodrm(t.xsc or 0, t.xreg or 4, t.reg) -- SIB.
420 else
421 wputmodrm(m or 2, s, t.reg) -- ModRM.
422 if imark and (m == 1 or m == 2) then waction("MARK") end
423 end
424
425 -- Put displacement.
426 if m == 1 then wputsbarg(disp)
427 elseif m == 2 then wputdarg(disp)
428 elseif not m then waction("DISP", disp) end
429end
430
431------------------------------------------------------------------------------
432
433-- Return human-readable operand mode string.
434local function opmodestr(op, args)
435 local m = {}
436 for i=1,#args do
437 local a = args[i]
438 m[#m+1] = sub(a.mode, 1, 1)..(a.opsize or "?")
439 end
440 return op.." "..concat(m, ",")
441end
442
443-- Convert number to valid integer or nil.
444local function toint(expr)
445 local n = tonumber(expr)
446 if n then
447 if n % 1 ~= 0 or n < -2147483648 or n > 4294967295 then
448 werror("bad integer number `"..expr.."'")
449 end
450 return n
451 end
452end
453
454-- Parse immediate expression.
455local function immexpr(expr)
456 -- &expr (pointer)
457 if sub(expr, 1, 1) == "&" then
458 return "iPJ", format("(ptrdiff_t)(%s)", sub(expr,2))
459 end
460
461 local prefix = sub(expr, 1, 2)
462 -- =>expr (pc label reference)
463 if prefix == "=>" then
464 return "iJ", sub(expr, 3)
465 end
466 -- ->name (global label reference)
467 if prefix == "->" then
468 return "iJ", map_global[sub(expr, 3)]
469 end
470
471 -- [<>][1-9] (local label reference)
472 local dir, lnum = match(expr, "^([<>])([1-9])$")
473 if dir then -- Fwd: 247-255, Bkwd: 1-9.
474 return "iJ", lnum + (dir == ">" and 246 or 0)
475 end
476
477 -- expr (interpreted as immediate)
478 return "iI", expr
479end
480
481-- Parse displacement expression: +-num, +-expr, +-opsize*num
482local function dispexpr(expr)
483 local disp = expr == "" and 0 or toint(expr)
484 if disp then return disp end
485 local c, dispt = match(expr, "^([+-])%s*(.+)$")
486 if c == "+" then
487 expr = dispt
488 elseif not c then
489 werror("bad displacement expression `"..expr.."'")
490 end
491 local opsize, tailops = match(dispt, "^(%w+)%s*%*%s*(.+)$")
492 local ops, imm = map_opsize[opsize], toint(tailops)
493 if ops and imm then
494 if c == "-" then imm = -imm end
495 return imm*map_opsizenum[ops]
496 end
497 local mode, iexpr = immexpr(dispt)
498 if mode == "iJ" then
499 if c == "-" then werror("cannot invert label reference") end
500 return { iexpr }
501 end
502 return expr -- Need to return original signed expression.
503end
504
505-- Parse register or type expression.
506local function rtexpr(expr)
507 if not expr then return end
508 local tname, ovreg = match(expr, "^([%w_]+):(@[%w_]+)$")
509 local tp = map_type[tname or expr]
510 if tp then
511 local reg = ovreg or tp.reg
512 local rnum = map_reg_num[reg]
513 if not rnum then
514 werror("type `"..(tname or expr).."' needs a register override")
515 end
516 if not map_reg_valid_base[reg] then
517 werror("bad base register override `"..(map_reg_rev[reg] or reg).."'")
518 end
519 return reg, rnum, tp
520 end
521 return expr, map_reg_num[expr]
522end
523
524-- Parse operand and return { mode, opsize, reg, xreg, xsc, disp, imm }.
525local function parseoperand(param)
526 local t = {}
527
528 local expr = param
529 local opsize, tailops = match(param, "^(%w+)%s*(.+)$")
530 if opsize then
531 t.opsize = map_opsize[opsize]
532 if t.opsize then expr = tailops end
533 end
534
535 local br = match(expr, "^%[%s*(.-)%s*%]$")
536 repeat
537 if br then
538 t.mode = "xm"
539
540 -- [disp]
541 t.disp = toint(br)
542 if t.disp then
543 t.mode = "xmO"
544 break
545 end
546
547 -- [reg...]
548 local tp
549 local reg, tailr = match(br, "^([@%w_:]+)%s*(.*)$")
550 reg, t.reg, tp = rtexpr(reg)
551 if not t.reg then
552 -- [expr]
553 t.mode = "xmO"
554 t.disp = dispexpr("+"..br)
555 break
556 end
557
558 -- [xreg*xsc] or [xreg*xsc+-disp] or [xreg*xsc+-expr]
559 local xsc, tailsc = match(tailr, "^%*%s*([1248])%s*(.*)$")
560 if xsc then
561 if not map_reg_valid_index[reg] then
562 werror("bad index register `"..map_reg_rev[reg].."'")
563 end
564 t.xsc = map_xsc[xsc]
565 t.xreg = t.reg
566 t.reg = nil
567 t.disp = dispexpr(tailsc)
568 break
569 end
570 if not map_reg_valid_base[reg] then
571 werror("bad base register `"..map_reg_rev[reg].."'")
572 end
573
574 -- [reg] or [reg+-disp]
575 t.disp = toint(tailr) or (tailr == "" and 0)
576 if t.disp then break end
577
578 -- [reg+xreg...]
579 local xreg, tailx = match(tailr, "^+%s*([@%w_:]+)%s*(.*)$")
580 xreg, t.xreg, tp = rtexpr(xreg)
581 if not t.xreg then
582 -- [reg+-expr]
583 t.disp = dispexpr(tailr)
584 break
585 end
586 if not map_reg_valid_index[xreg] then
587 werror("bad index register `"..map_reg_rev[xreg].."'")
588 end
589
590 -- [reg+xreg*xsc...]
591 local xsc, tailsc = match(tailx, "^%*%s*([1248])%s*(.*)$")
592 if xsc then
593 t.xsc = map_xsc[xsc]
594 tailx = tailsc
595 end
596
597 -- [...] or [...+-disp] or [...+-expr]
598 t.disp = dispexpr(tailx)
599 else
600 -- imm or opsize*imm
601 local imm = toint(expr)
602 if not imm and sub(expr, 1, 1) == "*" and t.opsize then
603 imm = toint(sub(expr, 2))
604 if imm then
605 imm = imm * map_opsizenum[t.opsize]
606 t.opsize = nil
607 end
608 end
609 if imm then
610 if t.opsize then werror("bad operand size override") end
611 local m = "i"
612 if imm == 1 then m = m.."1" end
613 if imm >= 4294967168 and imm <= 4294967295 then imm = imm-4294967296 end
614 if imm >= -128 and imm <= 127 then m = m.."S" end
615 t.imm = imm
616 t.mode = m
617 break
618 end
619
620 local tp
621 local reg, tailr = match(expr, "^([@%w_:]+)%s*(.*)$")
622 reg, t.reg, tp = rtexpr(reg)
623 if t.reg then
624 -- reg
625 if tailr == "" then
626 if t.opsize then werror("bad operand size override") end
627 t.opsize = map_reg_opsize[reg]
628 if t.opsize == "f" then
629 t.mode = t.reg == 0 and "fF" or "f"
630 else
631 if reg == "@w4" then wwarn("bad idea, try again with `esp'") end
632 t.mode = t.reg == 0 and "rmR" or (reg == "@b1" and "rmC" or "rm")
633 end
634 break
635 end
636
637 -- type[idx], type[idx].field, type->field -> [reg+offset_expr]
638 if not tp then werror("bad operand `"..param.."'") end
639 t.mode = "xm"
640 t.disp = format(tp.ctypefmt, tailr)
641 else
642 t.mode, t.imm = immexpr(expr)
643 if sub(t.mode, -1) == "J" then
644 if t.opsize and t.opsize ~= addrsize then
645 werror("bad operand size override")
646 end
647 t.opsize = addrsize
648 end
649 end
650 end
651 until true
652 return t
653end
654
655------------------------------------------------------------------------------
656-- x86 Template String Description
657-- ===============================
658--
659-- Each template string is a list of [match:]pattern pairs,
660-- separated by "|". The first match wins. No match means a
661-- bad or unsupported combination of operand modes or sizes.
662--
663-- The match part and the ":" is omitted if the operation has
664-- no operands. Otherwise the first N characters are matched
665-- against the mode strings of each of the N operands.
666--
667-- The mode string for each operand type is (see parseoperand()):
668-- Integer register: "rm", +"R" for eax, ax, al, +"C" for cl
669-- FP register: "f", +"F" for st0
670-- Index operand: "xm", +"O" for [disp] (pure offset)
671-- Immediate: "i", +"S" for signed 8 bit, +"1" for 1,
672-- +"I" for arg, +"P" for pointer
673-- Any: +"J" for valid jump targets
674--
675-- So a match character "m" (mixed) matches both an integer register
676-- and an index operand (to be encoded with the ModRM/SIB scheme).
677-- But "r" matches only a register and "x" only an index operand
678-- (e.g. for FP memory access operations).
679--
680-- The operand size match string starts right after the mode match
681-- characters and ends before the ":". "dwb" is assumed, if empty.
682-- The effective data size of the operation is matched against this list.
683--
684-- If only the regular "b", "w", "d", "q", "t" operand sizes are
685-- present, then all operands must be the same size. Unspecified sizes
686-- are ignored, but at least one operand must have a size or the pattern
687-- won't match (use the "byte", "word", "dword", "qword", "tword"
688-- operand size overrides. E.g.: mov dword [eax], 1).
689--
690-- If the list has a "1" or "2" prefix, the operand size is taken
691-- from the respective operand and any other operand sizes are ignored.
692-- If the list contains only ".", all operand sizes are ignored.
693-- If the list has a "/" prefix, the concatenated (mixed) operand sizes
694-- are compared to the match.
695--
696-- E.g. "rrdw" matches for either two dword registers or two word
697-- registers. "Fx2dq" matches an st0 operand plus an index operand
698-- pointing to a dword (float) or qword (double).
699--
700-- Every character after the ":" is part of the pattern string:
701-- Hex chars are accumulated to form the opcode (left to right).
702-- "n" disables the standard opcode mods
703-- (otherwise: -1 for "b", o16 prefix for "w")
704-- "r"/"R" adds the reg. number from the 1st/2nd operand to the opcode.
705-- "m"/"M" generates ModRM/SIB from the 1st/2nd operand.
706-- The spare 3 bits are either filled with the last hex digit or
707-- the result from a previous "r"/"R". The opcode is restored.
708--
709-- All of the following characters force a flush of the opcode:
710-- "o"/"O" stores a pure 32 bit disp (offset) from the 1st/2nd operand.
711-- "S" stores a signed 8 bit immediate from the last operand.
712-- "U" stores an unsigned 8 bit immediate from the last operand.
713-- "W" stores an unsigned 16 bit immediate from the last operand.
714-- "i" stores an operand sized immediate from the last operand.
715-- "I" dito, but generates an action code to optionally modify
716-- the opcode (+2) for a signed 8 bit immediate.
717-- "J" generates one of the REL action codes from the last operand.
718--
719------------------------------------------------------------------------------
720
721-- Template strings for x86 instructions. Ordered by first opcode byte.
722-- Unimplemented opcodes (deliberate omissions) are marked with *.
723local map_op = {
724 -- 00-05: add...
725 -- 06: *push es
726 -- 07: *pop es
727 -- 08-0D: or...
728 -- 0E: *push cs
729 -- 0F: two byte opcode prefix
730 -- 10-15: adc...
731 -- 16: *push ss
732 -- 17: *pop ss
733 -- 18-1D: sbb...
734 -- 1E: *push ds
735 -- 1F: *pop ds
736 -- 20-25: and...
737 es_0 = "26",
738 -- 27: *daa
739 -- 28-2D: sub...
740 cs_0 = "2E",
741 -- 2F: *das
742 -- 30-35: xor...
743 ss_0 = "36",
744 -- 37: *aaa
745 -- 38-3D: cmp...
746 ds_0 = "3E",
747 -- 3F: *aas
748 inc_1 = "rdw:40r|m:FF0m",
749 dec_1 = "rdw:48r|m:FF1m",
750 push_1 = "rdw:50r|mdw:FF6m|S.:6AS|ib:n6Ai|i.:68i",
751 pop_1 = "rdw:58r|mdw:8F0m",
752 -- 60: *pusha, *pushad, *pushaw
753 -- 61: *popa, *popad, *popaw
754 -- 62: *bound rdw,x
755 -- 63: *arpl mw,rw
756 fs_0 = "64",
757 gs_0 = "65",
758 o16_0 = "66",
759 a16_0 = "67",
760 -- 68: push idw
761 -- 69: imul rdw,mdw,idw
762 -- 6A: push ib
763 -- 6B: imul rdw,mdw,S
764 -- 6C: *insb
765 -- 6D: *insd, *insw
766 -- 6E: *outsb
767 -- 6F: *outsd, *outsw
768 -- 70-7F: jcc lb
769 -- 80: add... mb,i
770 -- 81: add... mdw,i
771 -- 82: *undefined
772 -- 83: add... mdw,S
773 test_2 = "mr:85Rm|rm:85rM|Ri:A9i|mi:F70mi",
774 -- 86: xchg rb,mb
775 -- 87: xchg rdw,mdw
776 -- 88: mov mb,r
777 -- 89: mov mdw,r
778 -- 8A: mov r,mb
779 -- 8B: mov r,mdw
780 -- 8C: *mov mdw,seg
781 lea_2 = "rxd:8DrM",
782 -- 8E: *mov seg,mdw
783 -- 8F: pop mdw
784 nop_0 = "90",
785 xchg_2 = "Rrdw:90R|rRdw:90r|rm:87rM|mr:87Rm",
786 cbw_0 = "6698",
787 cwde_0 = "98",
788 cwd_0 = "6699",
789 cdq_0 = "99",
790 -- 9A: *call iw:idw
791 wait_0 = "9B",
792 fwait_0 = "9B",
793 pushf_0 = "9C",
794 pushfw_0 = "669C",
795 pushfd_0 = "9C",
796 popf_0 = "9D",
797 popfw_0 = "669D",
798 popfd_0 = "9D",
799 sahf_0 = "9E",
800 lahf_0 = "9F",
801 mov_2 = "OR:A3o|RO:A1O|mr:89Rm|rm:8BrM|rib:nB0ri|ridw:B8ri|mi:C70mi",
802 movsb_0 = "A4",
803 movsw_0 = "66A5",
804 movsd_0 = "A5",
805 cmpsb_0 = "A6",
806 cmpsw_0 = "66A7",
807 cmpsd_0 = "A7",
808 -- A8: test Rb,i
809 -- A9: test Rdw,i
810 stosb_0 = "AA",
811 stosw_0 = "66AB",
812 stosd_0 = "AB",
813 lodsb_0 = "AC",
814 lodsw_0 = "66AD",
815 lodsd_0 = "AD",
816 scasb_0 = "AE",
817 scasw_0 = "66AF",
818 scasd_0 = "AF",
819 -- B0-B7: mov rb,i
820 -- B8-BF: mov rdw,i
821 -- C0: rol... mb,i
822 -- C1: rol... mdw,i
823 ret_1 = "i.:nC2W",
824 ret_0 = "C3",
825 -- C4: *les rdw,mq
826 -- C5: *lds rdw,mq
827 -- C6: mov mb,i
828 -- C7: mov mdw,i
829 -- C8: *enter iw,ib
830 leave_0 = "C9",
831 -- CA: *retf iw
832 -- CB: *retf
833 int3_0 = "CC",
834 int_1 = "i.:nCDU",
835 into_0 = "CE",
836 -- CF: *iret
837 -- D0: rol... mb,1
838 -- D1: rol... mdw,1
839 -- D2: rol... mb,cl
840 -- D3: rol... mb,cl
841 -- D4: *aam ib
842 -- D5: *aad ib
843 -- D6: *salc
844 -- D7: *xlat
845 -- D8-DF: floating point ops
846 -- E0: *loopne
847 -- E1: *loope
848 -- E2: *loop
849 -- E3: *jcxz, *jecxz
850 -- E4: *in Rb,ib
851 -- E5: *in Rdw,ib
852 -- E6: *out ib,Rb
853 -- E7: *out ib,Rdw
854 call_1 = "md:FF2m|J.:E8J",
855 jmp_1 = "md:FF4m|J.:E9J", -- short: EB
856 -- EA: *jmp iw:idw
857 -- EB: jmp ib
858 -- EC: *in Rb,dx
859 -- ED: *in Rdw,dx
860 -- EE: *out dx,Rb
861 -- EF: *out dx,Rdw
862 -- F0: *lock
863 int1_0 = "F1",
864 repne_0 = "F2",
865 repnz_0 = "F2",
866 rep_0 = "F3",
867 repe_0 = "F3",
868 repz_0 = "F3",
869 -- F4: *hlt
870 cmc_0 = "F5",
871 -- F6: test... mb,i; div... mb
872 -- F7: test... mdw,i; div... mdw
873 clc_0 = "F8",
874 stc_0 = "F9",
875 -- FA: *cli
876 cld_0 = "FC",
877 std_0 = "FD",
878 -- FE: inc... mb
879 -- FF: inc... mdw
880
881 -- misc ops
882 not_1 = "m:F72m",
883 neg_1 = "m:F73m",
884 mul_1 = "m:F74m",
885 imul_1 = "m:F75m",
886 div_1 = "m:F76m",
887 idiv_1 = "m:F77m",
888
889 imul_2 = "rmdw:0FAFrM|rIdw:69rmI|rSdw:6BrmS|ridw:69rmi",
890 imul_3 = "rmIdw:69rMI|rmSdw:6BrMS|rmidw:69rMi",
891
892 movzx_2 = "rm/db:0FB6rM|rm/wb:0FB6rM|rm/dw:0FB7rM",
893 movsx_2 = "rm/db:0FBErM|rm/wb:0FBErM|rm/dw:0FBFrM",
894
895 bswap_1 = "rd:0FC8r",
896 bsf_2 = "rmdw:0FBCrM",
897 bsr_2 = "rmdw:0FBDrM",
898 bt_2 = "mrdw:0FA3Rm|midw:0FBA4mU",
899 btc_2 = "mrdw:0FBBRm|midw:0FBA7mU",
900 btr_2 = "mrdw:0FB3Rm|midw:0FBA6mU",
901 bts_2 = "mrdw:0FABRm|midw:0FBA5mU",
902
903 rdtsc_0 = "0F31", -- P1+
904 cpuid_0 = "0FA2", -- P1+
905
906 -- floating point ops
907 fst_1 = "ff:DDD0r|xd:D92m|xq:DD2m",
908 fstp_1 = "ff:DDD8r|xd:D93m|xq:DD3m|xt:DB7m",
909 fld_1 = "ff:D9C0r|xd:D90m|xq:DD0m|xt:DB5m",
910
911 fpop_0 = "DDD8", -- Alias for fstp st0.
912
913 fist_1 = "xw:nDF2m|xd:DB2m",
914 fistp_1 = "xw:nDF3m|xd:DB3m|xq:DF7m",
915 fisttp_1 = "xw:nDF1m|xd:DB1m|xq:DD1m", -- SSE3
916 fild_1 = "xw:nDF0m|xd:DB0m|xq:DF5m",
917
918 fxch_0 = "D9C9",
919 fxch_1 = "ff:D9C8r",
920 fxch_2 = "fFf:D9C8r|Fff:D9C8R",
921
922 fucom_1 = "ff:DDE0r",
923 fucom_2 = "Fff:DDE0R",
924 fucomp_1 = "ff:DDE8r",
925 fucomp_2 = "Fff:DDE8R",
926 fucomi_1 = "ff:DBE8r", -- P6+
927 fucomi_2 = "Fff:DBE8R", -- P6+
928 fucomip_1 = "ff:DFE8r", -- P6+
929 fucomip_2 = "Fff:DFE8R", -- P6+
930 fcomi_1 = "ff:DBF0r", -- P6+
931 fcomi_2 = "Fff:DBF0R", -- P6+
932 fcomip_1 = "ff:DFF0r", -- P6+
933 fcomip_2 = "Fff:DFF0R", -- P6+
934 fucompp_0 = "DAE9",
935 fcompp_0 = "DED9",
936
937 fldcw_1 = "xw:nD95m",
938 fstcw_1 = "xw:n9BD97m",
939 fnstcw_1 = "xw:nD97m",
940 fstsw_1 = "Rw:n9BDFE0|xw:n9BDD7m",
941 fnstsw_1 = "Rw:nDFE0|xw:nDD7m",
942 fclex_0 = "9BDBE2",
943 fnclex_0 = "DBE2",
944
945 fnop_0 = "D9D0",
946 -- D9D1-D9DF: unassigned
947
948 fchs_0 = "D9E0",
949 fabs_0 = "D9E1",
950 -- D9E2: unassigned
951 -- D9E3: unassigned
952 ftst_0 = "D9E4",
953 fxam_0 = "D9E5",
954 -- D9E6: unassigned
955 -- D9E7: unassigned
956 fld1_0 = "D9E8",
957 fldl2t_0 = "D9E9",
958 fldl2e_0 = "D9EA",
959 fldpi_0 = "D9EB",
960 fldlg2_0 = "D9EC",
961 fldln2_0 = "D9ED",
962 fldz_0 = "D9EE",
963 -- D9EF: unassigned
964
965 f2xm1_0 = "D9F0",
966 fyl2x_0 = "D9F1",
967 fptan_0 = "D9F2",
968 fpatan_0 = "D9F3",
969 fxtract_0 = "D9F4",
970 fprem1_0 = "D9F5",
971 fdecstp_0 = "D9F6",
972 fincstp_0 = "D9F7",
973 fprem_0 = "D9F8",
974 fyl2xp1_0 = "D9F9",
975 fsqrt_0 = "D9FA",
976 fsincos_0 = "D9FB",
977 frndint_0 = "D9FC",
978 fscale_0 = "D9FD",
979 fsin_0 = "D9FE",
980 fcos_0 = "D9FF",
981
982 -- SSE, SSE2, SSE3, SSSE3 ops
983 addsubpd_2 = "rmo:660FD0rM",
984 addsubps_2 = "rmo:F20FD0rM",
985 andnpd_2 = "rmo:660F55rM",
986 andnps_2 = "rmo:0F55rM",
987 andpd_2 = "rmo:660F54rM",
988 andps_2 = "rmo:0F54rM",
989 clflush_1 = "x.:0FAE7m",
990 cmppd_3 = "rmio:660FC2rMU",
991 cmpps_3 = "rmio:0FC2rMU",
992 cmpsd_3 = "rmio:F20FC2rMU",
993 cmpss_3 = "rmio:F30FC2rMU",
994 comisd_2 = "rmo:660F2FrM",
995 comiss_2 = "rmo:0F2FrM",
996 cvtdq2pd_2 = "rro:F30FE6rM|rx/oq:",
997 cvtdq2ps_2 = "rmo:0F5BrM",
998 cvtpd2dq_2 = "rmo:F20FE6rM",
999 cvtpd2ps_2 = "rmo:660F5ArM",
1000 cvtpi2pd_2 = "rx/oq:660F2ArM",
1001 cvtpi2ps_2 = "rx/oq:0F2ArM",
1002 cvtps2dq_2 = "rmo:660F5BrM",
1003 cvtps2pd_2 = "rro:0F5ArM|rx/oq:",
1004 cvtsd2si_2 = "rr/do:F20F2DrM|rx/dq:",
1005 cvtsd2ss_2 = "rro:F20F5ArM|rx/oq:",
1006 cvtsi2sd_2 = "rm/od:F20F2ArM",
1007 cvtsi2ss_2 = "rm/od:F30F2ArM",
1008 cvtss2sd_2 = "rro:F30F5ArM|rx/od:",
1009 cvtss2si_2 = "rr/do:F20F2CrM|rx/dd:",
1010 cvttpd2dq_2 = "rmo:660FE6rM",
1011 cvttps2dq_2 = "rmo:F30F5BrM",
1012 cvttsd2si_2 = "rr/do:F20F2CrM|rx/dq:",
1013 cvttss2si_2 = "rr/do:F30F2CrM|rx/dd:",
1014 haddpd_2 = "rmo:660F7CrM",
1015 haddps_2 = "rmo:F20F7CrM",
1016 hsubpd_2 = "rmo:660F7DrM",
1017 hsubps_2 = "rmo:F20F7DrM",
1018 lddqu_2 = "rxo:F20FF0rM",
1019 ldmxcsr_1 = "xd:0FAE2m",
1020 lfence_0 = "0FAEE8",
1021 maskmovdqu_2 = "rro:660FF7rM",
1022 mfence_0 = "0FAEF0",
1023 movapd_2 = "rmo:660F28rM|mro:660F29Rm",
1024 movaps_2 = "rmo:0F28rM|mro:0F29Rm",
1025 movd_2 = "rm/od:660F6ErM|mr/do:660F7ERm",
1026 movddup_2 = "rmo:F20F12rM",
1027 movdqa_2 = "rmo:660F6FrM|mro:660F7FRm",
1028 movdqu_2 = "rmo:F30F6FrM|mro:F30F7FRm",
1029 movhlps_2 = "rro:0F12rM",
1030 movhpd_2 = "rx/oq:660F16rM|xr/qo:660F17Rm",
1031 movhps_2 = "rx/oq:0F16rM|xr/qo:0F17Rm",
1032 movlhps_2 = "rro:0F16rM",
1033 movlpd_2 = "rx/oq:660F12rM|xr/qo:660F13Rm",
1034 movlps_2 = "rx/oq:0F12rM|xr/qo:0F13Rm",
1035 movmskpd_2 = "rr/do:660F50rM",
1036 movmskps_2 = "rr/do:0F50rM",
1037 movntdq_2 = "xro:660FE7Rm",
1038 movnti_2 = "xrd:0FC3Rm",
1039 movntpd_2 = "xro:660F2BRm",
1040 movntps_2 = "xro:0F2BRm",
1041 movq_2 = "rro:F30F7ErM|rx/oq:|xr/qo:660FD6Rm",
1042 movsd_2 = "rro:F20F10rM|rx/oq:|xr/qo:F20F11Rm",
1043 movshdup_2 = "rmo:F30F16rM",
1044 movsldup_2 = "rmo:F30F12rM",
1045 movss_2 = "rro:F30F10rM|rx/od:|xr/do:F30F11Rm",
1046 movupd_2 = "rmo:660F10rM|mro:660F11Rm",
1047 movups_2 = "rmo:0F10rM|mro:0F11Rm",
1048 orpd_2 = "rmo:660F56rM",
1049 orps_2 = "rmo:0F56rM",
1050 pabsb_2 = "rmo:660F381CrM",
1051 pabsd_2 = "rmo:660F381ErM",
1052 pabsw_2 = "rmo:660F381DrM",
1053 packssdw_2 = "rmo:660F6BrM",
1054 packsswb_2 = "rmo:660F63rM",
1055 packuswb_2 = "rmo:660F67rM",
1056 paddb_2 = "rmo:660FFCrM",
1057 paddd_2 = "rmo:660FFErM",
1058 paddq_2 = "rmo:660FD4rM",
1059 paddsb_2 = "rmo:660FECrM",
1060 paddsw_2 = "rmo:660FEDrM",
1061 paddusb_2 = "rmo:660FDCrM",
1062 paddusw_2 = "rmo:660FDDrM",
1063 paddw_2 = "rmo:660FFDrM",
1064 palignr_3 = "rmio:660F3A0FrMU",
1065 pand_2 = "rmo:660FDBrM",
1066 pandn_2 = "rmo:660FDFrM",
1067 pause_0 = "F390",
1068 pavgb_2 = "rmo:660FE0rM",
1069 pavgw_2 = "rmo:660FE3rM",
1070 pcmpeqb_2 = "rmo:660F74rM",
1071 pcmpeqd_2 = "rmo:660F76rM",
1072 pcmpeqw_2 = "rmo:660F75rM",
1073 pcmpgtb_2 = "rmo:660F64rM",
1074 pcmpgtd_2 = "rmo:660F66rM",
1075 pcmpgtw_2 = "rmo:660F65rM",
1076 pextrw_3 = "rri/do:660FC5rMU",
1077 phaddd_2 = "rmo:660F3802rM",
1078 phaddsw_2 = "rmo:660F3803rM",
1079 phaddw_2 = "rmo:660F3801rM",
1080 phsubd_2 = "rmo:660F3806rM",
1081 phsubsw_2 = "rmo:660F3807rM",
1082 phsubw_2 = "rmo:660F3805rM",
1083 pinsrw_3 = "rri/od:660FC4rMU|rmi/ow:",
1084 pmaddubsw_2 = "rmo:660F3804rM",
1085 pmaddwd_2 = "rmo:660FF5rM",
1086 pmaxsw_2 = "rmo:660FEErM",
1087 pmaxub_2 = "rmo:660FDErM",
1088 pminsw_2 = "rmo:660FEArM",
1089 pminub_2 = "rmo:660FDArM",
1090 pmovmskb_2 = "rr/do:660FD7rM",
1091 pmulhrsw_2 = "rmo:660F380BrM",
1092 pmulhuw_2 = "rmo:660FE4rM",
1093 pmulhw_2 = "rmo:660FE5rM",
1094 pmullw_2 = "rmo:660FD5rM",
1095 pmuludq_2 = "rmo:660FF4rM",
1096 por_2 = "rmo:660FEBrM",
1097 prefetchnta_1 = "xb:n0F180m",
1098 prefetcht0_1 = "xb:n0F181m",
1099 prefetcht1_1 = "xb:n0F182m",
1100 prefetcht2_1 = "xb:n0F183m",
1101 psadbw_2 = "rmo:660FF6rM",
1102 pshufb_2 = "rmo:660F3800rM",
1103 pshufd_3 = "rmio:660F70rMU",
1104 pshufhw_3 = "rmio:F30F70rMU",
1105 pshuflw_3 = "rmio:F20F70rMU",
1106 psignb_2 = "rmo:660F3808rM",
1107 psignd_2 = "rmo:660F380ArM",
1108 psignw_2 = "rmo:660F3809rM",
1109 pslld_2 = "rmo:660FF2rM|rio:660F726mU",
1110 pslldq_2 = "rio:660F737mU",
1111 psllq_2 = "rmo:660FF3rM|rio:660F736mU",
1112 psllw_2 = "rmo:660FF1rM|rio:660F716mU",
1113 psrad_2 = "rmo:660FE2rM|rio:660F724mU",
1114 psraw_2 = "rmo:660FE1rM|rio:660F714mU",
1115 psrld_2 = "rmo:660FD2rM|rio:660F722mU",
1116 psrldq_2 = "rio:660F733mU",
1117 psrlq_2 = "rmo:660FD3rM|rio:660F732mU",
1118 psrlw_2 = "rmo:660FD1rM|rio:660F712mU",
1119 psubb_2 = "rmo:660FF8rM",
1120 psubd_2 = "rmo:660FFArM",
1121 psubq_2 = "rmo:660FFBrM",
1122 psubsb_2 = "rmo:660FE8rM",
1123 psubsw_2 = "rmo:660FE9rM",
1124 psubusb_2 = "rmo:660FD8rM",
1125 psubusw_2 = "rmo:660FD9rM",
1126 psubw_2 = "rmo:660FF9rM",
1127 punpckhbw_2 = "rmo:660F68rM",
1128 punpckhdq_2 = "rmo:660F6ArM",
1129 punpckhqdq_2 = "rmo:660F6DrM",
1130 punpckhwd_2 = "rmo:660F69rM",
1131 punpcklbw_2 = "rmo:660F60rM",
1132 punpckldq_2 = "rmo:660F62rM",
1133 punpcklqdq_2 = "rmo:660F6CrM",
1134 punpcklwd_2 = "rmo:660F61rM",
1135 pxor_2 = "rmo:660FEFrM",
1136 rcpps_2 = "rmo:0F53rM",
1137 rcpss_2 = "rmo:F30F53rM",
1138 rsqrtps_2 = "rmo:0F52rM",
1139 rsqrtss_2 = "rmo:F30F52rM",
1140 sfence_0 = "0FAEF8",
1141 shufpd_3 = "rmio:660FC6rMU",
1142 shufps_3 = "rmio:0FC6rMU",
1143 stmxcsr_1 = "xd:0FAE3m",
1144 ucomisd_2 = "rmo:660F2ErM",
1145 ucomiss_2 = "rmo:0F2ErM",
1146 unpckhpd_2 = "rmo:660F15rM",
1147 unpckhps_2 = "rmo:0F15rM",
1148 unpcklpd_2 = "rmo:660F14rM",
1149 unpcklps_2 = "rmo:0F14rM",
1150 xorpd_2 = "rmo:660F57rM",
1151 xorps_2 = "rmo:0F57rM",
1152}
1153
1154------------------------------------------------------------------------------
1155
1156-- Arithmetic ops.
1157for name,n in pairs{ add = 0, ["or"] = 1, adc = 2, sbb = 3,
1158 ["and"] = 4, sub = 5, xor = 6, cmp = 7 } do
1159 local n8 = n * 8
1160 map_op[name.."_2"] = format(
1161 "mr:%02XRm|rm:%02XrM|mI1dw:81%XmI|mS1dw:83%XmS|Ri1dwb:%02Xi|mi1dwb:81%Xmi",
1162 1+n8, 3+n8, n, n, 5+n8, n)
1163end
1164
1165-- Shift ops.
1166for name,n in pairs{ rol = 0, ror = 1, rcl = 2, rcr = 3,
1167 shl = 4, shr = 5, sar = 7, sal = 4 } do
1168 map_op[name.."_2"] = format("m1:D1%Xm|mC1dwb:D3%Xm|mi:C1%XmU", n, n, n)
1169end
1170
1171-- Conditional ops.
1172for cc,n in pairs(map_cc) do
1173 map_op["j"..cc.."_1"] = format("J.:0F8%XJ", n) -- short: 7%X
1174 map_op["set"..cc.."_1"] = format("mb:n0F9%X2m", n)
1175 map_op["cmov"..cc.."_2"] = format("rmdw:0F4%XrM", n) -- P6+
1176end
1177
1178-- FP arithmetic ops.
1179for name,n in pairs{ add = 0, mul = 1, com = 2, comp = 3,
1180 sub = 4, subr = 5, div = 6, divr = 7 } do
1181 local nc = 192 + n * 8
1182 local nr = nc + (n < 4 and 0 or (n % 2 == 0 and 8 or -8))
1183 local fn = "f"..name
1184 map_op[fn.."_1"] = format("ff:D8%02Xr|xd:D8%Xm|xq:DC%Xm", nc, n, n)
1185 if n == 2 or n == 3 then
1186 map_op[fn.."_2"] = format("Fff:D8%02XR|Fx2d:D8%XM|Fx2q:DC%XM", nc, n, n)
1187 else
1188 map_op[fn.."_2"] = format("Fff:D8%02XR|fFf:DC%02Xr|Fx2d:D8%XM|Fx2q:DC%XM", nc, nr, n, n)
1189 map_op[fn.."p_1"] = format("ff:DE%02Xr", nr)
1190 map_op[fn.."p_2"] = format("fFf:DE%02Xr", nr)
1191 end
1192 map_op["fi"..name.."_1"] = format("xd:DA%Xm|xw:nDE%Xm", n, n)
1193end
1194
1195-- FP conditional moves.
1196for cc,n in pairs{ b=0, e=1, be=2, u=3, nb=4, ne=5, nbe=6, nu=7 } do
1197 local n4 = n % 4
1198 local nc = 56000 + n4 * 8 + (n-n4) * 64
1199 map_op["fcmov"..cc.."_1"] = format("ff:%04Xr", nc) -- P6+
1200 map_op["fcmov"..cc.."_2"] = format("Fff:%04XR", nc) -- P6+
1201end
1202
1203-- SSE FP arithmetic ops.
1204for name,n in pairs{ sqrt = 1, add = 8, mul = 9,
1205 sub = 12, min = 13, div = 14, max = 15 } do
1206 map_op[name.."ps_2"] = format("rmo:0F5%XrM", n)
1207 map_op[name.."ss_2"] = format("rro:F30F5%XrM|rx/od:", n)
1208 map_op[name.."pd_2"] = format("rmo:660F5%XrM", n)
1209 map_op[name.."sd_2"] = format("rro:F20F5%XrM|rx/oq:", n)
1210end
1211
1212------------------------------------------------------------------------------
1213
1214-- Process pattern string.
1215local function dopattern(pat, args, sz, op)
1216 local digit, addin
1217 local opcode = 0
1218 local szov = sz
1219
1220 -- Limit number of section buffer positions used by a single dasm_put().
1221 -- A single opcode needs a maximum of 2 positions. !x64
1222 if secpos+2 > maxsecpos then wflush() end
1223
1224 -- Process each character.
1225 for c in gmatch(pat, ".") do
1226 if match(c, "%x") then -- Hex digit.
1227 digit = byte(c) - 48
1228 if digit > 48 then digit = digit - 39
1229 elseif digit > 16 then digit = digit - 7 end
1230 opcode = opcode*16 + digit
1231 addin = nil
1232 elseif c == "n" then -- Disable operand size mods for opcode.
1233 szov = nil
1234 elseif c == "r" then -- Merge 1st operand regno. into opcode.
1235 addin = args[1].reg; opcode = opcode + addin
1236 elseif c == "R" then -- Merge 2nd operand regno. into opcode.
1237 addin = args[2].reg; opcode = opcode + addin
1238 elseif c == "m" or c == "M" then -- Encode ModRM/SIB.
1239 if addin then
1240 opcode = opcode - addin -- Undo regno opcode merge.
1241 else
1242 addin = opcode % 16 -- Undo last digit.
1243 opcode = (opcode - addin) / 16
1244 end
1245 wputop(szov, opcode); opcode = nil
1246 local imark = (sub(pat, -1) == "I") -- Force a mark (ugly).
1247 -- Put ModRM/SIB with regno/last digit as spare.
1248 wputmrmsib(args[c == "m" and 1 or 2], addin, imark)
1249 else
1250 if opcode then wputop(szov, opcode); opcode = nil end -- Flush opcode.
1251 if c == "o" or c == "O" then -- Offset (pure 32 bit displacement).
1252 wputdarg(args[c == "o" and 1 or 2].disp)
1253 else
1254 -- Anything else is an immediate operand.
1255 local a = args[#args]
1256 local mode, imm = a.mode, a.imm
1257 if mode == "iJ" and not match("iIJ", c) then
1258 werror("bad operand size for label")
1259 end
1260 if c == "S" then
1261 wputsbarg(imm)
1262 elseif c == "U" then
1263 wputbarg(imm)
1264 elseif c == "W" then
1265 wputwarg(imm)
1266 elseif c == "i" or c == "I" then
1267 if mode == "iJ" then
1268 wputlabel("IMM_", imm, 1)
1269 elseif mode == "iI" and c == "I" then
1270 waction(sz == "w" and "IMM_WB" or "IMM_DB", imm)
1271 else
1272 wputszarg(sz, imm)
1273 end
1274 elseif c == "J" then
1275 if mode == "iPJ" then
1276 waction("REL_A", imm) -- !x64 (secpos)
1277 else
1278 wputlabel("REL_", imm, 2)
1279 end
1280 else
1281 werror("bad char `"..c.."' in pattern `"..pat.."' for `"..op.."'")
1282 end
1283 end
1284 end
1285 end
1286 if opcode then wputop(szov, opcode) end
1287end
1288
1289------------------------------------------------------------------------------
1290
1291-- Mapping of operand modes to short names. Suppress output with '#'.
1292local map_modename = {
1293 r = "reg", R = "eax", C = "cl", x = "mem", m = "mrm", i = "imm",
1294 f = "stx", F = "st0", J = "lbl", ["1"] = "1",
1295 I = "#", S = "#", O = "#",
1296}
1297
1298-- Return a table/string showing all possible operand modes.
1299local function templatehelp(template, nparams)
1300 if nparams == 0 then return "" end
1301 local t = {}
1302 for tm in gmatch(template, "[^%|]+") do
1303 local s = map_modename[sub(tm, 1, 1)]
1304 s = s..gsub(sub(tm, 2, nparams), ".", function(c)
1305 return ", "..map_modename[c]
1306 end)
1307 if not match(s, "#") then t[#t+1] = s end
1308 end
1309 return t
1310end
1311
1312-- Match operand modes against mode match part of template.
1313local function matchtm(tm, args)
1314 for i=1,#args do
1315 if not match(args[i].mode, sub(tm, i, i)) then return end
1316 end
1317 return true
1318end
1319
1320-- Handle opcodes defined with template strings.
1321map_op[".template__"] = function(params, template, nparams)
1322 if not params then return templatehelp(template, nparams) end
1323 local args = {}
1324
1325 -- Zero-operand opcodes have no match part.
1326 if #params == 0 then
1327 dopattern(template, args, "d", params.op)
1328 return
1329 end
1330
1331 -- Determine common operand size (coerce undefined size) or flag as mixed.
1332 local sz, szmix
1333 for i,p in ipairs(params) do
1334 args[i] = parseoperand(p)
1335 local nsz = args[i].opsize
1336 if nsz then
1337 if sz and sz ~= nsz then szmix = true else sz = nsz end
1338 end
1339 end
1340
1341 -- Try all match:pattern pairs (separated by '|').
1342 local gotmatch, lastpat
1343 for tm in gmatch(template, "[^%|]+") do
1344 -- Split off size match (starts after mode match) and pattern string.
1345 local szm, pat = match(tm, "^(.-):(.*)$", #args+1)
1346 if pat == "" then pat = lastpat else lastpat = pat end
1347 if matchtm(tm, args) then
1348 local prefix = sub(szm, 1, 1)
1349 if prefix == "/" then -- Match both operand sizes.
1350 if args[1].opsize == sub(szm, 2, 2) and
1351 args[2].opsize == sub(szm, 3, 3) then
1352 dopattern(pat, args, sz, params.op) -- Process pattern string.
1353 return
1354 end
1355 else -- Match common operand size.
1356 local szp = sz
1357 if szm == "" then szm = "dwb" end -- Default size match.
1358 if prefix == "1" then szp = args[1].opsize; szmix = nil
1359 elseif prefix == "2" then szp = args[2].opsize; szmix = nil end
1360 if not szmix and (prefix == "." or match(szm, szp or "#")) then
1361 dopattern(pat, args, szp, params.op) -- Process pattern string.
1362 return
1363 end
1364 end
1365 gotmatch = true
1366 end
1367 end
1368
1369 local msg = "bad operand mode"
1370 if gotmatch then
1371 if szmix then
1372 msg = "mixed operand size"
1373 else
1374 msg = sz and "bad operand size" or "missing operand size"
1375 end
1376 end
1377
1378 werror(msg.." in `"..opmodestr(params.op, args).."'")
1379end
1380
1381------------------------------------------------------------------------------
1382
1383-- Pseudo-opcodes for data storage.
1384local function op_data(params)
1385 if not params then return "imm..." end
1386 local sz = sub(params.op, 2, 2)
1387 if sz == "a" then sz = addrsize end
1388 for _,p in ipairs(params) do
1389 local a = parseoperand(p)
1390 if sub(a.mode, 1, 1) ~= "i" or (a.opsize and a.opsize ~= sz) then
1391 werror("bad mode or size in `"..p.."'")
1392 end
1393 if a.mode == "iJ" then
1394 wputlabel("IMM_", a.imm, 1)
1395 else
1396 wputszarg(sz, a.imm)
1397 end
1398 end
1399end
1400
1401map_op[".byte_*"] = op_data
1402map_op[".sbyte_*"] = op_data
1403map_op[".word_*"] = op_data
1404map_op[".dword_*"] = op_data
1405map_op[".aword_*"] = op_data
1406
1407------------------------------------------------------------------------------
1408
1409-- Pseudo-opcode to mark the position where the action list is to be emitted.
1410map_op[".actionlist_1"] = function(params)
1411 if not params then return "cvar" end
1412 local name = params[1] -- No syntax check. You get to keep the pieces.
1413 wline(function(out) writeactions(out, name) end)
1414end
1415
1416-- Pseudo-opcode to mark the position where the global enum is to be emitted.
1417map_op[".globals_1"] = function(params)
1418 if not params then return "prefix" end
1419 local prefix = params[1] -- No syntax check. You get to keep the pieces.
1420 wline(function(out) writeglobals(out, prefix) end)
1421end
1422
1423------------------------------------------------------------------------------
1424
1425-- Label pseudo-opcode (converted from trailing colon form).
1426map_op[".label_2"] = function(params)
1427 if not params then return "[1-9] | ->global | =>pcexpr [, addr]" end
1428 local a = parseoperand(params[1])
1429 local mode, imm = a.mode, a.imm
1430 if type(imm) == "number" and (mode == "iJ" or (imm >= 1 and imm <= 9)) then
1431 -- Local label (1: ... 9:) or global label (->global:).
1432 waction("LABEL_LG", nil, 1)
1433 wputxb(imm)
1434 elseif mode == "iJ" then
1435 -- PC label (=>pcexpr:).
1436 waction("LABEL_PC", imm)
1437 else
1438 werror("bad label definition")
1439 end
1440 -- SETLABEL must immediately follow LABEL_LG/LABEL_PC.
1441 local addr = params[2]
1442 if addr then
1443 local a = parseoperand(params[2])
1444 if a.mode == "iPJ" then
1445 waction("SETLABEL", a.imm) -- !x64 (secpos)
1446 else
1447 werror("bad label assignment")
1448 end
1449 end
1450end
1451map_op[".label_1"] = map_op[".label_2"]
1452
1453------------------------------------------------------------------------------
1454
1455-- Alignment pseudo-opcode.
1456map_op[".align_1"] = function(params)
1457 if not params then return "numpow2" end
1458 local align = tonumber(params[1]) or map_opsizenum[map_opsize[params[1]]]
1459 if align then
1460 local x = align
1461 -- Must be a power of 2 in the range (2 ... 256).
1462 for i=1,8 do
1463 x = x / 2
1464 if x == 1 then
1465 waction("ALIGN", nil, 1)
1466 wputxb(align-1) -- Action byte is 2**n-1.
1467 return
1468 end
1469 end
1470 end
1471 werror("bad alignment")
1472end
1473
1474-- Spacing pseudo-opcode.
1475map_op[".space_2"] = function(params)
1476 if not params then return "num [, filler]" end
1477 waction("SPACE", params[1])
1478 local fill = params[2]
1479 if fill then
1480 fill = tonumber(fill)
1481 if not fill or fill < 0 or fill > 255 then werror("bad filler") end
1482 end
1483 wputxb(fill or 0)
1484end
1485map_op[".space_1"] = map_op[".space_2"]
1486
1487------------------------------------------------------------------------------
1488
1489-- Pseudo-opcode for (primitive) type definitions (map to C types).
1490map_op[".type_3"] = function(params, nparams)
1491 if not params then
1492 return nparams == 2 and "name, ctype" or "name, ctype, reg"
1493 end
1494 local name, ctype, reg = params[1], params[2], params[3]
1495 if not match(name, "^[%a_][%w_]*$") then
1496 werror("bad type name `"..name.."'")
1497 end
1498 local tp = map_type[name]
1499 if tp then
1500 werror("duplicate type `"..name.."'")
1501 end
1502 if reg and not map_reg_valid_base[reg] then
1503 werror("bad base register `"..(map_reg_rev[reg] or reg).."'")
1504 end
1505 -- Add #type to defines. A bit unclean to put it in map_archdef.
1506 map_archdef["#"..name] = "sizeof("..ctype..")"
1507 -- Add new type and emit shortcut define.
1508 local num = ctypenum + 1
1509 map_type[name] = {
1510 ctype = ctype,
1511 ctypefmt = format("Dt%X(%%s)", num),
1512 reg = reg,
1513 }
1514 wline(format("#define Dt%X(_V) (int)&(((%s *)0)_V)", num, ctype))
1515 ctypenum = num
1516end
1517map_op[".type_2"] = map_op[".type_3"]
1518
1519-- Dump type definitions.
1520local function dumptypes(out, lvl)
1521 local t = {}
1522 for name in pairs(map_type) do t[#t+1] = name end
1523 sort(t)
1524 out:write("Type definitions:\n")
1525 for _,name in ipairs(t) do
1526 local tp = map_type[name]
1527 local reg = tp.reg and map_reg_rev[tp.reg] or ""
1528 out:write(format(" %-20s %-20s %s\n", name, tp.ctype, reg))
1529 end
1530 out:write("\n")
1531end
1532
1533------------------------------------------------------------------------------
1534
1535-- Set the current section.
1536function _M.section(num)
1537 waction("SECTION")
1538 wputxb(num)
1539 wflush(true) -- SECTION is a terminal action.
1540end
1541
1542------------------------------------------------------------------------------
1543
1544-- Dump architecture description.
1545function _M.dumparch(out)
1546 out:write(format("DynASM %s version %s, released %s\n\n",
1547 _info.arch, _info.version, _info.release))
1548 dumpregs(out)
1549 dumpactions(out)
1550end
1551
1552-- Dump all user defined elements.
1553function _M.dumpdef(out, lvl)
1554 dumptypes(out, lvl)
1555 dumpglobals(out, lvl)
1556end
1557
1558------------------------------------------------------------------------------
1559
1560-- Pass callbacks from/to the DynASM core.
1561function _M.passcb(wl, we, wf, ww)
1562 wline, werror, wfatal, wwarn = wl, we, wf, ww
1563 return wflush
1564end
1565
1566-- Setup the arch-specific module.
1567function _M.setup(arch, opt)
1568 g_arch, g_opt = arch, opt
1569end
1570
1571-- Merge the core maps and the arch-specific maps.
1572function _M.mergemaps(map_coreop, map_def)
1573 setmetatable(map_op, { __index = map_coreop })
1574 setmetatable(map_def, { __index = map_archdef })
1575 return map_op, map_def
1576end
1577
1578return _M
1579
1580------------------------------------------------------------------------------
1581
diff --git a/libraries/LuaJIT-1.1.7/dynasm/dynasm.lua b/libraries/LuaJIT-1.1.7/dynasm/dynasm.lua
new file mode 100644
index 0000000..264a4bb
--- /dev/null
+++ b/libraries/LuaJIT-1.1.7/dynasm/dynasm.lua
@@ -0,0 +1,1070 @@
1------------------------------------------------------------------------------
2-- DynASM. A dynamic assembler for code generation engines.
3-- Originally designed and implemented for LuaJIT.
4--
5-- Copyright (C) 2005-2008 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.1.4",
14 vernum = 10104,
15 release = "2008-01-29",
16 author = "Mike Pall",
17 url = "http://luajit.org/dynasm.html",
18 license = "MIT",
19 copyright = [[
20Copyright (C) 2005-2008 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 initially available, too.
374map_op[".include_1"] = map_coreop[".include_1"]
375
376------------------------------------------------------------------------------
377
378-- Support variables for macros.
379local mac_capture, mac_lineno, mac_name
380local mac_active = {}
381local mac_list = {}
382
383-- Pseudo-opcode to define a macro.
384map_coreop[".macro_*"] = function(mparams)
385 if not mparams then return "name [, params...]" end
386 -- Split off and validate macro name.
387 local name = remove(mparams, 1)
388 if not name then werror("missing macro name") end
389 if not (match(name, "^[%a_][%w_%.]*$") or match(name, "^%.[%w_%.]+$")) then
390 wfatal("bad macro name `"..name.."'")
391 end
392 -- Validate macro parameter names.
393 local mdup = {}
394 for _,mp in ipairs(mparams) do
395 if not match(mp, "^[%a_][%w_]*$") then
396 wfatal("bad macro parameter name `"..mp.."'")
397 end
398 if mdup[mp] then wfatal("duplicate macro parameter name `"..mp.."'") end
399 mdup[mp] = true
400 end
401 -- Check for duplicate or recursive macro definitions.
402 local opname = name.."_"..#mparams
403 if map_op[opname] or map_op[name.."_*"] then
404 wfatal("duplicate macro `"..name.."' ("..#mparams.." parameters)")
405 end
406 if mac_capture then wfatal("recursive macro definition") end
407
408 -- Enable statement capture.
409 local lines = {}
410 mac_lineno = g_lineno
411 mac_name = name
412 mac_capture = function(stmt) -- Statement capture function.
413 -- Stop macro definition with .endmacro pseudo-opcode.
414 if not match(stmt, "^%s*.endmacro%s*$") then
415 lines[#lines+1] = stmt
416 return
417 end
418 mac_capture = nil
419 mac_lineno = nil
420 mac_name = nil
421 mac_list[#mac_list+1] = opname
422 -- Add macro-op definition.
423 map_op[opname] = function(params)
424 if not params then return mparams, lines end
425 -- Protect against recursive macro invocation.
426 if mac_active[opname] then wfatal("recursive macro invocation") end
427 mac_active[opname] = true
428 -- Setup substitution map.
429 local subst = {}
430 for i,mp in ipairs(mparams) do subst[mp] = params[i] end
431 local mcom
432 if g_opt.maccomment and g_opt.comment then
433 mcom = " MACRO "..name.." ("..#mparams..")"
434 wcomment("{"..mcom)
435 end
436 -- Loop through all captured statements
437 for _,stmt in ipairs(lines) do
438 -- Substitute macro parameters.
439 local st = gsub(stmt, "[%w_]+", subst)
440 st = definesubst(st)
441 st = gsub(st, "%s*%.%.%s*", "") -- Token paste a..b.
442 if mcom and sub(st, 1, 1) ~= "|" then wcomment(st) end
443 -- Emit statement. Use a protected call for better diagnostics.
444 local ok, err = pcall(dostmt, st)
445 if not ok then
446 -- Add the captured statement to the error.
447 wprinterr(err, "\n", g_indent, "| ", stmt,
448 "\t[MACRO ", name, " (", #mparams, ")]\n")
449 end
450 end
451 if mcom then wcomment("}"..mcom) end
452 mac_active[opname] = nil
453 end
454 end
455end
456
457-- An .endmacro pseudo-opcode outside of a macro definition is an error.
458map_coreop[".endmacro_0"] = function(params)
459 wfatal(".endmacro without .macro")
460end
461
462-- Dump all macros and their contents (with -PP only).
463local function dumpmacros(out, lvl)
464 sort(mac_list)
465 out:write("Macros:\n")
466 for _,opname in ipairs(mac_list) do
467 local name = sub(opname, 1, -3)
468 local params, lines = map_op[opname]()
469 out:write(format(" %-20s %s\n", name, concat(params, ", ")))
470 if lvl > 1 then
471 for _,line in ipairs(lines) do
472 out:write(" |", line, "\n")
473 end
474 out:write("\n")
475 end
476 end
477 out:write("\n")
478end
479
480-- Check for unfinished macro definitions.
481local function checkmacros()
482 if mac_capture then
483 wprinterr(g_fname, ":", mac_lineno,
484 ": error: unfinished .macro `", mac_name ,"'\n")
485 end
486end
487
488------------------------------------------------------------------------------
489
490-- Support variables for captures.
491local cap_lineno, cap_name
492local cap_buffers = {}
493local cap_used = {}
494
495-- Start a capture.
496map_coreop[".capture_1"] = function(params)
497 if not params then return "name" end
498 wflush()
499 local name = params[1]
500 if not match(name, "^[%a_][%w_]*$") then
501 wfatal("bad capture name `"..name.."'")
502 end
503 if cap_name then
504 wfatal("already capturing to `"..cap_name.."' since line "..cap_lineno)
505 end
506 cap_name = name
507 cap_lineno = g_lineno
508 -- Create or continue a capture buffer and start the output line capture.
509 local buf = cap_buffers[name]
510 if not buf then buf = {}; cap_buffers[name] = buf end
511 g_capbuffer = buf
512 g_synclineno = 0
513end
514
515-- Stop a capture.
516map_coreop[".endcapture_0"] = function(params)
517 wflush()
518 if not cap_name then wfatal(".endcapture without a valid .capture") end
519 cap_name = nil
520 cap_lineno = nil
521 g_capbuffer = nil
522 g_synclineno = 0
523end
524
525-- Dump a capture buffer.
526map_coreop[".dumpcapture_1"] = function(params)
527 if not params then return "name" end
528 wflush()
529 local name = params[1]
530 if not match(name, "^[%a_][%w_]*$") then
531 wfatal("bad capture name `"..name.."'")
532 end
533 cap_used[name] = true
534 wline(function(out)
535 local buf = cap_buffers[name]
536 if buf then wdumplines(out, buf) end
537 end)
538 g_synclineno = 0
539end
540
541-- Dump all captures and their buffers (with -PP only).
542local function dumpcaptures(out, lvl)
543 out:write("Captures:\n")
544 for name,buf in pairs(cap_buffers) do
545 out:write(format(" %-20s %4s)\n", name, "("..#buf))
546 if lvl > 1 then
547 local bar = rep("=", 76)
548 out:write(" ", bar, "\n")
549 for _,line in ipairs(buf) do
550 out:write(" ", line, "\n")
551 end
552 out:write(" ", bar, "\n\n")
553 end
554 end
555 out:write("\n")
556end
557
558-- Check for unfinished or unused captures.
559local function checkcaptures()
560 if cap_name then
561 wprinterr(g_fname, ":", cap_lineno,
562 ": error: unfinished .capture `", cap_name,"'\n")
563 return
564 end
565 for name in pairs(cap_buffers) do
566 if not cap_used[name] then
567 wprinterr(g_fname, ":*: error: missing .dumpcapture ", name ,"\n")
568 end
569 end
570end
571
572------------------------------------------------------------------------------
573
574-- Sections names.
575local map_sections = {}
576
577-- Pseudo-opcode to define code sections.
578-- TODO: Data sections, BSS sections. Needs extra C code and API.
579map_coreop[".section_*"] = function(params)
580 if not params then return "name..." end
581 if #map_sections > 0 then werror("duplicate section definition") end
582 wflush()
583 for sn,name in ipairs(params) do
584 local opname = "."..name.."_0"
585 if not match(name, "^[%a][%w_]*$") or
586 map_op[opname] or map_op["."..name.."_*"] then
587 werror("bad section name `"..name.."'")
588 end
589 map_sections[#map_sections+1] = name
590 wline(format("#define DASM_SECTION_%s\t%d", upper(name), sn-1))
591 map_op[opname] = function(params) g_arch.section(sn-1) end
592 end
593 wline(format("#define DASM_MAXSECTION\t\t%d", #map_sections))
594end
595
596-- Dump all sections.
597local function dumpsections(out, lvl)
598 out:write("Sections:\n")
599 for _,name in ipairs(map_sections) do
600 out:write(format(" %s\n", name))
601 end
602 out:write("\n")
603end
604
605------------------------------------------------------------------------------
606
607-- Load architecture-specific module.
608local function loadarch(arch)
609 if not match(arch, "^[%w_]+$") then return "bad arch name" end
610 local ok, m_arch = pcall(require, "dasm_"..arch)
611 if not ok then return "cannot load module: "..m_arch end
612 g_arch = m_arch
613 wflush = m_arch.passcb(wline, werror, wfatal, wwarn)
614 m_arch.setup(arch, g_opt)
615 map_op, map_def = m_arch.mergemaps(map_coreop, map_def)
616end
617
618-- Dump architecture description.
619function opt_map.dumparch(args)
620 local name = optparam(args)
621 if not g_arch then
622 local err = loadarch(name)
623 if err then opterror(err) end
624 end
625
626 local t = {}
627 for name in pairs(map_coreop) do t[#t+1] = name end
628 for name in pairs(map_op) do t[#t+1] = name end
629 sort(t)
630
631 local out = stdout
632 local _arch = g_arch._info
633 out:write(format("%s version %s, released %s, %s\n",
634 _info.name, _info.version, _info.release, _info.url))
635 g_arch.dumparch(out)
636
637 local pseudo = true
638 out:write("Pseudo-Opcodes:\n")
639 for _,sname in ipairs(t) do
640 local name, nparam = match(sname, "^(.+)_([0-9%*])$")
641 if name then
642 if pseudo and sub(name, 1, 1) ~= "." then
643 out:write("\nOpcodes:\n")
644 pseudo = false
645 end
646 local f = map_op[sname]
647 local s
648 if nparam ~= "*" then nparam = nparam + 0 end
649 if nparam == 0 then
650 s = ""
651 elseif type(f) == "string" then
652 s = map_op[".template__"](nil, f, nparam)
653 else
654 s = f(nil, nparam)
655 end
656 if type(s) == "table" then
657 for _,s2 in ipairs(s) do
658 out:write(format(" %-12s %s\n", name, s2))
659 end
660 else
661 out:write(format(" %-12s %s\n", name, s))
662 end
663 end
664 end
665 out:write("\n")
666 exit(0)
667end
668
669-- Pseudo-opcode to set the architecture.
670-- Only initially available (map_op is replaced when called).
671map_op[".arch_1"] = function(params)
672 if not params then return "name" end
673 local err = loadarch(params[1])
674 if err then wfatal(err) end
675end
676
677-- Dummy .arch pseudo-opcode to improve the error report.
678map_coreop[".arch_1"] = function(params)
679 if not params then return "name" end
680 wfatal("duplicate .arch statement")
681end
682
683------------------------------------------------------------------------------
684
685-- Dummy pseudo-opcode. Don't confuse '.nop' with 'nop'.
686map_coreop[".nop_*"] = function(params)
687 if not params then return "[ignored...]" end
688end
689
690-- Pseudo-opcodes to raise errors.
691map_coreop[".error_1"] = function(params)
692 if not params then return "message" end
693 werror(params[1])
694end
695
696map_coreop[".fatal_1"] = function(params)
697 if not params then return "message" end
698 wfatal(params[1])
699end
700
701-- Dump all user defined elements.
702local function dumpdef(out)
703 local lvl = g_opt.dumpdef
704 if lvl == 0 then return end
705 dumpsections(out, lvl)
706 dumpdefines(out, lvl)
707 if g_arch then g_arch.dumpdef(out, lvl) end
708 dumpmacros(out, lvl)
709 dumpcaptures(out, lvl)
710end
711
712------------------------------------------------------------------------------
713
714-- Helper for splitstmt.
715local splitlvl
716
717local function splitstmt_one(c)
718 if c == "(" then
719 splitlvl = ")"..splitlvl
720 elseif c == "[" then
721 splitlvl = "]"..splitlvl
722 elseif c == ")" or c == "]" then
723 if sub(splitlvl, 1, 1) ~= c then werror("unbalanced () or []") end
724 splitlvl = sub(splitlvl, 2)
725 elseif splitlvl == "" then
726 return " \0 "
727 end
728 return c
729end
730
731-- Split statement into (pseudo-)opcode and params.
732local function splitstmt(stmt)
733 -- Convert label with trailing-colon into .label statement.
734 local label = match(stmt, "^%s*(.+):%s*$")
735 if label then return ".label", {label} end
736
737 -- Split at commas and equal signs, but obey parentheses and brackets.
738 splitlvl = ""
739 stmt = gsub(stmt, "[,%(%)%[%]]", splitstmt_one)
740 if splitlvl ~= "" then werror("unbalanced () or []") end
741
742 -- Split off opcode.
743 local op, other = match(stmt, "^%s*([^%s%z]+)%s*(.*)$")
744 if not op then werror("bad statement syntax") end
745
746 -- Split parameters.
747 local params = {}
748 for p in gmatch(other, "%s*(%Z+)%z?") do
749 params[#params+1] = gsub(p, "%s+$", "")
750 end
751 if #params > 16 then werror("too many parameters") end
752
753 params.op = op
754 return op, params
755end
756
757-- Process a single statement.
758dostmt = function(stmt)
759 -- Ignore empty statements.
760 if match(stmt, "^%s*$") then return end
761
762 -- Capture macro defs before substitution.
763 if mac_capture then return mac_capture(stmt) end
764 stmt = definesubst(stmt)
765
766 -- Emit C code without parsing the line.
767 if sub(stmt, 1, 1) == "|" then
768 local tail = sub(stmt, 2)
769 wflush()
770 if sub(tail, 1, 2) == "//" then wcomment(tail) else wline(tail, true) end
771 return
772 end
773
774 -- Split into (pseudo-)opcode and params.
775 local op, params = splitstmt(stmt)
776
777 -- Get opcode handler (matching # of parameters or generic handler).
778 local f = map_op[op.."_"..#params] or map_op[op.."_*"]
779 if not f then
780 if not g_arch then wfatal("first statement must be .arch") end
781 -- Improve error report.
782 for i=0,16 do
783 if map_op[op.."_"..i] then
784 werror("wrong number of parameters for `"..op.."'")
785 end
786 end
787 werror("unknown statement `"..op.."'")
788 end
789
790 -- Call opcode handler or special handler for template strings.
791 if type(f) == "string" then
792 map_op[".template__"](params, f)
793 else
794 f(params)
795 end
796end
797
798-- Process a single line.
799local function doline(line)
800 if g_opt.flushline then wflush() end
801
802 -- Assembler line?
803 local indent, aline = match(line, "^(%s*)%|(.*)$")
804 if not aline then
805 -- No, plain C code line, need to flush first.
806 wflush()
807 wsync()
808 wline(line, false)
809 return
810 end
811
812 g_indent = indent -- Remember current line indentation.
813
814 -- Emit C code (even from macros). Avoids echo and line parsing.
815 if sub(aline, 1, 1) == "|" then
816 if not mac_capture then
817 wsync()
818 elseif g_opt.comment then
819 wsync()
820 wcomment(aline)
821 end
822 dostmt(aline)
823 return
824 end
825
826 -- Echo assembler line as a comment.
827 if g_opt.comment then
828 wsync()
829 wcomment(aline)
830 end
831
832 -- Strip assembler comments.
833 aline = gsub(aline, "//.*$", "")
834
835 -- Split line into statements at semicolons.
836 if match(aline, ";") then
837 for stmt in gmatch(aline, "[^;]+") do dostmt(stmt) end
838 else
839 dostmt(aline)
840 end
841end
842
843------------------------------------------------------------------------------
844
845-- Write DynASM header.
846local function dasmhead(out)
847 out:write(format([[
848/*
849** This file has been pre-processed with DynASM.
850** %s
851** DynASM version %s, DynASM %s version %s
852** DO NOT EDIT! The original file is in "%s".
853*/
854
855#if DASM_VERSION != %d
856#error "Version mismatch between DynASM and included encoding engine"
857#endif
858
859]], _info.url,
860 _info.version, g_arch._info.arch, g_arch._info.version,
861 g_fname, _info.vernum))
862end
863
864-- Read input file.
865readfile = function(fin)
866 g_indent = ""
867 g_lineno = 0
868 g_synclineno = -1
869
870 -- Process all lines.
871 for line in fin:lines() do
872 g_lineno = g_lineno + 1
873 g_curline = line
874 local ok, err = pcall(doline, line)
875 if not ok and wprinterr(err, "\n") then return true end
876 end
877 wflush()
878
879 -- Close input file.
880 assert(fin == stdin or fin:close())
881end
882
883-- Write output file.
884local function writefile(outfile)
885 local fout
886
887 -- Open output file.
888 if outfile == nil or outfile == "-" then
889 fout = stdout
890 else
891 fout = assert(io.open(outfile, "w"))
892 end
893
894 -- Write all buffered lines
895 wdumplines(fout, g_wbuffer)
896
897 -- Close output file.
898 assert(fout == stdout or fout:close())
899
900 -- Optionally dump definitions.
901 dumpdef(fout == stdout and stderr or stdout)
902end
903
904-- Translate an input file to an output file.
905local function translate(infile, outfile)
906 g_wbuffer = {}
907 g_indent = ""
908 g_lineno = 0
909 g_synclineno = -1
910
911 -- Put header.
912 wline(dasmhead)
913
914 -- Read input file.
915 local fin
916 if infile == "-" then
917 g_fname = "(stdin)"
918 fin = stdin
919 else
920 g_fname = infile
921 fin = assert(io.open(infile, "r"))
922 end
923 readfile(fin)
924
925 -- Check for errors.
926 if not g_arch then
927 wprinterr(g_fname, ":*: error: missing .arch directive\n")
928 end
929 checkconds()
930 checkmacros()
931 checkcaptures()
932
933 if g_errcount ~= 0 then
934 stderr:write(g_fname, ":*: info: ", g_errcount, " error",
935 (type(g_errcount) == "number" and g_errcount > 1) and "s" or "",
936 " in input file -- no output file generated.\n")
937 dumpdef(stderr)
938 exit(1)
939 end
940
941 -- Write output file.
942 writefile(outfile)
943end
944
945------------------------------------------------------------------------------
946
947-- Print help text.
948function opt_map.help()
949 stdout:write("DynASM -- ", _info.description, ".\n")
950 stdout:write("DynASM ", _info.version, " ", _info.release, " ", _info.url, "\n")
951 stdout:write[[
952
953Usage: dynasm [OPTION]... INFILE.dasc|-
954
955 -h, --help Display this help text.
956 -V, --version Display version and copyright information.
957
958 -o, --outfile FILE Output file name (default is stdout).
959 -I, --include DIR Add directory to the include search path.
960
961 -c, --ccomment Use /* */ comments for assembler lines.
962 -C, --cppcomment Use // comments for assembler lines (default).
963 -N, --nocomment Suppress assembler lines in output.
964 -M, --maccomment Show macro expansions as comments (default off).
965
966 -L, --nolineno Suppress CPP line number information in output.
967 -F, --flushline Flush action list for every line.
968
969 -D NAME[=SUBST] Define a substitution.
970 -U NAME Undefine a substitution.
971
972 -P, --dumpdef Dump defines, macros, etc. Repeat for more output.
973 -A, --dumparch ARCH Load architecture ARCH and dump description.
974]]
975 exit(0)
976end
977
978-- Print version information.
979function opt_map.version()
980 stdout:write(format("%s version %s, released %s\n%s\n\n%s",
981 _info.name, _info.version, _info.release, _info.url, _info.copyright))
982 exit(0)
983end
984
985-- Misc. options.
986function opt_map.outfile(args) g_opt.outfile = optparam(args) end
987function opt_map.include(args) insert(g_opt.include, 1, optparam(args)) end
988function opt_map.ccomment() g_opt.comment = "/*|"; g_opt.endcomment = " */" end
989function opt_map.cppcomment() g_opt.comment = "//|"; g_opt.endcomment = "" end
990function opt_map.nocomment() g_opt.comment = false end
991function opt_map.maccomment() g_opt.maccomment = true end
992function opt_map.nolineno() g_opt.cpp = false end
993function opt_map.flushline() g_opt.flushline = true end
994function opt_map.dumpdef() g_opt.dumpdef = g_opt.dumpdef + 1 end
995
996------------------------------------------------------------------------------
997
998-- Short aliases for long options.
999local opt_alias = {
1000 h = "help", ["?"] = "help", V = "version",
1001 o = "outfile", I = "include",
1002 c = "ccomment", C = "cppcomment", N = "nocomment", M = "maccomment",
1003 L = "nolineno", F = "flushline",
1004 P = "dumpdef", A = "dumparch",
1005}
1006
1007-- Parse single option.
1008local function parseopt(opt, args)
1009 opt_current = #opt == 1 and "-"..opt or "--"..opt
1010 local f = opt_map[opt] or opt_map[opt_alias[opt]]
1011 if not f then
1012 opterror("unrecognized option `", opt_current, "'. Try `--help'.\n")
1013 end
1014 f(args)
1015end
1016
1017-- Parse arguments.
1018local function parseargs(args)
1019 -- Default options.
1020 g_opt.comment = "//|"
1021 g_opt.endcomment = ""
1022 g_opt.cpp = true
1023 g_opt.dumpdef = 0
1024 g_opt.include = { "" }
1025
1026 -- Process all option arguments.
1027 args.argn = 1
1028 repeat
1029 local a = args[args.argn]
1030 if not a then break end
1031 local lopt, opt = match(a, "^%-(%-?)(.+)")
1032 if not opt then break end
1033 args.argn = args.argn + 1
1034 if lopt == "" then
1035 -- Loop through short options.
1036 for o in gmatch(opt, ".") do parseopt(o, args) end
1037 else
1038 -- Long option.
1039 parseopt(opt, args)
1040 end
1041 until false
1042
1043 -- Check for proper number of arguments.
1044 local nargs = #args - args.argn + 1
1045 if nargs ~= 1 then
1046 if nargs == 0 then
1047 if g_opt.dumpdef > 0 then return dumpdef(stdout) end
1048 end
1049 opt_map.help()
1050 end
1051
1052 -- Translate a single input file to a single output file
1053 -- TODO: Handle multiple files?
1054 translate(args[args.argn], g_opt.outfile)
1055end
1056
1057------------------------------------------------------------------------------
1058
1059-- Add the directory dynasm.lua resides in to the Lua module search path.
1060local arg = arg
1061if arg and arg[0] then
1062 local prefix = match(arg[0], "^(.*/)")
1063 if prefix then package.path = prefix.."?.lua;"..package.path end
1064end
1065
1066-- Start DynASM.
1067parseargs{...}
1068
1069------------------------------------------------------------------------------
1070