summaryrefslogtreecommitdiff
path: root/Build/source/utils/xml2pmx/xml2pmx-src/interp.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/utils/xml2pmx/xml2pmx-src/interp.c')
-rw-r--r--Build/source/utils/xml2pmx/xml2pmx-src/interp.c240
1 files changed, 240 insertions, 0 deletions
diff --git a/Build/source/utils/xml2pmx/xml2pmx-src/interp.c b/Build/source/utils/xml2pmx/xml2pmx-src/interp.c
new file mode 100644
index 00000000000..7175d717267
--- /dev/null
+++ b/Build/source/utils/xml2pmx/xml2pmx-src/interp.c
@@ -0,0 +1,240 @@
+/*
+ * interp.c
+ *
+ * This file is part of the Oxford Oberon-2 compiler
+ * Copyright (c) 2006--2016 J. M. Spivey
+ * All rights reserved
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* This file is the skeleton of the bytecode interpreter; the parts
+ specific to each instruction are inserted from the file
+ 'keiko.iset' by the script 'iset.tcl'. There are three places that
+ code is inserted, each marked by two dollar signs. In order of
+ appearance, they are:
+
+ 1. A jump table for quick dispatching (used if JTABLE is defined).
+
+ 2. Macro definitions used in the action routines.
+
+ 3. Action routines for each instruction, forming the cases in a big
+ switch. */
+
+#include <math.h>
+#include <string.h>
+#include "obx.h"
+#include "keiko.h"
+
+#ifdef HAVE_INDEXED_JUMPS
+#define JTABLE 1
+#endif
+
+#ifdef TRACE
+#define DISASS 1
+#undef JTABLE
+#define do_find_proc if (dflag > 1) thisproc = find_proc(dsegaddr(cp))
+#else
+#define do_find_proc
+#endif
+
+#ifdef PROFILE
+#undef JTABLE
+#endif
+
+#ifdef UNALIGNED_MEM
+#define getdbl get_double
+#define putdbl put_double
+#define getlong get_long
+#define putlong put_long
+#else
+static inline double getdbl(value *v) {
+ dblbuf dd;
+ dd.n.lo = v[0].i;
+ dd.n.hi = v[1].i;
+ return dd.d;
+}
+
+static inline void putdbl(value *v, double x) {
+ dblbuf dd;
+ dd.d = x;
+ v[0].i = dd.n.lo;
+ v[1].i = dd.n.hi;
+}
+
+static inline longint getlong(value *v) {
+ dblbuf dd;
+ dd.n.lo = v[0].i;
+ dd.n.hi = v[1].i;
+ return dd.q;
+}
+
+static inline void putlong(value *v, longint x) {
+ dblbuf dd;
+ dd.q = x;
+ v[0].i = dd.n.lo;
+ v[1].i = dd.n.hi;
+}
+#endif
+
+/* Macros used in action routines */
+
+#define error(msg, n) runtime_error(msg, n, bp, pc0)
+
+#define local(n) ((uchar *) bp + (n))
+#define parent(a, t) indir(pointer(bp[SL]) + a, t)
+#define indir(p, t) (* (t *) (p))
+#define subs(p, n, t) ((t *) (p))[n]
+#define const(n) cp[CP_CONST+n]
+#define jump(lab) pc = pc0 + lab
+
+#define load(x, t) indir(pointer(x), t)
+#define store(x, y, t) indir(pointer(y), t) = x
+#define ldl(a, t) indir(local(a), t)
+#define stl(a, x, t) indir(local(a), t) = x
+#define ldg(a, t) indir(pointer(const(a)), t)
+#define stg(a, x, t) indir(pointer(const(a)), t) = x
+#define ldn(a, x) indir((char *) pointer(x) + a, int)
+#define stn(a, x, y) indir((char *) pointer(y) + a, int) = x
+#define ldi(x, y, t) subs(pointer(x), y.i, t)
+#define sti(x, y, z, t) subs(pointer(y), z.i, t) = x
+
+#define dup(n, sp) sp--; sp[0] = sp[n+1]
+#define swap(sp) sp[-1] = sp[1]; sp[1] = sp[0]; sp[0] = sp[-1]
+#define slide(nargs) sp += HEAD + nargs; cond_break();
+
+#define ror(a, b) ((((unsigned) a) >> b) | (((unsigned) a) << (32-b)))
+
+#define fcmpl(a, b) (a > b ? 1 : a == b ? 0 : -1)
+#define fcmpg(a, b) (a < b ? -1 : a == b ? 0 : 1)
+#define lcmp(a, b) (a < b ? -1 : a > b ? 1 : 0)
+
+#ifdef WORDS_BIGENDIAN
+#define alignx(a, n) (a << (32-n))
+#else
+#define alignx(a, n) a
+#endif
+
+#ifdef PROFILE
+#define prof_charge(n) ticks += n
+#else
+#define prof_charge(n)
+#endif
+
+#ifdef OBXDEB
+#define cond_break() \
+ if (one_shot && *pc != K_LNUM_2 && *pc != K_BREAK_2) \
+ debug_break(cp, bp, pc, "stop")
+#else
+#define cond_break()
+#endif
+
+/* interp -- main loop of the interpreter */
+value *interp(value *sp0) {
+ register value *cp = valptr(sp0[CP]);
+ uchar *pc = codeptr(cp[CP_CODE].a);
+ register uchar *pc0 = NULL;
+ register value *sp = sp0;
+ register value *rp = NULL;
+ register uchar ir = 0;
+#ifdef PROFILE
+ register counter ticks = 0;
+#endif
+ register value *bp = NULL;
+ value *base = sp0;
+#ifdef TRACE
+ proc thisproc = NULL;
+#endif
+
+#ifdef JTABLE
+ /* Save time by using gcc's label array feature */
+#define __o__(op, inst, patt, arg, len) &&lbl_ ## op,
+ static void *jtable[256] = { __OPCODES__(__o__) };
+#endif
+
+#ifdef JTABLE
+/* Each action ends with an indexed jump to the next */
+#define ACTION(op) lbl_ ## op:
+#define ALSO(op)
+#define DEFAULT
+#define NEXT goto *jtable[ir = *(pc0 = pc)]
+#else
+/* Actions are just cases in a big switch */
+#define ACTION(op) case K_ ## op:
+#define ALSO(op) case K_ ## op:
+#define DEFAULT default:
+#define NEXT break
+#endif
+
+ level++;
+
+enter:
+ do_find_proc;
+
+#ifdef PROFILE
+ prof_enter(dsegaddr(cp), ticks, PROF_CALL);
+#endif
+
+ bp = sp;
+ sp = (value *) ((uchar *) bp - cp[CP_FRAME].i);
+ if ((uchar *) sp < stack + SLIMIT) error(E_STACK, 0);
+
+ /* Preserve the static link if the routine starts with SAVELINK */
+ memset(sp, 0, (*pc == K_SAVELINK ? cp[CP_FRAME].i - 4 : cp[CP_FRAME].i));
+
+#ifdef JTABLE
+ NEXT;
+#else
+ while (TRUE) {
+#ifdef TRACE
+ if (dflag > 1) {
+ printf("pc=%s+%ld(%p) sp=%p bp=%p cp=%p",
+ thisproc->p_name,
+ (long) (pc - codeptr(cp[CP_CODE].a)),
+ pc, sp, bp, cp);
+ fflush(stdout);
+ for (int i = 0; i < 8; i++) printf(" %x", sp[i].i);
+ printf("\n");
+ printf("%6ld: %s\n", (long) (pc-imem), fmt_inst(pc));
+ fflush(stdout);
+ }
+#endif
+
+#ifdef PROFILE
+ ticks++;
+#endif
+
+ switch (ir = *(pc0 = pc)) {
+#endif
+
+#include "action.c"
+
+ ACTION(ILLEGAL)
+ DEFAULT
+ panic("*illegal instruction %d", ir);
+ return NULL;
+#ifndef JTABLE
+ }
+ }
+#endif
+}