summaryrefslogtreecommitdiff
path: root/third_party
diff options
context:
space:
mode:
authorJoshua Haberman <jhaberman@gmail.com>2019-01-16 15:53:13 -0800
committerJoshua Haberman <jhaberman@gmail.com>2019-01-16 15:53:13 -0800
commit84fb01ad0f7301b416e03d97fbffef1a7512e7ea (patch)
treee2c9c024b52f387e70c43daff9d0d6cbba549580 /third_party
parent2c26f60dbbc49bca6233cc20a15ff4b32454c6e8 (diff)
Removed the JIT. Nobody was actually using it, and table-driven should achieve 80-90% of the perf.
Diffstat (limited to 'third_party')
-rw-r--r--third_party/dynasm/LICENSE56
-rw-r--r--third_party/dynasm/README.google10
-rw-r--r--third_party/dynasm/dasm_arm.h448
-rw-r--r--third_party/dynasm/dasm_arm.lua949
-rw-r--r--third_party/dynasm/dasm_mips.h415
-rw-r--r--third_party/dynasm/dasm_mips.lua959
-rw-r--r--third_party/dynasm/dasm_ppc.h411
-rw-r--r--third_party/dynasm/dasm_ppc.lua1230
-rw-r--r--third_party/dynasm/dasm_proto.h83
-rw-r--r--third_party/dynasm/dasm_x64.lua12
-rw-r--r--third_party/dynasm/dasm_x86.h470
-rw-r--r--third_party/dynasm/dasm_x86.lua1931
-rw-r--r--third_party/dynasm/dynasm.lua1084
m---------third_party/protobuf0
14 files changed, 0 insertions, 8058 deletions
diff --git a/third_party/dynasm/LICENSE b/third_party/dynasm/LICENSE
deleted file mode 100644
index 6f2a45b..0000000
--- a/third_party/dynasm/LICENSE
+++ /dev/null
@@ -1,56 +0,0 @@
-===============================================================================
-LuaJIT -- a Just-In-Time Compiler for Lua. http://luajit.org/
-
-Copyright (C) 2005-2011 Mike Pall. All rights reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-
-[ MIT license: http://www.opensource.org/licenses/mit-license.php ]
-
-===============================================================================
-[ LuaJIT includes code from Lua 5.1/5.2, which has this license statement: ]
-
-Copyright (C) 1994-2011 Lua.org, PUC-Rio.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-
-===============================================================================
-[ LuaJIT includes code from dlmalloc, which has this license statement: ]
-
-This is a version (aka dlmalloc) of malloc/free/realloc written by
-Doug Lea and released to the public domain, as explained at
-http://creativecommons.org/licenses/publicdomain
-
-===============================================================================
diff --git a/third_party/dynasm/README.google b/third_party/dynasm/README.google
deleted file mode 100644
index dd829a0..0000000
--- a/third_party/dynasm/README.google
+++ /dev/null
@@ -1,10 +0,0 @@
-URL: http://repo.or.cz/w/luajit-2.0.git/tree/6c05739684527919293e25668589f17c35a7c129:/dynasm
-Version: 6c05739684527919293e25668589f17c35a7c129
-License: MIT
-License File: LICENSE
-Description:
-Taken from the larger LuaJIT project, DynASM is a tiny preprocessor and
-runtime for generating machine code at runtime.
-
-Local Modifications:
-No modifications.
diff --git a/third_party/dynasm/dasm_arm.h b/third_party/dynasm/dasm_arm.h
deleted file mode 100644
index b770c2d..0000000
--- a/third_party/dynasm/dasm_arm.h
+++ /dev/null
@@ -1,448 +0,0 @@
-/*
-** DynASM ARM encoding engine.
-** Copyright (C) 2005-2012 Mike Pall. All rights reserved.
-** Released under the MIT license. See dynasm.lua for full copyright notice.
-*/
-
-#include <stddef.h>
-#include <stdarg.h>
-#include <string.h>
-#include <stdlib.h>
-
-#define DASM_ARCH "arm"
-
-#ifndef DASM_EXTERN
-#define DASM_EXTERN(a,b,c,d) 0
-#endif
-
-/* Action definitions. */
-enum {
- DASM_STOP, DASM_SECTION, DASM_ESC, DASM_REL_EXT,
- /* The following actions need a buffer position. */
- DASM_ALIGN, DASM_REL_LG, DASM_LABEL_LG,
- /* The following actions also have an argument. */
- DASM_REL_PC, DASM_LABEL_PC,
- DASM_IMM, DASM_IMM12, DASM_IMM16, DASM_IMML8, DASM_IMML12,
- DASM__MAX
-};
-
-/* Maximum number of section buffer positions for a single dasm_put() call. */
-#define DASM_MAXSECPOS 25
-
-/* DynASM encoder status codes. Action list offset or number are or'ed in. */
-#define DASM_S_OK 0x00000000
-#define DASM_S_NOMEM 0x01000000
-#define DASM_S_PHASE 0x02000000
-#define DASM_S_MATCH_SEC 0x03000000
-#define DASM_S_RANGE_I 0x11000000
-#define DASM_S_RANGE_SEC 0x12000000
-#define DASM_S_RANGE_LG 0x13000000
-#define DASM_S_RANGE_PC 0x14000000
-#define DASM_S_RANGE_REL 0x15000000
-#define DASM_S_UNDEF_LG 0x21000000
-#define DASM_S_UNDEF_PC 0x22000000
-
-/* Macros to convert positions (8 bit section + 24 bit index). */
-#define DASM_POS2IDX(pos) ((pos)&0x00ffffff)
-#define DASM_POS2BIAS(pos) ((pos)&0xff000000)
-#define DASM_SEC2POS(sec) ((sec)<<24)
-#define DASM_POS2SEC(pos) ((pos)>>24)
-#define DASM_POS2PTR(D, pos) (D->sections[DASM_POS2SEC(pos)].rbuf + (pos))
-
-/* Action list type. */
-typedef const unsigned int *dasm_ActList;
-
-/* Per-section structure. */
-typedef struct dasm_Section {
- int *rbuf; /* Biased buffer pointer (negative section bias). */
- int *buf; /* True buffer pointer. */
- size_t bsize; /* Buffer size in bytes. */
- int pos; /* Biased buffer position. */
- int epos; /* End of biased buffer position - max single put. */
- int ofs; /* Byte offset into section. */
-} dasm_Section;
-
-/* Core structure holding the DynASM encoding state. */
-struct dasm_State {
- size_t psize; /* Allocated size of this structure. */
- dasm_ActList actionlist; /* Current actionlist pointer. */
- int *lglabels; /* Local/global chain/pos ptrs. */
- size_t lgsize;
- int *pclabels; /* PC label chains/pos ptrs. */
- size_t pcsize;
- void **globals; /* Array of globals (bias -10). */
- dasm_Section *section; /* Pointer to active section. */
- size_t codesize; /* Total size of all code sections. */
- int maxsection; /* 0 <= sectionidx < maxsection. */
- int status; /* Status code. */
- dasm_Section sections[1]; /* All sections. Alloc-extended. */
-};
-
-/* The size of the core structure depends on the max. number of sections. */
-#define DASM_PSZ(ms) (sizeof(dasm_State)+(ms-1)*sizeof(dasm_Section))
-
-
-/* Initialize DynASM state. */
-void dasm_init(Dst_DECL, int maxsection)
-{
- dasm_State *D;
- size_t psz = 0;
- int i;
- Dst_REF = NULL;
- DASM_M_GROW(Dst, struct dasm_State, Dst_REF, psz, DASM_PSZ(maxsection));
- D = Dst_REF;
- D->psize = psz;
- D->lglabels = NULL;
- D->lgsize = 0;
- D->pclabels = NULL;
- D->pcsize = 0;
- D->globals = NULL;
- D->maxsection = maxsection;
- for (i = 0; i < maxsection; i++) {
- D->sections[i].buf = NULL; /* Need this for pass3. */
- D->sections[i].rbuf = D->sections[i].buf - DASM_SEC2POS(i);
- D->sections[i].bsize = 0;
- D->sections[i].epos = 0; /* Wrong, but is recalculated after resize. */
- }
-}
-
-/* Free DynASM state. */
-void dasm_free(Dst_DECL)
-{
- dasm_State *D = Dst_REF;
- int i;
- for (i = 0; i < D->maxsection; i++)
- if (D->sections[i].buf)
- DASM_M_FREE(Dst, D->sections[i].buf, D->sections[i].bsize);
- if (D->pclabels) DASM_M_FREE(Dst, D->pclabels, D->pcsize);
- if (D->lglabels) DASM_M_FREE(Dst, D->lglabels, D->lgsize);
- DASM_M_FREE(Dst, D, D->psize);
-}
-
-/* Setup global label array. Must be called before dasm_setup(). */
-void dasm_setupglobal(Dst_DECL, void **gl, unsigned int maxgl)
-{
- dasm_State *D = Dst_REF;
- D->globals = gl - 10; /* Negative bias to compensate for locals. */
- DASM_M_GROW(Dst, int, D->lglabels, D->lgsize, (10+maxgl)*sizeof(int));
-}
-
-/* Grow PC label array. Can be called after dasm_setup(), too. */
-void dasm_growpc(Dst_DECL, unsigned int maxpc)
-{
- dasm_State *D = Dst_REF;
- size_t osz = D->pcsize;
- DASM_M_GROW(Dst, int, D->pclabels, D->pcsize, maxpc*sizeof(int));
- memset((void *)(((unsigned char *)D->pclabels)+osz), 0, D->pcsize-osz);
-}
-
-/* Setup encoder. */
-void dasm_setup(Dst_DECL, const void *actionlist)
-{
- dasm_State *D = Dst_REF;
- int i;
- D->actionlist = (dasm_ActList)actionlist;
- D->status = DASM_S_OK;
- D->section = &D->sections[0];
- memset((void *)D->lglabels, 0, D->lgsize);
- if (D->pclabels) memset((void *)D->pclabels, 0, D->pcsize);
- for (i = 0; i < D->maxsection; i++) {
- D->sections[i].pos = DASM_SEC2POS(i);
- D->sections[i].ofs = 0;
- }
-}
-
-
-#ifdef DASM_CHECKS
-#define CK(x, st) \
- do { if (!(x)) { \
- D->status = DASM_S_##st|(p-D->actionlist-1); return; } } while (0)
-#define CKPL(kind, st) \
- do { if ((size_t)((char *)pl-(char *)D->kind##labels) >= D->kind##size) { \
- D->status = DASM_S_RANGE_##st|(p-D->actionlist-1); return; } } while (0)
-#else
-#define CK(x, st) ((void)0)
-#define CKPL(kind, st) ((void)0)
-#endif
-
-static int dasm_imm12(unsigned int n)
-{
- int i;
- for (i = 0; i < 16; i++, n = (n << 2) | (n >> 30))
- if (n <= 255) return (int)(n + (i << 8));
- return -1;
-}
-
-/* Pass 1: Store actions and args, link branches/labels, estimate offsets. */
-void dasm_put(Dst_DECL, int start, ...)
-{
- va_list ap;
- dasm_State *D = Dst_REF;
- dasm_ActList p = D->actionlist + start;
- dasm_Section *sec = D->section;
- int pos = sec->pos, ofs = sec->ofs;
- int *b;
-
- if (pos >= sec->epos) {
- DASM_M_GROW(Dst, int, sec->buf, sec->bsize,
- sec->bsize + 2*DASM_MAXSECPOS*sizeof(int));
- sec->rbuf = sec->buf - DASM_POS2BIAS(pos);
- sec->epos = (int)sec->bsize/sizeof(int) - DASM_MAXSECPOS+DASM_POS2BIAS(pos);
- }
-
- b = sec->rbuf;
- b[pos++] = start;
-
- va_start(ap, start);
- while (1) {
- unsigned int ins = *p++;
- unsigned int action = (ins >> 16);
- if (action >= DASM__MAX) {
- ofs += 4;
- } else {
- int *pl, n = action >= DASM_REL_PC ? va_arg(ap, int) : 0;
- switch (action) {
- case DASM_STOP: goto stop;
- case DASM_SECTION:
- n = (ins & 255); CK(n < D->maxsection, RANGE_SEC);
- D->section = &D->sections[n]; goto stop;
- case DASM_ESC: p++; ofs += 4; break;
- case DASM_REL_EXT: break;
- case DASM_ALIGN: ofs += (ins & 255); b[pos++] = ofs; break;
- case DASM_REL_LG:
- n = (ins & 2047) - 10; pl = D->lglabels + n;
- if (n >= 0) { CKPL(lg, LG); goto putrel; } /* Bkwd rel or global. */
- pl += 10; n = *pl;
- if (n < 0) n = 0; /* Start new chain for fwd rel if label exists. */
- goto linkrel;
- case DASM_REL_PC:
- pl = D->pclabels + n; CKPL(pc, PC);
- putrel:
- n = *pl;
- if (n < 0) { /* Label exists. Get label pos and store it. */
- b[pos] = -n;
- } else {
- linkrel:
- b[pos] = n; /* Else link to rel chain, anchored at label. */
- *pl = pos;
- }
- pos++;
- break;
- case DASM_LABEL_LG:
- pl = D->lglabels + (ins & 2047) - 10; CKPL(lg, LG); goto putlabel;
- case DASM_LABEL_PC:
- pl = D->pclabels + n; CKPL(pc, PC);
- putlabel:
- n = *pl; /* n > 0: Collapse rel chain and replace with label pos. */
- while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = pos;
- }
- *pl = -pos; /* Label exists now. */
- b[pos++] = ofs; /* Store pass1 offset estimate. */
- break;
- case DASM_IMM:
- case DASM_IMM16:
-#ifdef DASM_CHECKS
- CK((n & ((1<<((ins>>10)&31))-1)) == 0, RANGE_I);
- if ((ins & 0x8000))
- CK(((n + (1<<(((ins>>5)&31)-1)))>>((ins>>5)&31)) == 0, RANGE_I);
- else
- CK((n>>((ins>>5)&31)) == 0, RANGE_I);
-#endif
- b[pos++] = n;
- break;
- case DASM_IMML8:
- case DASM_IMML12:
- CK(n >= 0 ? ((n>>((ins>>5)&31)) == 0) :
- (((-n)>>((ins>>5)&31)) == 0), RANGE_I);
- b[pos++] = n;
- break;
- case DASM_IMM12:
- CK(dasm_imm12((unsigned int)n) != -1, RANGE_I);
- b[pos++] = n;
- break;
- }
- }
- }
-stop:
- va_end(ap);
- sec->pos = pos;
- sec->ofs = ofs;
-}
-#undef CK
-
-/* Pass 2: Link sections, shrink aligns, fix label offsets. */
-int dasm_link(Dst_DECL, size_t *szp)
-{
- dasm_State *D = Dst_REF;
- int secnum;
- int ofs = 0;
-
-#ifdef DASM_CHECKS
- *szp = 0;
- if (D->status != DASM_S_OK) return D->status;
- {
- int pc;
- for (pc = 0; pc*sizeof(int) < D->pcsize; pc++)
- if (D->pclabels[pc] > 0) return DASM_S_UNDEF_PC|pc;
- }
-#endif
-
- { /* Handle globals not defined in this translation unit. */
- int idx;
- for (idx = 20; idx*sizeof(int) < D->lgsize; idx++) {
- int n = D->lglabels[idx];
- /* Undefined label: Collapse rel chain and replace with marker (< 0). */
- while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = -idx; }
- }
- }
-
- /* Combine all code sections. No support for data sections (yet). */
- for (secnum = 0; secnum < D->maxsection; secnum++) {
- dasm_Section *sec = D->sections + secnum;
- int *b = sec->rbuf;
- int pos = DASM_SEC2POS(secnum);
- int lastpos = sec->pos;
-
- while (pos != lastpos) {
- dasm_ActList p = D->actionlist + b[pos++];
- while (1) {
- unsigned int ins = *p++;
- unsigned int action = (ins >> 16);
- switch (action) {
- case DASM_STOP: case DASM_SECTION: goto stop;
- case DASM_ESC: p++; break;
- case DASM_REL_EXT: break;
- case DASM_ALIGN: ofs -= (b[pos++] + ofs) & (ins & 255); break;
- case DASM_REL_LG: case DASM_REL_PC: pos++; break;
- case DASM_LABEL_LG: case DASM_LABEL_PC: b[pos++] += ofs; break;
- case DASM_IMM: case DASM_IMM12: case DASM_IMM16:
- case DASM_IMML8: case DASM_IMML12: pos++; break;
- }
- }
- stop: (void)0;
- }
- ofs += sec->ofs; /* Next section starts right after current section. */
- }
-
- D->codesize = ofs; /* Total size of all code sections */
- *szp = ofs;
- return DASM_S_OK;
-}
-
-#ifdef DASM_CHECKS
-#define CK(x, st) \
- do { if (!(x)) return DASM_S_##st|(p-D->actionlist-1); } while (0)
-#else
-#define CK(x, st) ((void)0)
-#endif
-
-/* Pass 3: Encode sections. */
-int dasm_encode(Dst_DECL, void *buffer)
-{
- dasm_State *D = Dst_REF;
- char *base = (char *)buffer;
- unsigned int *cp = (unsigned int *)buffer;
- int secnum;
-
- /* Encode all code sections. No support for data sections (yet). */
- for (secnum = 0; secnum < D->maxsection; secnum++) {
- dasm_Section *sec = D->sections + secnum;
- int *b = sec->buf;
- int *endb = sec->rbuf + sec->pos;
-
- while (b != endb) {
- dasm_ActList p = D->actionlist + *b++;
- while (1) {
- unsigned int ins = *p++;
- unsigned int action = (ins >> 16);
- int n = (action >= DASM_ALIGN && action < DASM__MAX) ? *b++ : 0;
- switch (action) {
- case DASM_STOP: case DASM_SECTION: goto stop;
- case DASM_ESC: *cp++ = *p++; break;
- case DASM_REL_EXT:
- n = DASM_EXTERN(Dst, (unsigned char *)cp, (ins&2047), !(ins&2048));
- goto patchrel;
- case DASM_ALIGN:
- ins &= 255; while ((((char *)cp - base) & ins)) *cp++ = 0xe1a00000;
- break;
- case DASM_REL_LG:
- CK(n >= 0, UNDEF_LG);
- case DASM_REL_PC:
- CK(n >= 0, UNDEF_PC);
- n = *DASM_POS2PTR(D, n) - (int)((char *)cp - base) - 4;
- patchrel:
- if ((ins & 0x800) == 0) {
- CK((n & 3) == 0 && ((n+0x02000000) >> 26) == 0, RANGE_REL);
- cp[-1] |= ((n >> 2) & 0x00ffffff);
- } else if ((ins & 0x1000)) {
- CK((n & 3) == 0 && -256 <= n && n <= 256, RANGE_REL);
- goto patchimml8;
- } else {
- CK((n & 3) == 0 && -4096 <= n && n <= 4096, RANGE_REL);
- goto patchimml12;
- }
- break;
- case DASM_LABEL_LG:
- ins &= 2047; if (ins >= 20) D->globals[ins-10] = (void *)(base + n);
- break;
- case DASM_LABEL_PC: break;
- case DASM_IMM:
- cp[-1] |= ((n>>((ins>>10)&31)) & ((1<<((ins>>5)&31))-1)) << (ins&31);
- break;
- case DASM_IMM12:
- cp[-1] |= dasm_imm12((unsigned int)n);
- break;
- case DASM_IMM16:
- cp[-1] |= ((n & 0xf000) << 4) | (n & 0x0fff);
- break;
- case DASM_IMML8: patchimml8:
- cp[-1] |= n >= 0 ? (0x00800000 | (n & 0x0f) | ((n & 0xf0) << 4)) :
- ((-n & 0x0f) | ((-n & 0xf0) << 4));
- break;
- case DASM_IMML12: patchimml12:
- cp[-1] |= n >= 0 ? (0x00800000 | n) : (-n);
- break;
- default: *cp++ = ins; break;
- }
- }
- stop: (void)0;
- }
- }
-
- if (base + D->codesize != (char *)cp) /* Check for phase errors. */
- return DASM_S_PHASE;
- return DASM_S_OK;
-}
-#undef CK
-
-/* Get PC label offset. */
-int dasm_getpclabel(Dst_DECL, unsigned int pc)
-{
- dasm_State *D = Dst_REF;
- if (pc*sizeof(int) < D->pcsize) {
- int pos = D->pclabels[pc];
- if (pos < 0) return *DASM_POS2PTR(D, -pos);
- if (pos > 0) return -1; /* Undefined. */
- }
- return -2; /* Unused or out of range. */
-}
-
-#ifdef DASM_CHECKS
-/* Optional sanity checker to call between isolated encoding steps. */
-int dasm_checkstep(Dst_DECL, int secmatch)
-{
- dasm_State *D = Dst_REF;
- if (D->status == DASM_S_OK) {
- int i;
- for (i = 1; i <= 9; i++) {
- if (D->lglabels[i] > 0) { D->status = DASM_S_UNDEF_LG|i; break; }
- D->lglabels[i] = 0;
- }
- }
- if (D->status == DASM_S_OK && secmatch >= 0 &&
- D->section != &D->sections[secmatch])
- D->status = DASM_S_MATCH_SEC|(D->section-D->sections);
- return D->status;
-}
-#endif
-
diff --git a/third_party/dynasm/dasm_arm.lua b/third_party/dynasm/dasm_arm.lua
deleted file mode 100644
index cc4fa17..0000000
--- a/third_party/dynasm/dasm_arm.lua
+++ /dev/null
@@ -1,949 +0,0 @@
-------------------------------------------------------------------------------
--- DynASM ARM module.
---
--- Copyright (C) 2005-2012 Mike Pall. All rights reserved.
--- See dynasm.lua for full copyright notice.
-------------------------------------------------------------------------------
-
--- Module information:
-local _info = {
- arch = "arm",
- description = "DynASM ARM module",
- version = "1.3.0",
- vernum = 10300,
- release = "2011-05-05",
- author = "Mike Pall",
- license = "MIT",
-}
-
--- Exported glue functions for the arch-specific module.
-local _M = { _info = _info }
-
--- Cache library functions.
-local type, tonumber, pairs, ipairs = type, tonumber, pairs, ipairs
-local assert, setmetatable, rawget = assert, setmetatable, rawget
-local _s = string
-local sub, format, byte, char = _s.sub, _s.format, _s.byte, _s.char
-local match, gmatch, gsub = _s.match, _s.gmatch, _s.gsub
-local concat, sort, insert = table.concat, table.sort, table.insert
-
--- Inherited tables and callbacks.
-local g_opt, g_arch
-local wline, werror, wfatal, wwarn
-
--- Action name list.
--- CHECK: Keep this in sync with the C code!
-local action_names = {
- "STOP", "SECTION", "ESC", "REL_EXT",
- "ALIGN", "REL_LG", "LABEL_LG",
- "REL_PC", "LABEL_PC", "IMM", "IMM12", "IMM16", "IMML8", "IMML12",
-}
-
--- Maximum number of section buffer positions for dasm_put().
--- CHECK: Keep this in sync with the C code!
-local maxsecpos = 25 -- Keep this low, to avoid excessively long C lines.
-
--- Action name -> action number.
-local map_action = {}
-for n,name in ipairs(action_names) do
- map_action[name] = n-1
-end
-
--- Action list buffer.
-local actlist = {}
-
--- Argument list for next dasm_put(). Start with offset 0 into action list.
-local actargs = { 0 }
-
--- Current number of section buffer positions for dasm_put().
-local secpos = 1
-
-------------------------------------------------------------------------------
-
--- Return 8 digit hex number.
-local function tohex(x)
- return sub(format("%08x", x), -8) -- Avoid 64 bit portability problem in Lua.
-end
-
--- Dump action names and numbers.
-local function dumpactions(out)
- out:write("DynASM encoding engine action codes:\n")
- for n,name in ipairs(action_names) do
- local num = map_action[name]
- out:write(format(" %-10s %02X %d\n", name, num, num))
- end
- out:write("\n")
-end
-
--- Write action list buffer as a huge static C array.
-local function writeactions(out, name)
- local nn = #actlist
- if nn == 0 then nn = 1; actlist[0] = map_action.STOP end
- out:write("static const unsigned int ", name, "[", nn, "] = {\n")
- for i = 1,nn-1 do
- assert(out:write("0x", tohex(actlist[i]), ",\n"))
- end
- assert(out:write("0x", tohex(actlist[nn]), "\n};\n\n"))
-end
-
-------------------------------------------------------------------------------
-
--- Add word to action list.
-local function wputxw(n)
- assert(n >= 0 and n <= 0xffffffff and n % 1 == 0, "word out of range")
- actlist[#actlist+1] = n
-end
-
--- Add action to list with optional arg. Advance buffer pos, too.
-local function waction(action, val, a, num)
- local w = assert(map_action[action], "bad action name `"..action.."'")
- wputxw(w * 0x10000 + (val or 0))
- if a then actargs[#actargs+1] = a end
- if a or num then secpos = secpos + (num or 1) end
-end
-
--- Flush action list (intervening C code or buffer pos overflow).
-local function wflush(term)
- if #actlist == actargs[1] then return end -- Nothing to flush.
- if not term then waction("STOP") end -- Terminate action list.
- wline(format("dasm_put(Dst, %s);", concat(actargs, ", ")), true)
- actargs = { #actlist } -- Actionlist offset is 1st arg to next dasm_put().
- secpos = 1 -- The actionlist offset occupies a buffer position, too.
-end
-
--- Put escaped word.
-local function wputw(n)
- if n <= 0x000fffff then waction("ESC") end
- wputxw(n)
-end
-
--- Reserve position for word.
-local function wpos()
- local pos = #actlist+1
- actlist[pos] = ""
- return pos
-end
-
--- Store word to reserved position.
-local function wputpos(pos, n)
- assert(n >= 0 and n <= 0xffffffff and n % 1 == 0, "word out of range")
- if n <= 0x000fffff then
- insert(actlist, pos+1, n)
- n = map_action.ESC * 0x10000
- end
- actlist[pos] = n
-end
-
-------------------------------------------------------------------------------
-
--- Global label name -> global label number. With auto assignment on 1st use.
-local next_global = 20
-local map_global = setmetatable({}, { __index = function(t, name)
- if not match(name, "^[%a_][%w_]*$") then werror("bad global label") end
- local n = next_global
- if n > 2047 then werror("too many global labels") end
- next_global = n + 1
- t[name] = n
- return n
-end})
-
--- Dump global labels.
-local function dumpglobals(out, lvl)
- local t = {}
- for name, n in pairs(map_global) do t[n] = name end
- out:write("Global labels:\n")
- for i=20,next_global-1 do
- out:write(format(" %s\n", t[i]))
- end
- out:write("\n")
-end
-
--- Write global label enum.
-local function writeglobals(out, prefix)
- local t = {}
- for name, n in pairs(map_global) do t[n] = name end
- out:write("enum {\n")
- for i=20,next_global-1 do
- out:write(" ", prefix, t[i], ",\n")
- end
- out:write(" ", prefix, "_MAX\n};\n")
-end
-
--- Write global label names.
-local function writeglobalnames(out, name)
- local t = {}
- for name, n in pairs(map_global) do t[n] = name end
- out:write("static const char *const ", name, "[] = {\n")
- for i=20,next_global-1 do
- out:write(" \"", t[i], "\",\n")
- end
- out:write(" (const char *)0\n};\n")
-end
-
-------------------------------------------------------------------------------
-
--- Extern label name -> extern label number. With auto assignment on 1st use.
-local next_extern = 0
-local map_extern_ = {}
-local map_extern = setmetatable({}, { __index = function(t, name)
- -- No restrictions on the name for now.
- local n = next_extern
- if n > 2047 then werror("too many extern labels") end
- next_extern = n + 1
- t[name] = n
- map_extern_[n] = name
- return n
-end})
-
--- Dump extern labels.
-local function dumpexterns(out, lvl)
- out:write("Extern labels:\n")
- for i=0,next_extern-1 do
- out:write(format(" %s\n", map_extern_[i]))
- end
- out:write("\n")
-end
-
--- Write extern label names.
-local function writeexternnames(out, name)
- out:write("static const char *const ", name, "[] = {\n")
- for i=0,next_extern-1 do
- out:write(" \"", map_extern_[i], "\",\n")
- end
- out:write(" (const char *)0\n};\n")
-end
-
-------------------------------------------------------------------------------
-
--- Arch-specific maps.
-
--- Ext. register name -> int. name.
-local map_archdef = { sp = "r13", lr = "r14", pc = "r15", }
-
--- Int. register name -> ext. name.
-local map_reg_rev = { r13 = "sp", r14 = "lr", r15 = "pc", }
-
-local map_type = {} -- Type name -> { ctype, reg }
-local ctypenum = 0 -- Type number (for Dt... macros).
-
--- Reverse defines for registers.
-function _M.revdef(s)
- return map_reg_rev[s] or s
-end
-
-local map_shift = { lsl = 0, lsr = 1, asr = 2, ror = 3, }
-
-local map_cond = {
- eq = 0, ne = 1, cs = 2, cc = 3, mi = 4, pl = 5, vs = 6, vc = 7,
- hi = 8, ls = 9, ge = 10, lt = 11, gt = 12, le = 13, al = 14,
- hs = 2, lo = 3,
-}
-
-------------------------------------------------------------------------------
-
--- Template strings for ARM instructions.
-local map_op = {
- -- Basic data processing instructions.
- and_3 = "e0000000DNPs",
- eor_3 = "e0200000DNPs",
- sub_3 = "e0400000DNPs",
- rsb_3 = "e0600000DNPs",
- add_3 = "e0800000DNPs",
- adc_3 = "e0a00000DNPs",
- sbc_3 = "e0c00000DNPs",
- rsc_3 = "e0e00000DNPs",
- tst_2 = "e1100000NP",
- teq_2 = "e1300000NP",
- cmp_2 = "e1500000NP",
- cmn_2 = "e1700000NP",
- orr_3 = "e1800000DNPs",
- mov_2 = "e1a00000DPs",
- bic_3 = "e1c00000DNPs",
- mvn_2 = "e1e00000DPs",
-
- and_4 = "e0000000DNMps",
- eor_4 = "e0200000DNMps",
- sub_4 = "e0400000DNMps",
- rsb_4 = "e0600000DNMps",
- add_4 = "e0800000DNMps",
- adc_4 = "e0a00000DNMps",
- sbc_4 = "e0c00000DNMps",
- rsc_4 = "e0e00000DNMps",
- tst_3 = "e1100000NMp",
- teq_3 = "e1300000NMp",
- cmp_3 = "e1500000NMp",
- cmn_3 = "e1700000NMp",
- orr_4 = "e1800000DNMps",
- mov_3 = "e1a00000DMps",
- bic_4 = "e1c00000DNMps",
- mvn_3 = "e1e00000DMps",
-
- lsl_3 = "e1a00000DMws",
- lsr_3 = "e1a00020DMws",
- asr_3 = "e1a00040DMws",
- ror_3 = "e1a00060DMws",
- rrx_2 = "e1a00060DMs",
-
- -- Multiply and multiply-accumulate.
- mul_3 = "e0000090NMSs",
- mla_4 = "e0200090NMSDs",
- umaal_4 = "e0400090DNMSs", -- v6
- mls_4 = "e0600090DNMSs", -- v6T2
- umull_4 = "e0800090DNMSs",
- umlal_4 = "e0a00090DNMSs",
- smull_4 = "e0c00090DNMSs",
- smlal_4 = "e0e00090DNMSs",
-
- -- Halfword multiply and multiply-accumulate.
- smlabb_4 = "e1000080NMSD", -- v5TE
- smlatb_4 = "e10000a0NMSD", -- v5TE
- smlabt_4 = "e10000c0NMSD", -- v5TE
- smlatt_4 = "e10000e0NMSD", -- v5TE
- smlawb_4 = "e1200080NMSD", -- v5TE
- smulwb_3 = "e12000a0NMS", -- v5TE
- smlawt_4 = "e12000c0NMSD", -- v5TE
- smulwt_3 = "e12000e0NMS", -- v5TE
- smlalbb_4 = "e1400080NMSD", -- v5TE
- smlaltb_4 = "e14000a0NMSD", -- v5TE
- smlalbt_4 = "e14000c0NMSD", -- v5TE
- smlaltt_4 = "e14000e0NMSD", -- v5TE
- smulbb_3 = "e1600080NMS", -- v5TE
- smultb_3 = "e16000a0NMS", -- v5TE
- smulbt_3 = "e16000c0NMS", -- v5TE
- smultt_3 = "e16000e0NMS", -- v5TE
-
- -- Miscellaneous data processing instructions.
- clz_2 = "e16f0f10DM", -- v5T
- rev_2 = "e6bf0f30DM", -- v6
- rev16_2 = "e6bf0fb0DM", -- v6
- revsh_2 = "e6ff0fb0DM", -- v6
- sel_3 = "e6800fb0DNM", -- v6
- usad8_3 = "e780f010NMS", -- v6
- usada8_4 = "e7800010NMSD", -- v6
- rbit_2 = "e6ff0f30DM", -- v6T2
- movw_2 = "e3000000DW", -- v6T2
- movt_2 = "e3400000DW", -- v6T2
- -- Note: the X encodes width-1, not width.
- sbfx_4 = "e7a00050DMvX", -- v6T2
- ubfx_4 = "e7e00050DMvX", -- v6T2
- -- Note: the X encodes the msb field, not the width.
- bfc_3 = "e7c0001fDvX", -- v6T2
- bfi_4 = "e7c00010DMvX", -- v6T2
-
- -- Packing and unpacking instructions.
- pkhbt_3 = "e6800010DNM", pkhbt_4 = "e6800010DNMv", -- v6
- pkhtb_3 = "e6800050DNM", pkhtb_4 = "e6800050DNMv", -- v6
- sxtab_3 = "e6a00070DNM", sxtab_4 = "e6a00070DNMv", -- v6
- sxtab16_3 = "e6800070DNM", sxtab16_4 = "e6800070DNMv", -- v6
- sxtah_3 = "e6b00070DNM", sxtah_4 = "e6b00070DNMv", -- v6
- sxtb_2 = "e6af0070DM", sxtb_3 = "e6af0070DMv", -- v6
- sxtb16_2 = "e68f0070DM", sxtb16_3 = "e68f0070DMv", -- v6
- sxth_2 = "e6bf0070DM", sxth_3 = "e6bf0070DMv", -- v6
- uxtab_3 = "e6e00070DNM", uxtab_4 = "e6e00070DNMv", -- v6
- uxtab16_3 = "e6c00070DNM", uxtab16_4 = "e6c00070DNMv", -- v6
- uxtah_3 = "e6f00070DNM", uxtah_4 = "e6f00070DNMv", -- v6
- uxtb_2 = "e6ef0070DM", uxtb_3 = "e6ef0070DMv", -- v6
- uxtb16_2 = "e6cf0070DM", uxtb16_3 = "e6cf0070DMv", -- v6
- uxth_2 = "e6ff0070DM", uxth_3 = "e6ff0070DMv", -- v6
-
- -- Saturating instructions.
- qadd_3 = "e1000050DMN", -- v5TE
- qsub_3 = "e1200050DMN", -- v5TE
- qdadd_3 = "e1400050DMN", -- v5TE
- qdsub_3 = "e1600050DMN", -- v5TE
- -- Note: the X for ssat* encodes sat_imm-1, not sat_imm.
- ssat_3 = "e6a00010DXM", ssat_4 = "e6a00010DXMp", -- v6
- usat_3 = "e6e00010DXM", usat_4 = "e6e00010DXMp", -- v6
- ssat16_3 = "e6a00f30DXM", -- v6
- usat16_3 = "e6e00f30DXM", -- v6
-
- -- Parallel addition and subtraction.
- sadd16_3 = "e6100f10DNM", -- v6
- sasx_3 = "e6100f30DNM", -- v6
- ssax_3 = "e6100f50DNM", -- v6
- ssub16_3 = "e6100f70DNM", -- v6
- sadd8_3 = "e6100f90DNM", -- v6
- ssub8_3 = "e6100ff0DNM", -- v6
- qadd16_3 = "e6200f10DNM", -- v6
- qasx_3 = "e6200f30DNM", -- v6
- qsax_3 = "e6200f50DNM", -- v6
- qsub16_3 = "e6200f70DNM", -- v6
- qadd8_3 = "e6200f90DNM", -- v6
- qsub8_3 = "e6200ff0DNM", -- v6
- shadd16_3 = "e6300f10DNM", -- v6
- shasx_3 = "e6300f30DNM", -- v6
- shsax_3 = "e6300f50DNM", -- v6
- shsub16_3 = "e6300f70DNM", -- v6
- shadd8_3 = "e6300f90DNM", -- v6
- shsub8_3 = "e6300ff0DNM", -- v6
- uadd16_3 = "e6500f10DNM", -- v6
- uasx_3 = "e6500f30DNM", -- v6
- usax_3 = "e6500f50DNM", -- v6
- usub16_3 = "e6500f70DNM", -- v6
- uadd8_3 = "e6500f90DNM", -- v6
- usub8_3 = "e6500ff0DNM", -- v6
- uqadd16_3 = "e6600f10DNM", -- v6
- uqasx_3 = "e6600f30DNM", -- v6
- uqsax_3 = "e6600f50DNM", -- v6
- uqsub16_3 = "e6600f70DNM", -- v6
- uqadd8_3 = "e6600f90DNM", -- v6
- uqsub8_3 = "e6600ff0DNM", -- v6
- uhadd16_3 = "e6700f10DNM", -- v6
- uhasx_3 = "e6700f30DNM", -- v6
- uhsax_3 = "e6700f50DNM", -- v6
- uhsub16_3 = "e6700f70DNM", -- v6
- uhadd8_3 = "e6700f90DNM", -- v6
- uhsub8_3 = "e6700ff0DNM", -- v6
-
- -- Load/store instructions.
- str_2 = "e4000000DL", str_3 = "e4000000DL", str_4 = "e4000000DL",
- strb_2 = "e4400000DL", strb_3 = "e4400000DL", strb_4 = "e4400000DL",
- ldr_2 = "e4100000DL", ldr_3 = "e4100000DL", ldr_4 = "e4100000DL",
- ldrb_2 = "e4500000DL", ldrb_3 = "e4500000DL", ldrb_4 = "e4500000DL",
- strh_2 = "e00000b0DL", strh_3 = "e00000b0DL",
- ldrh_2 = "e01000b0DL", ldrh_3 = "e01000b0DL",
- ldrd_2 = "e00000d0DL", ldrd_3 = "e00000d0DL", -- v5TE
- ldrsb_2 = "e01000d0DL", ldrsb_3 = "e01000d0DL",
- strd_2 = "e00000f0DL", strd_3 = "e00000f0DL", -- v5TE
- ldrsh_2 = "e01000f0DL", ldrsh_3 = "e01000f0DL",
-
- ldm_2 = "e8900000nR", ldmia_2 = "e8900000nR", ldmfd_2 = "e8900000nR",
- ldmda_2 = "e8100000nR", ldmfa_2 = "e8100000nR",
- ldmdb_2 = "e9100000nR", ldmea_2 = "e9100000nR",
- ldmib_2 = "e9900000nR", ldmed_2 = "e9900000nR",
- stm_2 = "e8800000nR", stmia_2 = "e8800000nR", stmfd_2 = "e8800000nR",
- stmda_2 = "e8000000nR", stmfa_2 = "e8000000nR",
- stmdb_2 = "e9000000nR", stmea_2 = "e9000000nR",
- stmib_2 = "e9800000nR", stmed_2 = "e9800000nR",
- pop_1 = "e8bd0000R", push_1 = "e92d0000R",
-
- -- Branch instructions.
- b_1 = "ea000000B",
- bl_1 = "eb000000B",
- blx_1 = "e12fff30C",
- bx_1 = "e12fff10M",
-
- -- Miscellaneous instructions.
- nop_0 = "e1a00000",
- mrs_1 = "e10f0000D",
- bkpt_1 = "e1200070K", -- v5T
- svc_1 = "ef000000T", swi_1 = "ef000000T",
- ud_0 = "e7f001f0",
-
- -- NYI: Advanced SIMD and VFP instructions.
-
- -- NYI instructions, since I have no need for them right now:
- -- swp, swpb, strex, ldrex, strexd, ldrexd, strexb, ldrexb, strexh, ldrexh
- -- msr, nopv6, yield, wfe, wfi, sev, dbg, bxj, smc, srs, rfe
- -- cps, setend, pli, pld, pldw, clrex, dsb, dmb, isb
- -- stc, ldc, mcr, mcr2, mrc, mrc2, mcrr, mcrr2, mrrc, mrrc2, cdp, cdp2
-}
-
--- Add mnemonics for "s" variants.
-do
- local t = {}
- for k,v in pairs(map_op) do
- if sub(v, -1) == "s" then
- local v2 = sub(v, 1, 2)..char(byte(v, 3)+1)..sub(v, 4, -2)
- t[sub(k, 1, -3).."s"..sub(k, -2)] = v2
- end
- end
- for k,v in pairs(t) do
- map_op[k] = v
- end
-end
-
-------------------------------------------------------------------------------
-
-local function parse_gpr(expr)
- local tname, ovreg = match(expr, "^([%w_]+):(r1?[0-9])$")
- local tp = map_type[tname or expr]
- if tp then
- local reg = ovreg or tp.reg
- if not reg then
- werror("type `"..(tname or expr).."' needs a register override")
- end
- expr = reg
- end
- local r = match(expr, "^r(1?[0-9])$")
- if r then
- r = tonumber(r)
- if r <= 15 then return r, tp end
- end
- werror("bad register name `"..expr.."'")
-end
-
-local function parse_gpr_pm(expr)
- local pm, expr2 = match(expr, "^([+-]?)(.*)$")
- return parse_gpr(expr2), (pm == "-")
-end
-
-local function parse_reglist(reglist)
- reglist = match(reglist, "^{%s*([^}]*)}$")
- if not reglist then werror("register list expected") end
- local rr = 0
- for p in gmatch(reglist..",", "%s*([^,]*),") do
- local rbit = 2^parse_gpr(gsub(p, "%s+$", ""))
- if ((rr - (rr % rbit)) / rbit) % 2 ~= 0 then
- werror("duplicate register `"..p.."'")
- end
- rr = rr + rbit
- end
- return rr
-end
-
-local function parse_imm(imm, bits, shift, scale, signed)
- imm = match(imm, "^#(.*)$")
- if not imm then werror("expected immediate operand") end
- local n = tonumber(imm)
- if n then
- if n % 2^scale == 0 then
- n = n / 2^scale
- if signed then
- if n >= 0 then
- if n < 2^(bits-1) then return n*2^shift end
- else
- if n >= -(2^(bits-1))-1 then return (n+2^bits)*2^shift end
- end
- else
- if n >= 0 and n <= 2^bits-1 then return n*2^shift end
- end
- end
- werror("out of range immediate `"..imm.."'")
- else
- waction("IMM", (signed and 32768 or 0)+scale*1024+bits*32+shift, imm)
- return 0
- end
-end
-
-local function parse_imm12(imm)
- local n = tonumber(imm)
- if n then
- local m = n
- for i=0,-15,-1 do
- if m >= 0 and m <= 255 and n % 1 == 0 then return m + (i%16) * 256 end
- local t = m % 4
- m = (m - t) / 4 + t * 2^30
- end
- werror("out of range immediate `"..imm.."'")
- else
- waction("IMM12", 0, imm)
- return 0
- end
-end
-
-local function parse_imm16(imm)
- imm = match(imm, "^#(.*)$")
- if not imm then werror("expected immediate operand") end
- local n = tonumber(imm)
- if n then
- if n >= 0 and n <= 65535 and n % 1 == 0 then
- local t = n % 4096
- return (n - t) * 16 + t
- end
- werror("out of range immediate `"..imm.."'")
- else
- waction("IMM16", 32*16, imm)
- return 0
- end
-end
-
-local function parse_imm_load(imm, ext)
- local n = tonumber(imm)
- if n then
- if ext then
- if n >= -255 and n <= 255 then
- local up = 0x00800000
- if n < 0 then n = -n; up = 0 end
- return (n-(n%16))*16+(n%16) + up
- end
- else
- if n >= -4095 and n <= 4095 then
- if n >= 0 then return n+0x00800000 end
- return -n
- end
- end
- werror("out of range immediate `"..imm.."'")
- else
- waction(ext and "IMML8" or "IMML12", 32768 + 32*(ext and 8 or 12), imm)
- return 0
- end
-end
-
-local function parse_shift(shift, gprok)
- if shift == "rrx" then
- return 3 * 32
- else
- local s, s2 = match(shift, "^(%S+)%s*(.*)$")
- s = map_shift[s]
- if not s then werror("expected shift operand") end
- if sub(s2, 1, 1) == "#" then
- return parse_imm(s2, 5, 7, 0, false) + s * 32
- else
- if not gprok then werror("expected immediate shift operand") end
- return parse_gpr(s2) * 256 + s * 32 + 16
- end
- end
-end
-
-local function parse_label(label, def)
- local prefix = sub(label, 1, 2)
- -- =>label (pc label reference)
- if prefix == "=>" then
- return "PC", 0, sub(label, 3)
- end
- -- ->name (global label reference)
- if prefix == "->" then
- return "LG", map_global[sub(label, 3)]
- end
- if def then
- -- [1-9] (local label definition)
- if match(label, "^[1-9]$") then
- return "LG", 10+tonumber(label)
- end
- else
- -- [<>][1-9] (local label reference)
- local dir, lnum = match(label, "^([<>])([1-9])$")
- if dir then -- Fwd: 1-9, Bkwd: 11-19.
- return "LG", lnum + (dir == ">" and 0 or 10)
- end
- -- extern label (extern label reference)
- local extname = match(label, "^extern%s+(%S+)$")
- if extname then
- return "EXT", map_extern[extname]
- end
- end
- werror("bad label `"..label.."'")
-end
-
-local function parse_load(params, nparams, n, op)
- local oplo = op % 256
- local ext, ldrd = (oplo ~= 0), (oplo == 208)
- local d
- if (ldrd or oplo == 240) then
- d = ((op - (op % 4096)) / 4096) % 16
- if d % 2 ~= 0 then werror("odd destination register") end
- end
- local pn = params[n]
- local p1, wb = match(pn, "^%[%s*(.-)%s*%](!?)$")
- local p2 = params[n+1]
- if not p1 then
- if not p2 then
- if match(pn, "^[<>=%-]") or match(pn, "^extern%s+") then
- local mode, n, s = parse_label(pn, false)
- waction("REL_"..mode, n + (ext and 0x1800 or 0x0800), s, 1)
- return op + 15 * 65536 + 0x01000000 + (ext and 0x00400000 or 0)
- end
- local reg, tailr = match(pn, "^([%w_:]+)%s*(.*)$")
- if reg and tailr ~= "" then
- local d, tp = parse_gpr(reg)
- if tp then
- waction(ext and "IMML8" or "IMML12", 32768 + 32*(ext and 8 or 12),
- format(tp.ctypefmt, tailr))
- return op + d * 65536 + 0x01000000 + (ext and 0x00400000 or 0)
- end
- end
- end
- werror("expected address operand")
- end
- if wb == "!" then op = op + 0x00200000 end
- if p2 then
- if wb == "!" then werror("bad use of '!'") end
- local p3 = params[n+2]
- op = op + parse_gpr(p1) * 65536
- local imm = match(p2, "^#(.*)$")
- if imm then
- local m = parse_imm_load(imm, ext)
- if p3 then werror("too many parameters") end
- op = op + m + (ext and 0x00400000 or 0)
- else
- local m, neg = parse_gpr_pm(p2)
- if ldrd and (m == d or m-1 == d) then werror("register conflict") end
- op = op + m + (neg and 0 or 0x00800000) + (ext and 0 or 0x02000000)
- if p3 then op = op + parse_shift(p3) end
- end
- else
- local p1a, p2 = match(p1, "^([^,%s]*)%s*(.*)$")
- op = op + parse_gpr(p1a) * 65536 + 0x01000000
- if p2 ~= "" then
- local imm = match(p2, "^,%s*#(.*)$")
- if imm then
- local m = parse_imm_load(imm, ext)
- op = op + m + (ext and 0x00400000 or 0)
- else
- local p2a, p3 = match(p2, "^,%s*([^,%s]*)%s*,?%s*(.*)$")
- local m, neg = parse_gpr_pm(p2a)
- if ldrd and (m == d or m-1 == d) then werror("register conflict") end
- op = op + m + (neg and 0 or 0x00800000) + (ext and 0 or 0x02000000)
- if p3 ~= "" then
- if ext then werror("too many parameters") end
- op = op + parse_shift(p3)
- end
- end
- else
- if wb == "!" then werror("bad use of '!'") end
- op = op + (ext and 0x00c00000 or 0x00800000)
- end
- end
- return op
-end
-
-------------------------------------------------------------------------------
-
--- Handle opcodes defined with template strings.
-map_op[".template__"] = function(params, template, nparams)
- if not params then return sub(template, 9) end
- local op = tonumber(sub(template, 1, 8), 16)
- local n = 1
-
- -- Limit number of section buffer positions used by a single dasm_put().
- -- A single opcode needs a maximum of 3 positions.
- if secpos+3 > maxsecpos then wflush() end
- local pos = wpos()
-
- -- Process each character.
- for p in gmatch(sub(template, 9), ".") do
- if p == "D" then
- op = op + parse_gpr(params[n]) * 4096; n = n + 1
- elseif p == "N" then
- op = op + parse_gpr(params[n]) * 65536; n = n + 1
- elseif p == "S" then
- op = op + parse_gpr(params[n]) * 256; n = n + 1
- elseif p == "M" then
- op = op + parse_gpr(params[n]); n = n + 1
- elseif p == "P" then
- local imm = match(params[n], "^#(.*)$")
- if imm then
- op = op + parse_imm12(imm) + 0x02000000
- else
- op = op + parse_gpr(params[n])
- end
- n = n + 1
- elseif p == "p" then
- op = op + parse_shift(params[n], true); n = n + 1
- elseif p == "L" then
- op = parse_load(params, nparams, n, op)
- elseif p == "B" then
- local mode, n, s = parse_label(params[n], false)
- waction("REL_"..mode, n, s, 1)
- elseif p == "C" then -- blx gpr vs. blx label.
- local p = params[n]
- if match(p, "^([%w_]+):(r1?[0-9])$") or match(p, "^r(1?[0-9])$") then
- op = op + parse_gpr(p)
- else
- if op < 0xe0000000 then werror("unconditional instruction") end
- local mode, n, s = parse_label(p, false)
- waction("REL_"..mode, n, s, 1)
- op = 0xfa000000
- end
- elseif p == "n" then
- local r, wb = match(params[n], "^([^!]*)(!?)$")
- op = op + parse_gpr(r) * 65536 + (wb == "!" and 0x00200000 or 0)
- n = n + 1
- elseif p == "R" then
- op = op + parse_reglist(params[n]); n = n + 1
- elseif p == "W" then
- op = op + parse_imm16(params[n]); n = n + 1
- elseif p == "v" then
- op = op + parse_imm(params[n], 5, 7, 0, false); n = n + 1
- elseif p == "w" then
- local imm = match(params[n], "^#(.*)$")
- if imm then
- op = op + parse_imm(params[n], 5, 7, 0, false); n = n + 1
- else
- op = op + parse_gpr(params[n]) * 256 + 16
- end
- elseif p == "X" then
- op = op + parse_imm(params[n], 5, 16, 0, false); n = n + 1
- elseif p == "K" then
- local imm = tonumber(match(params[n], "^#(.*)$")); n = n + 1
- if not imm or imm % 1 ~= 0 or imm < 0 or imm > 0xffff then
- werror("bad immediate operand")
- end
- local t = imm % 16
- op = op + (imm - t) * 16 + t
- elseif p == "T" then
- op = op + parse_imm(params[n], 24, 0, 0, false); n = n + 1
- elseif p == "s" then
- -- Ignored.
- else
- assert(false)
- end
- end
- wputpos(pos, op)
-end
-
-------------------------------------------------------------------------------
-
--- Pseudo-opcode to mark the position where the action list is to be emitted.
-map_op[".actionlist_1"] = function(params)
- if not params then return "cvar" end
- local name = params[1] -- No syntax check. You get to keep the pieces.
- wline(function(out) writeactions(out, name) end)
-end
-
--- Pseudo-opcode to mark the position where the global enum is to be emitted.
-map_op[".globals_1"] = function(params)
- if not params then return "prefix" end
- local prefix = params[1] -- No syntax check. You get to keep the pieces.
- wline(function(out) writeglobals(out, prefix) end)
-end
-
--- Pseudo-opcode to mark the position where the global names are to be emitted.
-map_op[".globalnames_1"] = function(params)
- if not params then return "cvar" end
- local name = params[1] -- No syntax check. You get to keep the pieces.
- wline(function(out) writeglobalnames(out, name) end)
-end
-
--- Pseudo-opcode to mark the position where the extern names are to be emitted.
-map_op[".externnames_1"] = function(params)
- if not params then return "cvar" end
- local name = params[1] -- No syntax check. You get to keep the pieces.
- wline(function(out) writeexternnames(out, name) end)
-end
-
-------------------------------------------------------------------------------
-
--- Label pseudo-opcode (converted from trailing colon form).
-map_op[".label_1"] = function(params)
- if not params then return "[1-9] | ->global | =>pcexpr" end
- if secpos+1 > maxsecpos then wflush() end
- local mode, n, s = parse_label(params[1], true)
- if mode == "EXT" then werror("bad label definition") end
- waction("LABEL_"..mode, n, s, 1)
-end
-
-------------------------------------------------------------------------------
-
--- Pseudo-opcodes for data storage.
-map_op[".long_*"] = function(params)
- if not params then return "imm..." end
- for _,p in ipairs(params) do
- local n = tonumber(p)
- if not n then werror("bad immediate `"..p.."'") end
- if n < 0 then n = n + 2^32 end
- wputw(n)
- if secpos+2 > maxsecpos then wflush() end
- end
-end
-
--- Alignment pseudo-opcode.
-map_op[".align_1"] = function(params)
- if not params then return "numpow2" end
- if secpos+1 > maxsecpos then wflush() end
- local align = tonumber(params[1])
- if align then
- local x = align
- -- Must be a power of 2 in the range (2 ... 256).
- for i=1,8 do
- x = x / 2
- if x == 1 then
- waction("ALIGN", align-1, nil, 1) -- Action byte is 2**n-1.
- return
- end
- end
- end
- werror("bad alignment")
-end
-
-------------------------------------------------------------------------------
-
--- Pseudo-opcode for (primitive) type definitions (map to C types).
-map_op[".type_3"] = function(params, nparams)
- if not params then
- return nparams == 2 and "name, ctype" or "name, ctype, reg"
- end
- local name, ctype, reg = params[1], params[2], params[3]
- if not match(name, "^[%a_][%w_]*$") then
- werror("bad type name `"..name.."'")
- end
- local tp = map_type[name]
- if tp then
- werror("duplicate type `"..name.."'")
- end
- -- Add #type to defines. A bit unclean to put it in map_archdef.
- map_archdef["#"..name] = "sizeof("..ctype..")"
- -- Add new type and emit shortcut define.
- local num = ctypenum + 1
- map_type[name] = {
- ctype = ctype,
- ctypefmt = format("Dt%X(%%s)", num),
- reg = reg,
- }
- wline(format("#define Dt%X(_V) (int)(ptrdiff_t)&(((%s *)0)_V)", num, ctype))
- ctypenum = num
-end
-map_op[".type_2"] = map_op[".type_3"]
-
--- Dump type definitions.
-local function dumptypes(out, lvl)
- local t = {}
- for name in pairs(map_type) do t[#t+1] = name end
- sort(t)
- out:write("Type definitions:\n")
- for _,name in ipairs(t) do
- local tp = map_type[name]
- local reg = tp.reg or ""
- out:write(format(" %-20s %-20s %s\n", name, tp.ctype, reg))
- end
- out:write("\n")
-end
-
-------------------------------------------------------------------------------
-
--- Set the current section.
-function _M.section(num)
- waction("SECTION", num)
- wflush(true) -- SECTION is a terminal action.
-end
-
-------------------------------------------------------------------------------
-
--- Dump architecture description.
-function _M.dumparch(out)
- out:write(format("DynASM %s version %s, released %s\n\n",
- _info.arch, _info.version, _info.release))
- dumpactions(out)
-end
-
--- Dump all user defined elements.
-function _M.dumpdef(out, lvl)
- dumptypes(out, lvl)
- dumpglobals(out, lvl)
- dumpexterns(out, lvl)
-end
-
-------------------------------------------------------------------------------
-
--- Pass callbacks from/to the DynASM core.
-function _M.passcb(wl, we, wf, ww)
- wline, werror, wfatal, wwarn = wl, we, wf, ww
- return wflush
-end
-
--- Setup the arch-specific module.
-function _M.setup(arch, opt)
- g_arch, g_opt = arch, opt
-end
-
--- Merge the core maps and the arch-specific maps.
-function _M.mergemaps(map_coreop, map_def)
- setmetatable(map_op, { __index = function(t, k)
- local v = map_coreop[k]
- if v then return v end
- local cc = sub(k, -4, -3)
- local cv = map_cond[cc]
- if cv then
- local v = rawget(t, sub(k, 1, -5)..sub(k, -2))
- if type(v) == "string" then return format("%x%s", cv, sub(v, 2)) end
- end
- end })
- setmetatable(map_def, { __index = map_archdef })
- return map_op, map_def
-end
-
-return _M
-
-------------------------------------------------------------------------------
-
diff --git a/third_party/dynasm/dasm_mips.h b/third_party/dynasm/dasm_mips.h
deleted file mode 100644
index af87d99..0000000
--- a/third_party/dynasm/dasm_mips.h
+++ /dev/null
@@ -1,415 +0,0 @@
-/*
-** DynASM MIPS encoding engine.
-** Copyright (C) 2005-2012 Mike Pall. All rights reserved.
-** Released under the MIT license. See dynasm.lua for full copyright notice.
-*/
-
-#include <stddef.h>
-#include <stdarg.h>
-#include <string.h>
-#include <stdlib.h>
-
-#define DASM_ARCH "mips"
-
-#ifndef DASM_EXTERN
-#define DASM_EXTERN(a,b,c,d) 0
-#endif
-
-/* Action definitions. */
-enum {
- DASM_STOP, DASM_SECTION, DASM_ESC, DASM_REL_EXT,
- /* The following actions need a buffer position. */
- DASM_ALIGN, DASM_REL_LG, DASM_LABEL_LG,
- /* The following actions also have an argument. */
- DASM_REL_PC, DASM_LABEL_PC, DASM_IMM,
- DASM__MAX
-};
-
-/* Maximum number of section buffer positions for a single dasm_put() call. */
-#define DASM_MAXSECPOS 25
-
-/* DynASM encoder status codes. Action list offset or number are or'ed in. */
-#define DASM_S_OK 0x00000000
-#define DASM_S_NOMEM 0x01000000
-#define DASM_S_PHASE 0x02000000
-#define DASM_S_MATCH_SEC 0x03000000
-#define DASM_S_RANGE_I 0x11000000
-#define DASM_S_RANGE_SEC 0x12000000
-#define DASM_S_RANGE_LG 0x13000000
-#define DASM_S_RANGE_PC 0x14000000
-#define DASM_S_RANGE_REL 0x15000000
-#define DASM_S_UNDEF_LG 0x21000000
-#define DASM_S_UNDEF_PC 0x22000000
-
-/* Macros to convert positions (8 bit section + 24 bit index). */
-#define DASM_POS2IDX(pos) ((pos)&0x00ffffff)
-#define DASM_POS2BIAS(pos) ((pos)&0xff000000)
-#define DASM_SEC2POS(sec) ((sec)<<24)
-#define DASM_POS2SEC(pos) ((pos)>>24)
-#define DASM_POS2PTR(D, pos) (D->sections[DASM_POS2SEC(pos)].rbuf + (pos))
-
-/* Action list type. */
-typedef const unsigned int *dasm_ActList;
-
-/* Per-section structure. */
-typedef struct dasm_Section {
- int *rbuf; /* Biased buffer pointer (negative section bias). */
- int *buf; /* True buffer pointer. */
- size_t bsize; /* Buffer size in bytes. */
- int pos; /* Biased buffer position. */
- int epos; /* End of biased buffer position - max single put. */
- int ofs; /* Byte offset into section. */
-} dasm_Section;
-
-/* Core structure holding the DynASM encoding state. */
-struct dasm_State {
- size_t psize; /* Allocated size of this structure. */
- dasm_ActList actionlist; /* Current actionlist pointer. */
- int *lglabels; /* Local/global chain/pos ptrs. */
- size_t lgsize;
- int *pclabels; /* PC label chains/pos ptrs. */
- size_t pcsize;
- void **globals; /* Array of globals (bias -10). */
- dasm_Section *section; /* Pointer to active section. */
- size_t codesize; /* Total size of all code sections. */
- int maxsection; /* 0 <= sectionidx < maxsection. */
- int status; /* Status code. */
- dasm_Section sections[1]; /* All sections. Alloc-extended. */
-};
-
-/* The size of the core structure depends on the max. number of sections. */
-#define DASM_PSZ(ms) (sizeof(dasm_State)+(ms-1)*sizeof(dasm_Section))
-
-
-/* Initialize DynASM state. */
-void dasm_init(Dst_DECL, int maxsection)
-{
- dasm_State *D;
- size_t psz = 0;
- int i;
- Dst_REF = NULL;
- DASM_M_GROW(Dst, struct dasm_State, Dst_REF, psz, DASM_PSZ(maxsection));
- D = Dst_REF;
- D->psize = psz;
- D->lglabels = NULL;
- D->lgsize = 0;
- D->pclabels = NULL;
- D->pcsize = 0;
- D->globals = NULL;
- D->maxsection = maxsection;
- for (i = 0; i < maxsection; i++) {
- D->sections[i].buf = NULL; /* Need this for pass3. */
- D->sections[i].rbuf = D->sections[i].buf - DASM_SEC2POS(i);
- D->sections[i].bsize = 0;
- D->sections[i].epos = 0; /* Wrong, but is recalculated after resize. */
- }
-}
-
-/* Free DynASM state. */
-void dasm_free(Dst_DECL)
-{
- dasm_State *D = Dst_REF;
- int i;
- for (i = 0; i < D->maxsection; i++)
- if (D->sections[i].buf)
- DASM_M_FREE(Dst, D->sections[i].buf, D->sections[i].bsize);
- if (D->pclabels) DASM_M_FREE(Dst, D->pclabels, D->pcsize);
- if (D->lglabels) DASM_M_FREE(Dst, D->lglabels, D->lgsize);
- DASM_M_FREE(Dst, D, D->psize);
-}
-
-/* Setup global label array. Must be called before dasm_setup(). */
-void dasm_setupglobal(Dst_DECL, void **gl, unsigned int maxgl)
-{
- dasm_State *D = Dst_REF;
- D->globals = gl - 10; /* Negative bias to compensate for locals. */
- DASM_M_GROW(Dst, int, D->lglabels, D->lgsize, (10+maxgl)*sizeof(int));
-}
-
-/* Grow PC label array. Can be called after dasm_setup(), too. */
-void dasm_growpc(Dst_DECL, unsigned int maxpc)
-{
- dasm_State *D = Dst_REF;
- size_t osz = D->pcsize;
- DASM_M_GROW(Dst, int, D->pclabels, D->pcsize, maxpc*sizeof(int));
- memset((void *)(((unsigned char *)D->pclabels)+osz), 0, D->pcsize-osz);
-}
-
-/* Setup encoder. */
-void dasm_setup(Dst_DECL, const void *actionlist)
-{
- dasm_State *D = Dst_REF;
- int i;
- D->actionlist = (dasm_ActList)actionlist;
- D->status = DASM_S_OK;
- D->section = &D->sections[0];
- memset((void *)D->lglabels, 0, D->lgsize);
- if (D->pclabels) memset((void *)D->pclabels, 0, D->pcsize);
- for (i = 0; i < D->maxsection; i++) {
- D->sections[i].pos = DASM_SEC2POS(i);
- D->sections[i].ofs = 0;
- }
-}
-
-
-#ifdef DASM_CHECKS
-#define CK(x, st) \
- do { if (!(x)) { \
- D->status = DASM_S_##st|(p-D->actionlist-1); return; } } while (0)
-#define CKPL(kind, st) \
- do { if ((size_t)((char *)pl-(char *)D->kind##labels) >= D->kind##size) { \
- D->status = DASM_S_RANGE_##st|(p-D->actionlist-1); return; } } while (0)
-#else
-#define CK(x, st) ((void)0)
-#define CKPL(kind, st) ((void)0)
-#endif
-
-/* Pass 1: Store actions and args, link branches/labels, estimate offsets. */
-void dasm_put(Dst_DECL, int start, ...)
-{
- va_list ap;
- dasm_State *D = Dst_REF;
- dasm_ActList p = D->actionlist + start;
- dasm_Section *sec = D->section;
- int pos = sec->pos, ofs = sec->ofs;
- int *b;
-
- if (pos >= sec->epos) {
- DASM_M_GROW(Dst, int, sec->buf, sec->bsize,
- sec->bsize + 2*DASM_MAXSECPOS*sizeof(int));
- sec->rbuf = sec->buf - DASM_POS2BIAS(pos);
- sec->epos = (int)sec->bsize/sizeof(int) - DASM_MAXSECPOS+DASM_POS2BIAS(pos);
- }
-
- b = sec->rbuf;
- b[pos++] = start;
-
- va_start(ap, start);
- while (1) {
- unsigned int ins = *p++;
- unsigned int action = (ins >> 16) - 0xff00;
- if (action >= DASM__MAX) {
- ofs += 4;
- } else {
- int *pl, n = action >= DASM_REL_PC ? va_arg(ap, int) : 0;
- switch (action) {
- case DASM_STOP: goto stop;
- case DASM_SECTION:
- n = (ins & 255); CK(n < D->maxsection, RANGE_SEC);
- D->section = &D->sections[n]; goto stop;
- case DASM_ESC: p++; ofs += 4; break;
- case DASM_REL_EXT: break;
- case DASM_ALIGN: ofs += (ins & 255); b[pos++] = ofs; break;
- case DASM_REL_LG:
- n = (ins & 2047) - 10; pl = D->lglabels + n;
- if (n >= 0) { CKPL(lg, LG); goto putrel; } /* Bkwd rel or global. */
- pl += 10; n = *pl;
- if (n < 0) n = 0; /* Start new chain for fwd rel if label exists. */
- goto linkrel;
- case DASM_REL_PC:
- pl = D->pclabels + n; CKPL(pc, PC);
- putrel:
- n = *pl;
- if (n < 0) { /* Label exists. Get label pos and store it. */
- b[pos] = -n;
- } else {
- linkrel:
- b[pos] = n; /* Else link to rel chain, anchored at label. */
- *pl = pos;
- }
- pos++;
- break;
- case DASM_LABEL_LG:
- pl = D->lglabels + (ins & 2047) - 10; CKPL(lg, LG); goto putlabel;
- case DASM_LABEL_PC:
- pl = D->pclabels + n; CKPL(pc, PC);
- putlabel:
- n = *pl; /* n > 0: Collapse rel chain and replace with label pos. */
- while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = pos;
- }
- *pl = -pos; /* Label exists now. */
- b[pos++] = ofs; /* Store pass1 offset estimate. */
- break;
- case DASM_IMM:
-#ifdef DASM_CHECKS
- CK((n & ((1<<((ins>>10)&31))-1)) == 0, RANGE_I);
-#endif
- n >>= ((ins>>10)&31);
-#ifdef DASM_CHECKS
- if (ins & 0x8000)
- CK(((n + (1<<(((ins>>5)&31)-1)))>>((ins>>5)&31)) == 0, RANGE_I);
- else
- CK((n>>((ins>>5)&31)) == 0, RANGE_I);
-#endif
- b[pos++] = n;
- break;
- }
- }
- }
-stop:
- va_end(ap);
- sec->pos = pos;
- sec->ofs = ofs;
-}
-#undef CK
-
-/* Pass 2: Link sections, shrink aligns, fix label offsets. */
-int dasm_link(Dst_DECL, size_t *szp)
-{
- dasm_State *D = Dst_REF;
- int secnum;
- int ofs = 0;
-
-#ifdef DASM_CHECKS
- *szp = 0;
- if (D->status != DASM_S_OK) return D->status;
- {
- int pc;
- for (pc = 0; pc*sizeof(int) < D->pcsize; pc++)
- if (D->pclabels[pc] > 0) return DASM_S_UNDEF_PC|pc;
- }
-#endif
-
- { /* Handle globals not defined in this translation unit. */
- int idx;
- for (idx = 20; idx*sizeof(int) < D->lgsize; idx++) {
- int n = D->lglabels[idx];
- /* Undefined label: Collapse rel chain and replace with marker (< 0). */
- while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = -idx; }
- }
- }
-
- /* Combine all code sections. No support for data sections (yet). */
- for (secnum = 0; secnum < D->maxsection; secnum++) {
- dasm_Section *sec = D->sections + secnum;
- int *b = sec->rbuf;
- int pos = DASM_SEC2POS(secnum);
- int lastpos = sec->pos;
-
- while (pos != lastpos) {
- dasm_ActList p = D->actionlist + b[pos++];
- while (1) {
- unsigned int ins = *p++;
- unsigned int action = (ins >> 16) - 0xff00;
- switch (action) {
- case DASM_STOP: case DASM_SECTION: goto stop;
- case DASM_ESC: p++; break;
- case DASM_REL_EXT: break;
- case DASM_ALIGN: ofs -= (b[pos++] + ofs) & (ins & 255); break;
- case DASM_REL_LG: case DASM_REL_PC: pos++; break;
- case DASM_LABEL_LG: case DASM_LABEL_PC: b[pos++] += ofs; break;
- case DASM_IMM: pos++; break;
- }
- }
- stop: (void)0;
- }
- ofs += sec->ofs; /* Next section starts right after current section. */
- }
-
- D->codesize = ofs; /* Total size of all code sections */
- *szp = ofs;
- return DASM_S_OK;
-}
-
-#ifdef DASM_CHECKS
-#define CK(x, st) \
- do { if (!(x)) return DASM_S_##st|(p-D->actionlist-1); } while (0)
-#else
-#define CK(x, st) ((void)0)
-#endif
-
-/* Pass 3: Encode sections. */
-int dasm_encode(Dst_DECL, void *buffer)
-{
- dasm_State *D = Dst_REF;
- char *base = (char *)buffer;
- unsigned int *cp = (unsigned int *)buffer;
- int secnum;
-
- /* Encode all code sections. No support for data sections (yet). */
- for (secnum = 0; secnum < D->maxsection; secnum++) {
- dasm_Section *sec = D->sections + secnum;
- int *b = sec->buf;
- int *endb = sec->rbuf + sec->pos;
-
- while (b != endb) {
- dasm_ActList p = D->actionlist + *b++;
- while (1) {
- unsigned int ins = *p++;
- unsigned int action = (ins >> 16) - 0xff00;
- int n = (action >= DASM_ALIGN && action < DASM__MAX) ? *b++ : 0;
- switch (action) {
- case DASM_STOP: case DASM_SECTION: goto stop;
- case DASM_ESC: *cp++ = *p++; break;
- case DASM_REL_EXT:
- n = DASM_EXTERN(Dst, (unsigned char *)cp, (ins & 2047), 1);
- goto patchrel;
- case DASM_ALIGN:
- ins &= 255; while ((((char *)cp - base) & ins)) *cp++ = 0x60000000;
- break;
- case DASM_REL_LG:
- CK(n >= 0, UNDEF_LG);
- case DASM_REL_PC:
- CK(n >= 0, UNDEF_PC);
- n = *DASM_POS2PTR(D, n);
- if (ins & 2048)
- n = n - (int)((char *)cp - base);
- else
- n = (n + (int)base) & 0x0fffffff;
- patchrel:
- CK((n & 3) == 0 &&
- ((n + ((ins & 2048) ? 0x00020000 : 0)) >>
- ((ins & 2048) ? 18 : 28)) == 0, RANGE_REL);
- cp[-1] |= ((n>>2) & ((ins & 2048) ? 0x0000ffff: 0x03ffffff));
- break;
- case DASM_LABEL_LG:
- ins &= 2047; if (ins >= 20) D->globals[ins-10] = (void *)(base + n);
- break;
- case DASM_LABEL_PC: break;
- case DASM_IMM:
- cp[-1] |= (n & ((1<<((ins>>5)&31))-1)) << (ins&31);
- break;
- default: *cp++ = ins; break;
- }
- }
- stop: (void)0;
- }
- }
-
- if (base + D->codesize != (char *)cp) /* Check for phase errors. */
- return DASM_S_PHASE;
- return DASM_S_OK;
-}
-#undef CK
-
-/* Get PC label offset. */
-int dasm_getpclabel(Dst_DECL, unsigned int pc)
-{
- dasm_State *D = Dst_REF;
- if (pc*sizeof(int) < D->pcsize) {
- int pos = D->pclabels[pc];
- if (pos < 0) return *DASM_POS2PTR(D, -pos);
- if (pos > 0) return -1; /* Undefined. */
- }
- return -2; /* Unused or out of range. */
-}
-
-#ifdef DASM_CHECKS
-/* Optional sanity checker to call between isolated encoding steps. */
-int dasm_checkstep(Dst_DECL, int secmatch)
-{
- dasm_State *D = Dst_REF;
- if (D->status == DASM_S_OK) {
- int i;
- for (i = 1; i <= 9; i++) {
- if (D->lglabels[i] > 0) { D->status = DASM_S_UNDEF_LG|i; break; }
- D->lglabels[i] = 0;
- }
- }
- if (D->status == DASM_S_OK && secmatch >= 0 &&
- D->section != &D->sections[secmatch])
- D->status = DASM_S_MATCH_SEC|(D->section-D->sections);
- return D->status;
-}
-#endif
-
diff --git a/third_party/dynasm/dasm_mips.lua b/third_party/dynasm/dasm_mips.lua
deleted file mode 100644
index aa33f0c..0000000
--- a/third_party/dynasm/dasm_mips.lua
+++ /dev/null
@@ -1,959 +0,0 @@
-------------------------------------------------------------------------------
--- DynASM MIPS module.
---
--- Copyright (C) 2005-2012 Mike Pall. All rights reserved.
--- See dynasm.lua for full copyright notice.
-------------------------------------------------------------------------------
-
--- Module information:
-local _info = {
- arch = "mips",
- description = "DynASM MIPS module",
- version = "1.3.0",
- vernum = 10300,
- release = "2012-01-23",
- author = "Mike Pall",
- license = "MIT",
-}
-
--- Exported glue functions for the arch-specific module.
-local _M = { _info = _info }
-
--- Cache library functions.
-local type, tonumber, pairs, ipairs = type, tonumber, pairs, ipairs
-local assert, setmetatable = assert, setmetatable
-local _s = string
-local sub, format, byte, char = _s.sub, _s.format, _s.byte, _s.char
-local match, gmatch = _s.match, _s.gmatch
-local concat, sort = table.concat, table.sort
-
--- Inherited tables and callbacks.
-local g_opt, g_arch
-local wline, werror, wfatal, wwarn
-
--- Action name list.
--- CHECK: Keep this in sync with the C code!
-local action_names = {
- "STOP", "SECTION", "ESC", "REL_EXT",
- "ALIGN", "REL_LG", "LABEL_LG",
- "REL_PC", "LABEL_PC", "IMM",
-}
-
--- Maximum number of section buffer positions for dasm_put().
--- CHECK: Keep this in sync with the C code!
-local maxsecpos = 25 -- Keep this low, to avoid excessively long C lines.
-
--- Action name -> action number.
-local map_action = {}
-for n,name in ipairs(action_names) do
- map_action[name] = n-1
-end
-
--- Action list buffer.
-local actlist = {}
-
--- Argument list for next dasm_put(). Start with offset 0 into action list.
-local actargs = { 0 }
-
--- Current number of section buffer positions for dasm_put().
-local secpos = 1
-
-------------------------------------------------------------------------------
-
--- Return 8 digit hex number.
-local function tohex(x)
- return sub(format("%08x", x), -8) -- Avoid 64 bit portability problem in Lua.
-end
-
--- Dump action names and numbers.
-local function dumpactions(out)
- out:write("DynASM encoding engine action codes:\n")
- for n,name in ipairs(action_names) do
- local num = map_action[name]
- out:write(format(" %-10s %02X %d\n", name, num, num))
- end
- out:write("\n")
-end
-
--- Write action list buffer as a huge static C array.
-local function writeactions(out, name)
- local nn = #actlist
- if nn == 0 then nn = 1; actlist[0] = map_action.STOP end
- out:write("static const unsigned int ", name, "[", nn, "] = {\n")
- for i = 1,nn-1 do
- assert(out:write("0x", tohex(actlist[i]), ",\n"))
- end
- assert(out:write("0x", tohex(actlist[nn]), "\n};\n\n"))
-end
-
-------------------------------------------------------------------------------
-
--- Add word to action list.
-local function wputxw(n)
- assert(n >= 0 and n <= 0xffffffff and n % 1 == 0, "word out of range")
- actlist[#actlist+1] = n
-end
-
--- Add action to list with optional arg. Advance buffer pos, too.
-local function waction(action, val, a, num)
- local w = assert(map_action[action], "bad action name `"..action.."'")
- wputxw(0xff000000 + w * 0x10000 + (val or 0))
- if a then actargs[#actargs+1] = a end
- if a or num then secpos = secpos + (num or 1) end
-end
-
--- Flush action list (intervening C code or buffer pos overflow).
-local function wflush(term)
- if #actlist == actargs[1] then return end -- Nothing to flush.
- if not term then waction("STOP") end -- Terminate action list.
- wline(format("dasm_put(Dst, %s);", concat(actargs, ", ")), true)
- actargs = { #actlist } -- Actionlist offset is 1st arg to next dasm_put().
- secpos = 1 -- The actionlist offset occupies a buffer position, too.
-end
-
--- Put escaped word.
-local function wputw(n)
- if n >= 0xff000000 then waction("ESC") end
- wputxw(n)
-end
-
--- Reserve position for word.
-local function wpos()
- local pos = #actlist+1
- actlist[pos] = ""
- return pos
-end
-
--- Store word to reserved position.
-local function wputpos(pos, n)
- assert(n >= 0 and n <= 0xffffffff and n % 1 == 0, "word out of range")
- actlist[pos] = n
-end
-
-------------------------------------------------------------------------------
-
--- Global label name -> global label number. With auto assignment on 1st use.
-local next_global = 20
-local map_global = setmetatable({}, { __index = function(t, name)
- if not match(name, "^[%a_][%w_]*$") then werror("bad global label") end
- local n = next_global
- if n > 2047 then werror("too many global labels") end
- next_global = n + 1
- t[name] = n
- return n
-end})
-
--- Dump global labels.
-local function dumpglobals(out, lvl)
- local t = {}
- for name, n in pairs(map_global) do t[n] = name end
- out:write("Global labels:\n")
- for i=20,next_global-1 do
- out:write(format(" %s\n", t[i]))
- end
- out:write("\n")
-end
-
--- Write global label enum.
-local function writeglobals(out, prefix)
- local t = {}
- for name, n in pairs(map_global) do t[n] = name end
- out:write("enum {\n")
- for i=20,next_global-1 do
- out:write(" ", prefix, t[i], ",\n")
- end
- out:write(" ", prefix, "_MAX\n};\n")
-end
-
--- Write global label names.
-local function writeglobalnames(out, name)
- local t = {}
- for name, n in pairs(map_global) do t[n] = name end
- out:write("static const char *const ", name, "[] = {\n")
- for i=20,next_global-1 do
- out:write(" \"", t[i], "\",\n")
- end
- out:write(" (const char *)0\n};\n")
-end
-
-------------------------------------------------------------------------------
-
--- Extern label name -> extern label number. With auto assignment on 1st use.
-local next_extern = 0
-local map_extern_ = {}
-local map_extern = setmetatable({}, { __index = function(t, name)
- -- No restrictions on the name for now.
- local n = next_extern
- if n > 2047 then werror("too many extern labels") end
- next_extern = n + 1
- t[name] = n
- map_extern_[n] = name
- return n
-end})
-
--- Dump extern labels.
-local function dumpexterns(out, lvl)
- out:write("Extern labels:\n")
- for i=0,next_extern-1 do
- out:write(format(" %s\n", map_extern_[i]))
- end
- out:write("\n")
-end
-
--- Write extern label names.
-local function writeexternnames(out, name)
- out:write("static const char *const ", name, "[] = {\n")
- for i=0,next_extern-1 do
- out:write(" \"", map_extern_[i], "\",\n")
- end
- out:write(" (const char *)0\n};\n")
-end
-
-------------------------------------------------------------------------------
-
--- Arch-specific maps.
-local map_archdef = { sp="r29", ra="r31" } -- Ext. register name -> int. name.
-
-local map_type = {} -- Type name -> { ctype, reg }
-local ctypenum = 0 -- Type number (for Dt... macros).
-
--- Reverse defines for registers.
-function _M.revdef(s)
- if s == "r29" then return "sp"
- elseif s == "r31" then return "ra" end
- return s
-end
-
-------------------------------------------------------------------------------
-
--- Template strings for MIPS instructions.
-local map_op = {
- -- First-level opcodes.
- j_1 = "08000000J",
- jal_1 = "0c000000J",
- b_1 = "10000000B",
- beqz_2 = "10000000SB",
- beq_3 = "10000000STB",
- bnez_2 = "14000000SB",
- bne_3 = "14000000STB",
- blez_2 = "18000000SB",
- bgtz_2 = "1c000000SB",
- addi_3 = "20000000TSI",
- li_2 = "24000000TI",
- addiu_3 = "24000000TSI",
- slti_3 = "28000000TSI",
- sltiu_3 = "2c000000TSI",
- andi_3 = "30000000TSU",
- lu_2 = "34000000TU",
- ori_3 = "34000000TSU",
- xori_3 = "38000000TSU",
- lui_2 = "3c000000TU",
- beqzl_2 = "50000000SB",
- beql_3 = "50000000STB",
- bnezl_2 = "54000000SB",
- bnel_3 = "54000000STB",
- blezl_2 = "58000000SB",
- bgtzl_2 = "5c000000SB",
- lb_2 = "80000000TO",
- lh_2 = "84000000TO",
- lwl_2 = "88000000TO",
- lw_2 = "8c000000TO",
- lbu_2 = "90000000TO",
- lhu_2 = "94000000TO",
- lwr_2 = "98000000TO",
- sb_2 = "a0000000TO",
- sh_2 = "a4000000TO",
- swl_2 = "a8000000TO",
- sw_2 = "ac000000TO",
- swr_2 = "b8000000TO",
- cache_2 = "bc000000NO",
- ll_2 = "c0000000TO",
- lwc1_2 = "c4000000HO",
- pref_2 = "cc000000NO",
- ldc1_2 = "d4000000HO",
- sc_2 = "e0000000TO",
- swc1_2 = "e4000000HO",
- sdc1_2 = "f4000000HO",
-
- -- Opcode SPECIAL.
- nop_0 = "00000000",
- sll_3 = "00000000DTA",
- movf_2 = "00000001DS",
- movf_3 = "00000001DSC",
- movt_2 = "00010001DS",
- movt_3 = "00010001DSC",
- srl_3 = "00000002DTA",
- rotr_3 = "00200002DTA",
- sra_3 = "00000003DTA",
- sllv_3 = "00000004DTS",
- srlv_3 = "00000006DTS",
- rotrv_3 = "00000046DTS",
- srav_3 = "00000007DTS",
- jr_1 = "00000008S",
- jalr_1 = "0000f809S",
- jalr_2 = "00000009DS",
- movz_3 = "0000000aDST",
- movn_3 = "0000000bDST",
- syscall_0 = "0000000c",
- syscall_1 = "0000000cY",
- break_0 = "0000000d",
- break_1 = "0000000dY",
- sync_0 = "0000000f",
- mfhi_1 = "00000010D",
- mthi_1 = "00000011S",
- mflo_1 = "00000012D",
- mtlo_1 = "00000013S",
- mult_2 = "00000018ST",
- multu_2 = "00000019ST",
- div_2 = "0000001aST",
- divu_2 = "0000001bST",
- add_3 = "00000020DST",
- move_2 = "00000021DS",
- addu_3 = "00000021DST",
- sub_3 = "00000022DST",
- negu_2 = "00000023DT",
- subu_3 = "00000023DST",
- and_3 = "00000024DST",
- or_3 = "00000025DST",
- xor_3 = "00000026DST",
- not_2 = "00000027DS",
- nor_3 = "00000027DST",
- slt_3 = "0000002aDST",
- sltu_3 = "0000002bDST",
- tge_2 = "00000030ST",
- tge_3 = "00000030STZ",
- tgeu_2 = "00000031ST",
- tgeu_3 = "00000031STZ",
- tlt_2 = "00000032ST",
- tlt_3 = "00000032STZ",
- tltu_2 = "00000033ST",
- tltu_3 = "00000033STZ",
- teq_2 = "00000034ST",
- teq_3 = "00000034STZ",
- tne_2 = "00000036ST",
- tne_3 = "00000036STZ",
-
- -- Opcode REGIMM.
- bltz_2 = "04000000SB",
- bgez_2 = "04010000SB",
- bltzl_2 = "04020000SB",
- bgezl_2 = "04030000SB",
- tgei_2 = "04080000SI",
- tgeiu_2 = "04090000SI",
- tlti_2 = "040a0000SI",
- tltiu_2 = "040b0000SI",
- teqi_2 = "040c0000SI",
- tnei_2 = "040e0000SI",
- bltzal_2 = "04100000SB",
- bal_1 = "04110000B",
- bgezal_2 = "04110000SB",
- bltzall_2 = "04120000SB",
- bgezall_2 = "04130000SB",
- synci_1 = "041f0000O",
-
- -- Opcode SPECIAL2.
- madd_2 = "70000000ST",
- maddu_2 = "70000001ST",
- mul_3 = "70000002DST",
- msub_2 = "70000004ST",
- msubu_2 = "70000005ST",
- clz_2 = "70000020DS=",
- clo_2 = "70000021DS=",
- sdbbp_0 = "7000003f",
- sdbbp_1 = "7000003fY",
-
- -- Opcode SPECIAL3.
- ext_4 = "7c000000TSAM", -- Note: last arg is msbd = size-1
- ins_4 = "7c000004TSAM", -- Note: last arg is msb = pos+size-1
- wsbh_2 = "7c0000a0DT",
- seb_2 = "7c000420DT",
- seh_2 = "7c000620DT",
- rdhwr_2 = "7c00003bTD",
-
- -- Opcode COP0.
- mfc0_2 = "40000000TD",
- mfc0_3 = "40000000TDW",
- mtc0_2 = "40800000TD",
- mtc0_3 = "40800000TDW",
- rdpgpr_2 = "41400000DT",
- di_0 = "41606000",
- di_1 = "41606000T",
- ei_0 = "41606020",
- ei_1 = "41606020T",
- wrpgpr_2 = "41c00000DT",
- tlbr_0 = "42000001",
- tlbwi_0 = "42000002",
- tlbwr_0 = "42000006",
- tlbp_0 = "42000008",
- eret_0 = "42000018",
- deret_0 = "4200001f",
- wait_0 = "42000020",
-
- -- Opcode COP1.
- mfc1_2 = "44000000TG",
- cfc1_2 = "44400000TG",
- mfhc1_2 = "44600000TG",
- mtc1_2 = "44800000TG",
- ctc1_2 = "44c00000TG",
- mthc1_2 = "44e00000TG",
-
- bc1f_1 = "45000000B",
- bc1f_2 = "45000000CB",
- bc1t_1 = "45010000B",
- bc1t_2 = "45010000CB",
- bc1fl_1 = "45020000B",
- bc1fl_2 = "45020000CB",
- bc1tl_1 = "45030000B",
- bc1tl_2 = "45030000CB",
-
- ["add.s_3"] = "46000000FGH",
- ["sub.s_3"] = "46000001FGH",
- ["mul.s_3"] = "46000002FGH",
- ["div.s_3"] = "46000003FGH",
- ["sqrt.s_2"] = "46000004FG",
- ["abs.s_2"] = "46000005FG",
- ["mov.s_2"] = "46000006FG",
- ["neg.s_2"] = "46000007FG",
- ["round.l.s_2"] = "46000008FG",
- ["trunc.l.s_2"] = "46000009FG",
- ["ceil.l.s_2"] = "4600000aFG",
- ["floor.l.s_2"] = "4600000bFG",
- ["round.w.s_2"] = "4600000cFG",
- ["trunc.w.s_2"] = "4600000dFG",
- ["ceil.w.s_2"] = "4600000eFG",
- ["floor.w.s_2"] = "4600000fFG",
- ["movf.s_2"] = "46000011FG",
- ["movf.s_3"] = "46000011FGC",
- ["movt.s_2"] = "46010011FG",
- ["movt.s_3"] = "46010011FGC",
- ["movz.s_3"] = "46000012FGT",
- ["movn.s_3"] = "46000013FGT",
- ["recip.s_2"] = "46000015FG",
- ["rsqrt.s_2"] = "46000016FG",
- ["cvt.d.s_2"] = "46000021FG",
- ["cvt.w.s_2"] = "46000024FG",
- ["cvt.l.s_2"] = "46000025FG",
- ["cvt.ps.s_3"] = "46000026FGH",
- ["c.f.s_2"] = "46000030GH",
- ["c.f.s_3"] = "46000030VGH",
- ["c.un.s_2"] = "46000031GH",
- ["c.un.s_3"] = "46000031VGH",
- ["c.eq.s_2"] = "46000032GH",
- ["c.eq.s_3"] = "46000032VGH",
- ["c.ueq.s_2"] = "46000033GH",
- ["c.ueq.s_3"] = "46000033VGH",
- ["c.olt.s_2"] = "46000034GH",
- ["c.olt.s_3"] = "46000034VGH",
- ["c.ult.s_2"] = "46000035GH",
- ["c.ult.s_3"] = "46000035VGH",
- ["c.ole.s_2"] = "46000036GH",
- ["c.ole.s_3"] = "46000036VGH",
- ["c.ule.s_2"] = "46000037GH",
- ["c.ule.s_3"] = "46000037VGH",
- ["c.sf.s_2"] = "46000038GH",
- ["c.sf.s_3"] = "46000038VGH",
- ["c.ngle.s_2"] = "46000039GH",
- ["c.ngle.s_3"] = "46000039VGH",
- ["c.seq.s_2"] = "4600003aGH",
- ["c.seq.s_3"] = "4600003aVGH",
- ["c.ngl.s_2"] = "4600003bGH",
- ["c.ngl.s_3"] = "4600003bVGH",
- ["c.lt.s_2"] = "4600003cGH",
- ["c.lt.s_3"] = "4600003cVGH",
- ["c.nge.s_2"] = "4600003dGH",
- ["c.nge.s_3"] = "4600003dVGH",
- ["c.le.s_2"] = "4600003eGH",
- ["c.le.s_3"] = "4600003eVGH",
- ["c.ngt.s_2"] = "4600003fGH",
- ["c.ngt.s_3"] = "4600003fVGH",
-
- ["add.d_3"] = "46200000FGH",
- ["sub.d_3"] = "46200001FGH",
- ["mul.d_3"] = "46200002FGH",
- ["div.d_3"] = "46200003FGH",
- ["sqrt.d_2"] = "46200004FG",
- ["abs.d_2"] = "46200005FG",
- ["mov.d_2"] = "46200006FG",
- ["neg.d_2"] = "46200007FG",
- ["round.l.d_2"] = "46200008FG",
- ["trunc.l.d_2"] = "46200009FG",
- ["ceil.l.d_2"] = "4620000aFG",
- ["floor.l.d_2"] = "4620000bFG",
- ["round.w.d_2"] = "4620000cFG",
- ["trunc.w.d_2"] = "4620000dFG",
- ["ceil.w.d_2"] = "4620000eFG",
- ["floor.w.d_2"] = "4620000fFG",
- ["movf.d_2"] = "46200011FG",
- ["movf.d_3"] = "46200011FGC",
- ["movt.d_2"] = "46210011FG",
- ["movt.d_3"] = "46210011FGC",
- ["movz.d_3"] = "46200012FGT",
- ["movn.d_3"] = "46200013FGT",
- ["recip.d_2"] = "46200015FG",
- ["rsqrt.d_2"] = "46200016FG",
- ["cvt.s.d_2"] = "46200020FG",
- ["cvt.w.d_2"] = "46200024FG",
- ["cvt.l.d_2"] = "46200025FG",
- ["c.f.d_2"] = "46200030GH",
- ["c.f.d_3"] = "46200030VGH",
- ["c.un.d_2"] = "46200031GH",
- ["c.un.d_3"] = "46200031VGH",
- ["c.eq.d_2"] = "46200032GH",
- ["c.eq.d_3"] = "46200032VGH",
- ["c.ueq.d_2"] = "46200033GH",
- ["c.ueq.d_3"] = "46200033VGH",
- ["c.olt.d_2"] = "46200034GH",
- ["c.olt.d_3"] = "46200034VGH",
- ["c.ult.d_2"] = "46200035GH",
- ["c.ult.d_3"] = "46200035VGH",
- ["c.ole.d_2"] = "46200036GH",
- ["c.ole.d_3"] = "46200036VGH",
- ["c.ule.d_2"] = "46200037GH",
- ["c.ule.d_3"] = "46200037VGH",
- ["c.sf.d_2"] = "46200038GH",
- ["c.sf.d_3"] = "46200038VGH",
- ["c.ngle.d_2"] = "46200039GH",
- ["c.ngle.d_3"] = "46200039VGH",
- ["c.seq.d_2"] = "4620003aGH",
- ["c.seq.d_3"] = "4620003aVGH",
- ["c.ngl.d_2"] = "4620003bGH",
- ["c.ngl.d_3"] = "4620003bVGH",
- ["c.lt.d_2"] = "4620003cGH",
- ["c.lt.d_3"] = "4620003cVGH",
- ["c.nge.d_2"] = "4620003dGH",
- ["c.nge.d_3"] = "4620003dVGH",
- ["c.le.d_2"] = "4620003eGH",
- ["c.le.d_3"] = "4620003eVGH",
- ["c.ngt.d_2"] = "4620003fGH",
- ["c.ngt.d_3"] = "4620003fVGH",
-
- ["add.ps_3"] = "46c00000FGH",
- ["sub.ps_3"] = "46c00001FGH",
- ["mul.ps_3"] = "46c00002FGH",
- ["abs.ps_2"] = "46c00005FG",
- ["mov.ps_2"] = "46c00006FG",
- ["neg.ps_2"] = "46c00007FG",
- ["movf.ps_2"] = "46c00011FG",
- ["movf.ps_3"] = "46c00011FGC",
- ["movt.ps_2"] = "46c10011FG",
- ["movt.ps_3"] = "46c10011FGC",
- ["movz.ps_3"] = "46c00012FGT",
- ["movn.ps_3"] = "46c00013FGT",
- ["cvt.s.pu_2"] = "46c00020FG",
- ["cvt.s.pl_2"] = "46c00028FG",
- ["pll.ps_3"] = "46c0002cFGH",
- ["plu.ps_3"] = "46c0002dFGH",
- ["pul.ps_3"] = "46c0002eFGH",
- ["puu.ps_3"] = "46c0002fFGH",
- ["c.f.ps_2"] = "46c00030GH",
- ["c.f.ps_3"] = "46c00030VGH",
- ["c.un.ps_2"] = "46c00031GH",
- ["c.un.ps_3"] = "46c00031VGH",
- ["c.eq.ps_2"] = "46c00032GH",
- ["c.eq.ps_3"] = "46c00032VGH",
- ["c.ueq.ps_2"] = "46c00033GH",
- ["c.ueq.ps_3"] = "46c00033VGH",
- ["c.olt.ps_2"] = "46c00034GH",
- ["c.olt.ps_3"] = "46c00034VGH",
- ["c.ult.ps_2"] = "46c00035GH",
- ["c.ult.ps_3"] = "46c00035VGH",
- ["c.ole.ps_2"] = "46c00036GH",
- ["c.ole.ps_3"] = "46c00036VGH",
- ["c.ule.ps_2"] = "46c00037GH",
- ["c.ule.ps_3"] = "46c00037VGH",
- ["c.sf.ps_2"] = "46c00038GH",
- ["c.sf.ps_3"] = "46c00038VGH",
- ["c.ngle.ps_2"] = "46c00039GH",
- ["c.ngle.ps_3"] = "46c00039VGH",
- ["c.seq.ps_2"] = "46c0003aGH",
- ["c.seq.ps_3"] = "46c0003aVGH",
- ["c.ngl.ps_2"] = "46c0003bGH",
- ["c.ngl.ps_3"] = "46c0003bVGH",
- ["c.lt.ps_2"] = "46c0003cGH",
- ["c.lt.ps_3"] = "46c0003cVGH",
- ["c.nge.ps_2"] = "46c0003dGH",
- ["c.nge.ps_3"] = "46c0003dVGH",
- ["c.le.ps_2"] = "46c0003eGH",
- ["c.le.ps_3"] = "46c0003eVGH",
- ["c.ngt.ps_2"] = "46c0003fGH",
- ["c.ngt.ps_3"] = "46c0003fVGH",
-
- ["cvt.s.w_2"] = "46800020FG",
- ["cvt.d.w_2"] = "46800021FG",
-
- ["cvt.s.l_2"] = "46a00020FG",
- ["cvt.d.l_2"] = "46a00021FG",
-
- -- Opcode COP1X.
- lwxc1_2 = "4c000000FX",
- ldxc1_2 = "4c000001FX",
- luxc1_2 = "4c000005FX",
- swxc1_2 = "4c000008FX",
- sdxc1_2 = "4c000009FX",
- suxc1_2 = "4c00000dFX",
- prefx_2 = "4c00000fMX",
- ["alnv.ps_4"] = "4c00001eFGHS",
- ["madd.s_4"] = "4c000020FRGH",
- ["madd.d_4"] = "4c000021FRGH",
- ["madd.ps_4"] = "4c000026FRGH",
- ["msub.s_4"] = "4c000028FRGH",
- ["msub.d_4"] = "4c000029FRGH",
- ["msub.ps_4"] = "4c00002eFRGH",
- ["nmadd.s_4"] = "4c000030FRGH",
- ["nmadd.d_4"] = "4c000031FRGH",
- ["nmadd.ps_4"] = "4c000036FRGH",
- ["nmsub.s_4"] = "4c000038FRGH",
- ["nmsub.d_4"] = "4c000039FRGH",
- ["nmsub.ps_4"] = "4c00003eFRGH",
-}
-
-------------------------------------------------------------------------------
-
-local function parse_gpr(expr)
- local tname, ovreg = match(expr, "^([%w_]+):(r[1-3]?[0-9])$")
- local tp = map_type[tname or expr]
- if tp then
- local reg = ovreg or tp.reg
- if not reg then
- werror("type `"..(tname or expr).."' needs a register override")
- end
- expr = reg
- end
- local r = match(expr, "^r([1-3]?[0-9])$")
- if r then
- r = tonumber(r)
- if r <= 31 then return r, tp end
- end
- werror("bad register name `"..expr.."'")
-end
-
-local function parse_fpr(expr)
- local r = match(expr, "^f([1-3]?[0-9])$")
- if r then
- r = tonumber(r)
- if r <= 31 then return r end
- end
- werror("bad register name `"..expr.."'")
-end
-
-local function parse_imm(imm, bits, shift, scale, signed)
- local n = tonumber(imm)
- if n then
- if n % 2^scale == 0 then
- n = n / 2^scale
- if signed then
- if n >= 0 then
- if n < 2^(bits-1) then return n*2^shift end
- else
- if n >= -(2^(bits-1))-1 then return (n+2^bits)*2^shift end
- end
- else
- if n >= 0 and n <= 2^bits-1 then return n*2^shift end
- end
- end
- werror("out of range immediate `"..imm.."'")
- elseif match(imm, "^[rf]([1-3]?[0-9])$") or
- match(imm, "^([%w_]+):([rf][1-3]?[0-9])$") then
- werror("expected immediate operand, got register")
- else
- waction("IMM", (signed and 32768 or 0)+scale*1024+bits*32+shift, imm)
- return 0
- end
-end
-
-local function parse_disp(disp)
- local imm, reg = match(disp, "^(.*)%(([%w_:]+)%)$")
- if imm then
- local r = parse_gpr(reg)*2^21
- local extname = match(imm, "^extern%s+(%S+)$")
- if extname then
- waction("REL_EXT", map_extern[extname], nil, 1)
- return r
- else
- return r + parse_imm(imm, 16, 0, 0, true)
- end
- end
- local reg, tailr = match(disp, "^([%w_:]+)%s*(.*)$")
- if reg and tailr ~= "" then
- local r, tp = parse_gpr(reg)
- if tp then
- waction("IMM", 32768+16*32, format(tp.ctypefmt, tailr))
- return r*2^21
- end
- end
- werror("bad displacement `"..disp.."'")
-end
-
-local function parse_index(idx)
- local rt, rs = match(idx, "^(.*)%(([%w_:]+)%)$")
- if rt then
- rt = parse_gpr(rt)
- rs = parse_gpr(rs)
- return rt*2^16 + rs*2^21
- end
- werror("bad index `"..idx.."'")
-end
-
-local function parse_label(label, def)
- local prefix = sub(label, 1, 2)
- -- =>label (pc label reference)
- if prefix == "=>" then
- return "PC", 0, sub(label, 3)
- end
- -- ->name (global label reference)
- if prefix == "->" then
- return "LG", map_global[sub(label, 3)]
- end
- if def then
- -- [1-9] (local label definition)
- if match(label, "^[1-9]$") then
- return "LG", 10+tonumber(label)
- end
- else
- -- [<>][1-9] (local label reference)
- local dir, lnum = match(label, "^([<>])([1-9])$")
- if dir then -- Fwd: 1-9, Bkwd: 11-19.
- return "LG", lnum + (dir == ">" and 0 or 10)
- end
- -- extern label (extern label reference)
- local extname = match(label, "^extern%s+(%S+)$")
- if extname then
- return "EXT", map_extern[extname]
- end
- end
- werror("bad label `"..label.."'")
-end
-
-------------------------------------------------------------------------------
-
--- Handle opcodes defined with template strings.
-map_op[".template__"] = function(params, template, nparams)
- if not params then return sub(template, 9) end
- local op = tonumber(sub(template, 1, 8), 16)
- local n = 1
-
- -- Limit number of section buffer positions used by a single dasm_put().
- -- A single opcode needs a maximum of 2 positions (ins/ext).
- if secpos+2 > maxsecpos then wflush() end
- local pos = wpos()
-
- -- Process each character.
- for p in gmatch(sub(template, 9), ".") do
- if p == "D" then
- op = op + parse_gpr(params[n]) * 2^11; n = n + 1
- elseif p == "T" then
- op = op + parse_gpr(params[n]) * 2^16; n = n + 1
- elseif p == "S" then
- op = op + parse_gpr(params[n]) * 2^21; n = n + 1
- elseif p == "F" then
- op = op + parse_fpr(params[n]) * 2^6; n = n + 1
- elseif p == "G" then
- op = op + parse_fpr(params[n]) * 2^11; n = n + 1
- elseif p == "H" then
- op = op + parse_fpr(params[n]) * 2^16; n = n + 1
- elseif p == "R" then
- op = op + parse_fpr(params[n]) * 2^21; n = n + 1
- elseif p == "I" then
- op = op + parse_imm(params[n], 16, 0, 0, true); n = n + 1
- elseif p == "U" then
- op = op + parse_imm(params[n], 16, 0, 0, false); n = n + 1
- elseif p == "O" then
- op = op + parse_disp(params[n]); n = n + 1
- elseif p == "X" then
- op = op + parse_index(params[n]); n = n + 1
- elseif p == "B" or p == "J" then
- local mode, n, s = parse_label(params[n], false)
- if p == "B" then n = n + 2048 end
- waction("REL_"..mode, n, s, 1)
- n = n + 1
- elseif p == "A" then
- op = op + parse_imm(params[n], 5, 6, 0, false); n = n + 1
- elseif p == "M" then
- op = op + parse_imm(params[n], 5, 11, 0, false); n = n + 1
- elseif p == "N" then
- op = op + parse_imm(params[n], 5, 16, 0, false); n = n + 1
- elseif p == "C" then
- op = op + parse_imm(params[n], 3, 18, 0, false); n = n + 1
- elseif p == "V" then
- op = op + parse_imm(params[n], 3, 8, 0, false); n = n + 1
- elseif p == "W" then
- op = op + parse_imm(params[n], 3, 0, 0, false); n = n + 1
- elseif p == "Y" then
- op = op + parse_imm(params[n], 20, 6, 0, false); n = n + 1
- elseif p == "Z" then
- op = op + parse_imm(params[n], 10, 6, 0, false); n = n + 1
- elseif p == "=" then
- local d = ((op - op % 2^11) / 2^11) % 32
- op = op + d * 2^16 -- Copy D to T for clz, clo.
- else
- assert(false)
- end
- end
- wputpos(pos, op)
-end
-
-------------------------------------------------------------------------------
-
--- Pseudo-opcode to mark the position where the action list is to be emitted.
-map_op[".actionlist_1"] = function(params)
- if not params then return "cvar" end
- local name = params[1] -- No syntax check. You get to keep the pieces.
- wline(function(out) writeactions(out, name) end)
-end
-
--- Pseudo-opcode to mark the position where the global enum is to be emitted.
-map_op[".globals_1"] = function(params)
- if not params then return "prefix" end
- local prefix = params[1] -- No syntax check. You get to keep the pieces.
- wline(function(out) writeglobals(out, prefix) end)
-end
-
--- Pseudo-opcode to mark the position where the global names are to be emitted.
-map_op[".globalnames_1"] = function(params)
- if not params then return "cvar" end
- local name = params[1] -- No syntax check. You get to keep the pieces.
- wline(function(out) writeglobalnames(out, name) end)
-end
-
--- Pseudo-opcode to mark the position where the extern names are to be emitted.
-map_op[".externnames_1"] = function(params)
- if not params then return "cvar" end
- local name = params[1] -- No syntax check. You get to keep the pieces.
- wline(function(out) writeexternnames(out, name) end)
-end
-
-------------------------------------------------------------------------------
-
--- Label pseudo-opcode (converted from trailing colon form).
-map_op[".label_1"] = function(params)
- if not params then return "[1-9] | ->global | =>pcexpr" end
- if secpos+1 > maxsecpos then wflush() end
- local mode, n, s = parse_label(params[1], true)
- if mode == "EXT" then werror("bad label definition") end
- waction("LABEL_"..mode, n, s, 1)
-end
-
-------------------------------------------------------------------------------
-
--- Pseudo-opcodes for data storage.
-map_op[".long_*"] = function(params)
- if not params then return "imm..." end
- for _,p in ipairs(params) do
- local n = tonumber(p)
- if not n then werror("bad immediate `"..p.."'") end
- if n < 0 then n = n + 2^32 end
- wputw(n)
- if secpos+2 > maxsecpos then wflush() end
- end
-end
-
--- Alignment pseudo-opcode.
-map_op[".align_1"] = function(params)
- if not params then return "numpow2" end
- if secpos+1 > maxsecpos then wflush() end
- local align = tonumber(params[1])
- if align then
- local x = align
- -- Must be a power of 2 in the range (2 ... 256).
- for i=1,8 do
- x = x / 2
- if x == 1 then
- waction("ALIGN", align-1, nil, 1) -- Action byte is 2**n-1.
- return
- end
- end
- end
- werror("bad alignment")
-end
-
-------------------------------------------------------------------------------
-
--- Pseudo-opcode for (primitive) type definitions (map to C types).
-map_op[".type_3"] = function(params, nparams)
- if not params then
- return nparams == 2 and "name, ctype" or "name, ctype, reg"
- end
- local name, ctype, reg = params[1], params[2], params[3]
- if not match(name, "^[%a_][%w_]*$") then
- werror("bad type name `"..name.."'")
- end
- local tp = map_type[name]
- if tp then
- werror("duplicate type `"..name.."'")
- end
- -- Add #type to defines. A bit unclean to put it in map_archdef.
- map_archdef["#"..name] = "sizeof("..ctype..")"
- -- Add new type and emit shortcut define.
- local num = ctypenum + 1
- map_type[name] = {
- ctype = ctype,
- ctypefmt = format("Dt%X(%%s)", num),
- reg = reg,
- }
- wline(format("#define Dt%X(_V) (int)(ptrdiff_t)&(((%s *)0)_V)", num, ctype))
- ctypenum = num
-end
-map_op[".type_2"] = map_op[".type_3"]
-
--- Dump type definitions.
-local function dumptypes(out, lvl)
- local t = {}
- for name in pairs(map_type) do t[#t+1] = name end
- sort(t)
- out:write("Type definitions:\n")
- for _,name in ipairs(t) do
- local tp = map_type[name]
- local reg = tp.reg or ""
- out:write(format(" %-20s %-20s %s\n", name, tp.ctype, reg))
- end
- out:write("\n")
-end
-
-------------------------------------------------------------------------------
-
--- Set the current section.
-function _M.section(num)
- waction("SECTION", num)
- wflush(true) -- SECTION is a terminal action.
-end
-
-------------------------------------------------------------------------------
-
--- Dump architecture description.
-function _M.dumparch(out)
- out:write(format("DynASM %s version %s, released %s\n\n",
- _info.arch, _info.version, _info.release))
- dumpactions(out)
-end
-
--- Dump all user defined elements.
-function _M.dumpdef(out, lvl)
- dumptypes(out, lvl)
- dumpglobals(out, lvl)
- dumpexterns(out, lvl)
-end
-
-------------------------------------------------------------------------------
-
--- Pass callbacks from/to the DynASM core.
-function _M.passcb(wl, we, wf, ww)
- wline, werror, wfatal, wwarn = wl, we, wf, ww
- return wflush
-end
-
--- Setup the arch-specific module.
-function _M.setup(arch, opt)
- g_arch, g_opt = arch, opt
-end
-
--- Merge the core maps and the arch-specific maps.
-function _M.mergemaps(map_coreop, map_def)
- setmetatable(map_op, { __index = map_coreop })
- setmetatable(map_def, { __index = map_archdef })
- return map_op, map_def
-end
-
-return _M
-
-------------------------------------------------------------------------------
-
diff --git a/third_party/dynasm/dasm_ppc.h b/third_party/dynasm/dasm_ppc.h
deleted file mode 100644
index bf5957e..0000000
--- a/third_party/dynasm/dasm_ppc.h
+++ /dev/null
@@ -1,411 +0,0 @@
-/*
-** DynASM PPC encoding engine.
-** Copyright (C) 2005-2012 Mike Pall. All rights reserved.
-** Released under the MIT license. See dynasm.lua for full copyright notice.
-*/
-
-#include <stddef.h>
-#include <stdarg.h>
-#include <string.h>
-#include <stdlib.h>
-
-#define DASM_ARCH "ppc"
-
-#ifndef DASM_EXTERN
-#define DASM_EXTERN(a,b,c,d) 0
-#endif
-
-/* Action definitions. */
-enum {
- DASM_STOP, DASM_SECTION, DASM_ESC, DASM_REL_EXT,
- /* The following actions need a buffer position. */
- DASM_ALIGN, DASM_REL_LG, DASM_LABEL_LG,
- /* The following actions also have an argument. */
- DASM_REL_PC, DASM_LABEL_PC, DASM_IMM,
- DASM__MAX
-};
-
-/* Maximum number of section buffer positions for a single dasm_put() call. */
-#define DASM_MAXSECPOS 25
-
-/* DynASM encoder status codes. Action list offset or number are or'ed in. */
-#define DASM_S_OK 0x00000000
-#define DASM_S_NOMEM 0x01000000
-#define DASM_S_PHASE 0x02000000
-#define DASM_S_MATCH_SEC 0x03000000
-#define DASM_S_RANGE_I 0x11000000
-#define DASM_S_RANGE_SEC 0x12000000
-#define DASM_S_RANGE_LG 0x13000000
-#define DASM_S_RANGE_PC 0x14000000
-#define DASM_S_RANGE_REL 0x15000000
-#define DASM_S_UNDEF_LG 0x21000000
-#define DASM_S_UNDEF_PC 0x22000000
-
-/* Macros to convert positions (8 bit section + 24 bit index). */
-#define DASM_POS2IDX(pos) ((pos)&0x00ffffff)
-#define DASM_POS2BIAS(pos) ((pos)&0xff000000)
-#define DASM_SEC2POS(sec) ((sec)<<24)
-#define DASM_POS2SEC(pos) ((pos)>>24)
-#define DASM_POS2PTR(D, pos) (D->sections[DASM_POS2SEC(pos)].rbuf + (pos))
-
-/* Action list type. */
-typedef const unsigned int *dasm_ActList;
-
-/* Per-section structure. */
-typedef struct dasm_Section {
- int *rbuf; /* Biased buffer pointer (negative section bias). */
- int *buf; /* True buffer pointer. */
- size_t bsize; /* Buffer size in bytes. */
- int pos; /* Biased buffer position. */
- int epos; /* End of biased buffer position - max single put. */
- int ofs; /* Byte offset into section. */
-} dasm_Section;
-
-/* Core structure holding the DynASM encoding state. */
-struct dasm_State {
- size_t psize; /* Allocated size of this structure. */
- dasm_ActList actionlist; /* Current actionlist pointer. */
- int *lglabels; /* Local/global chain/pos ptrs. */
- size_t lgsize;
- int *pclabels; /* PC label chains/pos ptrs. */
- size_t pcsize;
- void **globals; /* Array of globals (bias -10). */
- dasm_Section *section; /* Pointer to active section. */
- size_t codesize; /* Total size of all code sections. */
- int maxsection; /* 0 <= sectionidx < maxsection. */
- int status; /* Status code. */
- dasm_Section sections[1]; /* All sections. Alloc-extended. */
-};
-
-/* The size of the core structure depends on the max. number of sections. */
-#define DASM_PSZ(ms) (sizeof(dasm_State)+(ms-1)*sizeof(dasm_Section))
-
-
-/* Initialize DynASM state. */
-void dasm_init(Dst_DECL, int maxsection)
-{
- dasm_State *D;
- size_t psz = 0;
- int i;
- Dst_REF = NULL;
- DASM_M_GROW(Dst, struct dasm_State, Dst_REF, psz, DASM_PSZ(maxsection));
- D = Dst_REF;
- D->psize = psz;
- D->lglabels = NULL;
- D->lgsize = 0;
- D->pclabels = NULL;
- D->pcsize = 0;
- D->globals = NULL;
- D->maxsection = maxsection;
- for (i = 0; i < maxsection; i++) {
- D->sections[i].buf = NULL; /* Need this for pass3. */
- D->sections[i].rbuf = D->sections[i].buf - DASM_SEC2POS(i);
- D->sections[i].bsize = 0;
- D->sections[i].epos = 0; /* Wrong, but is recalculated after resize. */
- }
-}
-
-/* Free DynASM state. */
-void dasm_free(Dst_DECL)
-{
- dasm_State *D = Dst_REF;
- int i;
- for (i = 0; i < D->maxsection; i++)
- if (D->sections[i].buf)
- DASM_M_FREE(Dst, D->sections[i].buf, D->sections[i].bsize);
- if (D->pclabels) DASM_M_FREE(Dst, D->pclabels, D->pcsize);
- if (D->lglabels) DASM_M_FREE(Dst, D->lglabels, D->lgsize);
- DASM_M_FREE(Dst, D, D->psize);
-}
-
-/* Setup global label array. Must be called before dasm_setup(). */
-void dasm_setupglobal(Dst_DECL, void **gl, unsigned int maxgl)
-{
- dasm_State *D = Dst_REF;
- D->globals = gl - 10; /* Negative bias to compensate for locals. */
- DASM_M_GROW(Dst, int, D->lglabels, D->lgsize, (10+maxgl)*sizeof(int));
-}
-
-/* Grow PC label array. Can be called after dasm_setup(), too. */
-void dasm_growpc(Dst_DECL, unsigned int maxpc)
-{
- dasm_State *D = Dst_REF;
- size_t osz = D->pcsize;
- DASM_M_GROW(Dst, int, D->pclabels, D->pcsize, maxpc*sizeof(int));
- memset((void *)(((unsigned char *)D->pclabels)+osz), 0, D->pcsize-osz);
-}
-
-/* Setup encoder. */
-void dasm_setup(Dst_DECL, const void *actionlist)
-{
- dasm_State *D = Dst_REF;
- int i;
- D->actionlist = (dasm_ActList)actionlist;
- D->status = DASM_S_OK;
- D->section = &D->sections[0];
- memset((void *)D->lglabels, 0, D->lgsize);
- if (D->pclabels) memset((void *)D->pclabels, 0, D->pcsize);
- for (i = 0; i < D->maxsection; i++) {
- D->sections[i].pos = DASM_SEC2POS(i);
- D->sections[i].ofs = 0;
- }
-}
-
-
-#ifdef DASM_CHECKS
-#define CK(x, st) \
- do { if (!(x)) { \
- D->status = DASM_S_##st|(p-D->actionlist-1); return; } } while (0)
-#define CKPL(kind, st) \
- do { if ((size_t)((char *)pl-(char *)D->kind##labels) >= D->kind##size) { \
- D->status = DASM_S_RANGE_##st|(p-D->actionlist-1); return; } } while (0)
-#else
-#define CK(x, st) ((void)0)
-#define CKPL(kind, st) ((void)0)
-#endif
-
-/* Pass 1: Store actions and args, link branches/labels, estimate offsets. */
-void dasm_put(Dst_DECL, int start, ...)
-{
- va_list ap;
- dasm_State *D = Dst_REF;
- dasm_ActList p = D->actionlist + start;
- dasm_Section *sec = D->section;
- int pos = sec->pos, ofs = sec->ofs;
- int *b;
-
- if (pos >= sec->epos) {
- DASM_M_GROW(Dst, int, sec->buf, sec->bsize,
- sec->bsize + 2*DASM_MAXSECPOS*sizeof(int));
- sec->rbuf = sec->buf - DASM_POS2BIAS(pos);
- sec->epos = (int)sec->bsize/sizeof(int) - DASM_MAXSECPOS+DASM_POS2BIAS(pos);
- }
-
- b = sec->rbuf;
- b[pos++] = start;
-
- va_start(ap, start);
- while (1) {
- unsigned int ins = *p++;
- unsigned int action = (ins >> 16);
- if (action >= DASM__MAX) {
- ofs += 4;
- } else {
- int *pl, n = action >= DASM_REL_PC ? va_arg(ap, int) : 0;
- switch (action) {
- case DASM_STOP: goto stop;
- case DASM_SECTION:
- n = (ins & 255); CK(n < D->maxsection, RANGE_SEC);
- D->section = &D->sections[n]; goto stop;
- case DASM_ESC: p++; ofs += 4; break;
- case DASM_REL_EXT: break;
- case DASM_ALIGN: ofs += (ins & 255); b[pos++] = ofs; break;
- case DASM_REL_LG:
- n = (ins & 2047) - 10; pl = D->lglabels + n;
- if (n >= 0) { CKPL(lg, LG); goto putrel; } /* Bkwd rel or global. */
- pl += 10; n = *pl;
- if (n < 0) n = 0; /* Start new chain for fwd rel if label exists. */
- goto linkrel;
- case DASM_REL_PC:
- pl = D->pclabels + n; CKPL(pc, PC);
- putrel:
- n = *pl;
- if (n < 0) { /* Label exists. Get label pos and store it. */
- b[pos] = -n;
- } else {
- linkrel:
- b[pos] = n; /* Else link to rel chain, anchored at label. */
- *pl = pos;
- }
- pos++;
- break;
- case DASM_LABEL_LG:
- pl = D->lglabels + (ins & 2047) - 10; CKPL(lg, LG); goto putlabel;
- case DASM_LABEL_PC:
- pl = D->pclabels + n; CKPL(pc, PC);
- putlabel:
- n = *pl; /* n > 0: Collapse rel chain and replace with label pos. */
- while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = pos;
- }
- *pl = -pos; /* Label exists now. */
- b[pos++] = ofs; /* Store pass1 offset estimate. */
- break;
- case DASM_IMM:
-#ifdef DASM_CHECKS
- CK((n & ((1<<((ins>>10)&31))-1)) == 0, RANGE_I);
-#endif
- n >>= ((ins>>10)&31);
-#ifdef DASM_CHECKS
- if (ins & 0x8000)
- CK(((n + (1<<(((ins>>5)&31)-1)))>>((ins>>5)&31)) == 0, RANGE_I);
- else
- CK((n>>((ins>>5)&31)) == 0, RANGE_I);
-#endif
- b[pos++] = n;
- break;
- }
- }
- }
-stop:
- va_end(ap);
- sec->pos = pos;
- sec->ofs = ofs;
-}
-#undef CK
-
-/* Pass 2: Link sections, shrink aligns, fix label offsets. */
-int dasm_link(Dst_DECL, size_t *szp)
-{
- dasm_State *D = Dst_REF;
- int secnum;
- int ofs = 0;
-
-#ifdef DASM_CHECKS
- *szp = 0;
- if (D->status != DASM_S_OK) return D->status;
- {
- int pc;
- for (pc = 0; pc*sizeof(int) < D->pcsize; pc++)
- if (D->pclabels[pc] > 0) return DASM_S_UNDEF_PC|pc;
- }
-#endif
-
- { /* Handle globals not defined in this translation unit. */
- int idx;
- for (idx = 20; idx*sizeof(int) < D->lgsize; idx++) {
- int n = D->lglabels[idx];
- /* Undefined label: Collapse rel chain and replace with marker (< 0). */
- while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = -idx; }
- }
- }
-
- /* Combine all code sections. No support for data sections (yet). */
- for (secnum = 0; secnum < D->maxsection; secnum++) {
- dasm_Section *sec = D->sections + secnum;
- int *b = sec->rbuf;
- int pos = DASM_SEC2POS(secnum);
- int lastpos = sec->pos;
-
- while (pos != lastpos) {
- dasm_ActList p = D->actionlist + b[pos++];
- while (1) {
- unsigned int ins = *p++;
- unsigned int action = (ins >> 16);
- switch (action) {
- case DASM_STOP: case DASM_SECTION: goto stop;
- case DASM_ESC: p++; break;
- case DASM_REL_EXT: break;
- case DASM_ALIGN: ofs -= (b[pos++] + ofs) & (ins & 255); break;
- case DASM_REL_LG: case DASM_REL_PC: pos++; break;
- case DASM_LABEL_LG: case DASM_LABEL_PC: b[pos++] += ofs; break;
- case DASM_IMM: pos++; break;
- }
- }
- stop: (void)0;
- }
- ofs += sec->ofs; /* Next section starts right after current section. */
- }
-
- D->codesize = ofs; /* Total size of all code sections */
- *szp = ofs;
- return DASM_S_OK;
-}
-
-#ifdef DASM_CHECKS
-#define CK(x, st) \
- do { if (!(x)) return DASM_S_##st|(p-D->actionlist-1); } while (0)
-#else
-#define CK(x, st) ((void)0)
-#endif
-
-/* Pass 3: Encode sections. */
-int dasm_encode(Dst_DECL, void *buffer)
-{
- dasm_State *D = Dst_REF;
- char *base = (char *)buffer;
- unsigned int *cp = (unsigned int *)buffer;
- int secnum;
-
- /* Encode all code sections. No support for data sections (yet). */
- for (secnum = 0; secnum < D->maxsection; secnum++) {
- dasm_Section *sec = D->sections + secnum;
- int *b = sec->buf;
- int *endb = sec->rbuf + sec->pos;
-
- while (b != endb) {
- dasm_ActList p = D->actionlist + *b++;
- while (1) {
- unsigned int ins = *p++;
- unsigned int action = (ins >> 16);
- int n = (action >= DASM_ALIGN && action < DASM__MAX) ? *b++ : 0;
- switch (action) {
- case DASM_STOP: case DASM_SECTION: goto stop;
- case DASM_ESC: *cp++ = *p++; break;
- case DASM_REL_EXT:
- n = DASM_EXTERN(Dst, (unsigned char *)cp, (ins & 2047), 1) - 4;
- goto patchrel;
- case DASM_ALIGN:
- ins &= 255; while ((((char *)cp - base) & ins)) *cp++ = 0x60000000;
- break;
- case DASM_REL_LG:
- CK(n >= 0, UNDEF_LG);
- case DASM_REL_PC:
- CK(n >= 0, UNDEF_PC);
- n = *DASM_POS2PTR(D, n) - (int)((char *)cp - base);
- patchrel:
- CK((n & 3) == 0 &&
- (((n+4) + ((ins & 2048) ? 0x00008000 : 0x02000000)) >>
- ((ins & 2048) ? 16 : 26)) == 0, RANGE_REL);
- cp[-1] |= ((n+4) & ((ins & 2048) ? 0x0000fffc: 0x03fffffc));
- break;
- case DASM_LABEL_LG:
- ins &= 2047; if (ins >= 20) D->globals[ins-10] = (void *)(base + n);
- break;
- case DASM_LABEL_PC: break;
- case DASM_IMM:
- cp[-1] |= (n & ((1<<((ins>>5)&31))-1)) << (ins&31);
- break;
- default: *cp++ = ins; break;
- }
- }
- stop: (void)0;
- }
- }
-
- if (base + D->codesize != (char *)cp) /* Check for phase errors. */
- return DASM_S_PHASE;
- return DASM_S_OK;
-}
-#undef CK
-
-/* Get PC label offset. */
-int dasm_getpclabel(Dst_DECL, unsigned int pc)
-{
- dasm_State *D = Dst_REF;
- if (pc*sizeof(int) < D->pcsize) {
- int pos = D->pclabels[pc];
- if (pos < 0) return *DASM_POS2PTR(D, -pos);
- if (pos > 0) return -1; /* Undefined. */
- }
- return -2; /* Unused or out of range. */
-}
-
-#ifdef DASM_CHECKS
-/* Optional sanity checker to call between isolated encoding steps. */
-int dasm_checkstep(Dst_DECL, int secmatch)
-{
- dasm_State *D = Dst_REF;
- if (D->status == DASM_S_OK) {
- int i;
- for (i = 1; i <= 9; i++) {
- if (D->lglabels[i] > 0) { D->status = DASM_S_UNDEF_LG|i; break; }
- D->lglabels[i] = 0;
- }
- }
- if (D->status == DASM_S_OK && secmatch >= 0 &&
- D->section != &D->sections[secmatch])
- D->status = DASM_S_MATCH_SEC|(D->section-D->sections);
- return D->status;
-}
-#endif
-
diff --git a/third_party/dynasm/dasm_ppc.lua b/third_party/dynasm/dasm_ppc.lua
deleted file mode 100644
index dc2af69..0000000
--- a/third_party/dynasm/dasm_ppc.lua
+++ /dev/null
@@ -1,1230 +0,0 @@
-------------------------------------------------------------------------------
--- DynASM PPC module.
---
--- Copyright (C) 2005-2012 Mike Pall. All rights reserved.
--- See dynasm.lua for full copyright notice.
-------------------------------------------------------------------------------
-
--- Module information:
-local _info = {
- arch = "ppc",
- description = "DynASM PPC module",
- version = "1.3.0",
- vernum = 10300,
- release = "2011-05-05",
- author = "Mike Pall",
- license = "MIT",
-}
-
--- Exported glue functions for the arch-specific module.
-local _M = { _info = _info }
-
--- Cache library functions.
-local type, tonumber, pairs, ipairs = type, tonumber, pairs, ipairs
-local assert, setmetatable = assert, setmetatable
-local _s = string
-local sub, format, byte, char = _s.sub, _s.format, _s.byte, _s.char
-local match, gmatch = _s.match, _s.gmatch
-local concat, sort = table.concat, table.sort
-
--- Inherited tables and callbacks.
-local g_opt, g_arch
-local wline, werror, wfatal, wwarn
-
--- Action name list.
--- CHECK: Keep this in sync with the C code!
-local action_names = {
- "STOP", "SECTION", "ESC", "REL_EXT",
- "ALIGN", "REL_LG", "LABEL_LG",
- "REL_PC", "LABEL_PC", "IMM",
-}
-
--- Maximum number of section buffer positions for dasm_put().
--- CHECK: Keep this in sync with the C code!
-local maxsecpos = 25 -- Keep this low, to avoid excessively long C lines.
-
--- Action name -> action number.
-local map_action = {}
-for n,name in ipairs(action_names) do
- map_action[name] = n-1
-end
-
--- Action list buffer.
-local actlist = {}
-
--- Argument list for next dasm_put(). Start with offset 0 into action list.
-local actargs = { 0 }
-
--- Current number of section buffer positions for dasm_put().
-local secpos = 1
-
-------------------------------------------------------------------------------
-
--- Return 8 digit hex number.
-local function tohex(x)
- return sub(format("%08x", x), -8) -- Avoid 64 bit portability problem in Lua.
-end
-
--- Dump action names and numbers.
-local function dumpactions(out)
- out:write("DynASM encoding engine action codes:\n")
- for n,name in ipairs(action_names) do
- local num = map_action[name]
- out:write(format(" %-10s %02X %d\n", name, num, num))
- end
- out:write("\n")
-end
-
--- Write action list buffer as a huge static C array.
-local function writeactions(out, name)
- local nn = #actlist
- if nn == 0 then nn = 1; actlist[0] = map_action.STOP end
- out:write("static const unsigned int ", name, "[", nn, "] = {\n")
- for i = 1,nn-1 do
- assert(out:write("0x", tohex(actlist[i]), ",\n"))
- end
- assert(out:write("0x", tohex(actlist[nn]), "\n};\n\n"))
-end
-
-------------------------------------------------------------------------------
-
--- Add word to action list.
-local function wputxw(n)
- assert(n >= 0 and n <= 0xffffffff and n % 1 == 0, "word out of range")
- actlist[#actlist+1] = n
-end
-
--- Add action to list with optional arg. Advance buffer pos, too.
-local function waction(action, val, a, num)
- local w = assert(map_action[action], "bad action name `"..action.."'")
- wputxw(w * 0x10000 + (val or 0))
- if a then actargs[#actargs+1] = a end
- if a or num then secpos = secpos + (num or 1) end
-end
-
--- Flush action list (intervening C code or buffer pos overflow).
-local function wflush(term)
- if #actlist == actargs[1] then return end -- Nothing to flush.
- if not term then waction("STOP") end -- Terminate action list.
- wline(format("dasm_put(Dst, %s);", concat(actargs, ", ")), true)
- actargs = { #actlist } -- Actionlist offset is 1st arg to next dasm_put().
- secpos = 1 -- The actionlist offset occupies a buffer position, too.
-end
-
--- Put escaped word.
-local function wputw(n)
- if n <= 0xffffff then waction("ESC") end
- wputxw(n)
-end
-
--- Reserve position for word.
-local function wpos()
- local pos = #actlist+1
- actlist[pos] = ""
- return pos
-end
-
--- Store word to reserved position.
-local function wputpos(pos, n)
- assert(n >= 0 and n <= 0xffffffff and n % 1 == 0, "word out of range")
- actlist[pos] = n
-end
-
-------------------------------------------------------------------------------
-
--- Global label name -> global label number. With auto assignment on 1st use.
-local next_global = 20
-local map_global = setmetatable({}, { __index = function(t, name)
- if not match(name, "^[%a_][%w_]*$") then werror("bad global label") end
- local n = next_global
- if n > 2047 then werror("too many global labels") end
- next_global = n + 1
- t[name] = n
- return n
-end})
-
--- Dump global labels.
-local function dumpglobals(out, lvl)
- local t = {}
- for name, n in pairs(map_global) do t[n] = name end
- out:write("Global labels:\n")
- for i=20,next_global-1 do
- out:write(format(" %s\n", t[i]))
- end
- out:write("\n")
-end
-
--- Write global label enum.
-local function writeglobals(out, prefix)
- local t = {}
- for name, n in pairs(map_global) do t[n] = name end
- out:write("enum {\n")
- for i=20,next_global-1 do
- out:write(" ", prefix, t[i], ",\n")
- end
- out:write(" ", prefix, "_MAX\n};\n")
-end
-
--- Write global label names.
-local function writeglobalnames(out, name)
- local t = {}
- for name, n in pairs(map_global) do t[n] = name end
- out:write("static const char *const ", name, "[] = {\n")
- for i=20,next_global-1 do
- out:write(" \"", t[i], "\",\n")
- end
- out:write(" (const char *)0\n};\n")
-end
-
-------------------------------------------------------------------------------
-
--- Extern label name -> extern label number. With auto assignment on 1st use.
-local next_extern = 0
-local map_extern_ = {}
-local map_extern = setmetatable({}, { __index = function(t, name)
- -- No restrictions on the name for now.
- local n = next_extern
- if n > 2047 then werror("too many extern labels") end
- next_extern = n + 1
- t[name] = n
- map_extern_[n] = name
- return n
-end})
-
--- Dump extern labels.
-local function dumpexterns(out, lvl)
- out:write("Extern labels:\n")
- for i=0,next_extern-1 do
- out:write(format(" %s\n", map_extern_[i]))
- end
- out:write("\n")
-end
-
--- Write extern label names.
-local function writeexternnames(out, name)
- out:write("static const char *const ", name, "[] = {\n")
- for i=0,next_extern-1 do
- out:write(" \"", map_extern_[i], "\",\n")
- end
- out:write(" (const char *)0\n};\n")
-end
-
-------------------------------------------------------------------------------
-
--- Arch-specific maps.
-local map_archdef = { sp = "r1" } -- Ext. register name -> int. name.
-
-local map_type = {} -- Type name -> { ctype, reg }
-local ctypenum = 0 -- Type number (for Dt... macros).
-
--- Reverse defines for registers.
-function _M.revdef(s)
- if s == "r1" then return "sp" end
- return s
-end
-
-local map_cond = {
- lt = 0, gt = 1, eq = 2, so = 3,
- ge = 4, le = 5, ne = 6, ns = 7,
-}
-
-------------------------------------------------------------------------------
-
--- Template strings for PPC instructions.
-local map_op = {
- tdi_3 = "08000000ARI",
- twi_3 = "0c000000ARI",
- mulli_3 = "1c000000RRI",
- subfic_3 = "20000000RRI",
- cmplwi_3 = "28000000XRU",
- cmplwi_2 = "28000000-RU",
- cmpldi_3 = "28200000XRU",
- cmpldi_2 = "28200000-RU",
- cmpwi_3 = "2c000000XRI",
- cmpwi_2 = "2c000000-RI",
- cmpdi_3 = "2c200000XRI",
- cmpdi_2 = "2c200000-RI",
- addic_3 = "30000000RRI",
- ["addic._3"] = "34000000RRI",
- addi_3 = "38000000RR0I",
- li_2 = "38000000RI",
- la_2 = "38000000RD",
- addis_3 = "3c000000RR0I",
- lis_2 = "3c000000RI",
- lus_2 = "3c000000RU",
- bc_3 = "40000000AAK",
- bcl_3 = "40000001AAK",
- bdnz_1 = "42000000K",
- bdz_1 = "42400000K",
- sc_0 = "44000000",
- b_1 = "48000000J",
- bl_1 = "48000001J",
- rlwimi_5 = "50000000RR~AAA.",
- rlwinm_5 = "54000000RR~AAA.",
- rlwnm_5 = "5c000000RR~RAA.",
- ori_3 = "60000000RR~U",
- nop_0 = "60000000",
- oris_3 = "64000000RR~U",
- xori_3 = "68000000RR~U",
- xoris_3 = "6c000000RR~U",
- ["andi._3"] = "70000000RR~U",
- ["andis._3"] = "74000000RR~U",
- lwz_2 = "80000000RD",
- lwzu_2 = "84000000RD",
- lbz_2 = "88000000RD",
- lbzu_2 = "8c000000RD",
- stw_2 = "90000000RD",
- stwu_2 = "94000000RD",
- stb_2 = "98000000RD",
- stbu_2 = "9c000000RD",
- lhz_2 = "a0000000RD",
- lhzu_2 = "a4000000RD",
- lha_2 = "a8000000RD",
- lhau_2 = "ac000000RD",
- sth_2 = "b0000000RD",
- sthu_2 = "b4000000RD",
- lmw_2 = "b8000000RD",
- stmw_2 = "bc000000RD",
- lfs_2 = "c0000000FD",
- lfsu_2 = "c4000000FD",
- lfd_2 = "c8000000FD",
- lfdu_2 = "cc000000FD",
- stfs_2 = "d0000000FD",
- stfsu_2 = "d4000000FD",
- stfd_2 = "d8000000FD",
- stfdu_2 = "dc000000FD",
- ld_2 = "e8000000RD", -- NYI: displacement must be divisible by 4.
- ldu_2 = "e8000001RD",
- lwa_2 = "e8000002RD",
- std_2 = "f8000000RD",
- stdu_2 = "f8000001RD",
-
- -- Primary opcode 19:
- mcrf_2 = "4c000000XX",
- isync_0 = "4c00012c",
- crnor_3 = "4c000042CCC",
- crnot_2 = "4c000042CC=",
- crandc_3 = "4c000102CCC",
- crxor_3 = "4c000182CCC",
- crclr_1 = "4c000182C==",
- crnand_3 = "4c0001c2CCC",
- crand_3 = "4c000202CCC",
- creqv_3 = "4c000242CCC",
- crset_1 = "4c000242C==",
- crorc_3 = "4c000342CCC",
- cror_3 = "4c000382CCC",
- crmove_2 = "4c000382CC=",
- bclr_2 = "4c000020AA",
- bclrl_2 = "4c000021AA",
- bcctr_2 = "4c000420AA",
- bcctrl_2 = "4c000421AA",
- blr_0 = "4e800020",
- blrl_0 = "4e800021",
- bctr_0 = "4e800420",
- bctrl_0 = "4e800421",
-
- -- Primary opcode 31:
- cmpw_3 = "7c000000XRR",
- cmpw_2 = "7c000000-RR",
- cmpd_3 = "7c200000XRR",
- cmpd_2 = "7c200000-RR",
- tw_3 = "7c000008ARR",
- subfc_3 = "7c000010RRR.",
- subc_3 = "7c000010RRR~.",
- mulhdu_3 = "7c000012RRR.",
- addc_3 = "7c000014RRR.",
- mulhwu_3 = "7c000016RRR.",
- isel_4 = "7c00001eRRRC",
- isellt_3 = "7c00001eRRR",
- iselgt_3 = "7c00005eRRR",
- iseleq_3 = "7c00009eRRR",
- mfcr_1 = "7c000026R",
- mtcrf_2 = "7c000120GR",
- -- NYI: mtocrf, mfocrf
- lwarx_3 = "7c000028RR0R",
- ldx_3 = "7c00002aRR0R",
- lwzx_3 = "7c00002eRR0R",
- slw_3 = "7c000030RR~R.",
- cntlzw_2 = "7c000034RR~",
- sld_3 = "7c000036RR~R.",
- and_3 = "7c000038RR~R.",
- cmplw_3 = "7c000040XRR",
- cmplw_2 = "7c000040-RR",
- cmpld_3 = "7c200040XRR",
- cmpld_2 = "7c200040-RR",
- subf_3 = "7c000050RRR.",
- sub_3 = "7c000050RRR~.",
- ldux_3 = "7c00006aRR0R",
- dcbst_2 = "7c00006c-RR",
- lwzux_3 = "7c00006eRR0R",
- cntlzd_2 = "7c000074RR~",
- andc_3 = "7c000078RR~R.",
- td_3 = "7c000088ARR",
- mulhd_3 = "7c000092RRR.",
- mulhw_3 = "7c000096RRR.",
- ldarx_3 = "7c0000a8RR0R",
- dcbf_2 = "7c0000ac-RR",
- lbzx_3 = "7c0000aeRR0R",
- neg_2 = "7c0000d0RR.",
- lbzux_3 = "7c0000eeRR0R",
- popcntb_2 = "7c0000f4RR~",
- not_2 = "7c0000f8RR~%.",
- nor_3 = "7c0000f8RR~R.",
- subfe_3 = "7c000110RRR.",
- sube_3 = "7c000110RRR~.",
- adde_3 = "7c000114RRR.",
- stdx_3 = "7c00012aRR0R",
- stwcx_3 = "7c00012cRR0R.",
- stwx_3 = "7c00012eRR0R",
- prtyw_2 = "7c000134RR~",
- stdux_3 = "7c00016aRR0R",
- stwux_3 = "7c00016eRR0R",
- prtyd_2 = "7c000174RR~",
- subfze_2 = "7c000190RR.",
- addze_2 = "7c000194RR.",
- stdcx_3 = "7c0001acRR0R.",
- stbx_3 = "7c0001aeRR0R",
- subfme_2 = "7c0001d0RR.",
- mulld_3 = "7c0001d2RRR.",
- addme_2 = "7c0001d4RR.",
- mullw_3 = "7c0001d6RRR.",
- dcbtst_2 = "7c0001ec-RR",
- stbux_3 = "7c0001eeRR0R",
- add_3 = "7c000214RRR.",
- dcbt_2 = "7c00022c-RR",
- lhzx_3 = "7c00022eRR0R",
- eqv_3 = "7c000238RR~R.",
- eciwx_3 = "7c00026cRR0R",
- lhzux_3 = "7c00026eRR0R",
- xor_3 = "7c000278RR~R.",
- mfspefscr_1 = "7c0082a6R",
- mfxer_1 = "7c0102a6R",
- mflr_1 = "7c0802a6R",
- mfctr_1 = "7c0902a6R",
- lwax_3 = "7c0002aaRR0R",
- lhax_3 = "7c0002aeRR0R",
- mftb_1 = "7c0c42e6R",
- mftbu_1 = "7c0d42e6R",
- lwaux_3 = "7c0002eaRR0R",
- lhaux_3 = "7c0002eeRR0R",
- sthx_3 = "7c00032eRR0R",
- orc_3 = "7c000338RR~R.",
- ecowx_3 = "7c00036cRR0R",
- sthux_3 = "7c00036eRR0R",
- or_3 = "7c000378RR~R.",
- mr_2 = "7c000378RR~%.",
- divdu_3 = "7c000392RRR.",
- divwu_3 = "7c000396RRR.",
- mtspefscr_1 = "7c0083a6R",
- mtxer_1 = "7c0103a6R",
- mtlr_1 = "7c0803a6R",
- mtctr_1 = "7c0903a6R",
- dcbi_2 = "7c0003ac-RR",
- nand_3 = "7c0003b8RR~R.",
- divd_3 = "7c0003d2RRR.",
- divw_3 = "7c0003d6RRR.",
- cmpb_3 = "7c0003f8RR~R.",
- mcrxr_1 = "7c000400X",
- subfco_3 = "7c000410RRR.",
- subco_3 = "7c000410RRR~.",
- addco_3 = "7c000414RRR.",
- ldbrx_3 = "7c000428RR0R",
- lswx_3 = "7c00042aRR0R",
- lwbrx_3 = "7c00042cRR0R",
- lfsx_3 = "7c00042eFR0R",
- srw_3 = "7c000430RR~R.",
- srd_3 = "7c000436RR~R.",
- subfo_3 = "7c000450RRR.",
- subo_3 = "7c000450RRR~.",
- lfsux_3 = "7c00046eFR0R",
- lswi_3 = "7c0004aaRR0A",
- sync_0 = "7c0004ac",
- lwsync_0 = "7c2004ac",
- ptesync_0 = "7c4004ac",
- lfdx_3 = "7c0004aeFR0R",
- nego_2 = "7c0004d0RR.",
- lfdux_3 = "7c0004eeFR0R",
- subfeo_3 = "7c000510RRR.",
- subeo_3 = "7c000510RRR~.",
- addeo_3 = "7c000514RRR.",
- stdbrx_3 = "7c000528RR0R",
- stswx_3 = "7c00052aRR0R",
- stwbrx_3 = "7c00052cRR0R",
- stfsx_3 = "7c00052eFR0R",
- stfsux_3 = "7c00056eFR0R",
- subfzeo_2 = "7c000590RR.",
- addzeo_2 = "7c000594RR.",
- stswi_3 = "7c0005aaRR0A",
- stfdx_3 = "7c0005aeFR0R",
- subfmeo_2 = "7c0005d0RR.",
- mulldo_3 = "7c0005d2RRR.",
- addmeo_2 = "7c0005d4RR.",
- mullwo_3 = "7c0005d6RRR.",
- dcba_2 = "7c0005ec-RR",
- stfdux_3 = "7c0005eeFR0R",
- addo_3 = "7c000614RRR.",
- lhbrx_3 = "7c00062cRR0R",
- sraw_3 = "7c000630RR~R.",
- srad_3 = "7c000634RR~R.",
- srawi_3 = "7c000670RR~A.",
- eieio_0 = "7c0006ac",
- lfiwax_3 = "7c0006aeFR0R",
- sthbrx_3 = "7c00072cRR0R",
- extsh_2 = "7c000734RR~.",
- extsb_2 = "7c000774RR~.",
- divduo_3 = "7c000792RRR.",
- divwou_3 = "7c000796RRR.",
- icbi_2 = "7c0007ac-RR",
- stfiwx_3 = "7c0007aeFR0R",
- extsw_2 = "7c0007b4RR~.",
- divdo_3 = "7c0007d2RRR.",
- divwo_3 = "7c0007d6RRR.",
- dcbz_2 = "7c0007ec-RR",
-
- -- Primary opcode 59:
- fdivs_3 = "ec000024FFF.",
- fsubs_3 = "ec000028FFF.",
- fadds_3 = "ec00002aFFF.",
- fsqrts_2 = "ec00002cF-F.",
- fres_2 = "ec000030F-F.",
- fmuls_3 = "ec000032FF-F.",
- frsqrtes_2 = "ec000034F-F.",
- fmsubs_4 = "ec000038FFFF~.",
- fmadds_4 = "ec00003aFFFF~.",
- fnmsubs_4 = "ec00003cFFFF~.",
- fnmadds_4 = "ec00003eFFFF~.",
-
- -- Primary opcode 63:
- fdiv_3 = "fc000024FFF.",
- fsub_3 = "fc000028FFF.",
- fadd_3 = "fc00002aFFF.",
- fsqrt_2 = "fc00002cF-F.",
- fsel_4 = "fc00002eFFFF~.",
- fre_2 = "fc000030F-F.",
- fmul_3 = "fc000032FF-F.",
- frsqrte_2 = "fc000034F-F.",
- fmsub_4 = "fc000038FFFF~.",
- fmadd_4 = "fc00003aFFFF~.",
- fnmsub_4 = "fc00003cFFFF~.",
- fnmadd_4 = "fc00003eFFFF~.",
- fcmpu_3 = "fc000000XFF",
- fcpsgn_3 = "fc000010FFF.",
- fcmpo_3 = "fc000040XFF",
- mtfsb1_1 = "fc00004cA",
- fneg_2 = "fc000050F-F.",
- mcrfs_2 = "fc000080XX",
- mtfsb0_1 = "fc00008cA",
- fmr_2 = "fc000090F-F.",
- frsp_2 = "fc000018F-F.",
- fctiw_2 = "fc00001cF-F.",
- fctiwz_2 = "fc00001eF-F.",
- mtfsfi_2 = "fc00010cAA", -- NYI: upshift.
- fnabs_2 = "fc000110F-F.",
- fabs_2 = "fc000210F-F.",
- frin_2 = "fc000310F-F.",
- friz_2 = "fc000350F-F.",
- frip_2 = "fc000390F-F.",
- frim_2 = "fc0003d0F-F.",
- mffs_1 = "fc00048eF.",
- -- NYI: mtfsf, mtfsb0, mtfsb1.
- fctid_2 = "fc00065cF-F.",
- fctidz_2 = "fc00065eF-F.",
- fcfid_2 = "fc00069cF-F.",
-
- -- Primary opcode 4, SPE APU extension:
- evaddw_3 = "10000200RRR",
- evaddiw_3 = "10000202RAR~",
- evsubw_3 = "10000204RRR~",
- evsubiw_3 = "10000206RAR~",
- evabs_2 = "10000208RR",
- evneg_2 = "10000209RR",
- evextsb_2 = "1000020aRR",
- evextsh_2 = "1000020bRR",
- evrndw_2 = "1000020cRR",
- evcntlzw_2 = "1000020dRR",
- evcntlsw_2 = "1000020eRR",
- brinc_3 = "1000020fRRR",
- evand_3 = "10000211RRR",
- evandc_3 = "10000212RRR",
- evxor_3 = "10000216RRR",
- evor_3 = "10000217RRR",
- evmr_2 = "10000217RR=",
- evnor_3 = "10000218RRR",
- evnot_2 = "10000218RR=",
- eveqv_3 = "10000219RRR",
- evorc_3 = "1000021bRRR",
- evnand_3 = "1000021eRRR",
- evsrwu_3 = "10000220RRR",
- evsrws_3 = "10000221RRR",
- evsrwiu_3 = "10000222RRA",
- evsrwis_3 = "10000223RRA",
- evslw_3 = "10000224RRR",
- evslwi_3 = "10000226RRA",
- evrlw_3 = "10000228RRR",
- evsplati_2 = "10000229RS",
- evrlwi_3 = "1000022aRRA",
- evsplatfi_2 = "1000022bRS",
- evmergehi_3 = "1000022cRRR",
- evmergelo_3 = "1000022dRRR",
- evcmpgtu_3 = "10000230XRR",
- evcmpgtu_2 = "10000230-RR",
- evcmpgts_3 = "10000231XRR",
- evcmpgts_2 = "10000231-RR",
- evcmpltu_3 = "10000232XRR",
- evcmpltu_2 = "10000232-RR",
- evcmplts_3 = "10000233XRR",
- evcmplts_2 = "10000233-RR",
- evcmpeq_3 = "10000234XRR",
- evcmpeq_2 = "10000234-RR",
- evsel_4 = "10000278RRRW",
- evsel_3 = "10000278RRR",
- evfsadd_3 = "10000280RRR",
- evfssub_3 = "10000281RRR",
- evfsabs_2 = "10000284RR",
- evfsnabs_2 = "10000285RR",
- evfsneg_2 = "10000286RR",
- evfsmul_3 = "10000288RRR",
- evfsdiv_3 = "10000289RRR",
- evfscmpgt_3 = "1000028cXRR",
- evfscmpgt_2 = "1000028c-RR",
- evfscmplt_3 = "1000028dXRR",
- evfscmplt_2 = "1000028d-RR",
- evfscmpeq_3 = "1000028eXRR",
- evfscmpeq_2 = "1000028e-RR",
- evfscfui_2 = "10000290R-R",
- evfscfsi_2 = "10000291R-R",
- evfscfuf_2 = "10000292R-R",
- evfscfsf_2 = "10000293R-R",
- evfsctui_2 = "10000294R-R",
- evfsctsi_2 = "10000295R-R",
- evfsctuf_2 = "10000296R-R",
- evfsctsf_2 = "10000297R-R",
- evfsctuiz_2 = "10000298R-R",
- evfsctsiz_2 = "1000029aR-R",
- evfststgt_3 = "1000029cXRR",
- evfststgt_2 = "1000029c-RR",
- evfststlt_3 = "1000029dXRR",
- evfststlt_2 = "1000029d-RR",
- evfststeq_3 = "1000029eXRR",
- evfststeq_2 = "1000029e-RR",
- efsadd_3 = "100002c0RRR",
- efssub_3 = "100002c1RRR",
- efsabs_2 = "100002c4RR",
- efsnabs_2 = "100002c5RR",
- efsneg_2 = "100002c6RR",
- efsmul_3 = "100002c8RRR",
- efsdiv_3 = "100002c9RRR",
- efscmpgt_3 = "100002ccXRR",
- efscmpgt_2 = "100002cc-RR",
- efscmplt_3 = "100002cdXRR",
- efscmplt_2 = "100002cd-RR",
- efscmpeq_3 = "100002ceXRR",
- efscmpeq_2 = "100002ce-RR",
- efscfd_2 = "100002cfR-R",
- efscfui_2 = "100002d0R-R",
- efscfsi_2 = "100002d1R-R",
- efscfuf_2 = "100002d2R-R",
- efscfsf_2 = "100002d3R-R",
- efsctui_2 = "100002d4R-R",
- efsctsi_2 = "100002d5R-R",
- efsctuf_2 = "100002d6R-R",
- efsctsf_2 = "100002d7R-R",
- efsctuiz_2 = "100002d8R-R",
- efsctsiz_2 = "100002daR-R",
- efststgt_3 = "100002dcXRR",
- efststgt_2 = "100002dc-RR",
- efststlt_3 = "100002ddXRR",
- efststlt_2 = "100002dd-RR",
- efststeq_3 = "100002deXRR",
- efststeq_2 = "100002de-RR",
- efdadd_3 = "100002e0RRR",
- efdsub_3 = "100002e1RRR",
- efdcfuid_2 = "100002e2R-R",
- efdcfsid_2 = "100002e3R-R",
- efdabs_2 = "100002e4RR",
- efdnabs_2 = "100002e5RR",
- efdneg_2 = "100002e6RR",
- efdmul_3 = "100002e8RRR",
- efddiv_3 = "100002e9RRR",
- efdctuidz_2 = "100002eaR-R",
- efdctsidz_2 = "100002ebR-R",
- efdcmpgt_3 = "100002ecXRR",
- efdcmpgt_2 = "100002ec-RR",
- efdcmplt_3 = "100002edXRR",
- efdcmplt_2 = "100002ed-RR",
- efdcmpeq_3 = "100002eeXRR",
- efdcmpeq_2 = "100002ee-RR",
- efdcfs_2 = "100002efR-R",
- efdcfui_2 = "100002f0R-R",
- efdcfsi_2 = "100002f1R-R",
- efdcfuf_2 = "100002f2R-R",
- efdcfsf_2 = "100002f3R-R",
- efdctui_2 = "100002f4R-R",
- efdctsi_2 = "100002f5R-R",
- efdctuf_2 = "100002f6R-R",
- efdctsf_2 = "100002f7R-R",
- efdctuiz_2 = "100002f8R-R",
- efdctsiz_2 = "100002faR-R",
- efdtstgt_3 = "100002fcXRR",
- efdtstgt_2 = "100002fc-RR",
- efdtstlt_3 = "100002fdXRR",
- efdtstlt_2 = "100002fd-RR",
- efdtsteq_3 = "100002feXRR",
- efdtsteq_2 = "100002fe-RR",
- evlddx_3 = "10000300RR0R",
- evldd_2 = "10000301R8",
- evldwx_3 = "10000302RR0R",
- evldw_2 = "10000303R8",
- evldhx_3 = "10000304RR0R",
- evldh_2 = "10000305R8",
- evlwhex_3 = "10000310RR0R",
- evlwhe_2 = "10000311R4",
- evlwhoux_3 = "10000314RR0R",
- evlwhou_2 = "10000315R4",
- evlwhosx_3 = "10000316RR0R",
- evlwhos_2 = "10000317R4",
- evstddx_3 = "10000320RR0R",
- evstdd_2 = "10000321R8",
- evstdwx_3 = "10000322RR0R",
- evstdw_2 = "10000323R8",
- evstdhx_3 = "10000324RR0R",
- evstdh_2 = "10000325R8",
- evstwhex_3 = "10000330RR0R",
- evstwhe_2 = "10000331R4",
- evstwhox_3 = "10000334RR0R",
- evstwho_2 = "10000335R4",
- evstwwex_3 = "10000338RR0R",
- evstwwe_2 = "10000339R4",
- evstwwox_3 = "1000033cRR0R",
- evstwwo_2 = "1000033dR4",
- evmhessf_3 = "10000403RRR",
- evmhossf_3 = "10000407RRR",
- evmheumi_3 = "10000408RRR",
- evmhesmi_3 = "10000409RRR",
- evmhesmf_3 = "1000040bRRR",
- evmhoumi_3 = "1000040cRRR",
- evmhosmi_3 = "1000040dRRR",
- evmhosmf_3 = "1000040fRRR",
- evmhessfa_3 = "10000423RRR",
- evmhossfa_3 = "10000427RRR",
- evmheumia_3 = "10000428RRR",
- evmhesmia_3 = "10000429RRR",
- evmhesmfa_3 = "1000042bRRR",
- evmhoumia_3 = "1000042cRRR",
- evmhosmia_3 = "1000042dRRR",
- evmhosmfa_3 = "1000042fRRR",
- evmwhssf_3 = "10000447RRR",
- evmwlumi_3 = "10000448RRR",
- evmwhumi_3 = "1000044cRRR",
- evmwhsmi_3 = "1000044dRRR",
- evmwhsmf_3 = "1000044fRRR",
- evmwssf_3 = "10000453RRR",
- evmwumi_3 = "10000458RRR",
- evmwsmi_3 = "10000459RRR",
- evmwsmf_3 = "1000045bRRR",
- evmwhssfa_3 = "10000467RRR",
- evmwlumia_3 = "10000468RRR",
- evmwhumia_3 = "1000046cRRR",
- evmwhsmia_3 = "1000046dRRR",
- evmwhsmfa_3 = "1000046fRRR",
- evmwssfa_3 = "10000473RRR",
- evmwumia_3 = "10000478RRR",
- evmwsmia_3 = "10000479RRR",
- evmwsmfa_3 = "1000047bRRR",
- evmra_2 = "100004c4RR",
- evdivws_3 = "100004c6RRR",
- evdivwu_3 = "100004c7RRR",
- evmwssfaa_3 = "10000553RRR",
- evmwumiaa_3 = "10000558RRR",
- evmwsmiaa_3 = "10000559RRR",
- evmwsmfaa_3 = "1000055bRRR",
- evmwssfan_3 = "100005d3RRR",
- evmwumian_3 = "100005d8RRR",
- evmwsmian_3 = "100005d9RRR",
- evmwsmfan_3 = "100005dbRRR",
- evmergehilo_3 = "1000022eRRR",
- evmergelohi_3 = "1000022fRRR",
- evlhhesplatx_3 = "10000308RR0R",
- evlhhesplat_2 = "10000309R2",
- evlhhousplatx_3 = "1000030cRR0R",
- evlhhousplat_2 = "1000030dR2",
- evlhhossplatx_3 = "1000030eRR0R",
- evlhhossplat_2 = "1000030fR2",
- evlwwsplatx_3 = "10000318RR0R",
- evlwwsplat_2 = "10000319R4",
- evlwhsplatx_3 = "1000031cRR0R",
- evlwhsplat_2 = "1000031dR4",
- evaddusiaaw_2 = "100004c0RR",
- evaddssiaaw_2 = "100004c1RR",
- evsubfusiaaw_2 = "100004c2RR",
- evsubfssiaaw_2 = "100004c3RR",
- evaddumiaaw_2 = "100004c8RR",
- evaddsmiaaw_2 = "100004c9RR",
- evsubfumiaaw_2 = "100004caRR",
- evsubfsmiaaw_2 = "100004cbRR",
- evmheusiaaw_3 = "10000500RRR",
- evmhessiaaw_3 = "10000501RRR",
- evmhessfaaw_3 = "10000503RRR",
- evmhousiaaw_3 = "10000504RRR",
- evmhossiaaw_3 = "10000505RRR",
- evmhossfaaw_3 = "10000507RRR",
- evmheumiaaw_3 = "10000508RRR",
- evmhesmiaaw_3 = "10000509RRR",
- evmhesmfaaw_3 = "1000050bRRR",
- evmhoumiaaw_3 = "1000050cRRR",
- evmhosmiaaw_3 = "1000050dRRR",
- evmhosmfaaw_3 = "1000050fRRR",
- evmhegumiaa_3 = "10000528RRR",
- evmhegsmiaa_3 = "10000529RRR",
- evmhegsmfaa_3 = "1000052bRRR",
- evmhogumiaa_3 = "1000052cRRR",
- evmhogsmiaa_3 = "1000052dRRR",
- evmhogsmfaa_3 = "1000052fRRR",
- evmwlusiaaw_3 = "10000540RRR",
- evmwlssiaaw_3 = "10000541RRR",
- evmwlumiaaw_3 = "10000548RRR",
- evmwlsmiaaw_3 = "10000549RRR",
- evmheusianw_3 = "10000580RRR",
- evmhessianw_3 = "10000581RRR",
- evmhessfanw_3 = "10000583RRR",
- evmhousianw_3 = "10000584RRR",
- evmhossianw_3 = "10000585RRR",
- evmhossfanw_3 = "10000587RRR",
- evmheumianw_3 = "10000588RRR",
- evmhesmianw_3 = "10000589RRR",
- evmhesmfanw_3 = "1000058bRRR",
- evmhoumianw_3 = "1000058cRRR",
- evmhosmianw_3 = "1000058dRRR",
- evmhosmfanw_3 = "1000058fRRR",
- evmhegumian_3 = "100005a8RRR",
- evmhegsmian_3 = "100005a9RRR",
- evmhegsmfan_3 = "100005abRRR",
- evmhogumian_3 = "100005acRRR",
- evmhogsmian_3 = "100005adRRR",
- evmhogsmfan_3 = "100005afRRR",
- evmwlusianw_3 = "100005c0RRR",
- evmwlssianw_3 = "100005c1RRR",
- evmwlumianw_3 = "100005c8RRR",
- evmwlsmianw_3 = "100005c9RRR",
-
- -- NYI: some 64 bit PowerPC and Book E instructions:
- -- rldicl, rldicr, rldic, rldimi, rldcl, rldcr, sradi, 64 bit ext. add/sub,
- -- extended addressing branches, cache management, loads and stores
-}
-
--- Add mnemonics for "." variants.
-do
- local t = {}
- for k,v in pairs(map_op) do
- if sub(v, -1) == "." then
- local v2 = sub(v, 1, 7)..char(byte(v, 8)+1)..sub(v, 9, -2)
- t[sub(k, 1, -3).."."..sub(k, -2)] = v2
- end
- end
- for k,v in pairs(t) do
- map_op[k] = v
- end
-end
-
--- Add more branch mnemonics.
-for cond,c in pairs(map_cond) do
- local b1 = "b"..cond
- local c1 = (c%4)*0x00010000 + (c < 4 and 0x01000000 or 0)
- -- bX[l]
- map_op[b1.."_1"] = tohex(0x40800000 + c1).."K"
- map_op[b1.."y_1"] = tohex(0x40a00000 + c1).."K"
- map_op[b1.."l_1"] = tohex(0x40800001 + c1).."K"
- map_op[b1.."_2"] = tohex(0x40800000 + c1).."-XK"
- map_op[b1.."y_2"] = tohex(0x40a00000 + c1).."-XK"
- map_op[b1.."l_2"] = tohex(0x40800001 + c1).."-XK"
- -- bXlr[l]
- map_op[b1.."lr_0"] = tohex(0x4c800020 + c1)
- map_op[b1.."lrl_0"] = tohex(0x4c800021 + c1)
- map_op[b1.."ctr_0"] = tohex(0x4c800420 + c1)
- map_op[b1.."ctrl_0"] = tohex(0x4c800421 + c1)
- -- bXctr[l]
- map_op[b1.."lr_1"] = tohex(0x4c800020 + c1).."-X"
- map_op[b1.."lrl_1"] = tohex(0x4c800021 + c1).."-X"
- map_op[b1.."ctr_1"] = tohex(0x4c800420 + c1).."-X"
- map_op[b1.."ctrl_1"] = tohex(0x4c800421 + c1).."-X"
-end
-
-------------------------------------------------------------------------------
-
-local function parse_gpr(expr)
- local tname, ovreg = match(expr, "^([%w_]+):(r[1-3]?[0-9])$")
- local tp = map_type[tname or expr]
- if tp then
- local reg = ovreg or tp.reg
- if not reg then
- werror("type `"..(tname or expr).."' needs a register override")
- end
- expr = reg
- end
- local r = match(expr, "^r([1-3]?[0-9])$")
- if r then
- r = tonumber(r)
- if r <= 31 then return r, tp end
- end
- werror("bad register name `"..expr.."'")
-end
-
-local function parse_fpr(expr)
- local r = match(expr, "^f([1-3]?[0-9])$")
- if r then
- r = tonumber(r)
- if r <= 31 then return r end
- end
- werror("bad register name `"..expr.."'")
-end
-
-local function parse_cr(expr)
- local r = match(expr, "^cr([0-7])$")
- if r then return tonumber(r) end
- werror("bad condition register name `"..expr.."'")
-end
-
-local function parse_cond(expr)
- local r, cond = match(expr, "^4%*cr([0-7])%+(%w%w)$")
- if r then
- r = tonumber(r)
- local c = map_cond[cond]
- if c and c < 4 then return r*4+c end
- end
- werror("bad condition bit name `"..expr.."'")
-end
-
-local function parse_imm(imm, bits, shift, scale, signed)
- local n = tonumber(imm)
- if n then
- if n % 2^scale == 0 then
- n = n / 2^scale
- if signed then
- if n >= 0 then
- if n < 2^(bits-1) then return n*2^shift end
- else
- if n >= -(2^(bits-1))-1 then return (n+2^bits)*2^shift end
- end
- else
- if n >= 0 and n <= 2^bits-1 then return n*2^shift end
- end
- end
- werror("out of range immediate `"..imm.."'")
- elseif match(imm, "^r([1-3]?[0-9])$") or
- match(imm, "^([%w_]+):(r[1-3]?[0-9])$") then
- werror("expected immediate operand, got register")
- else
- waction("IMM", (signed and 32768 or 0)+scale*1024+bits*32+shift, imm)
- return 0
- end
-end
-
-local function parse_disp(disp)
- local imm, reg = match(disp, "^(.*)%(([%w_:]+)%)$")
- if imm then
- local r = parse_gpr(reg)
- if r == 0 then werror("cannot use r0 in displacement") end
- return r*65536 + parse_imm(imm, 16, 0, 0, true)
- end
- local reg, tailr = match(disp, "^([%w_:]+)%s*(.*)$")
- if reg and tailr ~= "" then
- local r, tp = parse_gpr(reg)
- if r == 0 then werror("cannot use r0 in displacement") end
- if tp then
- waction("IMM", 32768+16*32, format(tp.ctypefmt, tailr))
- return r*65536
- end
- end
- werror("bad displacement `"..disp.."'")
-end
-
-local function parse_u5disp(disp, scale)
- local imm, reg = match(disp, "^(.*)%(([%w_:]+)%)$")
- if imm then
- local r = parse_gpr(reg)
- if r == 0 then werror("cannot use r0 in displacement") end
- return r*65536 + parse_imm(imm, 5, 11, scale, false)
- end
- local reg, tailr = match(disp, "^([%w_:]+)%s*(.*)$")
- if reg and tailr ~= "" then
- local r, tp = parse_gpr(reg)
- if r == 0 then werror("cannot use r0 in displacement") end
- if tp then
- waction("IMM", scale*1024+5*32+11, format(tp.ctypefmt, tailr))
- return r*65536
- end
- end
- werror("bad displacement `"..disp.."'")
-end
-
-local function parse_label(label, def)
- local prefix = sub(label, 1, 2)
- -- =>label (pc label reference)
- if prefix == "=>" then
- return "PC", 0, sub(label, 3)
- end
- -- ->name (global label reference)
- if prefix == "->" then
- return "LG", map_global[sub(label, 3)]
- end
- if def then
- -- [1-9] (local label definition)
- if match(label, "^[1-9]$") then
- return "LG", 10+tonumber(label)
- end
- else
- -- [<>][1-9] (local label reference)
- local dir, lnum = match(label, "^([<>])([1-9])$")
- if dir then -- Fwd: 1-9, Bkwd: 11-19.
- return "LG", lnum + (dir == ">" and 0 or 10)
- end
- -- extern label (extern label reference)
- local extname = match(label, "^extern%s+(%S+)$")
- if extname then
- return "EXT", map_extern[extname]
- end
- end
- werror("bad label `"..label.."'")
-end
-
-------------------------------------------------------------------------------
-
--- Handle opcodes defined with template strings.
-map_op[".template__"] = function(params, template, nparams)
- if not params then return sub(template, 9) end
- local op = tonumber(sub(template, 1, 8), 16)
- local n, rs = 1, 26
-
- -- Limit number of section buffer positions used by a single dasm_put().
- -- A single opcode needs a maximum of 3 positions (rlwinm).
- if secpos+3 > maxsecpos then wflush() end
- local pos = wpos()
-
- -- Process each character.
- for p in gmatch(sub(template, 9), ".") do
- if p == "R" then
- rs = rs - 5; op = op + parse_gpr(params[n]) * 2^rs; n = n + 1
- elseif p == "F" then
- rs = rs - 5; op = op + parse_fpr(params[n]) * 2^rs; n = n + 1
- elseif p == "A" then
- rs = rs - 5; op = op + parse_imm(params[n], 5, rs, 0, false); n = n + 1
- elseif p == "S" then
- rs = rs - 5; op = op + parse_imm(params[n], 5, rs, 0, true); n = n + 1
- elseif p == "I" then
- op = op + parse_imm(params[n], 16, 0, 0, true); n = n + 1
- elseif p == "U" then
- op = op + parse_imm(params[n], 16, 0, 0, false); n = n + 1
- elseif p == "D" then
- op = op + parse_disp(params[n]); n = n + 1
- elseif p == "2" then
- op = op + parse_u5disp(params[n], 1); n = n + 1
- elseif p == "4" then
- op = op + parse_u5disp(params[n], 2); n = n + 1
- elseif p == "8" then
- op = op + parse_u5disp(params[n], 3); n = n + 1
- elseif p == "C" then
- rs = rs - 5; op = op + parse_cond(params[n]) * 2^rs; n = n + 1
- elseif p == "X" then
- rs = rs - 5; op = op + parse_cr(params[n]) * 2^(rs+2); n = n + 1
- elseif p == "W" then
- op = op + parse_cr(params[n]); n = n + 1
- elseif p == "G" then
- op = op + parse_imm(params[n], 8, 12, 0, false); n = n + 1
- elseif p == "J" or p == "K" then
- local mode, n, s = parse_label(params[n], false)
- if p == "K" then n = n + 2048 end
- waction("REL_"..mode, n, s, 1)
- n = n + 1
- elseif p == "0" then
- local mm = 2^rs
- local t = op % mm
- if ((op - t) / mm) % 32 == 0 then werror("cannot use r0") end
- elseif p == "=" or p == "%" then
- local mm = 2^(rs + (p == "%" and 5 or 0))
- local t = ((op - op % mm) / mm) % 32
- rs = rs - 5
- op = op + t * 2^rs
- elseif p == "~" then
- local mm = 2^rs
- local t1l = op % mm
- local t1h = (op - t1l) / mm
- local t2l = t1h % 32
- local t2h = (t1h - t2l) / 32
- local t3l = t2h % 32
- op = ((t2h - t3l + t2l)*32 + t3l)*mm + t1l
- elseif p == "-" then
- rs = rs - 5
- elseif p == "." then
- -- Ignored.
- else
- assert(false)
- end
- end
- wputpos(pos, op)
-end
-
-------------------------------------------------------------------------------
-
--- Pseudo-opcode to mark the position where the action list is to be emitted.
-map_op[".actionlist_1"] = function(params)
- if not params then return "cvar" end
- local name = params[1] -- No syntax check. You get to keep the pieces.
- wline(function(out) writeactions(out, name) end)
-end
-
--- Pseudo-opcode to mark the position where the global enum is to be emitted.
-map_op[".globals_1"] = function(params)
- if not params then return "prefix" end
- local prefix = params[1] -- No syntax check. You get to keep the pieces.
- wline(function(out) writeglobals(out, prefix) end)
-end
-
--- Pseudo-opcode to mark the position where the global names are to be emitted.
-map_op[".globalnames_1"] = function(params)
- if not params then return "cvar" end
- local name = params[1] -- No syntax check. You get to keep the pieces.
- wline(function(out) writeglobalnames(out, name) end)
-end
-
--- Pseudo-opcode to mark the position where the extern names are to be emitted.
-map_op[".externnames_1"] = function(params)
- if not params then return "cvar" end
- local name = params[1] -- No syntax check. You get to keep the pieces.
- wline(function(out) writeexternnames(out, name) end)
-end
-
-------------------------------------------------------------------------------
-
--- Label pseudo-opcode (converted from trailing colon form).
-map_op[".label_1"] = function(params)
- if not params then return "[1-9] | ->global | =>pcexpr" end
- if secpos+1 > maxsecpos then wflush() end
- local mode, n, s = parse_label(params[1], true)
- if mode == "EXT" then werror("bad label definition") end
- waction("LABEL_"..mode, n, s, 1)
-end
-
-------------------------------------------------------------------------------
-
--- Pseudo-opcodes for data storage.
-map_op[".long_*"] = function(params)
- if not params then return "imm..." end
- for _,p in ipairs(params) do
- local n = tonumber(p)
- if not n then werror("bad immediate `"..p.."'") end
- if n < 0 then n = n + 2^32 end
- wputw(n)
- if secpos+2 > maxsecpos then wflush() end
- end
-end
-
--- Alignment pseudo-opcode.
-map_op[".align_1"] = function(params)
- if not params then return "numpow2" end
- if secpos+1 > maxsecpos then wflush() end
- local align = tonumber(params[1])
- if align then
- local x = align
- -- Must be a power of 2 in the range (2 ... 256).
- for i=1,8 do
- x = x / 2
- if x == 1 then
- waction("ALIGN", align-1, nil, 1) -- Action byte is 2**n-1.
- return
- end
- end
- end
- werror("bad alignment")
-end
-
-------------------------------------------------------------------------------
-
--- Pseudo-opcode for (primitive) type definitions (map to C types).
-map_op[".type_3"] = function(params, nparams)
- if not params then
- return nparams == 2 and "name, ctype" or "name, ctype, reg"
- end
- local name, ctype, reg = params[1], params[2], params[3]
- if not match(name, "^[%a_][%w_]*$") then
- werror("bad type name `"..name.."'")
- end
- local tp = map_type[name]
- if tp then
- werror("duplicate type `"..name.."'")
- end
- -- Add #type to defines. A bit unclean to put it in map_archdef.
- map_archdef["#"..name] = "sizeof("..ctype..")"
- -- Add new type and emit shortcut define.
- local num = ctypenum + 1
- map_type[name] = {
- ctype = ctype,
- ctypefmt = format("Dt%X(%%s)", num),
- reg = reg,
- }
- wline(format("#define Dt%X(_V) (int)(ptrdiff_t)&(((%s *)0)_V)", num, ctype))
- ctypenum = num
-end
-map_op[".type_2"] = map_op[".type_3"]
-
--- Dump type definitions.
-local function dumptypes(out, lvl)
- local t = {}
- for name in pairs(map_type) do t[#t+1] = name end
- sort(t)
- out:write("Type definitions:\n")
- for _,name in ipairs(t) do
- local tp = map_type[name]
- local reg = tp.reg or ""
- out:write(format(" %-20s %-20s %s\n", name, tp.ctype, reg))
- end
- out:write("\n")
-end
-
-------------------------------------------------------------------------------
-
--- Set the current section.
-function _M.section(num)
- waction("SECTION", num)
- wflush(true) -- SECTION is a terminal action.
-end
-
-------------------------------------------------------------------------------
-
--- Dump architecture description.
-function _M.dumparch(out)
- out:write(format("DynASM %s version %s, released %s\n\n",
- _info.arch, _info.version, _info.release))
- dumpactions(out)
-end
-
--- Dump all user defined elements.
-function _M.dumpdef(out, lvl)
- dumptypes(out, lvl)
- dumpglobals(out, lvl)
- dumpexterns(out, lvl)
-end
-
-------------------------------------------------------------------------------
-
--- Pass callbacks from/to the DynASM core.
-function _M.passcb(wl, we, wf, ww)
- wline, werror, wfatal, wwarn = wl, we, wf, ww
- return wflush
-end
-
--- Setup the arch-specific module.
-function _M.setup(arch, opt)
- g_arch, g_opt = arch, opt
-end
-
--- Merge the core maps and the arch-specific maps.
-function _M.mergemaps(map_coreop, map_def)
- setmetatable(map_op, { __index = map_coreop })
- setmetatable(map_def, { __index = map_archdef })
- return map_op, map_def
-end
-
-return _M
-
-------------------------------------------------------------------------------
-
diff --git a/third_party/dynasm/dasm_proto.h b/third_party/dynasm/dasm_proto.h
deleted file mode 100644
index 3002811..0000000
--- a/third_party/dynasm/dasm_proto.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
-** DynASM encoding engine prototypes.
-** Copyright (C) 2005-2012 Mike Pall. All rights reserved.
-** Released under the MIT license. See dynasm.lua for full copyright notice.
-*/
-
-#ifndef _DASM_PROTO_H
-#define _DASM_PROTO_H
-
-#include <stddef.h>
-#include <stdarg.h>
-
-#define DASM_IDENT "DynASM 1.3.0"
-#define DASM_VERSION 10300 /* 1.3.0 */
-
-#ifndef Dst_DECL
-#define Dst_DECL dasm_State **Dst
-#endif
-
-#ifndef Dst_REF
-#define Dst_REF (*Dst)
-#endif
-
-#ifndef DASM_FDEF
-#define DASM_FDEF extern
-#endif
-
-#ifndef DASM_M_GROW
-#define DASM_M_GROW(ctx, t, p, sz, need) \
- do { \
- size_t _sz = (sz), _need = (need); \
- if (_sz < _need) { \
- if (_sz < 16) _sz = 16; \
- while (_sz < _need) _sz += _sz; \
- (p) = (t *)realloc((p), _sz); \
- if ((p) == NULL) exit(1); \
- (sz) = _sz; \
- } \
- } while(0)
-#endif
-
-#ifndef DASM_M_FREE
-#define DASM_M_FREE(ctx, p, sz) free(p)
-#endif
-
-/* Internal DynASM encoder state. */
-typedef struct dasm_State dasm_State;
-
-
-/* Initialize and free DynASM state. */
-DASM_FDEF void dasm_init(Dst_DECL, int maxsection);
-DASM_FDEF void dasm_free(Dst_DECL);
-
-/* Setup global array. Must be called before dasm_setup(). */
-DASM_FDEF void dasm_setupglobal(Dst_DECL, void **gl, unsigned int maxgl);
-
-/* Grow PC label array. Can be called after dasm_setup(), too. */
-DASM_FDEF void dasm_growpc(Dst_DECL, unsigned int maxpc);
-
-/* Setup encoder. */
-DASM_FDEF void dasm_setup(Dst_DECL, const void *actionlist);
-
-/* Feed encoder with actions. Calls are generated by pre-processor. */
-DASM_FDEF void dasm_put(Dst_DECL, int start, ...);
-
-/* Link sections and return the resulting size. */
-DASM_FDEF int dasm_link(Dst_DECL, size_t *szp);
-
-/* Encode sections into buffer. */
-DASM_FDEF int dasm_encode(Dst_DECL, void *buffer);
-
-/* Get PC label offset. */
-DASM_FDEF int dasm_getpclabel(Dst_DECL, unsigned int pc);
-
-#ifdef DASM_CHECKS
-/* Optional sanity checker to call between isolated encoding steps. */
-DASM_FDEF int dasm_checkstep(Dst_DECL, int secmatch);
-#else
-#define dasm_checkstep(a, b) 0
-#endif
-
-
-#endif /* _DASM_PROTO_H */
diff --git a/third_party/dynasm/dasm_x64.lua b/third_party/dynasm/dasm_x64.lua
deleted file mode 100644
index bae72ac..0000000
--- a/third_party/dynasm/dasm_x64.lua
+++ /dev/null
@@ -1,12 +0,0 @@
-------------------------------------------------------------------------------
--- DynASM x64 module.
---
--- Copyright (C) 2005-2012 Mike Pall. All rights reserved.
--- See dynasm.lua for full copyright notice.
-------------------------------------------------------------------------------
--- This module just sets 64 bit mode for the combined x86/x64 module.
--- All the interesting stuff is there.
-------------------------------------------------------------------------------
-
-x64 = true -- Using a global is an ugly, but effective solution.
-return require("dasm_x86")
diff --git a/third_party/dynasm/dasm_x86.h b/third_party/dynasm/dasm_x86.h
deleted file mode 100644
index 7c6dcd3..0000000
--- a/third_party/dynasm/dasm_x86.h
+++ /dev/null
@@ -1,470 +0,0 @@
-/*
-** DynASM x86 encoding engine.
-** Copyright (C) 2005-2012 Mike Pall. All rights reserved.
-** Released under the MIT license. See dynasm.lua for full copyright notice.
-*/
-
-#include <stddef.h>
-#include <stdarg.h>
-#include <string.h>
-#include <stdlib.h>
-
-#define DASM_ARCH "x86"
-
-#ifndef DASM_EXTERN
-#define DASM_EXTERN(a,b,c,d) 0
-#endif
-
-/* Action definitions. DASM_STOP must be 255. */
-enum {
- DASM_DISP = 233,
- DASM_IMM_S, DASM_IMM_B, DASM_IMM_W, DASM_IMM_D, DASM_IMM_WB, DASM_IMM_DB,
- DASM_VREG, DASM_SPACE, DASM_SETLABEL, DASM_REL_A, DASM_REL_LG, DASM_REL_PC,
- DASM_IMM_LG, DASM_IMM_PC, DASM_LABEL_LG, DASM_LABEL_PC, DASM_ALIGN,
- DASM_EXTERN, DASM_ESC, DASM_MARK, DASM_SECTION, DASM_STOP
-};
-
-/* Maximum number of section buffer positions for a single dasm_put() call. */
-#define DASM_MAXSECPOS 25
-
-/* DynASM encoder status codes. Action list offset or number are or'ed in. */
-#define DASM_S_OK 0x00000000
-#define DASM_S_NOMEM 0x01000000
-#define DASM_S_PHASE 0x02000000
-#define DASM_S_MATCH_SEC 0x03000000
-#define DASM_S_RANGE_I 0x11000000
-#define DASM_S_RANGE_SEC 0x12000000
-#define DASM_S_RANGE_LG 0x13000000
-#define DASM_S_RANGE_PC 0x14000000
-#define DASM_S_RANGE_VREG 0x15000000
-#define DASM_S_UNDEF_L 0x21000000
-#define DASM_S_UNDEF_PC 0x22000000
-
-/* Macros to convert positions (8 bit section + 24 bit index). */
-#define DASM_POS2IDX(pos) ((pos)&0x00ffffff)
-#define DASM_POS2BIAS(pos) ((pos)&0xff000000)
-#define DASM_SEC2POS(sec) ((sec)<<24)
-#define DASM_POS2SEC(pos) ((pos)>>24)
-#define DASM_POS2PTR(D, pos) (D->sections[DASM_POS2SEC(pos)].rbuf + (pos))
-
-/* Action list type. */
-typedef const unsigned char *dasm_ActList;
-
-/* Per-section structure. */
-typedef struct dasm_Section {
- int *rbuf; /* Biased buffer pointer (negative section bias). */
- int *buf; /* True buffer pointer. */
- size_t bsize; /* Buffer size in bytes. */
- int pos; /* Biased buffer position. */
- int epos; /* End of biased buffer position - max single put. */
- int ofs; /* Byte offset into section. */
-} dasm_Section;
-
-/* Core structure holding the DynASM encoding state. */
-struct dasm_State {
- size_t psize; /* Allocated size of this structure. */
- dasm_ActList actionlist; /* Current actionlist pointer. */
- int *lglabels; /* Local/global chain/pos ptrs. */
- size_t lgsize;
- int *pclabels; /* PC label chains/pos ptrs. */
- size_t pcsize;
- void **globals; /* Array of globals (bias -10). */
- dasm_Section *section; /* Pointer to active section. */
- size_t codesize; /* Total size of all code sections. */
- int maxsection; /* 0 <= sectionidx < maxsection. */
- int status; /* Status code. */
- dasm_Section sections[1]; /* All sections. Alloc-extended. */
-};
-
-/* The size of the core structure depends on the max. number of sections. */
-#define DASM_PSZ(ms) (sizeof(dasm_State)+(ms-1)*sizeof(dasm_Section))
-
-
-/* Initialize DynASM state. */
-void dasm_init(Dst_DECL, int maxsection)
-{
- dasm_State *D;
- size_t psz = 0;
- int i;
- Dst_REF = NULL;
- DASM_M_GROW(Dst, struct dasm_State, Dst_REF, psz, DASM_PSZ(maxsection));
- D = Dst_REF;
- D->psize = psz;
- D->lglabels = NULL;
- D->lgsize = 0;
- D->pclabels = NULL;
- D->pcsize = 0;
- D->globals = NULL;
- D->maxsection = maxsection;
- for (i = 0; i < maxsection; i++) {
- D->sections[i].buf = NULL; /* Need this for pass3. */
- D->sections[i].rbuf = D->sections[i].buf - DASM_SEC2POS(i);
- D->sections[i].bsize = 0;
- D->sections[i].epos = 0; /* Wrong, but is recalculated after resize. */
- }
-}
-
-/* Free DynASM state. */
-void dasm_free(Dst_DECL)
-{
- dasm_State *D = Dst_REF;
- int i;
- for (i = 0; i < D->maxsection; i++)
- if (D->sections[i].buf)
- DASM_M_FREE(Dst, D->sections[i].buf, D->sections[i].bsize);
- if (D->pclabels) DASM_M_FREE(Dst, D->pclabels, D->pcsize);
- if (D->lglabels) DASM_M_FREE(Dst, D->lglabels, D->lgsize);
- DASM_M_FREE(Dst, D, D->psize);
-}
-
-/* Setup global label array. Must be called before dasm_setup(). */
-void dasm_setupglobal(Dst_DECL, void **gl, unsigned int maxgl)
-{
- dasm_State *D = Dst_REF;
- D->globals = gl - 10; /* Negative bias to compensate for locals. */
- DASM_M_GROW(Dst, int, D->lglabels, D->lgsize, (10+maxgl)*sizeof(int));
-}
-
-/* Grow PC label array. Can be called after dasm_setup(), too. */
-void dasm_growpc(Dst_DECL, unsigned int maxpc)
-{
- dasm_State *D = Dst_REF;
- size_t osz = D->pcsize;
- DASM_M_GROW(Dst, int, D->pclabels, D->pcsize, maxpc*sizeof(int));
- memset((void *)(((unsigned char *)D->pclabels)+osz), 0, D->pcsize-osz);
-}
-
-/* Setup encoder. */
-void dasm_setup(Dst_DECL, const void *actionlist)
-{
- dasm_State *D = Dst_REF;
- int i;
- D->actionlist = (dasm_ActList)actionlist;
- D->status = DASM_S_OK;
- D->section = &D->sections[0];
- memset((void *)D->lglabels, 0, D->lgsize);
- if (D->pclabels) memset((void *)D->pclabels, 0, D->pcsize);
- for (i = 0; i < D->maxsection; i++) {
- D->sections[i].pos = DASM_SEC2POS(i);
- D->sections[i].ofs = 0;
- }
-}
-
-
-#ifdef DASM_CHECKS
-#define CK(x, st) \
- do { if (!(x)) { \
- D->status = DASM_S_##st|(int)(p-D->actionlist-1); return; } } while (0)
-#define CKPL(kind, st) \
- do { if ((size_t)((char *)pl-(char *)D->kind##labels) >= D->kind##size) { \
- D->status=DASM_S_RANGE_##st|(int)(p-D->actionlist-1); return; } } while (0)
-#else
-#define CK(x, st) ((void)0)
-#define CKPL(kind, st) ((void)0)
-#endif
-
-/* Pass 1: Store actions and args, link branches/labels, estimate offsets. */
-void dasm_put(Dst_DECL, int start, ...)
-{
- va_list ap;
- dasm_State *D = Dst_REF;
- dasm_ActList p = D->actionlist + start;
- dasm_Section *sec = D->section;
- int pos = sec->pos, ofs = sec->ofs, mrm = 4;
- int *b;
-
- if (pos >= sec->epos) {
- DASM_M_GROW(Dst, int, sec->buf, sec->bsize,
- sec->bsize + 2*DASM_MAXSECPOS*sizeof(int));
- sec->rbuf = sec->buf - DASM_POS2BIAS(pos);
- sec->epos = (int)sec->bsize/sizeof(int) - DASM_MAXSECPOS+DASM_POS2BIAS(pos);
- }
-
- b = sec->rbuf;
- b[pos++] = start;
-
- va_start(ap, start);
- while (1) {
- int action = *p++;
- if (action < DASM_DISP) {
- ofs++;
- } else if (action <= DASM_REL_A) {
- int n = va_arg(ap, int);
- b[pos++] = n;
- switch (action) {
- case DASM_DISP:
- if (n == 0) { if ((mrm&7) == 4) mrm = p[-2]; if ((mrm&7) != 5) break; }
- case DASM_IMM_DB: if (((n+128)&-256) == 0) goto ob;
- case DASM_REL_A: /* Assumes ptrdiff_t is int. !x64 */
- case DASM_IMM_D: ofs += 4; break;
- case DASM_IMM_S: CK(((n+128)&-256) == 0, RANGE_I); goto ob;
- case DASM_IMM_B: CK((n&-256) == 0, RANGE_I); ob: ofs++; break;
- case DASM_IMM_WB: if (((n+128)&-256) == 0) goto ob;
- case DASM_IMM_W: CK((n&-65536) == 0, RANGE_I); ofs += 2; break;
- case DASM_SPACE: p++; ofs += n; break;
- case DASM_SETLABEL: b[pos-2] = -0x40000000; break; /* Neg. label ofs. */
- case DASM_VREG: CK((n&-8) == 0 && (n != 4 || (*p&1) == 0), RANGE_VREG);
- if (*p++ == 1 && *p == DASM_DISP) mrm = n; continue;
- }
- mrm = 4;
- } else {
- int *pl, n;
- switch (action) {
- case DASM_REL_LG:
- case DASM_IMM_LG:
- n = *p++; pl = D->lglabels + n;
- if (n <= 246) { CKPL(lg, LG); goto putrel; } /* Bkwd rel or global. */
- pl -= 246; n = *pl;
- if (n < 0) n = 0; /* Start new chain for fwd rel if label exists. */
- goto linkrel;
- case DASM_REL_PC:
- case DASM_IMM_PC: pl = D->pclabels + va_arg(ap, int); CKPL(pc, PC);
- putrel:
- n = *pl;
- if (n < 0) { /* Label exists. Get label pos and store it. */
- b[pos] = -n;
- } else {
- linkrel:
- b[pos] = n; /* Else link to rel chain, anchored at label. */
- *pl = pos;
- }
- pos++;
- ofs += 4; /* Maximum offset needed. */
- if (action == DASM_REL_LG || action == DASM_REL_PC)
- b[pos++] = ofs; /* Store pass1 offset estimate. */
- break;
- case DASM_LABEL_LG: pl = D->lglabels + *p++; CKPL(lg, LG); goto putlabel;
- case DASM_LABEL_PC: pl = D->pclabels + va_arg(ap, int); CKPL(pc, PC);
- putlabel:
- n = *pl; /* n > 0: Collapse rel chain and replace with label pos. */
- while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = pos; }
- *pl = -pos; /* Label exists now. */
- b[pos++] = ofs; /* Store pass1 offset estimate. */
- break;
- case DASM_ALIGN:
- ofs += *p++; /* Maximum alignment needed (arg is 2**n-1). */
- b[pos++] = ofs; /* Store pass1 offset estimate. */
- break;
- case DASM_EXTERN: p += 2; ofs += 4; break;
- case DASM_ESC: p++; ofs++; break;
- case DASM_MARK: mrm = p[-2]; break;
- case DASM_SECTION:
- n = *p; CK(n < D->maxsection, RANGE_SEC); D->section = &D->sections[n];
- case DASM_STOP: goto stop;
- }
- }
- }
-stop:
- va_end(ap);
- sec->pos = pos;
- sec->ofs = ofs;
-}
-#undef CK
-
-/* Pass 2: Link sections, shrink branches/aligns, fix label offsets. */
-int dasm_link(Dst_DECL, size_t *szp)
-{
- dasm_State *D = Dst_REF;
- int secnum;
- int ofs = 0;
-
-#ifdef DASM_CHECKS
- *szp = 0;
- if (D->status != DASM_S_OK) return D->status;
- {
- int pc;
- for (pc = 0; pc*sizeof(int) < D->pcsize; pc++)
- if (D->pclabels[pc] > 0) return DASM_S_UNDEF_PC|pc;
- }
-#endif
-
- { /* Handle globals not defined in this translation unit. */
- int idx;
- for (idx = 10; idx*sizeof(int) < D->lgsize; idx++) {
- int n = D->lglabels[idx];
- /* Undefined label: Collapse rel chain and replace with marker (< 0). */
- while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = -idx; }
- }
- }
-
- /* Combine all code sections. No support for data sections (yet). */
- for (secnum = 0; secnum < D->maxsection; secnum++) {
- dasm_Section *sec = D->sections + secnum;
- int *b = sec->rbuf;
- int pos = DASM_SEC2POS(secnum);
- int lastpos = sec->pos;
-
- while (pos != lastpos) {
- dasm_ActList p = D->actionlist + b[pos++];
- while (1) {
- int op, action = *p++;
- switch (action) {
- case DASM_REL_LG: p++; op = p[-3]; goto rel_pc;
- case DASM_REL_PC: op = p[-2]; rel_pc: {
- int shrink = op == 0xe9 ? 3 : ((op&0xf0) == 0x80 ? 4 : 0);
- if (shrink) { /* Shrinkable branch opcode? */
- int lofs, lpos = b[pos];
- if (lpos < 0) goto noshrink; /* Ext global? */
- lofs = *DASM_POS2PTR(D, lpos);
- if (lpos > pos) { /* Fwd label: add cumulative section offsets. */
- int i;
- for (i = secnum; i < DASM_POS2SEC(lpos); i++)
- lofs += D->sections[i].ofs;
- } else {
- lofs -= ofs; /* Bkwd label: unfix offset. */
- }
- lofs -= b[pos+1]; /* Short branch ok? */
- if (lofs >= -128-shrink && lofs <= 127) ofs -= shrink; /* Yes. */
- else { noshrink: shrink = 0; } /* No, cannot shrink op. */
- }
- b[pos+1] = shrink;
- pos += 2;
- break;
- }
- case DASM_SPACE: case DASM_IMM_LG: case DASM_VREG: p++;
- case DASM_DISP: case DASM_IMM_S: case DASM_IMM_B: case DASM_IMM_W:
- case DASM_IMM_D: case DASM_IMM_WB: case DASM_IMM_DB:
- case DASM_SETLABEL: case DASM_REL_A: case DASM_IMM_PC: pos++; break;
- case DASM_LABEL_LG: p++;
- case DASM_LABEL_PC: b[pos++] += ofs; break; /* Fix label offset. */
- case DASM_ALIGN: ofs -= (b[pos++]+ofs)&*p++; break; /* Adjust ofs. */
- case DASM_EXTERN: p += 2; break;
- case DASM_ESC: p++; break;
- case DASM_MARK: break;
- case DASM_SECTION: case DASM_STOP: goto stop;
- }
- }
- stop: (void)0;
- }
- ofs += sec->ofs; /* Next section starts right after current section. */
- }
-
- D->codesize = ofs; /* Total size of all code sections */
- *szp = ofs;
- return DASM_S_OK;
-}
-
-#define dasmb(x) *cp++ = (unsigned char)(x)
-#ifndef DASM_ALIGNED_WRITES
-#define dasmw(x) \
- do { *((unsigned short *)cp) = (unsigned short)(x); cp+=2; } while (0)
-#define dasmd(x) \
- do { *((unsigned int *)cp) = (unsigned int)(x); cp+=4; } while (0)
-#else
-#define dasmw(x) do { dasmb(x); dasmb((x)>>8); } while (0)
-#define dasmd(x) do { dasmw(x); dasmw((x)>>16); } while (0)
-#endif
-
-/* Pass 3: Encode sections. */
-int dasm_encode(Dst_DECL, void *buffer)
-{
- dasm_State *D = Dst_REF;
- unsigned char *base = (unsigned char *)buffer;
- unsigned char *cp = base;
- int secnum;
-
- /* Encode all code sections. No support for data sections (yet). */
- for (secnum = 0; secnum < D->maxsection; secnum++) {
- dasm_Section *sec = D->sections + secnum;
- int *b = sec->buf;
- int *endb = sec->rbuf + sec->pos;
-
- while (b != endb) {
- dasm_ActList p = D->actionlist + *b++;
- unsigned char *mark = NULL;
- while (1) {
- int action = *p++;
- int n = (action >= DASM_DISP && action <= DASM_ALIGN) ? *b++ : 0;
- switch (action) {
- case DASM_DISP: if (!mark) mark = cp; {
- unsigned char *mm = mark;
- if (*p != DASM_IMM_DB && *p != DASM_IMM_WB) mark = NULL;
- if (n == 0) { int mrm = mm[-1]&7; if (mrm == 4) mrm = mm[0]&7;
- if (mrm != 5) { mm[-1] -= 0x80; break; } }
- if (((n+128) & -256) != 0) goto wd; else mm[-1] -= 0x40;
- }
- case DASM_IMM_S: case DASM_IMM_B: wb: dasmb(n); break;
- case DASM_IMM_DB: if (((n+128)&-256) == 0) {
- db: if (!mark) mark = cp; mark[-2] += 2; mark = NULL; goto wb;
- } else mark = NULL;
- case DASM_IMM_D: wd: dasmd(n); break;
- case DASM_IMM_WB: if (((n+128)&-256) == 0) goto db; else mark = NULL;
- case DASM_IMM_W: dasmw(n); break;
- case DASM_VREG: { int t = *p++; if (t >= 2) n<<=3; cp[-1] |= n; break; }
- case DASM_REL_LG: p++; if (n >= 0) goto rel_pc;
- b++; n = (int)(ptrdiff_t)D->globals[-n];
- case DASM_REL_A: rel_a: n -= (int)(ptrdiff_t)(cp+4); goto wd; /* !x64 */
- case DASM_REL_PC: rel_pc: {
- int shrink = *b++;
- int *pb = DASM_POS2PTR(D, n); if (*pb < 0) { n = pb[1]; goto rel_a; }
- n = *pb - ((int)(cp-base) + 4-shrink);
- if (shrink == 0) goto wd;
- if (shrink == 4) { cp--; cp[-1] = *cp-0x10; } else cp[-1] = 0xeb;
- goto wb;
- }
- case DASM_IMM_LG:
- p++; if (n < 0) { n = (int)(ptrdiff_t)D->globals[-n]; goto wd; }
- case DASM_IMM_PC: {
- int *pb = DASM_POS2PTR(D, n);
- n = *pb < 0 ? pb[1] : (*pb + (int)(ptrdiff_t)base);
- goto wd;
- }
- case DASM_LABEL_LG: {
- int idx = *p++;
- if (idx >= 10)
- D->globals[idx] = (void *)(base + (*p == DASM_SETLABEL ? *b : n));
- break;
- }
- case DASM_LABEL_PC: case DASM_SETLABEL: break;
- case DASM_SPACE: { int fill = *p++; while (n--) *cp++ = fill; break; }
- case DASM_ALIGN:
- n = *p++;
- while (((cp-base) & n)) *cp++ = 0x90; /* nop */
- break;
- case DASM_EXTERN: n = DASM_EXTERN(Dst, cp, p[1], *p); p += 2; goto wd;
- case DASM_MARK: mark = cp; break;
- case DASM_ESC: action = *p++;
- default: *cp++ = action; break;
- case DASM_SECTION: case DASM_STOP: goto stop;
- }
- }
- stop: (void)0;
- }
- }
-
- if (base + D->codesize != cp) /* Check for phase errors. */
- return DASM_S_PHASE;
- return DASM_S_OK;
-}
-
-/* Get PC label offset. */
-int dasm_getpclabel(Dst_DECL, unsigned int pc)
-{
- dasm_State *D = Dst_REF;
- if (pc*sizeof(int) < D->pcsize) {
- int pos = D->pclabels[pc];
- if (pos < 0) return *DASM_POS2PTR(D, -pos);
- if (pos > 0) return -1; /* Undefined. */
- }
- return -2; /* Unused or out of range. */
-}
-
-#ifdef DASM_CHECKS
-/* Optional sanity checker to call between isolated encoding steps. */
-int dasm_checkstep(Dst_DECL, int secmatch)
-{
- dasm_State *D = Dst_REF;
- if (D->status == DASM_S_OK) {
- int i;
- for (i = 1; i <= 9; i++) {
- if (D->lglabels[i] > 0) { D->status = DASM_S_UNDEF_L|i; break; }
- D->lglabels[i] = 0;
- }
- }
- if (D->status == DASM_S_OK && secmatch >= 0 &&
- D->section != &D->sections[secmatch])
- D->status = DASM_S_MATCH_SEC|(int)(D->section-D->sections);
- return D->status;
-}
-#endif
-
diff --git a/third_party/dynasm/dasm_x86.lua b/third_party/dynasm/dasm_x86.lua
deleted file mode 100644
index 3bebb83..0000000
--- a/third_party/dynasm/dasm_x86.lua
+++ /dev/null
@@ -1,1931 +0,0 @@
-------------------------------------------------------------------------------
--- DynASM x86/x64 module.
---
--- Copyright (C) 2005-2012 Mike Pall. All rights reserved.
--- See dynasm.lua for full copyright notice.
-------------------------------------------------------------------------------
-
-local x64 = x64
-
--- Module information:
-local _info = {
- arch = x64 and "x64" or "x86",
- description = "DynASM x86/x64 module",
- version = "1.3.0",
- vernum = 10300,
- release = "2011-05-05",
- author = "Mike Pall",
- license = "MIT",
-}
-
--- Exported glue functions for the arch-specific module.
-local _M = { _info = _info }
-
--- Cache library functions.
-local type, tonumber, pairs, ipairs = type, tonumber, pairs, ipairs
-local assert, unpack, setmetatable = assert, unpack or table.unpack, setmetatable
-local _s = string
-local sub, format, byte, char = _s.sub, _s.format, _s.byte, _s.char
-local find, match, gmatch, gsub = _s.find, _s.match, _s.gmatch, _s.gsub
-local concat, sort = table.concat, table.sort
-
--- Inherited tables and callbacks.
-local g_opt, g_arch
-local wline, werror, wfatal, wwarn
-
--- Action name list.
--- CHECK: Keep this in sync with the C code!
-local action_names = {
- -- int arg, 1 buffer pos:
- "DISP", "IMM_S", "IMM_B", "IMM_W", "IMM_D", "IMM_WB", "IMM_DB",
- -- action arg (1 byte), int arg, 1 buffer pos (reg/num):
- "VREG", "SPACE", -- !x64: VREG support NYI.
- -- ptrdiff_t arg, 1 buffer pos (address): !x64
- "SETLABEL", "REL_A",
- -- action arg (1 byte) or int arg, 2 buffer pos (link, offset):
- "REL_LG", "REL_PC",
- -- action arg (1 byte) or int arg, 1 buffer pos (link):
- "IMM_LG", "IMM_PC",
- -- action arg (1 byte) or int arg, 1 buffer pos (offset):
- "LABEL_LG", "LABEL_PC",
- -- action arg (1 byte), 1 buffer pos (offset):
- "ALIGN",
- -- action args (2 bytes), no buffer pos.
- "EXTERN",
- -- action arg (1 byte), no buffer pos.
- "ESC",
- -- no action arg, no buffer pos.
- "MARK",
- -- action arg (1 byte), no buffer pos, terminal action:
- "SECTION",
- -- no args, no buffer pos, terminal action:
- "STOP"
-}
-
--- Maximum number of section buffer positions for dasm_put().
--- CHECK: Keep this in sync with the C code!
-local maxsecpos = 25 -- Keep this low, to avoid excessively long C lines.
-
--- Action name -> action number (dynamically generated below).
-local map_action = {}
--- First action number. Everything below does not need to be escaped.
-local actfirst = 256-#action_names
-
--- Action list buffer and string (only used to remove dupes).
-local actlist = {}
-local actstr = ""
-
--- Argument list for next dasm_put(). Start with offset 0 into action list.
-local actargs = { 0 }
-
--- Current number of section buffer positions for dasm_put().
-local secpos = 1
-
-------------------------------------------------------------------------------
-
--- Compute action numbers for action names.
-for n,name in ipairs(action_names) do
- local num = actfirst + n - 1
- map_action[name] = num
-end
-
--- Dump action names and numbers.
-local function dumpactions(out)
- out:write("DynASM encoding engine action codes:\n")
- for n,name in ipairs(action_names) do
- local num = map_action[name]
- out:write(format(" %-10s %02X %d\n", name, num, num))
- end
- out:write("\n")
-end
-
--- Write action list buffer as a huge static C array.
-local function writeactions(out, name)
- local nn = #actlist
- local last = actlist[nn] or 255
- actlist[nn] = nil -- Remove last byte.
- if nn == 0 then nn = 1 end
- out:write("static const unsigned char ", name, "[", nn, "] = {\n")
- local s = " "
- for n,b in ipairs(actlist) do
- s = s..b..","
- if #s >= 75 then
- assert(out:write(s, "\n"))
- s = " "
- end
- end
- out:write(s, last, "\n};\n\n") -- Add last byte back.
-end
-
-------------------------------------------------------------------------------
-
--- Add byte to action list.
-local function wputxb(n)
- assert(n >= 0 and n <= 255 and n % 1 == 0, "byte out of range")
- actlist[#actlist+1] = n
-end
-
--- Add action to list with optional arg. Advance buffer pos, too.
-local function waction(action, a, num)
- wputxb(assert(map_action[action], "bad action name `"..action.."'"))
- if a then actargs[#actargs+1] = a end
- if a or num then secpos = secpos + (num or 1) end
-end
-
--- Add call to embedded DynASM C code.
-local function wcall(func, args)
- wline(format("dasm_%s(Dst, %s);", func, concat(args, ", ")), true)
-end
-
--- Delete duplicate action list chunks. A tad slow, but so what.
-local function dedupechunk(offset)
- local al, as = actlist, actstr
- local chunk = char(unpack(al, offset+1, #al))
- local orig = find(as, chunk, 1, true)
- if orig then
- actargs[1] = orig-1 -- Replace with original offset.
- for i=offset+1,#al do al[i] = nil end -- Kill dupe.
- else
- actstr = as..chunk
- end
-end
-
--- Flush action list (intervening C code or buffer pos overflow).
-local function wflush(term)
- local offset = actargs[1]
- if #actlist == offset then return end -- Nothing to flush.
- if not term then waction("STOP") end -- Terminate action list.
- dedupechunk(offset)
- wcall("put", actargs) -- Add call to dasm_put().
- actargs = { #actlist } -- Actionlist offset is 1st arg to next dasm_put().
- secpos = 1 -- The actionlist offset occupies a buffer position, too.
-end
-
--- Put escaped byte.
-local function wputb(n)
- if n >= actfirst then waction("ESC") end -- Need to escape byte.
- wputxb(n)
-end
-
-------------------------------------------------------------------------------
-
--- Global label name -> global label number. With auto assignment on 1st use.
-local next_global = 10
-local map_global = setmetatable({}, { __index = function(t, name)
- if not match(name, "^[%a_][%w_@]*$") then werror("bad global label") end
- local n = next_global
- if n > 246 then werror("too many global labels") end
- next_global = n + 1
- t[name] = n
- return n
-end})
-
--- Dump global labels.
-local function dumpglobals(out, lvl)
- local t = {}
- for name, n in pairs(map_global) do t[n] = name end
- out:write("Global labels:\n")
- for i=10,next_global-1 do
- out:write(format(" %s\n", t[i]))
- end
- out:write("\n")
-end
-
--- Write global label enum.
-local function writeglobals(out, prefix)
- local t = {}
- for name, n in pairs(map_global) do t[n] = name end
- out:write("enum {\n")
- for i=10,next_global-1 do
- out:write(" ", prefix, gsub(t[i], "@.*", ""), ",\n")
- end
- out:write(" ", prefix, "_MAX\n};\n")
-end
-
--- Write global label names.
-local function writeglobalnames(out, name)
- local t = {}
- for name, n in pairs(map_global) do t[n] = name end
- out:write("static const char *const ", name, "[] = {\n")
- for i=10,next_global-1 do
- out:write(" \"", t[i], "\",\n")
- end
- out:write(" (const char *)0\n};\n")
-end
-
-------------------------------------------------------------------------------
-
--- Extern label name -> extern label number. With auto assignment on 1st use.
-local next_extern = -1
-local map_extern = setmetatable({}, { __index = function(t, name)
- -- No restrictions on the name for now.
- local n = next_extern
- if n < -256 then werror("too many extern labels") end
- next_extern = n - 1
- t[name] = n
- return n
-end})
-
--- Dump extern labels.
-local function dumpexterns(out, lvl)
- local t = {}
- for name, n in pairs(map_extern) do t[-n] = name end
- out:write("Extern labels:\n")
- for i=1,-next_extern-1 do
- out:write(format(" %s\n", t[i]))
- end
- out:write("\n")
-end
-
--- Write extern label names.
-local function writeexternnames(out, name)
- local t = {}
- for name, n in pairs(map_extern) do t[-n] = name end
- out:write("static const char *const ", name, "[] = {\n")
- for i=1,-next_extern-1 do
- out:write(" \"", t[i], "\",\n")
- end
- out:write(" (const char *)0\n};\n")
-end
-
-------------------------------------------------------------------------------
-
--- Arch-specific maps.
-local map_archdef = {} -- Ext. register name -> int. name.
-local map_reg_rev = {} -- Int. register name -> ext. name.
-local map_reg_num = {} -- Int. register name -> register number.
-local map_reg_opsize = {} -- Int. register name -> operand size.
-local map_reg_valid_base = {} -- Int. register name -> valid base register?
-local map_reg_valid_index = {} -- Int. register name -> valid index register?
-local map_reg_needrex = {} -- Int. register name -> need rex vs. no rex.
-local reg_list = {} -- Canonical list of int. register names.
-
-local map_type = {} -- Type name -> { ctype, reg }
-local ctypenum = 0 -- Type number (for _PTx macros).
-
-local addrsize = x64 and "q" or "d" -- Size for address operands.
-
--- Helper functions to fill register maps.
-local function mkrmap(sz, cl, names)
- local cname = format("@%s", sz)
- reg_list[#reg_list+1] = cname
- map_archdef[cl] = cname
- map_reg_rev[cname] = cl
- map_reg_num[cname] = -1
- map_reg_opsize[cname] = sz
- if sz == addrsize or sz == "d" then
- map_reg_valid_base[cname] = true
- map_reg_valid_index[cname] = true
- end
- if names then
- for n,name in ipairs(names) do
- local iname = format("@%s%x", sz, n-1)
- reg_list[#reg_list+1] = iname
- map_archdef[name] = iname
- map_reg_rev[iname] = name
- map_reg_num[iname] = n-1
- map_reg_opsize[iname] = sz
- if sz == "b" and n > 4 then map_reg_needrex[iname] = false end
- if sz == addrsize or sz == "d" then
- map_reg_valid_base[iname] = true
- map_reg_valid_index[iname] = true
- end
- end
- end
- for i=0,(x64 and sz ~= "f") and 15 or 7 do
- local needrex = sz == "b" and i > 3
- local iname = format("@%s%x%s", sz, i, needrex and "R" or "")
- if needrex then map_reg_needrex[iname] = true end
- local name
- if sz == "o" then name = format("xmm%d", i)
- elseif sz == "f" then name = format("st%d", i)
- else name = format("r%d%s", i, sz == addrsize and "" or sz) end
- map_archdef[name] = iname
- if not map_reg_rev[iname] then
- reg_list[#reg_list+1] = iname
- map_reg_rev[iname] = name
- map_reg_num[iname] = i
- map_reg_opsize[iname] = sz
- if sz == addrsize or sz == "d" then
- map_reg_valid_base[iname] = true
- map_reg_valid_index[iname] = true
- end
- end
- end
- reg_list[#reg_list+1] = ""
-end
-
--- Integer registers (qword, dword, word and byte sized).
-if x64 then
- mkrmap("q", "Rq", {"rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi"})
-end
-mkrmap("d", "Rd", {"eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"})
-mkrmap("w", "Rw", {"ax", "cx", "dx", "bx", "sp", "bp", "si", "di"})
-mkrmap("b", "Rb", {"al", "cl", "dl", "bl", "ah", "ch", "dh", "bh"})
-map_reg_valid_index[map_archdef.esp] = false
-if x64 then map_reg_valid_index[map_archdef.rsp] = false end
-map_archdef["Ra"] = "@"..addrsize
-
--- FP registers (internally tword sized, but use "f" as operand size).
-mkrmap("f", "Rf")
-
--- SSE registers (oword sized, but qword and dword accessible).
-mkrmap("o", "xmm")
-
--- Operand size prefixes to codes.
-local map_opsize = {
- byte = "b", word = "w", dword = "d", qword = "q", oword = "o", tword = "t",
- aword = addrsize,
-}
-
--- Operand size code to number.
-local map_opsizenum = {
- b = 1, w = 2, d = 4, q = 8, o = 16, t = 10,
-}
-
--- Operand size code to name.
-local map_opsizename = {
- b = "byte", w = "word", d = "dword", q = "qword", o = "oword", t = "tword",
- f = "fpword",
-}
-
--- Valid index register scale factors.
-local map_xsc = {
- ["1"] = 0, ["2"] = 1, ["4"] = 2, ["8"] = 3,
-}
-
--- Condition codes.
-local map_cc = {
- o = 0, no = 1, b = 2, nb = 3, e = 4, ne = 5, be = 6, nbe = 7,
- s = 8, ns = 9, p = 10, np = 11, l = 12, nl = 13, le = 14, nle = 15,
- c = 2, nae = 2, nc = 3, ae = 3, z = 4, nz = 5, na = 6, a = 7,
- pe = 10, po = 11, nge = 12, ge = 13, ng = 14, g = 15,
-}
-
-
--- Reverse defines for registers.
-function _M.revdef(s)
- return gsub(s, "@%w+", map_reg_rev)
-end
-
--- Dump register names and numbers
-local function dumpregs(out)
- out:write("Register names, sizes and internal numbers:\n")
- for _,reg in ipairs(reg_list) do
- if reg == "" then
- out:write("\n")
- else
- local name = map_reg_rev[reg]
- local num = map_reg_num[reg]
- local opsize = map_opsizename[map_reg_opsize[reg]]
- out:write(format(" %-5s %-8s %s\n", name, opsize,
- num < 0 and "(variable)" or num))
- end
- end
-end
-
-------------------------------------------------------------------------------
-
--- Put action for label arg (IMM_LG, IMM_PC, REL_LG, REL_PC).
-local function wputlabel(aprefix, imm, num)
- if type(imm) == "number" then
- if imm < 0 then
- waction("EXTERN")
- wputxb(aprefix == "IMM_" and 0 or 1)
- imm = -imm-1
- else
- waction(aprefix.."LG", nil, num);
- end
- wputxb(imm)
- else
- waction(aprefix.."PC", imm, num)
- end
-end
-
--- Put signed byte or arg.
-local function wputsbarg(n)
- if type(n) == "number" then
- if n < -128 or n > 127 then
- werror("signed immediate byte out of range")
- end
- if n < 0 then n = n + 256 end
- wputb(n)
- else waction("IMM_S", n) end
-end
-
--- Put unsigned byte or arg.
-local function wputbarg(n)
- if type(n) == "number" then
- if n < 0 or n > 255 then
- werror("unsigned immediate byte out of range")
- end
- wputb(n)
- else waction("IMM_B", n) end
-end
-
--- Put unsigned word or arg.
-local function wputwarg(n)
- if type(n) == "number" then
- if n < 0 or n > 65535 then
- werror("unsigned immediate word out of range")
- end
- local r = n%256; n = (n-r)/256; wputb(r); wputb(n);
- else waction("IMM_W", n) end
-end
-
--- Put signed or unsigned dword or arg.
-local function wputdarg(n)
- local tn = type(n)
- if tn == "number" then
- if n < 0 then n = n + 4294967296 end
- local r = n%256; n = (n-r)/256; wputb(r);
- r = n%256; n = (n-r)/256; wputb(r);
- r = n%256; n = (n-r)/256; wputb(r); wputb(n);
- elseif tn == "table" then
- wputlabel("IMM_", n[1], 1)
- else
- waction("IMM_D", n)
- end
-end
-
--- Put operand-size dependent number or arg (defaults to dword).
-local function wputszarg(sz, n)
- if not sz or sz == "d" or sz == "q" then wputdarg(n)
- elseif sz == "w" then wputwarg(n)
- elseif sz == "b" then wputbarg(n)
- elseif sz == "s" then wputsbarg(n)
- else werror("bad operand size") end
-end
-
--- Put multi-byte opcode with operand-size dependent modifications.
-local function wputop(sz, op, rex)
- local r
- if rex ~= 0 and not x64 then werror("bad operand size") end
- if sz == "w" then wputb(102) end
- -- Needs >32 bit numbers, but only for crc32 eax, word [ebx]
- if op >= 4294967296 then r = op%4294967296 wputb((op-r)/4294967296) op = r end
- if op >= 16777216 then r = op % 16777216 wputb((op-r) / 16777216) op = r end
- if op >= 65536 then
- if rex ~= 0 then
- local opc3 = op - op % 256
- if opc3 == 0x0f3a00 or opc3 == 0x0f3800 then
- wputb(64 + rex % 16); rex = 0
- end
- end
- r = op % 65536 wputb((op-r) / 65536) op = r
- end
- if op >= 256 then
- r = op % 256
- local b = (op-r) / 256
- if b == 15 and rex ~= 0 then wputb(64 + rex % 16); rex = 0 end
- wputb(b)
- op = r
- end
- if rex ~= 0 then wputb(64 + rex % 16) end
- if sz == "b" then op = op - 1 end
- wputb(op)
-end
-
--- Put ModRM or SIB formatted byte.
-local function wputmodrm(m, s, rm, vs, vrm)
- assert(m < 4 and s < 16 and rm < 16, "bad modrm operands")
- wputb(64*m + 8*(s%8) + (rm%8))
-end
-
--- Put ModRM/SIB plus optional displacement.
-local function wputmrmsib(t, imark, s, vsreg)
- local vreg, vxreg
- local reg, xreg = t.reg, t.xreg
- if reg and reg < 0 then reg = 0; vreg = t.vreg end
- if xreg and xreg < 0 then xreg = 0; vxreg = t.vxreg end
- if s < 0 then s = 0 end
-
- -- Register mode.
- if sub(t.mode, 1, 1) == "r" then
- wputmodrm(3, s, reg)
- if vsreg then waction("VREG", vsreg); wputxb(2) end
- if vreg then waction("VREG", vreg); wputxb(0) end
- return
- end
-
- local disp = t.disp
- local tdisp = type(disp)
- -- No base register?
- if not reg then
- local riprel = false
- if xreg then
- -- Indexed mode with index register only.
- -- [xreg*xsc+disp] -> (0, s, esp) (xsc, xreg, ebp)
- wputmodrm(0, s, 4)
- if imark == "I" then waction("MARK") end
- if vsreg then waction("VREG", vsreg); wputxb(2) end
- wputmodrm(t.xsc, xreg, 5)
- if vxreg then waction("VREG", vxreg); wputxb(3) end
- else
- -- Pure 32 bit displacement.
- if x64 and tdisp ~= "table" then
- wputmodrm(0, s, 4) -- [disp] -> (0, s, esp) (0, esp, ebp)
- if imark == "I" then waction("MARK") end
- wputmodrm(0, 4, 5)
- else
- riprel = x64
- wputmodrm(0, s, 5) -- [disp|rip-label] -> (0, s, ebp)
- if imark == "I" then waction("MARK") end
- end
- if vsreg then waction("VREG", vsreg); wputxb(2) end
- end
- if riprel then -- Emit rip-relative displacement.
- if match("UWSiI", imark) then
- werror("NYI: rip-relative displacement followed by immediate")
- end
- -- The previous byte in the action buffer cannot be 0xe9 or 0x80-0x8f.
- wputlabel("REL_", disp[1], 2)
- else
- wputdarg(disp)
- end
- return
- end
-
- local m
- if tdisp == "number" then -- Check displacement size at assembly time.
- if disp == 0 and (reg%8) ~= 5 then -- [ebp] -> [ebp+0] (in SIB, too)
- if not vreg then m = 0 end -- Force DISP to allow [Rd(5)] -> [ebp+0]
- elseif disp >= -128 and disp <= 127 then m = 1
- else m = 2 end
- elseif tdisp == "table" then
- m = 2
- end
-
- -- Index register present or esp as base register: need SIB encoding.
- if xreg or (reg%8) == 4 then
- wputmodrm(m or 2, s, 4) -- ModRM.
- if m == nil or imark == "I" then waction("MARK") end
- if vsreg then waction("VREG", vsreg); wputxb(2) end
- wputmodrm(t.xsc or 0, xreg or 4, reg) -- SIB.
- if vxreg then waction("VREG", vxreg); wputxb(3) end
- if vreg then waction("VREG", vreg); wputxb(1) end
- else
- wputmodrm(m or 2, s, reg) -- ModRM.
- if (imark == "I" and (m == 1 or m == 2)) or
- (m == nil and (vsreg or vreg)) then waction("MARK") end
- if vsreg then waction("VREG", vsreg); wputxb(2) end
- if vreg then waction("VREG", vreg); wputxb(1) end
- end
-
- -- Put displacement.
- if m == 1 then wputsbarg(disp)
- elseif m == 2 then wputdarg(disp)
- elseif m == nil then waction("DISP", disp) end
-end
-
-------------------------------------------------------------------------------
-
--- Return human-readable operand mode string.
-local function opmodestr(op, args)
- local m = {}
- for i=1,#args do
- local a = args[i]
- m[#m+1] = sub(a.mode, 1, 1)..(a.opsize or "?")
- end
- return op.." "..concat(m, ",")
-end
-
--- Convert number to valid integer or nil.
-local function toint(expr)
- local n = tonumber(expr)
- if n then
- if n % 1 ~= 0 or n < -2147483648 or n > 4294967295 then
- werror("bad integer number `"..expr.."'")
- end
- return n
- end
-end
-
--- Parse immediate expression.
-local function immexpr(expr)
- -- &expr (pointer)
- if sub(expr, 1, 1) == "&" then
- return "iPJ", format("(ptrdiff_t)(%s)", sub(expr,2))
- end
-
- local prefix = sub(expr, 1, 2)
- -- =>expr (pc label reference)
- if prefix == "=>" then
- return "iJ", sub(expr, 3)
- end
- -- ->name (global label reference)
- if prefix == "->" then
- return "iJ", map_global[sub(expr, 3)]
- end
-
- -- [<>][1-9] (local label reference)
- local dir, lnum = match(expr, "^([<>])([1-9])$")
- if dir then -- Fwd: 247-255, Bkwd: 1-9.
- return "iJ", lnum + (dir == ">" and 246 or 0)
- end
-
- local extname = match(expr, "^extern%s+(%S+)$")
- if extname then
- return "iJ", map_extern[extname]
- end
-
- -- expr (interpreted as immediate)
- return "iI", expr
-end
-
--- Parse displacement expression: +-num, +-expr, +-opsize*num
-local function dispexpr(expr)
- local disp = expr == "" and 0 or toint(expr)
- if disp then return disp end
- local c, dispt = match(expr, "^([+-])%s*(.+)$")
- if c == "+" then
- expr = dispt
- elseif not c then
- werror("bad displacement expression `"..expr.."'")
- end
- local opsize, tailops = match(dispt, "^(%w+)%s*%*%s*(.+)$")
- local ops, imm = map_opsize[opsize], toint(tailops)
- if ops and imm then
- if c == "-" then imm = -imm end
- return imm*map_opsizenum[ops]
- end
- local mode, iexpr = immexpr(dispt)
- if mode == "iJ" then
- if c == "-" then werror("cannot invert label reference") end
- return { iexpr }
- end
- return expr -- Need to return original signed expression.
-end
-
--- Parse register or type expression.
-local function rtexpr(expr)
- if not expr then return end
- local tname, ovreg = match(expr, "^([%w_]+):(@[%w_]+)$")
- local tp = map_type[tname or expr]
- if tp then
- local reg = ovreg or tp.reg
- local rnum = map_reg_num[reg]
- if not rnum then
- werror("type `"..(tname or expr).."' needs a register override")
- end
- if not map_reg_valid_base[reg] then
- werror("bad base register override `"..(map_reg_rev[reg] or reg).."'")
- end
- return reg, rnum, tp
- end
- return expr, map_reg_num[expr]
-end
-
--- Parse operand and return { mode, opsize, reg, xreg, xsc, disp, imm }.
-local function parseoperand(param)
- local t = {}
-
- local expr = param
- local opsize, tailops = match(param, "^(%w+)%s*(.+)$")
- if opsize then
- t.opsize = map_opsize[opsize]
- if t.opsize then expr = tailops end
- end
-
- local br = match(expr, "^%[%s*(.-)%s*%]$")
- repeat
- if br then
- t.mode = "xm"
-
- -- [disp]
- t.disp = toint(br)
- if t.disp then
- t.mode = x64 and "xm" or "xmO"
- break
- end
-
- -- [reg...]
- local tp
- local reg, tailr = match(br, "^([@%w_:]+)%s*(.*)$")
- reg, t.reg, tp = rtexpr(reg)
- if not t.reg then
- -- [expr]
- t.mode = x64 and "xm" or "xmO"
- t.disp = dispexpr("+"..br)
- break
- end
-
- if t.reg == -1 then
- t.vreg, tailr = match(tailr, "^(%b())(.*)$")
- if not t.vreg then werror("bad variable register expression") end
- end
-
- -- [xreg*xsc] or [xreg*xsc+-disp] or [xreg*xsc+-expr]
- local xsc, tailsc = match(tailr, "^%*%s*([1248])%s*(.*)$")
- if xsc then
- if not map_reg_valid_index[reg] then
- werror("bad index register `"..map_reg_rev[reg].."'")
- end
- t.xsc = map_xsc[xsc]
- t.xreg = t.reg
- t.vxreg = t.vreg
- t.reg = nil
- t.vreg = nil
- t.disp = dispexpr(tailsc)
- break
- end
- if not map_reg_valid_base[reg] then
- werror("bad base register `"..map_reg_rev[reg].."'")
- end
-
- -- [reg] or [reg+-disp]
- t.disp = toint(tailr) or (tailr == "" and 0)
- if t.disp then break end
-
- -- [reg+xreg...]
- local xreg, tailx = match(tailr, "^+%s*([@%w_:]+)%s*(.*)$")
- xreg, t.xreg, tp = rtexpr(xreg)
- if not t.xreg then
- -- [reg+-expr]
- t.disp = dispexpr(tailr)
- break
- end
- if not map_reg_valid_index[xreg] then
- werror("bad index register `"..map_reg_rev[xreg].."'")
- end
-
- if t.xreg == -1 then
- t.vxreg, tailx = match(tailx, "^(%b())(.*)$")
- if not t.vxreg then werror("bad variable register expression") end
- end
-
- -- [reg+xreg*xsc...]
- local xsc, tailsc = match(tailx, "^%*%s*([1248])%s*(.*)$")
- if xsc then
- t.xsc = map_xsc[xsc]
- tailx = tailsc
- end
-
- -- [...] or [...+-disp] or [...+-expr]
- t.disp = dispexpr(tailx)
- else
- -- imm or opsize*imm
- local imm = toint(expr)
- if not imm and sub(expr, 1, 1) == "*" and t.opsize then
- imm = toint(sub(expr, 2))
- if imm then
- imm = imm * map_opsizenum[t.opsize]
- t.opsize = nil
- end
- end
- if imm then
- if t.opsize then werror("bad operand size override") end
- local m = "i"
- if imm == 1 then m = m.."1" end
- if imm >= 4294967168 and imm <= 4294967295 then imm = imm-4294967296 end
- if imm >= -128 and imm <= 127 then m = m.."S" end
- t.imm = imm
- t.mode = m
- break
- end
-
- local tp
- local reg, tailr = match(expr, "^([@%w_:]+)%s*(.*)$")
- reg, t.reg, tp = rtexpr(reg)
- if t.reg then
- if t.reg == -1 then
- t.vreg, tailr = match(tailr, "^(%b())(.*)$")
- if not t.vreg then werror("bad variable register expression") end
- end
- -- reg
- if tailr == "" then
- if t.opsize then werror("bad operand size override") end
- t.opsize = map_reg_opsize[reg]
- if t.opsize == "f" then
- t.mode = t.reg == 0 and "fF" or "f"
- else
- if reg == "@w4" or (x64 and reg == "@d4") then
- wwarn("bad idea, try again with `"..(x64 and "rsp'" or "esp'"))
- end
- t.mode = t.reg == 0 and "rmR" or (reg == "@b1" and "rmC" or "rm")
- end
- t.needrex = map_reg_needrex[reg]
- break
- end
-
- -- type[idx], type[idx].field, type->field -> [reg+offset_expr]
- if not tp then werror("bad operand `"..param.."'") end
- t.mode = "xm"
- t.disp = format(tp.ctypefmt, tailr)
- else
- t.mode, t.imm = immexpr(expr)
- if sub(t.mode, -1) == "J" then
- if t.opsize and t.opsize ~= addrsize then
- werror("bad operand size override")
- end
- t.opsize = addrsize
- end
- end
- end
- until true
- return t
-end
-
-------------------------------------------------------------------------------
--- x86 Template String Description
--- ===============================
---
--- Each template string is a list of [match:]pattern pairs,
--- separated by "|". The first match wins. No match means a
--- bad or unsupported combination of operand modes or sizes.
---
--- The match part and the ":" is omitted if the operation has
--- no operands. Otherwise the first N characters are matched
--- against the mode strings of each of the N operands.
---
--- The mode string for each operand type is (see parseoperand()):
--- Integer register: "rm", +"R" for eax, ax, al, +"C" for cl
--- FP register: "f", +"F" for st0
--- Index operand: "xm", +"O" for [disp] (pure offset)
--- Immediate: "i", +"S" for signed 8 bit, +"1" for 1,
--- +"I" for arg, +"P" for pointer
--- Any: +"J" for valid jump targets
---
--- So a match character "m" (mixed) matches both an integer register
--- and an index operand (to be encoded with the ModRM/SIB scheme).
--- But "r" matches only a register and "x" only an index operand
--- (e.g. for FP memory access operations).
---
--- The operand size match string starts right after the mode match
--- characters and ends before the ":". "dwb" or "qdwb" is assumed, if empty.
--- The effective data size of the operation is matched against this list.
---
--- If only the regular "b", "w", "d", "q", "t" operand sizes are
--- present, then all operands must be the same size. Unspecified sizes
--- are ignored, but at least one operand must have a size or the pattern
--- won't match (use the "byte", "word", "dword", "qword", "tword"
--- operand size overrides. E.g.: mov dword [eax], 1).
---
--- If the list has a "1" or "2" prefix, the operand size is taken
--- from the respective operand and any other operand sizes are ignored.
--- If the list contains only ".", all operand sizes are ignored.
--- If the list has a "/" prefix, the concatenated (mixed) operand sizes
--- are compared to the match.
---
--- E.g. "rrdw" matches for either two dword registers or two word
--- registers. "Fx2dq" matches an st0 operand plus an index operand
--- pointing to a dword (float) or qword (double).
---
--- Every character after the ":" is part of the pattern string:
--- Hex chars are accumulated to form the opcode (left to right).
--- "n" disables the standard opcode mods
--- (otherwise: -1 for "b", o16 prefix for "w", rex.w for "q")
--- "X" Force REX.W.
--- "r"/"R" adds the reg. number from the 1st/2nd operand to the opcode.
--- "m"/"M" generates ModRM/SIB from the 1st/2nd operand.
--- The spare 3 bits are either filled with the last hex digit or
--- the result from a previous "r"/"R". The opcode is restored.
---
--- All of the following characters force a flush of the opcode:
--- "o"/"O" stores a pure 32 bit disp (offset) from the 1st/2nd operand.
--- "S" stores a signed 8 bit immediate from the last operand.
--- "U" stores an unsigned 8 bit immediate from the last operand.
--- "W" stores an unsigned 16 bit immediate from the last operand.
--- "i" stores an operand sized immediate from the last operand.
--- "I" dito, but generates an action code to optionally modify
--- the opcode (+2) for a signed 8 bit immediate.
--- "J" generates one of the REL action codes from the last operand.
---
-------------------------------------------------------------------------------
-
--- Template strings for x86 instructions. Ordered by first opcode byte.
--- Unimplemented opcodes (deliberate omissions) are marked with *.
-local map_op = {
- -- 00-05: add...
- -- 06: *push es
- -- 07: *pop es
- -- 08-0D: or...
- -- 0E: *push cs
- -- 0F: two byte opcode prefix
- -- 10-15: adc...
- -- 16: *push ss
- -- 17: *pop ss
- -- 18-1D: sbb...
- -- 1E: *push ds
- -- 1F: *pop ds
- -- 20-25: and...
- es_0 = "26",
- -- 27: *daa
- -- 28-2D: sub...
- cs_0 = "2E",
- -- 2F: *das
- -- 30-35: xor...
- ss_0 = "36",
- -- 37: *aaa
- -- 38-3D: cmp...
- ds_0 = "3E",
- -- 3F: *aas
- inc_1 = x64 and "m:FF0m" or "rdw:40r|m:FF0m",
- dec_1 = x64 and "m:FF1m" or "rdw:48r|m:FF1m",
- push_1 = (x64 and "rq:n50r|rw:50r|mq:nFF6m|mw:FF6m" or
- "rdw:50r|mdw:FF6m").."|S.:6AS|ib:n6Ai|i.:68i",
- pop_1 = x64 and "rq:n58r|rw:58r|mq:n8F0m|mw:8F0m" or "rdw:58r|mdw:8F0m",
- -- 60: *pusha, *pushad, *pushaw
- -- 61: *popa, *popad, *popaw
- -- 62: *bound rdw,x
- -- 63: x86: *arpl mw,rw
- movsxd_2 = x64 and "rm/qd:63rM",
- fs_0 = "64",
- gs_0 = "65",
- o16_0 = "66",
- a16_0 = not x64 and "67" or nil,
- a32_0 = x64 and "67",
- -- 68: push idw
- -- 69: imul rdw,mdw,idw
- -- 6A: push ib
- -- 6B: imul rdw,mdw,S
- -- 6C: *insb
- -- 6D: *insd, *insw
- -- 6E: *outsb
- -- 6F: *outsd, *outsw
- -- 70-7F: jcc lb
- -- 80: add... mb,i
- -- 81: add... mdw,i
- -- 82: *undefined
- -- 83: add... mdw,S
- test_2 = "mr:85Rm|rm:85rM|Ri:A9ri|mi:F70mi",
- -- 86: xchg rb,mb
- -- 87: xchg rdw,mdw
- -- 88: mov mb,r
- -- 89: mov mdw,r
- -- 8A: mov r,mb
- -- 8B: mov r,mdw
- -- 8C: *mov mdw,seg
- lea_2 = "rx1dq:8DrM",
- -- 8E: *mov seg,mdw
- -- 8F: pop mdw
- nop_0 = "90",
- xchg_2 = "Rrqdw:90R|rRqdw:90r|rm:87rM|mr:87Rm",
- cbw_0 = "6698",
- cwde_0 = "98",
- cdqe_0 = "4898",
- cwd_0 = "6699",
- cdq_0 = "99",
- cqo_0 = "4899",
- -- 9A: *call iw:idw
- wait_0 = "9B",
- fwait_0 = "9B",
- pushf_0 = "9C",
- pushfd_0 = not x64 and "9C",
- pushfq_0 = x64 and "9C",
- popf_0 = "9D",
- popfd_0 = not x64 and "9D",
- popfq_0 = x64 and "9D",
- sahf_0 = "9E",
- lahf_0 = "9F",
- mov_2 = "OR:A3o|RO:A1O|mr:89Rm|rm:8BrM|rib:nB0ri|ridw:B8ri|mi:C70mi",
- movsb_0 = "A4",
- movsw_0 = "66A5",
- movsd_0 = "A5",
- cmpsb_0 = "A6",
- cmpsw_0 = "66A7",
- cmpsd_0 = "A7",
- -- A8: test Rb,i
- -- A9: test Rdw,i
- stosb_0 = "AA",
- stosw_0 = "66AB",
- stosd_0 = "AB",
- lodsb_0 = "AC",
- lodsw_0 = "66AD",
- lodsd_0 = "AD",
- scasb_0 = "AE",
- scasw_0 = "66AF",
- scasd_0 = "AF",
- -- B0-B7: mov rb,i
- -- B8-BF: mov rdw,i
- -- C0: rol... mb,i
- -- C1: rol... mdw,i
- ret_1 = "i.:nC2W",
- ret_0 = "C3",
- -- C4: *les rdw,mq
- -- C5: *lds rdw,mq
- -- C6: mov mb,i
- -- C7: mov mdw,i
- -- C8: *enter iw,ib
- leave_0 = "C9",
- -- CA: *retf iw
- -- CB: *retf
- int3_0 = "CC",
- int_1 = "i.:nCDU",
- into_0 = "CE",
- -- CF: *iret
- -- D0: rol... mb,1
- -- D1: rol... mdw,1
- -- D2: rol... mb,cl
- -- D3: rol... mb,cl
- -- D4: *aam ib
- -- D5: *aad ib
- -- D6: *salc
- -- D7: *xlat
- -- D8-DF: floating point ops
- -- E0: *loopne
- -- E1: *loope
- -- E2: *loop
- -- E3: *jcxz, *jecxz
- -- E4: *in Rb,ib
- -- E5: *in Rdw,ib
- -- E6: *out ib,Rb
- -- E7: *out ib,Rdw
- call_1 = x64 and "mq:nFF2m|J.:E8nJ" or "md:FF2m|J.:E8J",
- jmp_1 = x64 and "mq:nFF4m|J.:E9nJ" or "md:FF4m|J.:E9J", -- short: EB
- -- EA: *jmp iw:idw
- -- EB: jmp ib
- -- EC: *in Rb,dx
- -- ED: *in Rdw,dx
- -- EE: *out dx,Rb
- -- EF: *out dx,Rdw
- -- F0: *lock
- int1_0 = "F1",
- repne_0 = "F2",
- repnz_0 = "F2",
- rep_0 = "F3",
- repe_0 = "F3",
- repz_0 = "F3",
- -- F4: *hlt
- cmc_0 = "F5",
- -- F6: test... mb,i; div... mb
- -- F7: test... mdw,i; div... mdw
- clc_0 = "F8",
- stc_0 = "F9",
- -- FA: *cli
- cld_0 = "FC",
- std_0 = "FD",
- -- FE: inc... mb
- -- FF: inc... mdw
-
- -- misc ops
- not_1 = "m:F72m",
- neg_1 = "m:F73m",
- mul_1 = "m:F74m",
- imul_1 = "m:F75m",
- div_1 = "m:F76m",
- idiv_1 = "m:F77m",
-
- imul_2 = "rmqdw:0FAFrM|rIqdw:69rmI|rSqdw:6BrmS|riqdw:69rmi",
- imul_3 = "rmIqdw:69rMI|rmSqdw:6BrMS|rmiqdw:69rMi",
-
- movzx_2 = "rm/db:0FB6rM|rm/qb:|rm/wb:0FB6rM|rm/dw:0FB7rM|rm/qw:",
- movsx_2 = "rm/db:0FBErM|rm/qb:|rm/wb:0FBErM|rm/dw:0FBFrM|rm/qw:",
-
- bswap_1 = "rqd:0FC8r",
- bsf_2 = "rmqdw:0FBCrM",
- bsr_2 = "rmqdw:0FBDrM",
- bt_2 = "mrqdw:0FA3Rm|miqdw:0FBA4mU",
- btc_2 = "mrqdw:0FBBRm|miqdw:0FBA7mU",
- btr_2 = "mrqdw:0FB3Rm|miqdw:0FBA6mU",
- bts_2 = "mrqdw:0FABRm|miqdw:0FBA5mU",
-
- rdtsc_0 = "0F31", -- P1+
- cpuid_0 = "0FA2", -- P1+
-
- -- floating point ops
- fst_1 = "ff:DDD0r|xd:D92m|xq:nDD2m",
- fstp_1 = "ff:DDD8r|xd:D93m|xq:nDD3m|xt:DB7m",
- fld_1 = "ff:D9C0r|xd:D90m|xq:nDD0m|xt:DB5m",
-
- fpop_0 = "DDD8", -- Alias for fstp st0.
-
- fist_1 = "xw:nDF2m|xd:DB2m",
- fistp_1 = "xw:nDF3m|xd:DB3m|xq:nDF7m",
- fild_1 = "xw:nDF0m|xd:DB0m|xq:nDF5m",
-
- fxch_0 = "D9C9",
- fxch_1 = "ff:D9C8r",
- fxch_2 = "fFf:D9C8r|Fff:D9C8R",
-
- fucom_1 = "ff:DDE0r",
- fucom_2 = "Fff:DDE0R",
- fucomp_1 = "ff:DDE8r",
- fucomp_2 = "Fff:DDE8R",
- fucomi_1 = "ff:DBE8r", -- P6+
- fucomi_2 = "Fff:DBE8R", -- P6+
- fucomip_1 = "ff:DFE8r", -- P6+
- fucomip_2 = "Fff:DFE8R", -- P6+
- fcomi_1 = "ff:DBF0r", -- P6+
- fcomi_2 = "Fff:DBF0R", -- P6+
- fcomip_1 = "ff:DFF0r", -- P6+
- fcomip_2 = "Fff:DFF0R", -- P6+
- fucompp_0 = "DAE9",
- fcompp_0 = "DED9",
-
- fldcw_1 = "xw:nD95m",
- fstcw_1 = "xw:n9BD97m",
- fnstcw_1 = "xw:nD97m",
- fstsw_1 = "Rw:n9BDFE0|xw:n9BDD7m",
- fnstsw_1 = "Rw:nDFE0|xw:nDD7m",
- fclex_0 = "9BDBE2",
- fnclex_0 = "DBE2",
-
- fnop_0 = "D9D0",
- -- D9D1-D9DF: unassigned
-
- fchs_0 = "D9E0",
- fabs_0 = "D9E1",
- -- D9E2: unassigned
- -- D9E3: unassigned
- ftst_0 = "D9E4",
- fxam_0 = "D9E5",
- -- D9E6: unassigned
- -- D9E7: unassigned
- fld1_0 = "D9E8",
- fldl2t_0 = "D9E9",
- fldl2e_0 = "D9EA",
- fldpi_0 = "D9EB",
- fldlg2_0 = "D9EC",
- fldln2_0 = "D9ED",
- fldz_0 = "D9EE",
- -- D9EF: unassigned
-
- f2xm1_0 = "D9F0",
- fyl2x_0 = "D9F1",
- fptan_0 = "D9F2",
- fpatan_0 = "D9F3",
- fxtract_0 = "D9F4",
- fprem1_0 = "D9F5",
- fdecstp_0 = "D9F6",
- fincstp_0 = "D9F7",
- fprem_0 = "D9F8",
- fyl2xp1_0 = "D9F9",
- fsqrt_0 = "D9FA",
- fsincos_0 = "D9FB",
- frndint_0 = "D9FC",
- fscale_0 = "D9FD",
- fsin_0 = "D9FE",
- fcos_0 = "D9FF",
-
- -- SSE, SSE2
- andnpd_2 = "rmo:660F55rM",
- andnps_2 = "rmo:0F55rM",
- andpd_2 = "rmo:660F54rM",
- andps_2 = "rmo:0F54rM",
- clflush_1 = "x.:0FAE7m",
- cmppd_3 = "rmio:660FC2rMU",
- cmpps_3 = "rmio:0FC2rMU",
- cmpsd_3 = "rrio:F20FC2rMU|rxi/oq:",
- cmpss_3 = "rrio:F30FC2rMU|rxi/od:",
- comisd_2 = "rro:660F2FrM|rx/oq:",
- comiss_2 = "rro:0F2FrM|rx/od:",
- cvtdq2pd_2 = "rro:F30FE6rM|rx/oq:",
- cvtdq2ps_2 = "rmo:0F5BrM",
- cvtpd2dq_2 = "rmo:F20FE6rM",
- cvtpd2ps_2 = "rmo:660F5ArM",
- cvtpi2pd_2 = "rx/oq:660F2ArM",
- cvtpi2ps_2 = "rx/oq:0F2ArM",
- cvtps2dq_2 = "rmo:660F5BrM",
- cvtps2pd_2 = "rro:0F5ArM|rx/oq:",
- cvtsd2si_2 = "rr/do:F20F2DrM|rr/qo:|rx/dq:|rxq:",
- cvtsd2ss_2 = "rro:F20F5ArM|rx/oq:",
- cvtsi2sd_2 = "rm/od:F20F2ArM|rm/oq:F20F2ArXM",
- cvtsi2ss_2 = "rm/od:F30F2ArM|rm/oq:F30F2ArXM",
- cvtss2sd_2 = "rro:F30F5ArM|rx/od:",
- cvtss2si_2 = "rr/do:F20F2CrM|rr/qo:|rxd:|rx/qd:",
- cvttpd2dq_2 = "rmo:660FE6rM",
- cvttps2dq_2 = "rmo:F30F5BrM",
- cvttsd2si_2 = "rr/do:F20F2CrM|rr/qo:|rx/dq:|rxq:",
- cvttss2si_2 = "rr/do:F30F2CrM|rr/qo:|rxd:|rx/qd:",
- ldmxcsr_1 = "xd:0FAE2m",
- lfence_0 = "0FAEE8",
- maskmovdqu_2 = "rro:660FF7rM",
- mfence_0 = "0FAEF0",
- movapd_2 = "rmo:660F28rM|mro:660F29Rm",
- movaps_2 = "rmo:0F28rM|mro:0F29Rm",
- movd_2 = "rm/od:660F6ErM|rm/oq:660F6ErXM|mr/do:660F7ERm|mr/qo:",
- movdqa_2 = "rmo:660F6FrM|mro:660F7FRm",
- movdqu_2 = "rmo:F30F6FrM|mro:F30F7FRm",
- movhlps_2 = "rro:0F12rM",
- movhpd_2 = "rx/oq:660F16rM|xr/qo:n660F17Rm",
- movhps_2 = "rx/oq:0F16rM|xr/qo:n0F17Rm",
- movlhps_2 = "rro:0F16rM",
- movlpd_2 = "rx/oq:660F12rM|xr/qo:n660F13Rm",
- movlps_2 = "rx/oq:0F12rM|xr/qo:n0F13Rm",
- movmskpd_2 = "rr/do:660F50rM",
- movmskps_2 = "rr/do:0F50rM",
- movntdq_2 = "xro:660FE7Rm",
- movnti_2 = "xrqd:0FC3Rm",
- movntpd_2 = "xro:660F2BRm",
- movntps_2 = "xro:0F2BRm",
- movq_2 = "rro:F30F7ErM|rx/oq:|xr/qo:n660FD6Rm",
- movsd_2 = "rro:F20F10rM|rx/oq:|xr/qo:nF20F11Rm",
- movss_2 = "rro:F30F10rM|rx/od:|xr/do:F30F11Rm",
- movupd_2 = "rmo:660F10rM|mro:660F11Rm",
- movups_2 = "rmo:0F10rM|mro:0F11Rm",
- orpd_2 = "rmo:660F56rM",
- orps_2 = "rmo:0F56rM",
- packssdw_2 = "rmo:660F6BrM",
- packsswb_2 = "rmo:660F63rM",
- packuswb_2 = "rmo:660F67rM",
- paddb_2 = "rmo:660FFCrM",
- paddd_2 = "rmo:660FFErM",
- paddq_2 = "rmo:660FD4rM",
- paddsb_2 = "rmo:660FECrM",
- paddsw_2 = "rmo:660FEDrM",
- paddusb_2 = "rmo:660FDCrM",
- paddusw_2 = "rmo:660FDDrM",
- paddw_2 = "rmo:660FFDrM",
- pand_2 = "rmo:660FDBrM",
- pandn_2 = "rmo:660FDFrM",
- pause_0 = "F390",
- pavgb_2 = "rmo:660FE0rM",
- pavgw_2 = "rmo:660FE3rM",
- pcmpeqb_2 = "rmo:660F74rM",
- pcmpeqd_2 = "rmo:660F76rM",
- pcmpeqw_2 = "rmo:660F75rM",
- pcmpgtb_2 = "rmo:660F64rM",
- pcmpgtd_2 = "rmo:660F66rM",
- pcmpgtw_2 = "rmo:660F65rM",
- pextrw_3 = "rri/do:660FC5rMU|xri/wo:660F3A15nrMU", -- Mem op: SSE4.1 only.
- pinsrw_3 = "rri/od:660FC4rMU|rxi/ow:",
- pmaddwd_2 = "rmo:660FF5rM",
- pmaxsw_2 = "rmo:660FEErM",
- pmaxub_2 = "rmo:660FDErM",
- pminsw_2 = "rmo:660FEArM",
- pminub_2 = "rmo:660FDArM",
- pmovmskb_2 = "rr/do:660FD7rM",
- pmulhuw_2 = "rmo:660FE4rM",
- pmulhw_2 = "rmo:660FE5rM",
- pmullw_2 = "rmo:660FD5rM",
- pmuludq_2 = "rmo:660FF4rM",
- por_2 = "rmo:660FEBrM",
- prefetchnta_1 = "xb:n0F180m",
- prefetcht0_1 = "xb:n0F181m",
- prefetcht1_1 = "xb:n0F182m",
- prefetcht2_1 = "xb:n0F183m",
- psadbw_2 = "rmo:660FF6rM",
- pshufd_3 = "rmio:660F70rMU",
- pshufhw_3 = "rmio:F30F70rMU",
- pshuflw_3 = "rmio:F20F70rMU",
- pslld_2 = "rmo:660FF2rM|rio:660F726mU",
- pslldq_2 = "rio:660F737mU",
- psllq_2 = "rmo:660FF3rM|rio:660F736mU",
- psllw_2 = "rmo:660FF1rM|rio:660F716mU",
- psrad_2 = "rmo:660FE2rM|rio:660F724mU",
- psraw_2 = "rmo:660FE1rM|rio:660F714mU",
- psrld_2 = "rmo:660FD2rM|rio:660F722mU",
- psrldq_2 = "rio:660F733mU",
- psrlq_2 = "rmo:660FD3rM|rio:660F732mU",
- psrlw_2 = "rmo:660FD1rM|rio:660F712mU",
- psubb_2 = "rmo:660FF8rM",
- psubd_2 = "rmo:660FFArM",
- psubq_2 = "rmo:660FFBrM",
- psubsb_2 = "rmo:660FE8rM",
- psubsw_2 = "rmo:660FE9rM",
- psubusb_2 = "rmo:660FD8rM",
- psubusw_2 = "rmo:660FD9rM",
- psubw_2 = "rmo:660FF9rM",
- punpckhbw_2 = "rmo:660F68rM",
- punpckhdq_2 = "rmo:660F6ArM",
- punpckhqdq_2 = "rmo:660F6DrM",
- punpckhwd_2 = "rmo:660F69rM",
- punpcklbw_2 = "rmo:660F60rM",
- punpckldq_2 = "rmo:660F62rM",
- punpcklqdq_2 = "rmo:660F6CrM",
- punpcklwd_2 = "rmo:660F61rM",
- pxor_2 = "rmo:660FEFrM",
- rcpps_2 = "rmo:0F53rM",
- rcpss_2 = "rro:F30F53rM|rx/od:",
- rsqrtps_2 = "rmo:0F52rM",
- rsqrtss_2 = "rmo:F30F52rM",
- sfence_0 = "0FAEF8",
- shufpd_3 = "rmio:660FC6rMU",
- shufps_3 = "rmio:0FC6rMU",
- stmxcsr_1 = "xd:0FAE3m",
- ucomisd_2 = "rro:660F2ErM|rx/oq:",
- ucomiss_2 = "rro:0F2ErM|rx/od:",
- unpckhpd_2 = "rmo:660F15rM",
- unpckhps_2 = "rmo:0F15rM",
- unpcklpd_2 = "rmo:660F14rM",
- unpcklps_2 = "rmo:0F14rM",
- xorpd_2 = "rmo:660F57rM",
- xorps_2 = "rmo:0F57rM",
-
- -- SSE3 ops
- fisttp_1 = "xw:nDF1m|xd:DB1m|xq:nDD1m",
- addsubpd_2 = "rmo:660FD0rM",
- addsubps_2 = "rmo:F20FD0rM",
- haddpd_2 = "rmo:660F7CrM",
- haddps_2 = "rmo:F20F7CrM",
- hsubpd_2 = "rmo:660F7DrM",
- hsubps_2 = "rmo:F20F7DrM",
- lddqu_2 = "rxo:F20FF0rM",
- movddup_2 = "rmo:F20F12rM",
- movshdup_2 = "rmo:F30F16rM",
- movsldup_2 = "rmo:F30F12rM",
-
- -- SSSE3 ops
- pabsb_2 = "rmo:660F381CrM",
- pabsd_2 = "rmo:660F381ErM",
- pabsw_2 = "rmo:660F381DrM",
- palignr_3 = "rmio:660F3A0FrMU",
- phaddd_2 = "rmo:660F3802rM",
- phaddsw_2 = "rmo:660F3803rM",
- phaddw_2 = "rmo:660F3801rM",
- phsubd_2 = "rmo:660F3806rM",
- phsubsw_2 = "rmo:660F3807rM",
- phsubw_2 = "rmo:660F3805rM",
- pmaddubsw_2 = "rmo:660F3804rM",
- pmulhrsw_2 = "rmo:660F380BrM",
- pshufb_2 = "rmo:660F3800rM",
- psignb_2 = "rmo:660F3808rM",
- psignd_2 = "rmo:660F380ArM",
- psignw_2 = "rmo:660F3809rM",
-
- -- SSE4.1 ops
- blendpd_3 = "rmio:660F3A0DrMU",
- blendps_3 = "rmio:660F3A0CrMU",
- blendvpd_3 = "rmRo:660F3815rM",
- blendvps_3 = "rmRo:660F3814rM",
- dppd_3 = "rmio:660F3A41rMU",
- dpps_3 = "rmio:660F3A40rMU",
- extractps_3 = "mri/do:660F3A17RmU|rri/qo:660F3A17RXmU",
- insertps_3 = "rrio:660F3A41rMU|rxi/od:",
- movntdqa_2 = "rmo:660F382ArM",
- mpsadbw_3 = "rmio:660F3A42rMU",
- packusdw_2 = "rmo:660F382BrM",
- pblendvb_3 = "rmRo:660F3810rM",
- pblendw_3 = "rmio:660F3A0ErMU",
- pcmpeqq_2 = "rmo:660F3829rM",
- pextrb_3 = "rri/do:660F3A14nRmU|rri/qo:|xri/bo:",
- pextrd_3 = "mri/do:660F3A16RmU",
- pextrq_3 = "mri/qo:660F3A16RmU",
- -- pextrw is SSE2, mem operand is SSE4.1 only
- phminposuw_2 = "rmo:660F3841rM",
- pinsrb_3 = "rri/od:660F3A20nrMU|rxi/ob:",
- pinsrd_3 = "rmi/od:660F3A22rMU",
- pinsrq_3 = "rmi/oq:660F3A22rXMU",
- pmaxsb_2 = "rmo:660F383CrM",
- pmaxsd_2 = "rmo:660F383DrM",
- pmaxud_2 = "rmo:660F383FrM",
- pmaxuw_2 = "rmo:660F383ErM",
- pminsb_2 = "rmo:660F3838rM",
- pminsd_2 = "rmo:660F3839rM",
- pminud_2 = "rmo:660F383BrM",
- pminuw_2 = "rmo:660F383ArM",
- pmovsxbd_2 = "rro:660F3821rM|rx/od:",
- pmovsxbq_2 = "rro:660F3822rM|rx/ow:",
- pmovsxbw_2 = "rro:660F3820rM|rx/oq:",
- pmovsxdq_2 = "rro:660F3825rM|rx/oq:",
- pmovsxwd_2 = "rro:660F3823rM|rx/oq:",
- pmovsxwq_2 = "rro:660F3824rM|rx/od:",
- pmovzxbd_2 = "rro:660F3831rM|rx/od:",
- pmovzxbq_2 = "rro:660F3832rM|rx/ow:",
- pmovzxbw_2 = "rro:660F3830rM|rx/oq:",
- pmovzxdq_2 = "rro:660F3835rM|rx/oq:",
- pmovzxwd_2 = "rro:660F3833rM|rx/oq:",
- pmovzxwq_2 = "rro:660F3834rM|rx/od:",
- pmuldq_2 = "rmo:660F3828rM",
- pmulld_2 = "rmo:660F3840rM",
- ptest_2 = "rmo:660F3817rM",
- roundpd_3 = "rmio:660F3A09rMU",
- roundps_3 = "rmio:660F3A08rMU",
- roundsd_3 = "rrio:660F3A0BrMU|rxi/oq:",
- roundss_3 = "rrio:660F3A0ArMU|rxi/od:",
-
- -- SSE4.2 ops
- crc32_2 = "rmqd:F20F38F1rM|rm/dw:66F20F38F1rM|rm/db:F20F38F0rM|rm/qb:",
- pcmpestri_3 = "rmio:660F3A61rMU",
- pcmpestrm_3 = "rmio:660F3A60rMU",
- pcmpgtq_2 = "rmo:660F3837rM",
- pcmpistri_3 = "rmio:660F3A63rMU",
- pcmpistrm_3 = "rmio:660F3A62rMU",
- popcnt_2 = "rmqdw:F30FB8rM",
-
- -- SSE4a
- extrq_2 = "rro:660F79rM",
- extrq_3 = "riio:660F780mUU",
- insertq_2 = "rro:F20F79rM",
- insertq_4 = "rriio:F20F78rMUU",
- lzcnt_2 = "rmqdw:F30FBDrM",
- movntsd_2 = "xr/qo:nF20F2BRm",
- movntss_2 = "xr/do:F30F2BRm",
- -- popcnt is also in SSE4.2
-}
-
-------------------------------------------------------------------------------
-
--- Arithmetic ops.
-for name,n in pairs{ add = 0, ["or"] = 1, adc = 2, sbb = 3,
- ["and"] = 4, sub = 5, xor = 6, cmp = 7 } do
- local n8 = n * 8
- map_op[name.."_2"] = format(
- "mr:%02XRm|rm:%02XrM|mI1qdw:81%XmI|mS1qdw:83%XmS|Ri1qdwb:%02Xri|mi1qdwb:81%Xmi",
- 1+n8, 3+n8, n, n, 5+n8, n)
-end
-
--- Shift ops.
-for name,n in pairs{ rol = 0, ror = 1, rcl = 2, rcr = 3,
- shl = 4, shr = 5, sar = 7, sal = 4 } do
- map_op[name.."_2"] = format("m1:D1%Xm|mC1qdwb:D3%Xm|mi:C1%XmU", n, n, n)
-end
-
--- Conditional ops.
-for cc,n in pairs(map_cc) do
- map_op["j"..cc.."_1"] = format("J.:n0F8%XJ", n) -- short: 7%X
- map_op["set"..cc.."_1"] = format("mb:n0F9%X2m", n)
- map_op["cmov"..cc.."_2"] = format("rmqdw:0F4%XrM", n) -- P6+
-end
-
--- FP arithmetic ops.
-for name,n in pairs{ add = 0, mul = 1, com = 2, comp = 3,
- sub = 4, subr = 5, div = 6, divr = 7 } do
- local nc = 192 + n * 8
- local nr = nc + (n < 4 and 0 or (n % 2 == 0 and 8 or -8))
- local fn = "f"..name
- map_op[fn.."_1"] = format("ff:D8%02Xr|xd:D8%Xm|xq:nDC%Xm", nc, n, n)
- if n == 2 or n == 3 then
- map_op[fn.."_2"] = format("Fff:D8%02XR|Fx2d:D8%XM|Fx2q:nDC%XM", nc, n, n)
- else
- map_op[fn.."_2"] = format("Fff:D8%02XR|fFf:DC%02Xr|Fx2d:D8%XM|Fx2q:nDC%XM", nc, nr, n, n)
- map_op[fn.."p_1"] = format("ff:DE%02Xr", nr)
- map_op[fn.."p_2"] = format("fFf:DE%02Xr", nr)
- end
- map_op["fi"..name.."_1"] = format("xd:DA%Xm|xw:nDE%Xm", n, n)
-end
-
--- FP conditional moves.
-for cc,n in pairs{ b=0, e=1, be=2, u=3, nb=4, ne=5, nbe=6, nu=7 } do
- local n4 = n % 4
- local nc = 56000 + n4 * 8 + (n-n4) * 64
- map_op["fcmov"..cc.."_1"] = format("ff:%04Xr", nc) -- P6+
- map_op["fcmov"..cc.."_2"] = format("Fff:%04XR", nc) -- P6+
-end
-
--- SSE FP arithmetic ops.
-for name,n in pairs{ sqrt = 1, add = 8, mul = 9,
- sub = 12, min = 13, div = 14, max = 15 } do
- map_op[name.."ps_2"] = format("rmo:0F5%XrM", n)
- map_op[name.."ss_2"] = format("rro:F30F5%XrM|rx/od:", n)
- map_op[name.."pd_2"] = format("rmo:660F5%XrM", n)
- map_op[name.."sd_2"] = format("rro:F20F5%XrM|rx/oq:", n)
-end
-
-------------------------------------------------------------------------------
-
--- Process pattern string.
-local function dopattern(pat, args, sz, op, needrex)
- local digit, addin
- local opcode = 0
- local szov = sz
- local narg = 1
- local rex = 0
-
- -- Limit number of section buffer positions used by a single dasm_put().
- -- A single opcode needs a maximum of 5 positions.
- if secpos+5 > maxsecpos then wflush() end
-
- -- Process each character.
- for c in gmatch(pat.."|", ".") do
- if match(c, "%x") then -- Hex digit.
- digit = byte(c) - 48
- if digit > 48 then digit = digit - 39
- elseif digit > 16 then digit = digit - 7 end
- opcode = opcode*16 + digit
- addin = nil
- elseif c == "n" then -- Disable operand size mods for opcode.
- szov = nil
- elseif c == "X" then -- Force REX.W.
- rex = 8
- elseif c == "r" then -- Merge 1st operand regno. into opcode.
- addin = args[1]; opcode = opcode + (addin.reg % 8)
- if narg < 2 then narg = 2 end
- elseif c == "R" then -- Merge 2nd operand regno. into opcode.
- addin = args[2]; opcode = opcode + (addin.reg % 8)
- narg = 3
- elseif c == "m" or c == "M" then -- Encode ModRM/SIB.
- local s
- if addin then
- s = addin.reg
- opcode = opcode - (s%8) -- Undo regno opcode merge.
- else
- s = opcode % 16 -- Undo last digit.
- opcode = (opcode - s) / 16
- end
- local nn = c == "m" and 1 or 2
- local t = args[nn]
- if narg <= nn then narg = nn + 1 end
- if szov == "q" and rex == 0 then rex = rex + 8 end
- if t.reg and t.reg > 7 then rex = rex + 1 end
- if t.xreg and t.xreg > 7 then rex = rex + 2 end
- if s > 7 then rex = rex + 4 end
- if needrex then rex = rex + 16 end
- wputop(szov, opcode, rex); opcode = nil
- local imark = sub(pat, -1) -- Force a mark (ugly).
- -- Put ModRM/SIB with regno/last digit as spare.
- wputmrmsib(t, imark, s, addin and addin.vreg)
- addin = nil
- else
- if opcode then -- Flush opcode.
- if szov == "q" and rex == 0 then rex = rex + 8 end
- if needrex then rex = rex + 16 end
- if addin and addin.reg == -1 then
- wputop(szov, opcode - 7, rex)
- waction("VREG", addin.vreg); wputxb(0)
- else
- if addin and addin.reg > 7 then rex = rex + 1 end
- wputop(szov, opcode, rex)
- end
- opcode = nil
- end
- if c == "|" then break end
- if c == "o" then -- Offset (pure 32 bit displacement).
- wputdarg(args[1].disp); if narg < 2 then narg = 2 end
- elseif c == "O" then
- wputdarg(args[2].disp); narg = 3
- else
- -- Anything else is an immediate operand.
- local a = args[narg]
- narg = narg + 1
- local mode, imm = a.mode, a.imm
- if mode == "iJ" and not match("iIJ", c) then
- werror("bad operand size for label")
- end
- if c == "S" then
- wputsbarg(imm)
- elseif c == "U" then
- wputbarg(imm)
- elseif c == "W" then
- wputwarg(imm)
- elseif c == "i" or c == "I" then
- if mode == "iJ" then
- wputlabel("IMM_", imm, 1)
- elseif mode == "iI" and c == "I" then
- waction(sz == "w" and "IMM_WB" or "IMM_DB", imm)
- else
- wputszarg(sz, imm)
- end
- elseif c == "J" then
- if mode == "iPJ" then
- waction("REL_A", imm) -- !x64 (secpos)
- else
- wputlabel("REL_", imm, 2)
- end
- else
- werror("bad char `"..c.."' in pattern `"..pat.."' for `"..op.."'")
- end
- end
- end
- end
-end
-
-------------------------------------------------------------------------------
-
--- Mapping of operand modes to short names. Suppress output with '#'.
-local map_modename = {
- r = "reg", R = "eax", C = "cl", x = "mem", m = "mrm", i = "imm",
- f = "stx", F = "st0", J = "lbl", ["1"] = "1",
- I = "#", S = "#", O = "#",
-}
-
--- Return a table/string showing all possible operand modes.
-local function templatehelp(template, nparams)
- if nparams == 0 then return "" end
- local t = {}
- for tm in gmatch(template, "[^%|]+") do
- local s = map_modename[sub(tm, 1, 1)]
- s = s..gsub(sub(tm, 2, nparams), ".", function(c)
- return ", "..map_modename[c]
- end)
- if not match(s, "#") then t[#t+1] = s end
- end
- return t
-end
-
--- Match operand modes against mode match part of template.
-local function matchtm(tm, args)
- for i=1,#args do
- if not match(args[i].mode, sub(tm, i, i)) then return end
- end
- return true
-end
-
--- Handle opcodes defined with template strings.
-map_op[".template__"] = function(params, template, nparams)
- if not params then return templatehelp(template, nparams) end
- local args = {}
-
- -- Zero-operand opcodes have no match part.
- if #params == 0 then
- dopattern(template, args, "d", params.op, nil)
- return
- end
-
- -- Determine common operand size (coerce undefined size) or flag as mixed.
- local sz, szmix, needrex
- for i,p in ipairs(params) do
- args[i] = parseoperand(p)
- local nsz = args[i].opsize
- if nsz then
- if sz and sz ~= nsz then szmix = true else sz = nsz end
- end
- local nrex = args[i].needrex
- if nrex ~= nil then
- if needrex == nil then
- needrex = nrex
- elseif needrex ~= nrex then
- werror("bad mix of byte-addressable registers")
- end
- end
- end
-
- -- Try all match:pattern pairs (separated by '|').
- local gotmatch, lastpat
- for tm in gmatch(template, "[^%|]+") do
- -- Split off size match (starts after mode match) and pattern string.
- local szm, pat = match(tm, "^(.-):(.*)$", #args+1)
- if pat == "" then pat = lastpat else lastpat = pat end
- if matchtm(tm, args) then
- local prefix = sub(szm, 1, 1)
- if prefix == "/" then -- Match both operand sizes.
- if args[1].opsize == sub(szm, 2, 2) and
- args[2].opsize == sub(szm, 3, 3) then
- dopattern(pat, args, sz, params.op, needrex) -- Process pattern.
- return
- end
- else -- Match common operand size.
- local szp = sz
- if szm == "" then szm = x64 and "qdwb" or "dwb" end -- Default sizes.
- if prefix == "1" then szp = args[1].opsize; szmix = nil
- elseif prefix == "2" then szp = args[2].opsize; szmix = nil end
- if not szmix and (prefix == "." or match(szm, szp or "#")) then
- dopattern(pat, args, szp, params.op, needrex) -- Process pattern.
- return
- end
- end
- gotmatch = true
- end
- end
-
- local msg = "bad operand mode"
- if gotmatch then
- if szmix then
- msg = "mixed operand size"
- else
- msg = sz and "bad operand size" or "missing operand size"
- end
- end
-
- werror(msg.." in `"..opmodestr(params.op, args).."'")
-end
-
-------------------------------------------------------------------------------
-
--- x64-specific opcode for 64 bit immediates and displacements.
-if x64 then
- function map_op.mov64_2(params)
- if not params then return { "reg, imm", "reg, [disp]", "[disp], reg" } end
- if secpos+2 > maxsecpos then wflush() end
- local opcode, op64, sz, rex
- local op64 = match(params[1], "^%[%s*(.-)%s*%]$")
- if op64 then
- local a = parseoperand(params[2])
- if a.mode ~= "rmR" then werror("bad operand mode") end
- sz = a.opsize
- rex = sz == "q" and 8 or 0
- opcode = 0xa3
- else
- op64 = match(params[2], "^%[%s*(.-)%s*%]$")
- local a = parseoperand(params[1])
- if op64 then
- if a.mode ~= "rmR" then werror("bad operand mode") end
- sz = a.opsize
- rex = sz == "q" and 8 or 0
- opcode = 0xa1
- else
- if sub(a.mode, 1, 1) ~= "r" or a.opsize ~= "q" then
- werror("bad operand mode")
- end
- op64 = params[2]
- opcode = 0xb8 + (a.reg%8) -- !x64: no VREG support.
- rex = a.reg > 7 and 9 or 8
- end
- end
- wputop(sz, opcode, rex)
- waction("IMM_D", format("(unsigned int)(%s)", op64))
- waction("IMM_D", format("(unsigned int)((%s)>>32)", op64))
- end
-end
-
-------------------------------------------------------------------------------
-
--- Pseudo-opcodes for data storage.
-local function op_data(params)
- if not params then return "imm..." end
- local sz = sub(params.op, 2, 2)
- if sz == "a" then sz = addrsize end
- for _,p in ipairs(params) do
- local a = parseoperand(p)
- if sub(a.mode, 1, 1) ~= "i" or (a.opsize and a.opsize ~= sz) then
- werror("bad mode or size in `"..p.."'")
- end
- if a.mode == "iJ" then
- wputlabel("IMM_", a.imm, 1)
- else
- wputszarg(sz, a.imm)
- end
- if secpos+2 > maxsecpos then wflush() end
- end
-end
-
-map_op[".byte_*"] = op_data
-map_op[".sbyte_*"] = op_data
-map_op[".word_*"] = op_data
-map_op[".dword_*"] = op_data
-map_op[".aword_*"] = op_data
-
-------------------------------------------------------------------------------
-
--- Pseudo-opcode to mark the position where the action list is to be emitted.
-map_op[".actionlist_1"] = function(params)
- if not params then return "cvar" end
- local name = params[1] -- No syntax check. You get to keep the pieces.
- wline(function(out) writeactions(out, name) end)
-end
-
--- Pseudo-opcode to mark the position where the global enum is to be emitted.
-map_op[".globals_1"] = function(params)
- if not params then return "prefix" end
- local prefix = params[1] -- No syntax check. You get to keep the pieces.
- wline(function(out) writeglobals(out, prefix) end)
-end
-
--- Pseudo-opcode to mark the position where the global names are to be emitted.
-map_op[".globalnames_1"] = function(params)
- if not params then return "cvar" end
- local name = params[1] -- No syntax check. You get to keep the pieces.
- wline(function(out) writeglobalnames(out, name) end)
-end
-
--- Pseudo-opcode to mark the position where the extern names are to be emitted.
-map_op[".externnames_1"] = function(params)
- if not params then return "cvar" end
- local name = params[1] -- No syntax check. You get to keep the pieces.
- wline(function(out) writeexternnames(out, name) end)
-end
-
-------------------------------------------------------------------------------
-
--- Label pseudo-opcode (converted from trailing colon form).
-map_op[".label_2"] = function(params)
- if not params then return "[1-9] | ->global | =>pcexpr [, addr]" end
- if secpos+2 > maxsecpos then wflush() end
- local a = parseoperand(params[1])
- local mode, imm = a.mode, a.imm
- if type(imm) == "number" and (mode == "iJ" or (imm >= 1 and imm <= 9)) then
- -- Local label (1: ... 9:) or global label (->global:).
- waction("LABEL_LG", nil, 1)
- wputxb(imm)
- elseif mode == "iJ" then
- -- PC label (=>pcexpr:).
- waction("LABEL_PC", imm)
- else
- werror("bad label definition")
- end
- -- SETLABEL must immediately follow LABEL_LG/LABEL_PC.
- local addr = params[2]
- if addr then
- local a = parseoperand(addr)
- if a.mode == "iPJ" then
- waction("SETLABEL", a.imm)
- else
- werror("bad label assignment")
- end
- end
-end
-map_op[".label_1"] = map_op[".label_2"]
-
-------------------------------------------------------------------------------
-
--- Alignment pseudo-opcode.
-map_op[".align_1"] = function(params)
- if not params then return "numpow2" end
- if secpos+1 > maxsecpos then wflush() end
- local align = tonumber(params[1]) or map_opsizenum[map_opsize[params[1]]]
- if align then
- local x = align
- -- Must be a power of 2 in the range (2 ... 256).
- for i=1,8 do
- x = x / 2
- if x == 1 then
- waction("ALIGN", nil, 1)
- wputxb(align-1) -- Action byte is 2**n-1.
- return
- end
- end
- end
- werror("bad alignment")
-end
-
--- Spacing pseudo-opcode.
-map_op[".space_2"] = function(params)
- if not params then return "num [, filler]" end
- if secpos+1 > maxsecpos then wflush() end
- waction("SPACE", params[1])
- local fill = params[2]
- if fill then
- fill = tonumber(fill)
- if not fill or fill < 0 or fill > 255 then werror("bad filler") end
- end
- wputxb(fill or 0)
-end
-map_op[".space_1"] = map_op[".space_2"]
-
-------------------------------------------------------------------------------
-
--- Pseudo-opcode for (primitive) type definitions (map to C types).
-map_op[".type_3"] = function(params, nparams)
- if not params then
- return nparams == 2 and "name, ctype" or "name, ctype, reg"
- end
- local name, ctype, reg = params[1], params[2], params[3]
- if not match(name, "^[%a_][%w_]*$") then
- werror("bad type name `"..name.."'")
- end
- local tp = map_type[name]
- if tp then
- werror("duplicate type `"..name.."'")
- end
- if reg and not map_reg_valid_base[reg] then
- werror("bad base register `"..(map_reg_rev[reg] or reg).."'")
- end
- -- Add #type to defines. A bit unclean to put it in map_archdef.
- map_archdef["#"..name] = "sizeof("..ctype..")"
- -- Add new type and emit shortcut define.
- local num = ctypenum + 1
- map_type[name] = {
- ctype = ctype,
- ctypefmt = format("Dt%X(%%s)", num),
- reg = reg,
- }
- wline(format("#define Dt%X(_V) (int)(ptrdiff_t)&(((%s *)0)_V)", num, ctype))
- ctypenum = num
-end
-map_op[".type_2"] = map_op[".type_3"]
-
--- Dump type definitions.
-local function dumptypes(out, lvl)
- local t = {}
- for name in pairs(map_type) do t[#t+1] = name end
- sort(t)
- out:write("Type definitions:\n")
- for _,name in ipairs(t) do
- local tp = map_type[name]
- local reg = tp.reg and map_reg_rev[tp.reg] or ""
- out:write(format(" %-20s %-20s %s\n", name, tp.ctype, reg))
- end
- out:write("\n")
-end
-
-------------------------------------------------------------------------------
-
--- Set the current section.
-function _M.section(num)
- waction("SECTION")
- wputxb(num)
- wflush(true) -- SECTION is a terminal action.
-end
-
-------------------------------------------------------------------------------
-
--- Dump architecture description.
-function _M.dumparch(out)
- out:write(format("DynASM %s version %s, released %s\n\n",
- _info.arch, _info.version, _info.release))
- dumpregs(out)
- dumpactions(out)
-end
-
--- Dump all user defined elements.
-function _M.dumpdef(out, lvl)
- dumptypes(out, lvl)
- dumpglobals(out, lvl)
- dumpexterns(out, lvl)
-end
-
-------------------------------------------------------------------------------
-
--- Pass callbacks from/to the DynASM core.
-function _M.passcb(wl, we, wf, ww)
- wline, werror, wfatal, wwarn = wl, we, wf, ww
- return wflush
-end
-
--- Setup the arch-specific module.
-function _M.setup(arch, opt)
- g_arch, g_opt = arch, opt
-end
-
--- Merge the core maps and the arch-specific maps.
-function _M.mergemaps(map_coreop, map_def)
- setmetatable(map_op, { __index = map_coreop })
- setmetatable(map_def, { __index = map_archdef })
- return map_op, map_def
-end
-
-return _M
-
-------------------------------------------------------------------------------
-
diff --git a/third_party/dynasm/dynasm.lua b/third_party/dynasm/dynasm.lua
deleted file mode 100644
index 2ef8164..0000000
--- a/third_party/dynasm/dynasm.lua
+++ /dev/null
@@ -1,1084 +0,0 @@
-------------------------------------------------------------------------------
--- DynASM. A dynamic assembler for code generation engines.
--- Originally designed and implemented for LuaJIT.
---
--- Copyright (C) 2005-2012 Mike Pall. All rights reserved.
--- See below for full copyright notice.
-------------------------------------------------------------------------------
-
--- Application information.
-local _info = {
- name = "DynASM",
- description = "A dynamic assembler for code generation engines",
- version = "1.3.0",
- vernum = 10300,
- release = "2011-05-05",
- author = "Mike Pall",
- url = "http://luajit.org/dynasm.html",
- license = "MIT",
- copyright = [[
-Copyright (C) 2005-2012 Mike Pall. All rights reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-[ MIT license: http://www.opensource.org/licenses/mit-license.php ]
-]],
-}
-
--- Cache library functions.
-local type, pairs, ipairs = type, pairs, ipairs
-local pcall, error, assert = pcall, error, assert
-local _s = string
-local sub, match, gmatch, gsub = _s.sub, _s.match, _s.gmatch, _s.gsub
-local format, rep, upper = _s.format, _s.rep, _s.upper
-local _t = table
-local insert, remove, concat, sort = _t.insert, _t.remove, _t.concat, _t.sort
-local exit = os.exit
-local io = io
-local stdin, stdout, stderr = io.stdin, io.stdout, io.stderr
-
-------------------------------------------------------------------------------
-
--- Program options.
-local g_opt = {}
-
--- Global state for current file.
-local g_fname, g_curline, g_indent, g_lineno, g_synclineno, g_arch
-local g_errcount = 0
-
--- Write buffer for output file.
-local g_wbuffer, g_capbuffer
-
-------------------------------------------------------------------------------
-
--- Write an output line (or callback function) to the buffer.
-local function wline(line, needindent)
- local buf = g_capbuffer or g_wbuffer
- buf[#buf+1] = needindent and g_indent..line or line
- g_synclineno = g_synclineno + 1
-end
-
--- Write assembler line as a comment, if requestd.
-local function wcomment(aline)
- if g_opt.comment then
- wline(g_opt.comment..aline..g_opt.endcomment, true)
- end
-end
-
--- Resync CPP line numbers.
-local function wsync()
- if g_synclineno ~= g_lineno and g_opt.cpp then
- wline("# "..g_lineno..' "'..g_fname..'"')
- g_synclineno = g_lineno
- end
-end
-
--- Dummy action flush function. Replaced with arch-specific function later.
-local function wflush(term)
-end
-
--- Dump all buffered output lines.
-local function wdumplines(out, buf)
- for _,line in ipairs(buf) do
- if type(line) == "string" then
- assert(out:write(line, "\n"))
- else
- -- Special callback to dynamically insert lines after end of processing.
- line(out)
- end
- end
-end
-
-------------------------------------------------------------------------------
-
--- Emit an error. Processing continues with next statement.
-local function werror(msg)
- error(format("%s:%s: error: %s:\n%s", g_fname, g_lineno, msg, g_curline), 0)
-end
-
--- Emit a fatal error. Processing stops.
-local function wfatal(msg)
- g_errcount = "fatal"
- werror(msg)
-end
-
--- Print a warning. Processing continues.
-local function wwarn(msg)
- stderr:write(format("%s:%s: warning: %s:\n%s\n",
- g_fname, g_lineno, msg, g_curline))
-end
-
--- Print caught error message. But suppress excessive errors.
-local function wprinterr(...)
- if type(g_errcount) == "number" then
- -- Regular error.
- g_errcount = g_errcount + 1
- if g_errcount < 21 then -- Seems to be a reasonable limit.
- stderr:write(...)
- elseif g_errcount == 21 then
- stderr:write(g_fname,
- ":*: warning: too many errors (suppressed further messages).\n")
- end
- else
- -- Fatal error.
- stderr:write(...)
- return true -- Stop processing.
- end
-end
-
-------------------------------------------------------------------------------
-
--- Map holding all option handlers.
-local opt_map = {}
-local opt_current
-
--- Print error and exit with error status.
-local function opterror(...)
- stderr:write("dynasm.lua: ERROR: ", ...)
- stderr:write("\n")
- exit(1)
-end
-
--- Get option parameter.
-local function optparam(args)
- local argn = args.argn
- local p = args[argn]
- if not p then
- opterror("missing parameter for option `", opt_current, "'.")
- end
- args.argn = argn + 1
- return p
-end
-
-------------------------------------------------------------------------------
-
--- Core pseudo-opcodes.
-local map_coreop = {}
--- Dummy opcode map. Replaced by arch-specific map.
-local map_op = {}
-
--- Forward declarations.
-local dostmt
-local readfile
-
-------------------------------------------------------------------------------
-
--- Map for defines (initially empty, chains to arch-specific map).
-local map_def = {}
-
--- Pseudo-opcode to define a substitution.
-map_coreop[".define_2"] = function(params, nparams)
- if not params then return nparams == 1 and "name" or "name, subst" end
- local name, def = params[1], params[2] or "1"
- if not match(name, "^[%a_][%w_]*$") then werror("bad or duplicate define") end
- map_def[name] = def
-end
-map_coreop[".define_1"] = map_coreop[".define_2"]
-
--- Define a substitution on the command line.
-function opt_map.D(args)
- local namesubst = optparam(args)
- local name, subst = match(namesubst, "^([%a_][%w_]*)=(.*)$")
- if name then
- map_def[name] = subst
- elseif match(namesubst, "^[%a_][%w_]*$") then
- map_def[namesubst] = "1"
- else
- opterror("bad define")
- end
-end
-
--- Undefine a substitution on the command line.
-function opt_map.U(args)
- local name = optparam(args)
- if match(name, "^[%a_][%w_]*$") then
- map_def[name] = nil
- else
- opterror("bad define")
- end
-end
-
--- Helper for definesubst.
-local gotsubst
-
-local function definesubst_one(word)
- local subst = map_def[word]
- if subst then gotsubst = word; return subst else return word end
-end
-
--- Iteratively substitute defines.
-local function definesubst(stmt)
- -- Limit number of iterations.
- for i=1,100 do
- gotsubst = false
- stmt = gsub(stmt, "#?[%w_]+", definesubst_one)
- if not gotsubst then break end
- end
- if gotsubst then wfatal("recursive define involving `"..gotsubst.."'") end
- return stmt
-end
-
--- Dump all defines.
-local function dumpdefines(out, lvl)
- local t = {}
- for name in pairs(map_def) do
- t[#t+1] = name
- end
- sort(t)
- out:write("Defines:\n")
- for _,name in ipairs(t) do
- local subst = map_def[name]
- if g_arch then subst = g_arch.revdef(subst) end
- out:write(format(" %-20s %s\n", name, subst))
- end
- out:write("\n")
-end
-
-------------------------------------------------------------------------------
-
--- Support variables for conditional assembly.
-local condlevel = 0
-local condstack = {}
-
--- Evaluate condition with a Lua expression. Substitutions already performed.
-local function cond_eval(cond)
- local func, err
- if setfenv then
- func, err = loadstring("return "..cond, "=expr")
- else
- -- No globals. All unknown identifiers evaluate to nil.
- func, err = load("return "..cond, "=expr", "t", {})
- end
- if func then
- if setfenv then
- setfenv(func, {}) -- No globals. All unknown identifiers evaluate to nil.
- end
- local ok, res = pcall(func)
- if ok then
- if res == 0 then return false end -- Oh well.
- return not not res
- end
- err = res
- end
- wfatal("bad condition: "..err)
-end
-
--- Skip statements until next conditional pseudo-opcode at the same level.
-local function stmtskip()
- local dostmt_save = dostmt
- local lvl = 0
- dostmt = function(stmt)
- local op = match(stmt, "^%s*(%S+)")
- if op == ".if" then
- lvl = lvl + 1
- elseif lvl ~= 0 then
- if op == ".endif" then lvl = lvl - 1 end
- elseif op == ".elif" or op == ".else" or op == ".endif" then
- dostmt = dostmt_save
- dostmt(stmt)
- end
- end
-end
-
--- Pseudo-opcodes for conditional assembly.
-map_coreop[".if_1"] = function(params)
- if not params then return "condition" end
- local lvl = condlevel + 1
- local res = cond_eval(params[1])
- condlevel = lvl
- condstack[lvl] = res
- if not res then stmtskip() end
-end
-
-map_coreop[".elif_1"] = function(params)
- if not params then return "condition" end
- if condlevel == 0 then wfatal(".elif without .if") end
- local lvl = condlevel
- local res = condstack[lvl]
- if res then
- if res == "else" then wfatal(".elif after .else") end
- else
- res = cond_eval(params[1])
- if res then
- condstack[lvl] = res
- return
- end
- end
- stmtskip()
-end
-
-map_coreop[".else_0"] = function(params)
- if condlevel == 0 then wfatal(".else without .if") end
- local lvl = condlevel
- local res = condstack[lvl]
- condstack[lvl] = "else"
- if res then
- if res == "else" then wfatal(".else after .else") end
- stmtskip()
- end
-end
-
-map_coreop[".endif_0"] = function(params)
- local lvl = condlevel
- if lvl == 0 then wfatal(".endif without .if") end
- condlevel = lvl - 1
-end
-
--- Check for unfinished conditionals.
-local function checkconds()
- if g_errcount ~= "fatal" and condlevel ~= 0 then
- wprinterr(g_fname, ":*: error: unbalanced conditional\n")
- end
-end
-
-------------------------------------------------------------------------------
-
--- Search for a file in the given path and open it for reading.
-local function pathopen(path, name)
- local dirsep = match(package.path, "\\") and "\\" or "/"
- for _,p in ipairs(path) do
- local fullname = p == "" and name or p..dirsep..name
- local fin = io.open(fullname, "r")
- if fin then
- g_fname = fullname
- return fin
- end
- end
-end
-
--- Include a file.
-map_coreop[".include_1"] = function(params)
- if not params then return "filename" end
- local name = params[1]
- -- Save state. Ugly, I know. but upvalues are fast.
- local gf, gl, gcl, gi = g_fname, g_lineno, g_curline, g_indent
- -- Read the included file.
- local fatal = readfile(pathopen(g_opt.include, name) or
- wfatal("include file `"..name.."' not found"))
- -- Restore state.
- g_synclineno = -1
- g_fname, g_lineno, g_curline, g_indent = gf, gl, gcl, gi
- if fatal then wfatal("in include file") end
-end
-
--- Make .include and conditionals initially available, too.
-map_op[".include_1"] = map_coreop[".include_1"]
-map_op[".if_1"] = map_coreop[".if_1"]
-map_op[".elif_1"] = map_coreop[".elif_1"]
-map_op[".else_0"] = map_coreop[".else_0"]
-map_op[".endif_0"] = map_coreop[".endif_0"]
-
-------------------------------------------------------------------------------
-
--- Support variables for macros.
-local mac_capture, mac_lineno, mac_name
-local mac_active = {}
-local mac_list = {}
-
--- Pseudo-opcode to define a macro.
-map_coreop[".macro_*"] = function(mparams)
- if not mparams then return "name [, params...]" end
- -- Split off and validate macro name.
- local name = remove(mparams, 1)
- if not name then werror("missing macro name") end
- if not (match(name, "^[%a_][%w_%.]*$") or match(name, "^%.[%w_%.]*$")) then
- wfatal("bad macro name `"..name.."'")
- end
- -- Validate macro parameter names.
- local mdup = {}
- for _,mp in ipairs(mparams) do
- if not match(mp, "^[%a_][%w_]*$") then
- wfatal("bad macro parameter name `"..mp.."'")
- end
- if mdup[mp] then wfatal("duplicate macro parameter name `"..mp.."'") end
- mdup[mp] = true
- end
- -- Check for duplicate or recursive macro definitions.
- local opname = name.."_"..#mparams
- if map_op[opname] or map_op[name.."_*"] then
- wfatal("duplicate macro `"..name.."' ("..#mparams.." parameters)")
- end
- if mac_capture then wfatal("recursive macro definition") end
-
- -- Enable statement capture.
- local lines = {}
- mac_lineno = g_lineno
- mac_name = name
- mac_capture = function(stmt) -- Statement capture function.
- -- Stop macro definition with .endmacro pseudo-opcode.
- if not match(stmt, "^%s*.endmacro%s*$") then
- lines[#lines+1] = stmt
- return
- end
- mac_capture = nil
- mac_lineno = nil
- mac_name = nil
- mac_list[#mac_list+1] = opname
- -- Add macro-op definition.
- map_op[opname] = function(params)
- if not params then return mparams, lines end
- -- Protect against recursive macro invocation.
- if mac_active[opname] then wfatal("recursive macro invocation") end
- mac_active[opname] = true
- -- Setup substitution map.
- local subst = {}
- for i,mp in ipairs(mparams) do subst[mp] = params[i] end
- local mcom
- if g_opt.maccomment and g_opt.comment then
- mcom = " MACRO "..name.." ("..#mparams..")"
- wcomment("{"..mcom)
- end
- -- Loop through all captured statements
- for _,stmt in ipairs(lines) do
- -- Substitute macro parameters.
- local st = gsub(stmt, "[%w_]+", subst)
- st = definesubst(st)
- st = gsub(st, "%s*%.%.%s*", "") -- Token paste a..b.
- if mcom and sub(st, 1, 1) ~= "|" then wcomment(st) end
- -- Emit statement. Use a protected call for better diagnostics.
- local ok, err = pcall(dostmt, st)
- if not ok then
- -- Add the captured statement to the error.
- wprinterr(err, "\n", g_indent, "| ", stmt,
- "\t[MACRO ", name, " (", #mparams, ")]\n")
- end
- end
- if mcom then wcomment("}"..mcom) end
- mac_active[opname] = nil
- end
- end
-end
-
--- An .endmacro pseudo-opcode outside of a macro definition is an error.
-map_coreop[".endmacro_0"] = function(params)
- wfatal(".endmacro without .macro")
-end
-
--- Dump all macros and their contents (with -PP only).
-local function dumpmacros(out, lvl)
- sort(mac_list)
- out:write("Macros:\n")
- for _,opname in ipairs(mac_list) do
- local name = sub(opname, 1, -3)
- local params, lines = map_op[opname]()
- out:write(format(" %-20s %s\n", name, concat(params, ", ")))
- if lvl > 1 then
- for _,line in ipairs(lines) do
- out:write(" |", line, "\n")
- end
- out:write("\n")
- end
- end
- out:write("\n")
-end
-
--- Check for unfinished macro definitions.
-local function checkmacros()
- if mac_capture then
- wprinterr(g_fname, ":", mac_lineno,
- ": error: unfinished .macro `", mac_name ,"'\n")
- end
-end
-
-------------------------------------------------------------------------------
-
--- Support variables for captures.
-local cap_lineno, cap_name
-local cap_buffers = {}
-local cap_used = {}
-
--- Start a capture.
-map_coreop[".capture_1"] = function(params)
- if not params then return "name" end
- wflush()
- local name = params[1]
- if not match(name, "^[%a_][%w_]*$") then
- wfatal("bad capture name `"..name.."'")
- end
- if cap_name then
- wfatal("already capturing to `"..cap_name.."' since line "..cap_lineno)
- end
- cap_name = name
- cap_lineno = g_lineno
- -- Create or continue a capture buffer and start the output line capture.
- local buf = cap_buffers[name]
- if not buf then buf = {}; cap_buffers[name] = buf end
- g_capbuffer = buf
- g_synclineno = 0
-end
-
--- Stop a capture.
-map_coreop[".endcapture_0"] = function(params)
- wflush()
- if not cap_name then wfatal(".endcapture without a valid .capture") end
- cap_name = nil
- cap_lineno = nil
- g_capbuffer = nil
- g_synclineno = 0
-end
-
--- Dump a capture buffer.
-map_coreop[".dumpcapture_1"] = function(params)
- if not params then return "name" end
- wflush()
- local name = params[1]
- if not match(name, "^[%a_][%w_]*$") then
- wfatal("bad capture name `"..name.."'")
- end
- cap_used[name] = true
- wline(function(out)
- local buf = cap_buffers[name]
- if buf then wdumplines(out, buf) end
- end)
- g_synclineno = 0
-end
-
--- Dump all captures and their buffers (with -PP only).
-local function dumpcaptures(out, lvl)
- out:write("Captures:\n")
- for name,buf in pairs(cap_buffers) do
- out:write(format(" %-20s %4s)\n", name, "("..#buf))
- if lvl > 1 then
- local bar = rep("=", 76)
- out:write(" ", bar, "\n")
- for _,line in ipairs(buf) do
- out:write(" ", line, "\n")
- end
- out:write(" ", bar, "\n\n")
- end
- end
- out:write("\n")
-end
-
--- Check for unfinished or unused captures.
-local function checkcaptures()
- if cap_name then
- wprinterr(g_fname, ":", cap_lineno,
- ": error: unfinished .capture `", cap_name,"'\n")
- return
- end
- for name in pairs(cap_buffers) do
- if not cap_used[name] then
- wprinterr(g_fname, ":*: error: missing .dumpcapture ", name ,"\n")
- end
- end
-end
-
-------------------------------------------------------------------------------
-
--- Sections names.
-local map_sections = {}
-
--- Pseudo-opcode to define code sections.
--- TODO: Data sections, BSS sections. Needs extra C code and API.
-map_coreop[".section_*"] = function(params)
- if not params then return "name..." end
- if #map_sections > 0 then werror("duplicate section definition") end
- wflush()
- for sn,name in ipairs(params) do
- local opname = "."..name.."_0"
- if not match(name, "^[%a][%w_]*$") or
- map_op[opname] or map_op["."..name.."_*"] then
- werror("bad section name `"..name.."'")
- end
- map_sections[#map_sections+1] = name
- wline(format("#define DASM_SECTION_%s\t%d", upper(name), sn-1))
- map_op[opname] = function(params) g_arch.section(sn-1) end
- end
- wline(format("#define DASM_MAXSECTION\t\t%d", #map_sections))
-end
-
--- Dump all sections.
-local function dumpsections(out, lvl)
- out:write("Sections:\n")
- for _,name in ipairs(map_sections) do
- out:write(format(" %s\n", name))
- end
- out:write("\n")
-end
-
-------------------------------------------------------------------------------
-
--- Load architecture-specific module.
-local function loadarch(arch)
- if not match(arch, "^[%w_]+$") then return "bad arch name" end
- local ok, m_arch = pcall(require, "dasm_"..arch)
- if not ok then return "cannot load module: "..m_arch end
- g_arch = m_arch
- wflush = m_arch.passcb(wline, werror, wfatal, wwarn)
- m_arch.setup(arch, g_opt)
- map_op, map_def = m_arch.mergemaps(map_coreop, map_def)
-end
-
--- Dump architecture description.
-function opt_map.dumparch(args)
- local name = optparam(args)
- if not g_arch then
- local err = loadarch(name)
- if err then opterror(err) end
- end
-
- local t = {}
- for name in pairs(map_coreop) do t[#t+1] = name end
- for name in pairs(map_op) do t[#t+1] = name end
- sort(t)
-
- local out = stdout
- local _arch = g_arch._info
- out:write(format("%s version %s, released %s, %s\n",
- _info.name, _info.version, _info.release, _info.url))
- g_arch.dumparch(out)
-
- local pseudo = true
- out:write("Pseudo-Opcodes:\n")
- for _,sname in ipairs(t) do
- local name, nparam = match(sname, "^(.+)_([0-9%*])$")
- if name then
- if pseudo and sub(name, 1, 1) ~= "." then
- out:write("\nOpcodes:\n")
- pseudo = false
- end
- local f = map_op[sname]
- local s
- if nparam ~= "*" then nparam = nparam + 0 end
- if nparam == 0 then
- s = ""
- elseif type(f) == "string" then
- s = map_op[".template__"](nil, f, nparam)
- else
- s = f(nil, nparam)
- end
- if type(s) == "table" then
- for _,s2 in ipairs(s) do
- out:write(format(" %-12s %s\n", name, s2))
- end
- else
- out:write(format(" %-12s %s\n", name, s))
- end
- end
- end
- out:write("\n")
- exit(0)
-end
-
--- Pseudo-opcode to set the architecture.
--- Only initially available (map_op is replaced when called).
-map_op[".arch_1"] = function(params)
- if not params then return "name" end
- local err = loadarch(params[1])
- if err then wfatal(err) end
-end
-
--- Dummy .arch pseudo-opcode to improve the error report.
-map_coreop[".arch_1"] = function(params)
- if not params then return "name" end
- wfatal("duplicate .arch statement")
-end
-
-------------------------------------------------------------------------------
-
--- Dummy pseudo-opcode. Don't confuse '.nop' with 'nop'.
-map_coreop[".nop_*"] = function(params)
- if not params then return "[ignored...]" end
-end
-
--- Pseudo-opcodes to raise errors.
-map_coreop[".error_1"] = function(params)
- if not params then return "message" end
- werror(params[1])
-end
-
-map_coreop[".fatal_1"] = function(params)
- if not params then return "message" end
- wfatal(params[1])
-end
-
--- Dump all user defined elements.
-local function dumpdef(out)
- local lvl = g_opt.dumpdef
- if lvl == 0 then return end
- dumpsections(out, lvl)
- dumpdefines(out, lvl)
- if g_arch then g_arch.dumpdef(out, lvl) end
- dumpmacros(out, lvl)
- dumpcaptures(out, lvl)
-end
-
-------------------------------------------------------------------------------
-
--- Helper for splitstmt.
-local splitlvl
-
-local function splitstmt_one(c)
- if c == "(" then
- splitlvl = ")"..splitlvl
- elseif c == "[" then
- splitlvl = "]"..splitlvl
- elseif c == "{" then
- splitlvl = "}"..splitlvl
- elseif c == ")" or c == "]" or c == "}" then
- if sub(splitlvl, 1, 1) ~= c then werror("unbalanced (), [] or {}") end
- splitlvl = sub(splitlvl, 2)
- elseif splitlvl == "" then
- return " \0 "
- end
- return c
-end
-
--- Split statement into (pseudo-)opcode and params.
-local function splitstmt(stmt)
- -- Convert label with trailing-colon into .label statement.
- local label = match(stmt, "^%s*(.+):%s*$")
- if label then return ".label", {label} end
-
- -- Split at commas and equal signs, but obey parentheses and brackets.
- splitlvl = ""
- stmt = gsub(stmt, "[,%(%)%[%]{}]", splitstmt_one)
- if splitlvl ~= "" then werror("unbalanced () or []") end
-
- -- Split off opcode.
- local op, other = match(stmt, "^%s*([^%s%z]+)%s*(.*)$")
- if not op then werror("bad statement syntax") end
-
- -- Split parameters.
- local params = {}
- for p in gmatch(other, "%s*(%Z+)%z?") do
- params[#params+1] = gsub(p, "%s+$", "")
- end
- if #params > 16 then werror("too many parameters") end
-
- params.op = op
- return op, params
-end
-
--- Process a single statement.
-dostmt = function(stmt)
- -- Ignore empty statements.
- if match(stmt, "^%s*$") then return end
-
- -- Capture macro defs before substitution.
- if mac_capture then return mac_capture(stmt) end
- stmt = definesubst(stmt)
-
- -- Emit C code without parsing the line.
- if sub(stmt, 1, 1) == "|" then
- local tail = sub(stmt, 2)
- wflush()
- if sub(tail, 1, 2) == "//" then wcomment(tail) else wline(tail, true) end
- return
- end
-
- -- Split into (pseudo-)opcode and params.
- local op, params = splitstmt(stmt)
-
- -- Get opcode handler (matching # of parameters or generic handler).
- local f = map_op[op.."_"..#params] or map_op[op.."_*"]
- if not f then
- if not g_arch then wfatal("first statement must be .arch") end
- -- Improve error report.
- for i=0,9 do
- if map_op[op.."_"..i] then
- werror("wrong number of parameters for `"..op.."'")
- end
- end
- werror("unknown statement `"..op.."'")
- end
-
- -- Call opcode handler or special handler for template strings.
- if type(f) == "string" then
- map_op[".template__"](params, f)
- else
- f(params)
- end
-end
-
--- Process a single line.
-local function doline(line)
- if g_opt.flushline then wflush() end
-
- -- Assembler line?
- local indent, aline = match(line, "^(%s*)%|(.*)$")
- if not aline then
- -- No, plain C code line, need to flush first.
- wflush()
- wsync()
- wline(line, false)
- return
- end
-
- g_indent = indent -- Remember current line indentation.
-
- -- Emit C code (even from macros). Avoids echo and line parsing.
- if sub(aline, 1, 1) == "|" then
- if not mac_capture then
- wsync()
- elseif g_opt.comment then
- wsync()
- wcomment(aline)
- end
- dostmt(aline)
- return
- end
-
- -- Echo assembler line as a comment.
- if g_opt.comment then
- wsync()
- wcomment(aline)
- end
-
- -- Strip assembler comments.
- aline = gsub(aline, "//.*$", "")
-
- -- Split line into statements at semicolons.
- if match(aline, ";") then
- for stmt in gmatch(aline, "[^;]+") do dostmt(stmt) end
- else
- dostmt(aline)
- end
-end
-
-------------------------------------------------------------------------------
-
--- Write DynASM header.
-local function dasmhead(out)
- out:write(format([[
-/*
-** This file has been pre-processed with DynASM.
-** %s
-** DynASM version %s, DynASM %s version %s
-** DO NOT EDIT! The original file is in "%s".
-*/
-
-#if DASM_VERSION != %d
-#error "Version mismatch between DynASM and included encoding engine"
-#endif
-
-]], _info.url,
- _info.version, g_arch._info.arch, g_arch._info.version,
- g_fname, _info.vernum))
-end
-
--- Read input file.
-readfile = function(fin)
- g_indent = ""
- g_lineno = 0
- g_synclineno = -1
-
- -- Process all lines.
- for line in fin:lines() do
- g_lineno = g_lineno + 1
- g_curline = line
- local ok, err = pcall(doline, line)
- if not ok and wprinterr(err, "\n") then return true end
- end
- wflush()
-
- -- Close input file.
- assert(fin == stdin or fin:close())
-end
-
--- Write output file.
-local function writefile(outfile)
- local fout
-
- -- Open output file.
- if outfile == nil or outfile == "-" then
- fout = stdout
- else
- fout = assert(io.open(outfile, "w"))
- end
-
- -- Write all buffered lines
- wdumplines(fout, g_wbuffer)
-
- -- Close output file.
- assert(fout == stdout or fout:close())
-
- -- Optionally dump definitions.
- dumpdef(fout == stdout and stderr or stdout)
-end
-
--- Translate an input file to an output file.
-local function translate(infile, outfile)
- g_wbuffer = {}
- g_indent = ""
- g_lineno = 0
- g_synclineno = -1
-
- -- Put header.
- wline(dasmhead)
-
- -- Read input file.
- local fin
- if infile == "-" then
- g_fname = "(stdin)"
- fin = stdin
- else
- g_fname = infile
- fin = assert(io.open(infile, "r"))
- end
- readfile(fin)
-
- -- Check for errors.
- if not g_arch then
- wprinterr(g_fname, ":*: error: missing .arch directive\n")
- end
- checkconds()
- checkmacros()
- checkcaptures()
-
- if g_errcount ~= 0 then
- stderr:write(g_fname, ":*: info: ", g_errcount, " error",
- (type(g_errcount) == "number" and g_errcount > 1) and "s" or "",
- " in input file -- no output file generated.\n")
- dumpdef(stderr)
- exit(1)
- end
-
- -- Write output file.
- writefile(outfile)
-end
-
-------------------------------------------------------------------------------
-
--- Print help text.
-function opt_map.help()
- stdout:write("DynASM -- ", _info.description, ".\n")
- stdout:write("DynASM ", _info.version, " ", _info.release, " ", _info.url, "\n")
- stdout:write[[
-
-Usage: dynasm [OPTION]... INFILE.dasc|-
-
- -h, --help Display this help text.
- -V, --version Display version and copyright information.
-
- -o, --outfile FILE Output file name (default is stdout).
- -I, --include DIR Add directory to the include search path.
-
- -c, --ccomment Use /* */ comments for assembler lines.
- -C, --cppcomment Use // comments for assembler lines (default).
- -N, --nocomment Suppress assembler lines in output.
- -M, --maccomment Show macro expansions as comments (default off).
-
- -L, --nolineno Suppress CPP line number information in output.
- -F, --flushline Flush action list for every line.
-
- -D NAME[=SUBST] Define a substitution.
- -U NAME Undefine a substitution.
-
- -P, --dumpdef Dump defines, macros, etc. Repeat for more output.
- -A, --dumparch ARCH Load architecture ARCH and dump description.
-]]
- exit(0)
-end
-
--- Print version information.
-function opt_map.version()
- stdout:write(format("%s version %s, released %s\n%s\n\n%s",
- _info.name, _info.version, _info.release, _info.url, _info.copyright))
- exit(0)
-end
-
--- Misc. options.
-function opt_map.outfile(args) g_opt.outfile = optparam(args) end
-function opt_map.include(args) insert(g_opt.include, 1, optparam(args)) end
-function opt_map.ccomment() g_opt.comment = "/*|"; g_opt.endcomment = " */" end
-function opt_map.cppcomment() g_opt.comment = "//|"; g_opt.endcomment = "" end
-function opt_map.nocomment() g_opt.comment = false end
-function opt_map.maccomment() g_opt.maccomment = true end
-function opt_map.nolineno() g_opt.cpp = false end
-function opt_map.flushline() g_opt.flushline = true end
-function opt_map.dumpdef() g_opt.dumpdef = g_opt.dumpdef + 1 end
-
-------------------------------------------------------------------------------
-
--- Short aliases for long options.
-local opt_alias = {
- h = "help", ["?"] = "help", V = "version",
- o = "outfile", I = "include",
- c = "ccomment", C = "cppcomment", N = "nocomment", M = "maccomment",
- L = "nolineno", F = "flushline",
- P = "dumpdef", A = "dumparch",
-}
-
--- Parse single option.
-local function parseopt(opt, args)
- opt_current = #opt == 1 and "-"..opt or "--"..opt
- local f = opt_map[opt] or opt_map[opt_alias[opt]]
- if not f then
- opterror("unrecognized option `", opt_current, "'. Try `--help'.\n")
- end
- f(args)
-end
-
--- Parse arguments.
-local function parseargs(args)
- -- Default options.
- g_opt.comment = "//|"
- g_opt.endcomment = ""
- g_opt.cpp = true
- g_opt.dumpdef = 0
- g_opt.include = { "" }
-
- -- Process all option arguments.
- args.argn = 1
- repeat
- local a = args[args.argn]
- if not a then break end
- local lopt, opt = match(a, "^%-(%-?)(.+)")
- if not opt then break end
- args.argn = args.argn + 1
- if lopt == "" then
- -- Loop through short options.
- for o in gmatch(opt, ".") do parseopt(o, args) end
- else
- -- Long option.
- parseopt(opt, args)
- end
- until false
-
- -- Check for proper number of arguments.
- local nargs = #args - args.argn + 1
- if nargs ~= 1 then
- if nargs == 0 then
- if g_opt.dumpdef > 0 then return dumpdef(stdout) end
- end
- opt_map.help()
- end
-
- -- Translate a single input file to a single output file
- -- TODO: Handle multiple files?
- translate(args[args.argn], g_opt.outfile)
-end
-
-------------------------------------------------------------------------------
-
--- Add the directory dynasm.lua resides in to the Lua module search path.
-local arg = arg
-if arg and arg[0] then
- local prefix = match(arg[0], "^(.*[/\\])")
- if prefix then package.path = prefix.."?.lua;"..package.path end
-end
-
--- Start DynASM.
-parseargs{...}
-
-------------------------------------------------------------------------------
-
diff --git a/third_party/protobuf b/third_party/protobuf
deleted file mode 160000
-Subproject 5aeee3dc910d37f37b75f5a6d1486fe75cb0928
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback