eclair snapshot
diff --git a/libacc/tests/.gitignore b/libacc/tests/.gitignore
new file mode 100644
index 0000000..a26b298
--- /dev/null
+++ b/libacc/tests/.gitignore
@@ -0,0 +1,2 @@
+test-acc
+*.out
diff --git a/libacc/tests/Android.mk b/libacc/tests/Android.mk
new file mode 100644
index 0000000..e9fbe03
--- /dev/null
+++ b/libacc/tests/Android.mk
@@ -0,0 +1,66 @@
+LOCAL_PATH:= $(call my-dir)
+
+# Executable for host
+# ========================================================
+include $(CLEAR_VARS)
+LOCAL_MODULE:= acc
+
+LOCAL_SRC_FILES:= \
+	main.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+    libacc
+
+LOCAL_MODULE_TAGS := tests
+
+include $(BUILD_HOST_EXECUTABLE)
+
+# Executable for target
+# ========================================================
+include $(CLEAR_VARS)
+LOCAL_MODULE:= acc
+
+LOCAL_SRC_FILES:= \
+	main.cpp \
+    disassem.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+    libacc
+
+LOCAL_CFLAGS := -O0 -g 
+
+LOCAL_MODULE_TAGS := tests
+
+include $(BUILD_EXECUTABLE)
+
+# Runtime tests for host
+# ========================================================
+include $(CLEAR_VARS)
+LOCAL_MODULE:= accRuntimeTest
+
+LOCAL_SRC_FILES:= \
+	runtimeTest.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+    libacc
+
+LOCAL_MODULE_TAGS := tests
+
+include $(BUILD_HOST_EXECUTABLE)
+
+# Runtime tests for target
+# ========================================================
+include $(CLEAR_VARS)
+LOCAL_MODULE:= accRuntimeTest
+
+LOCAL_SRC_FILES:= \
+	runtimeTest.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+    libacc
+
+LOCAL_CFLAGS := -O0 -g 
+
+LOCAL_MODULE_TAGS := tests
+
+include $(BUILD_EXECUTABLE)
diff --git a/libacc/tests/accarm b/libacc/tests/accarm
new file mode 100755
index 0000000..6b1bf66
--- /dev/null
+++ b/libacc/tests/accarm
@@ -0,0 +1,69 @@
+#!/usr/bin/python
+#
+# Run a test on the ARM version of acc.
+
+import unittest
+import subprocess
+import os
+import sys
+
+def compile(args):
+    proc = subprocess.Popen(["acc"] + args, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
+    result = proc.communicate()
+    return result
+
+def runCmd(args):
+    proc = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+    result = proc.communicate()
+    return result[0].strip()
+
+def uname():
+    return runCmd(["uname"])
+
+def unameM():
+    return runCmd(["uname", "-m"])
+
+def which(item):
+    return runCmd(["which", item])
+
+def adb(args):
+    return runCmd(["adb"] + args)
+
+def setupArm(file):
+    print "Setting up arm"
+    adb(["remount"])
+    adb(["shell", "rm", "/system/bin/acc"])
+    adb(["shell", "mkdir", "/system/bin/accdata"])
+    adb(["shell", "mkdir", "/system/bin/accdata/data"])
+
+    remoteFileName = os.path.join("/system/bin/accdata", file)
+    adb(["push", file, remoteFileName])
+
+    # Copy over compiler
+    adb(["sync"])
+    return remoteFileName
+
+def compileArm(args):
+    remoteArgs = []
+    fileName = ""
+    for arg in sys.argv[1:]:
+        if arg.startswith('-'):
+            remoteArgs.append(arg)
+        else:
+            fileName = arg
+
+    remoteFileName = setupArm(fileName)
+    remoteArgs.append(remoteFileName)
+    remoteCmdLine = ["adb", "shell", "/system/bin/acc"] + remoteArgs
+    proc = subprocess.Popen(remoteCmdLine, stdout=subprocess.PIPE)
+    result = proc.communicate()
+    return result[0].replace("\r","")
+
+
+def main():
+    print compileArm(sys.argv[1:])
+
+if __name__ == '__main__':
+    main()
+
+
diff --git a/libacc/tests/armreg.h b/libacc/tests/armreg.h
new file mode 100644
index 0000000..fde81ba
--- /dev/null
+++ b/libacc/tests/armreg.h
@@ -0,0 +1,300 @@
+/*	$NetBSD: armreg.h,v 1.28 2003/10/31 16:30:15 scw Exp $	*/
+
+/*-
+ * Copyright (c) 1998, 2001 Ben Harris
+ * Copyright (c) 1994-1996 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * 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. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``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 BRINI OR CONTRIBUTORS 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.
+ *
+ * $FreeBSD: /repoman/r/ncvs/src/sys/arm/include/armreg.h,v 1.3 2005/11/21 19:06:25 cognet Exp $
+ */
+
+#ifndef MACHINE_ARMREG_H
+#define MACHINE_ARMREG_H
+#define INSN_SIZE	4
+#define INSN_COND_MASK	0xf0000000	/* Condition mask */
+#define PSR_MODE        0x0000001f      /* mode mask */
+#define PSR_USR26_MODE  0x00000000
+#define PSR_FIQ26_MODE  0x00000001
+#define PSR_IRQ26_MODE  0x00000002
+#define PSR_SVC26_MODE  0x00000003
+#define PSR_USR32_MODE  0x00000010
+#define PSR_FIQ32_MODE  0x00000011
+#define PSR_IRQ32_MODE  0x00000012
+#define PSR_SVC32_MODE  0x00000013
+#define PSR_ABT32_MODE  0x00000017
+#define PSR_UND32_MODE  0x0000001b
+#define PSR_SYS32_MODE  0x0000001f
+#define PSR_32_MODE     0x00000010
+#define PSR_FLAGS	0xf0000000    /* flags */
+
+#define PSR_C_bit (1 << 29)       /* carry */
+
+/* The high-order byte is always the implementor */
+#define CPU_ID_IMPLEMENTOR_MASK	0xff000000
+#define CPU_ID_ARM_LTD		0x41000000 /* 'A' */
+#define CPU_ID_DEC		0x44000000 /* 'D' */
+#define CPU_ID_INTEL		0x69000000 /* 'i' */
+#define	CPU_ID_TI		0x54000000 /* 'T' */
+
+/* How to decide what format the CPUID is in. */
+#define CPU_ID_ISOLD(x)		(((x) & 0x0000f000) == 0x00000000)
+#define CPU_ID_IS7(x)		(((x) & 0x0000f000) == 0x00007000)
+#define CPU_ID_ISNEW(x)		(!CPU_ID_ISOLD(x) && !CPU_ID_IS7(x))
+
+/* On ARM3 and ARM6, this byte holds the foundry ID. */
+#define CPU_ID_FOUNDRY_MASK	0x00ff0000
+#define CPU_ID_FOUNDRY_VLSI	0x00560000
+
+/* On ARM7 it holds the architecture and variant (sub-model) */
+#define CPU_ID_7ARCH_MASK	0x00800000
+#define CPU_ID_7ARCH_V3		0x00000000
+#define CPU_ID_7ARCH_V4T	0x00800000
+#define CPU_ID_7VARIANT_MASK	0x007f0000
+
+/* On more recent ARMs, it does the same, but in a different format */
+#define CPU_ID_ARCH_MASK	0x000f0000
+#define CPU_ID_ARCH_V3		0x00000000
+#define CPU_ID_ARCH_V4		0x00010000
+#define CPU_ID_ARCH_V4T		0x00020000
+#define CPU_ID_ARCH_V5		0x00030000
+#define CPU_ID_ARCH_V5T		0x00040000
+#define CPU_ID_ARCH_V5TE	0x00050000
+#define CPU_ID_VARIANT_MASK	0x00f00000
+
+/* Next three nybbles are part number */
+#define CPU_ID_PARTNO_MASK	0x0000fff0
+
+/* Intel XScale has sub fields in part number */
+#define CPU_ID_XSCALE_COREGEN_MASK	0x0000e000 /* core generation */
+#define CPU_ID_XSCALE_COREREV_MASK	0x00001c00 /* core revision */
+#define CPU_ID_XSCALE_PRODUCT_MASK	0x000003f0 /* product number */
+
+/* And finally, the revision number. */
+#define CPU_ID_REVISION_MASK	0x0000000f
+
+/* Individual CPUs are probably best IDed by everything but the revision. */
+#define CPU_ID_CPU_MASK		0xfffffff0
+
+/* Fake CPU IDs for ARMs without CP15 */
+#define CPU_ID_ARM2		0x41560200
+#define CPU_ID_ARM250		0x41560250
+
+/* Pre-ARM7 CPUs -- [15:12] == 0 */
+#define CPU_ID_ARM3		0x41560300
+#define CPU_ID_ARM600		0x41560600
+#define CPU_ID_ARM610		0x41560610
+#define CPU_ID_ARM620		0x41560620
+
+/* ARM7 CPUs -- [15:12] == 7 */
+#define CPU_ID_ARM700		0x41007000 /* XXX This is a guess. */
+#define CPU_ID_ARM710		0x41007100
+#define CPU_ID_ARM7500		0x41027100 /* XXX This is a guess. */
+#define CPU_ID_ARM710A		0x41047100 /* inc ARM7100 */
+#define CPU_ID_ARM7500FE	0x41077100
+#define CPU_ID_ARM710T		0x41807100
+#define CPU_ID_ARM720T		0x41807200
+#define CPU_ID_ARM740T8K	0x41807400 /* XXX no MMU, 8KB cache */
+#define CPU_ID_ARM740T4K	0x41817400 /* XXX no MMU, 4KB cache */
+
+/* Post-ARM7 CPUs */
+#define CPU_ID_ARM810		0x41018100
+#define CPU_ID_ARM920T		0x41129200
+#define CPU_ID_ARM920T_ALT	0x41009200
+#define CPU_ID_ARM922T		0x41029220
+#define CPU_ID_ARM940T		0x41029400 /* XXX no MMU */
+#define CPU_ID_ARM946ES		0x41049460 /* XXX no MMU */
+#define	CPU_ID_ARM966ES		0x41049660 /* XXX no MMU */
+#define	CPU_ID_ARM966ESR1	0x41059660 /* XXX no MMU */
+#define CPU_ID_ARM1020E		0x4115a200 /* (AKA arm10 rev 1) */
+#define CPU_ID_ARM1022ES	0x4105a220
+#define CPU_ID_SA110		0x4401a100
+#define CPU_ID_SA1100		0x4401a110
+#define	CPU_ID_TI925T		0x54029250
+#define CPU_ID_SA1110		0x6901b110
+#define CPU_ID_IXP1200		0x6901c120
+#define CPU_ID_80200		0x69052000
+#define CPU_ID_PXA250    	0x69052100 /* sans core revision */
+#define CPU_ID_PXA210    	0x69052120
+#define CPU_ID_PXA250A		0x69052100 /* 1st version Core */
+#define CPU_ID_PXA210A		0x69052120 /* 1st version Core */
+#define CPU_ID_PXA250B		0x69052900 /* 3rd version Core */
+#define CPU_ID_PXA210B		0x69052920 /* 3rd version Core */
+#define CPU_ID_PXA250C		0x69052d00 /* 4th version Core */
+#define CPU_ID_PXA210C		0x69052d20 /* 4th version Core */
+#define	CPU_ID_80321_400	0x69052420
+#define	CPU_ID_80321_600	0x69052430
+#define	CPU_ID_80321_400_B0	0x69052c20
+#define	CPU_ID_80321_600_B0	0x69052c30
+#define	CPU_ID_IXP425_533	0x690541c0
+#define	CPU_ID_IXP425_400	0x690541d0
+#define	CPU_ID_IXP425_266	0x690541f0
+
+/* ARM3-specific coprocessor 15 registers */
+#define ARM3_CP15_FLUSH		1
+#define ARM3_CP15_CONTROL	2
+#define ARM3_CP15_CACHEABLE	3
+#define ARM3_CP15_UPDATEABLE	4
+#define ARM3_CP15_DISRUPTIVE	5	
+
+/* ARM3 Control register bits */
+#define ARM3_CTL_CACHE_ON	0x00000001
+#define ARM3_CTL_SHARED		0x00000002
+#define ARM3_CTL_MONITOR	0x00000004
+
+/*
+ * Post-ARM3 CP15 registers:
+ *
+ *	1	Control register
+ *
+ *	2	Translation Table Base
+ *
+ *	3	Domain Access Control
+ *
+ *	4	Reserved
+ *
+ *	5	Fault Status
+ *
+ *	6	Fault Address
+ *
+ *	7	Cache/write-buffer Control
+ *
+ *	8	TLB Control
+ *
+ *	9	Cache Lockdown
+ *
+ *	10	TLB Lockdown
+ *
+ *	11	Reserved
+ *
+ *	12	Reserved
+ *
+ *	13	Process ID (for FCSE)
+ *
+ *	14	Reserved
+ *
+ *	15	Implementation Dependent
+ */
+
+/* Some of the definitions below need cleaning up for V3/V4 architectures */
+
+/* CPU control register (CP15 register 1) */
+#define CPU_CONTROL_MMU_ENABLE	0x00000001 /* M: MMU/Protection unit enable */
+#define CPU_CONTROL_AFLT_ENABLE	0x00000002 /* A: Alignment fault enable */
+#define CPU_CONTROL_DC_ENABLE	0x00000004 /* C: IDC/DC enable */
+#define CPU_CONTROL_WBUF_ENABLE 0x00000008 /* W: Write buffer enable */
+#define CPU_CONTROL_32BP_ENABLE 0x00000010 /* P: 32-bit exception handlers */
+#define CPU_CONTROL_32BD_ENABLE 0x00000020 /* D: 32-bit addressing */
+#define CPU_CONTROL_LABT_ENABLE 0x00000040 /* L: Late abort enable */
+#define CPU_CONTROL_BEND_ENABLE 0x00000080 /* B: Big-endian mode */
+#define CPU_CONTROL_SYST_ENABLE 0x00000100 /* S: System protection bit */
+#define CPU_CONTROL_ROM_ENABLE	0x00000200 /* R: ROM protection bit */
+#define CPU_CONTROL_CPCLK	0x00000400 /* F: Implementation defined */
+#define CPU_CONTROL_BPRD_ENABLE 0x00000800 /* Z: Branch prediction enable */
+#define CPU_CONTROL_IC_ENABLE   0x00001000 /* I: IC enable */
+#define CPU_CONTROL_VECRELOC	0x00002000 /* V: Vector relocation */
+#define CPU_CONTROL_ROUNDROBIN	0x00004000 /* RR: Predictable replacement */
+#define CPU_CONTROL_V4COMPAT	0x00008000 /* L4: ARMv4 compat LDR R15 etc */
+
+#define CPU_CONTROL_IDC_ENABLE	CPU_CONTROL_DC_ENABLE
+
+/* XScale Auxillary Control Register (CP15 register 1, opcode2 1) */
+#define	XSCALE_AUXCTL_K		0x00000001 /* dis. write buffer coalescing */
+#define	XSCALE_AUXCTL_P		0x00000002 /* ECC protect page table access */
+#define	XSCALE_AUXCTL_MD_WB_RA	0x00000000 /* mini-D$ wb, read-allocate */
+#define	XSCALE_AUXCTL_MD_WB_RWA	0x00000010 /* mini-D$ wb, read/write-allocate */
+#define	XSCALE_AUXCTL_MD_WT	0x00000020 /* mini-D$ wt, read-allocate */
+#define	XSCALE_AUXCTL_MD_MASK	0x00000030
+
+/* Cache type register definitions */
+#define	CPU_CT_ISIZE(x)		((x) & 0xfff)		/* I$ info */
+#define	CPU_CT_DSIZE(x)		(((x) >> 12) & 0xfff)	/* D$ info */
+#define	CPU_CT_S		(1U << 24)		/* split cache */
+#define	CPU_CT_CTYPE(x)		(((x) >> 25) & 0xf)	/* cache type */
+
+#define	CPU_CT_CTYPE_WT		0	/* write-through */
+#define	CPU_CT_CTYPE_WB1	1	/* write-back, clean w/ read */
+#define	CPU_CT_CTYPE_WB2	2	/* w/b, clean w/ cp15,7 */
+#define	CPU_CT_CTYPE_WB6	6	/* w/b, cp15,7, lockdown fmt A */
+#define	CPU_CT_CTYPE_WB7	7	/* w/b, cp15,7, lockdown fmt B */
+
+#define	CPU_CT_xSIZE_LEN(x)	((x) & 0x3)		/* line size */
+#define	CPU_CT_xSIZE_M		(1U << 2)		/* multiplier */
+#define	CPU_CT_xSIZE_ASSOC(x)	(((x) >> 3) & 0x7)	/* associativity */
+#define	CPU_CT_xSIZE_SIZE(x)	(((x) >> 6) & 0x7)	/* size */
+
+/* Fault status register definitions */
+
+#define FAULT_TYPE_MASK 0x0f
+#define FAULT_USER      0x10
+
+#define FAULT_WRTBUF_0  0x00 /* Vector Exception */
+#define FAULT_WRTBUF_1  0x02 /* Terminal Exception */
+#define FAULT_BUSERR_0  0x04 /* External Abort on Linefetch -- Section */
+#define FAULT_BUSERR_1  0x06 /* External Abort on Linefetch -- Page */
+#define FAULT_BUSERR_2  0x08 /* External Abort on Non-linefetch -- Section */
+#define FAULT_BUSERR_3  0x0a /* External Abort on Non-linefetch -- Page */
+#define FAULT_BUSTRNL1  0x0c /* External abort on Translation -- Level 1 */
+#define FAULT_BUSTRNL2  0x0e /* External abort on Translation -- Level 2 */
+#define FAULT_ALIGN_0   0x01 /* Alignment */
+#define FAULT_ALIGN_1   0x03 /* Alignment */
+#define FAULT_TRANS_S   0x05 /* Translation -- Section */
+#define FAULT_TRANS_P   0x07 /* Translation -- Page */
+#define FAULT_DOMAIN_S  0x09 /* Domain -- Section */
+#define FAULT_DOMAIN_P  0x0b /* Domain -- Page */
+#define FAULT_PERM_S    0x0d /* Permission -- Section */
+#define FAULT_PERM_P    0x0f /* Permission -- Page */
+
+#define	FAULT_IMPRECISE	0x400	/* Imprecise exception (XSCALE) */
+
+/*
+ * Address of the vector page, low and high versions.
+ */
+#define	ARM_VECTORS_LOW		0x00000000U
+#define	ARM_VECTORS_HIGH	0xffff0000U
+
+/*
+ * ARM Instructions
+ *
+ *       3 3 2 2 2                              
+ *       1 0 9 8 7                                                     0
+ *      +-------+-------------------------------------------------------+
+ *      | cond  |              instruction dependant                    |
+ *      |c c c c|                                                       |
+ *      +-------+-------------------------------------------------------+
+ */
+
+#define INSN_SIZE		4		/* Always 4 bytes */
+#define INSN_COND_MASK		0xf0000000	/* Condition mask */
+#define INSN_COND_AL		0xe0000000	/* Always condition */
+
+#endif /* !MACHINE_ARMREG_H */
diff --git a/libacc/tests/data/addressOf.c b/libacc/tests/data/addressOf.c
new file mode 100644
index 0000000..e7acde5
--- /dev/null
+++ b/libacc/tests/data/addressOf.c
@@ -0,0 +1,31 @@
+void testStruct() {
+    struct str {
+        float x;
+        float y;
+    };
+
+    struct str base;
+    int index = 0;
+
+    base.x = 10.0;
+    struct str *s = &base;
+
+    float *v = &(*s).x;
+    float *v2 = &s[index].x;
+    printf("testStruct: %g %g %g\n",base.x, *v, *v2);
+}
+
+void testArray() {
+    int a[2];
+    a[0] = 1;
+    a[1] = 2;
+    int* p = &a[0];
+    int* p2 = a;
+    printf("testArray: %d %d %d\n", a[0], *p, *p2);
+}
+
+int main() {
+    testStruct();
+    testArray();
+    return 0;
+}
diff --git a/libacc/tests/data/array.c b/libacc/tests/data/array.c
new file mode 100644
index 0000000..ca4a728
--- /dev/null
+++ b/libacc/tests/data/array.c
@@ -0,0 +1,107 @@
+// Array allocation tests
+
+void testLocalInt()
+{
+    int a[3];
+    a[0] = 1;
+    a[1] = 2;
+    a[2] = a[0] + a[1];
+    printf("localInt: %d\n", a[2]);
+}
+
+char a[3];
+double d[3];
+
+void testGlobalChar()
+{
+    a[0] = 1;
+    a[1] = 2;
+    a[2] = a[0] + a[1];
+    printf("globalChar: %d\n", a[2]);
+}
+
+void testGlobalDouble()
+{
+    d[0] = 1;
+    d[1] = 2;
+    d[2] = d[0] + d[1];
+    printf("globalDouble: %g\n", d[2]);
+}
+
+void testLocalDouble()
+{
+    double d[3];
+    float  m[12];
+    m[0] = 1.0f;
+    m[1] = 2.0f;
+    d[0] = 1.0;
+    d[1] = 2.0;
+    d[2] = d[0] + d[1];
+    m[2] = m[0] + m[1];
+    printf("localDouble: %g %g\n", d[2], m[2]);
+}
+
+void vectorAdd(int* a, int* b, float* c, int len) {
+    int i;
+    for(i = 0; i < len; i++) {
+        c[i] = a[i] + b[i];
+    }
+}
+
+void testArgs() {
+    int a[3], b[3];
+    float c[3];
+    int i;
+    int len = 3;
+    for(i = 0; i < len; i++) {
+        a[i] = i;
+        b[i] = i;
+        c[i] = 0;
+    }
+    vectorAdd(a,b,c, len);
+    printf("testArgs:");
+    for(i = 0; i < len; i++) {
+        printf(" %g", c[i]);
+    }
+    printf("\n");
+}
+
+void testDecay() {
+    char c[4];
+    c[0] = 'H';
+    c[1] = 'i';
+    c[2] = '!';
+    c[3] = 0;
+    printf("testDecay: %s\n", c);
+}
+
+void test2D() {
+    char c[10][20];
+    int x;
+    int y;
+    printf("test2D:\n");
+    for(y = 0; y < 10; y++) {
+        for(x = 0; x < 20; x++) {
+            c[y][x] = 'a' + (15 & (y * 19 + x));
+        }
+    }
+    for(y = 0; y < 10; y++) {
+        for(x = 0; x < 20; x++) {
+            printf("%c", c[y][x]);
+        }
+        printf("\n");
+    }
+
+}
+
+int main()
+{
+    testLocalInt();
+    testLocalDouble();
+    testGlobalChar();
+    testGlobalDouble();
+    testArgs();
+    testDecay();
+    test2D();
+    return 0;
+}
diff --git a/libacc/tests/data/assignment.c b/libacc/tests/data/assignment.c
new file mode 100644
index 0000000..4fc7801
--- /dev/null
+++ b/libacc/tests/data/assignment.c
@@ -0,0 +1,9 @@
+int main() {
+    int a = 0;
+    int b = 1;
+    a = b = 2; // Test that "b = 2" generates an rvalue.
+    if (a = 7) { // Test that a = 7 generates an rvalue.
+        b = 3;
+    }
+    return a;
+}
diff --git a/libacc/tests/data/assignmentop.c b/libacc/tests/data/assignmentop.c
new file mode 100644
index 0000000..649edf9
--- /dev/null
+++ b/libacc/tests/data/assignmentop.c
@@ -0,0 +1,62 @@
+// Test assignment operations
+
+void testAssignment() {
+    int a = 2;
+    a *= 5;
+    printf("2 *= 5  %d\n", a);
+    a = 20;
+    a /= 5;
+    printf("20 /= 5  %d\n", a);
+    a = 17;
+    a %= 5;
+    printf("17 %%= 5  %d\n", a);
+    a = 17;
+    a += 5;
+    printf("17 += 5  %d\n", a);
+    a = 17;
+    a-=5;
+    printf("17 -= 5  %d\n", a);
+    a = 17;
+    a<<=1;
+    printf("17<<= 1  %d\n", a);
+    a = 17;
+    a>>=1;
+    printf("17>>= 1  %d\n", a);
+    a = 17;
+    a&=1;
+    printf("17&= 1  %d\n", a);
+    a = 17;
+    a^=1;
+    printf("17^= 1  %d\n", a);
+    a = 16;
+    a^=1;
+    printf("16|= 1  %d\n", a);
+}
+
+int a;
+
+int* f() {
+    printf("f()\n");
+    return &a;
+}
+
+void testEval() {
+    a = 0;
+    printf("*f() = *f() + 10;\n");
+    *f() = *f() + 10;
+    printf("a = %d\n", a);
+}
+
+void testOpEval() {
+    a = 0;
+    printf("*f() += 10;\n");
+    *f() += 10;
+    printf("a = %d\n", a);
+}
+
+int main() {
+    testAssignment();
+    testEval();
+    testOpEval();
+    return 0;
+}
diff --git a/libacc/tests/data/b2071670.c b/libacc/tests/data/b2071670.c
new file mode 100644
index 0000000..311bc4f
--- /dev/null
+++ b/libacc/tests/data/b2071670.c
@@ -0,0 +1,9 @@
+// See http://b/2071670
+
+int main() {
+    float f = 10.0f;
+    float* floatPointer = &f;
+    // The following line used to incorrectly error: "Incompatible pointer or array types"
+    int* buffer = (int*) floatPointer;
+    return *buffer;
+}
diff --git a/libacc/tests/data/bellard.otccex.c b/libacc/tests/data/bellard.otccex.c
new file mode 100644
index 0000000..e8f0989
--- /dev/null
+++ b/libacc/tests/data/bellard.otccex.c
@@ -0,0 +1,126 @@
+/* #!/usr/local/bin/otcc */
+/*
+ * Sample OTCC C example. You can uncomment the first line and install
+ * otcc in /usr/local/bin to make otcc scripts !  
+ */
+
+/* Any preprocessor directive except #define are ignored. We put this
+   include so that a standard C compiler can compile this code too. */
+#include <stdio.h>
+
+/* defines are handled, but macro arguments cannot be given. No
+   recursive defines are tolerated */
+#define DEFAULT_BASE 10
+
+/*
+ * Only old style K&R prototypes are parsed. Only int arguments are
+ * allowed (implicit types).
+ * 
+ * By benchmarking the execution time of this function (for example
+ * for fib(35)), you'll notice that OTCC is quite fast because it
+ * generates native i386 machine code.  
+ */
+fib(n)
+{
+    if (n <= 2)
+        return 1;
+    else
+        return fib(n-1) + fib(n-2);
+}
+
+/* Identifiers are parsed the same way as C: begins with letter or
+   '_', and then letters, '_' or digits */
+fact(n)
+{
+    /* local variables can be declared. Only 'int' type is supported */
+    int i, r;
+    r = 1;
+    /* 'while' and 'for' loops are supported */
+    for(i=2;i<=n;i++)
+        r = r * i;
+    return r;
+}
+
+/* Well, we could use printf, but it would be too easy */
+print_num(n, b)
+{
+    int tab, p, c;
+    /* Numbers can be entered in decimal, hexadecimal ('0x' prefix) and
+       octal ('0' prefix) */
+    /* more complex programs use malloc */
+    tab = malloc(0x100); 
+    p = tab;
+    while (1) {
+        c = n % b;
+        /* Character constants can be used */
+        if (c >= 10)
+            c = c + 'a' - 10;
+        else
+            c = c + '0';
+        *(char *)p = c;
+        p++;
+        n = n / b;
+        /* 'break' is supported */
+        if (n == 0)
+            break;
+    }
+    while (p != tab) {
+        p--;
+        printf("%c", *(char *)p);
+    }
+    free(tab);
+}
+
+/* 'main' takes standard 'argc' and 'argv' parameters */
+main(argc, argv)
+{
+    /* no local name space is supported, but local variables ARE
+       supported. As long as you do not use a globally defined
+       variable name as local variable (which is a bad habbit), you
+       won't have any problem */
+    int s, n, f, base;
+    
+    /* && and || operator have the same semantics as C (left to right
+       evaluation and early exit) */
+    if (argc != 2 && argc != 3) {
+        /* '*' operator is supported with explicit casting to 'int *',
+           'char *' or 'int (*)()' (function pointer). Of course, 'int'
+           are supposed to be used as pointers too. */
+        s = *(int *)argv;
+        help(s);
+        return 1;
+    }
+    /* Any libc function can be used because OTCC uses dynamic linking */
+    n = atoi(*(int *)(argv + 4));
+    base = DEFAULT_BASE;
+    if (argc >= 3) {
+        base = atoi(*(int *)(argv + 8));
+        if (base < 2 || base > 36) {
+            /* external variables can be used too (here: 'stderr') */
+            fprintf(stderr, "Invalid base\n");
+            return 1;
+        }
+    }
+    printf("fib(%d) = ", n);
+    print_num(fib(n), base);
+    printf("\n");
+
+    printf("fact(%d) = ", n);
+    if (n > 12) {
+        printf("Overflow");
+    } else {
+        /* why not using a function pointer ? */
+        f = &fact;
+        print_num((*(int (*)())f)(n), base);
+    }
+    printf("\n");
+    return 0;
+}
+
+/* functions can be used before being defined */
+help(name)
+{
+    printf("usage: %s n [base]\n", name);
+    printf("Compute fib(n) and fact(n) and output the result in base 'base'\n");
+}
+
diff --git a/libacc/tests/data/brackets.c b/libacc/tests/data/brackets.c
new file mode 100644
index 0000000..bab88a2
--- /dev/null
+++ b/libacc/tests/data/brackets.c
@@ -0,0 +1,61 @@
+void testBrackets(int* ar, int len) {
+    int i;
+    int errors = 0;
+    for (i = 0; i < len; i++) {
+        ar[i] = i;
+    }
+    for (i = 0; i < len; i++) {
+        if (ar[i] != i) {
+            printf("error: [%d] %d != %d\n", i, ar[i], i);
+            errors++;
+        }
+    }
+    printf("Errors: %d\n", errors);
+}
+
+void testBrackets2D(int** ar2D, int lenX, int lenY) {
+    int x, y;
+    int errors = 0;
+    for (x = 0; x < lenX; x++) {
+        for (y = 0; y < lenY; y++) {
+            ar2D[x][y] = x * lenY + y;
+        }
+    }
+    for (x = 0; x < lenX; x++) {
+        for (y = 0; y < lenY; y++) {
+            int expected = x * lenY + y;
+            int val = ar2D[x][y];
+            if (val != expected) {
+                printf("error: [%d][%d] %d != %d\n", x, y, val, expected);
+                errors++;
+            }
+        }
+    }
+    printf("2D Errors: %d\n", errors);
+}
+
+void testHeap() {
+    int* ar = (int*) malloc(100);
+    testBrackets(ar, 25);
+    free(ar);
+}
+
+void testHeap2D() {
+    int lenX = 10;
+    int lenY = 5;
+    int* ar = (int*) malloc(lenX * lenY * 4);
+    int** ar2D = (int**) malloc(lenX * 4);
+    int i;
+    for(i = 0; i < lenX; i++) {
+        ar2D[i] = ar + lenY * i;
+    }
+    testBrackets2D(ar2D, lenX, lenY);
+    free(ar);
+    free(ar2D);
+}
+
+int main() {
+    testHeap();
+    testHeap2D();
+    return 0;
+}
diff --git a/libacc/tests/data/casts.c b/libacc/tests/data/casts.c
new file mode 100644
index 0000000..d3a49b4
--- /dev/null
+++ b/libacc/tests/data/casts.c
@@ -0,0 +1,85 @@
+void test1() {
+    int a = 3;
+    int* pb = &a;
+    int c = *pb;
+    printf("Reading from a pointer: %d %d\n", a, c);
+    *pb = 4;
+    printf("Writing to a pointer: %d\n", a);
+    printf("Testing casts: %d %g %g %d\n", 3, (float) 3, 4.5, (int) 4.5);
+}
+
+void test2() {
+    int x = 4;
+    int px = &x;
+    // int z = * px; // An error, expected a pointer type
+    int y = * (int*) px;
+    printf("Testing reading (int*): %d\n", y);
+}
+
+void test3() {
+    int px = (int) malloc(120);
+    * (int*) px = 8;
+    * (int*) (px + 4) = 9;
+    printf("Testing writing (int*): %d %d\n", * (int*) px, * (int*) (px + 4));
+    free((void*) px);
+}
+
+void test4() {
+    int x = 0x12345678;
+    int px = &x;
+    int a = * (char*) px;
+    int b = * (char*) (px + 1);
+    int c = * (char*) (px + 2);
+    int d = * (char*) (px + 3);
+    printf("Testing reading (char*): 0x%02x 0x%02x 0x%02x 0x%02x\n", a, b, c, d);
+}
+
+void test5() {
+    int x = 0xFFFFFFFF;
+    int px = &x;
+    * (char*) px = 0x21;
+    * (char*) (px + 1) = 0x43;
+    * (char*) (px + 2) = 0x65;
+    * (char*) (px + 3) = 0x87;
+    printf("Testing writing (char*): 0x%08x\n", x);
+}
+
+int f(int b) {
+    printf("f(%d)\n", b);
+    return 7 * b;
+}
+
+void test6() {
+    int fp = &f;
+    int x = (*(int(*)()) fp)(10);
+    printf("Function pointer result: %d\n", x);
+}
+
+void test7() {
+    int px = (int) malloc(120);
+    * (float*) px = 8.8f;
+    * (float*) (px + 4) = 9.9f;
+    printf("Testing read/write (float*): %g %g\n", * (float*) px, * (float*) (px + 4));
+    free((void*) px);
+}
+
+void test8() {
+    int px = (int) malloc(120);
+    * (double*) px = 8.8;
+    * (double*) (px + 8) = 9.9;
+    printf("Testing read/write (double*): %g %g\n", * (double*) px, * (double*) (px + 8));
+    free((void*) px);
+}
+
+
+int main() {
+    test1();
+    test2();
+    test3();
+    test4();
+    test5();
+    test6();
+    test7();
+    test8();
+    return 0;
+}
diff --git a/libacc/tests/data/char.c b/libacc/tests/data/char.c
new file mode 100644
index 0000000..8c63ba2
--- /dev/null
+++ b/libacc/tests/data/char.c
@@ -0,0 +1,13 @@
+char ga;
+char gb;
+
+int main() {
+    char a = 'c';
+    char b = a * 3;
+    printf("a = %d, b = %d\n", a, b);
+    ga = 'd';
+    gb = ga * 3;
+    printf("ga = %d, gb = %d\n", ga, gb);
+    return 0;
+}
+
diff --git a/libacc/tests/data/comma.c b/libacc/tests/data/comma.c
new file mode 100644
index 0000000..496944c
--- /dev/null
+++ b/libacc/tests/data/comma.c
@@ -0,0 +1,35 @@
+int testReturn() {
+    return 10, 20, 30;
+}
+
+int testArg(int a) {
+    return a;
+}
+
+void testComma() {
+    int a;
+    0, a = 10,20;
+    printf("statement: %d\n", a);
+    a = 1;
+    if (a = 0, 1) {
+        printf("if: a = %d\n", a);
+    }
+    int b = 0;
+    a = 10;
+    while(b++,a--) {}
+    printf("while: b = %d\n", b);
+    b = 0;
+    for(b++,a = 0;b++, a < 10; b++, a++) {}
+    printf("for: b = %d\n", b);
+    b = testReturn();
+    printf("return: %d\n", b);
+    b = testArg((a,12));
+    printf("arg: %d\n", b);
+}
+
+
+
+int main() {
+    testComma();
+    return 0;
+}
diff --git a/libacc/tests/data/constants.c b/libacc/tests/data/constants.c
new file mode 100644
index 0000000..230109a
--- /dev/null
+++ b/libacc/tests/data/constants.c
@@ -0,0 +1,30 @@
+#define FOO 0x10
+
+int main() {
+    printf("0 = %d\n", 0);
+    printf("010 = %d\n", 010);
+    printf("0x10 = %d\n", FOO);
+    printf("'\\a' = %d\n", '\a');
+    printf("'\\b' = %d\n", '\b');
+    printf("'\\f' = %d\n", '\f');
+    printf("'\\n' = %d\n", '\n');
+    printf("'\\r' = %d\n", '\r');
+    printf("'\\t' = %d\n", '\t');
+    printf("'\\v' = %d\n", '\v');
+    // Undefined
+    // printf("'\\z' = %d\n", '\z');
+    printf("'\\\\' = %d\n", '\\');
+    printf("'\\'' = %d\n", '\'');
+    printf("'\\\"' = %d\n", '\"');
+    printf("'\\?' = %d\n", '\?');
+    printf("'\\0' = %d\n", '\0');
+    printf("'\\1' = %d\n", '\1');
+    printf("'\\12' = %d\n", '\12');
+    printf("'\\123' = %d\n", '\123');
+    printf("'\\x0' = %d\n", '\x0');
+    printf("'\\x1' = %d\n", '\x1');
+    printf("'\\x12' = %d\n", '\x12');
+    printf("'\\x123' = %d\n", '\x123');
+    printf("'\\x1f' = %d\n", '\x1f');
+    printf("'\\x1F' = %d\n", '\x1F');
+}
diff --git a/libacc/tests/data/defines.c b/libacc/tests/data/defines.c
new file mode 100644
index 0000000..6cb6f7e
--- /dev/null
+++ b/libacc/tests/data/defines.c
@@ -0,0 +1,9 @@
+// Simple tests of the C preprocessor
+
+#define A 1
+#define A (4 / 2)
+#define B 1 // This is a comment. With a / in it.
+
+int main() {
+    return A + B;
+}
diff --git a/libacc/tests/data/double.c b/libacc/tests/data/double.c
new file mode 100644
index 0000000..5bc20a3
--- /dev/null
+++ b/libacc/tests/data/double.c
@@ -0,0 +1,7 @@
+double atof(char *nptr);
+
+int main() {
+    printf("Value = %g\n", atof("10.42"));
+    return 0;
+}
+
diff --git a/libacc/tests/data/error.c b/libacc/tests/data/error.c
new file mode 100644
index 0000000..2e08dcc
--- /dev/null
+++ b/libacc/tests/data/error.c
@@ -0,0 +1,2 @@
+void foo;
+
diff --git a/libacc/tests/data/expr-ansi.c b/libacc/tests/data/expr-ansi.c
new file mode 100644
index 0000000..d463659
--- /dev/null
+++ b/libacc/tests/data/expr-ansi.c
@@ -0,0 +1,60 @@
+/* Test operators */
+
+void testInc() { int a, b; a = 3; b = a++; printf("3++ = %d %d\n", b, a); }
+void testDec() { int a, b; a = 3; b = a--; printf("3-- = %d %d\n", b, a); }
+void testTimes(){ printf("%d * %d = %d\n", 10, 4, 10 * 4); }
+void testDiv(){ printf("%d / %d = %d\n", 11, 4, 11 / 4); }
+void testMod(){ printf("%d %% %d = %d\n", 11, 4, 11 % 4); }
+void testPlus(){ printf("%d + %d = %d\n", 10, 4, 10 + 4); }
+void testMinus(){ printf("%d - %d = %d\n", 10, 4, 10 - 4); }
+void testShiftLeft(){ printf("%d << %d = %d\n", 10, 4, 10 << 4); }
+void testShiftRight(){ printf("%d >> %d = %d\n", 100, 4, 100 >> 4); }
+void testLess(){ printf("%d < %d = %d\n", 10, 4, 10 < 4); }
+void testLesEqual(){ printf("%d <= %d = %d\n", 10, 4, 10 <= 4); }
+void testGreater(){ printf("%d > %d = %d\n", 10, 4, 10 > 4); }
+void testGreaterEqual(){ printf("%d >= %d = %d\n", 10, 4, 10 >= 4); }
+void testEqualTo(){ printf("%d == %d = %d\n", 10, 4, 10 == 4); }
+void testNotEqualTo(){ printf("%d != %d = %d\n", 10, 4, 10 != 4); }
+void testBitAnd(){ printf("%d & %d = %d\n", 10, 7, 10 & 7); }
+void testBitXor(){ printf("%d ^ %d = %d\n", 10, 7, 10 ^ 7); }
+void testBitOr(){ printf("%d | %d = %d\n", 10, 4, 10 | 4); }
+void testAssignment(){ int a, b; a = 3; b = a; printf("b == %d\n", b); }
+void testLogicalAnd(){ printf("%d && %d = %d\n", 10, 4, 10 && 4); }
+void testLogicalOr(){ printf("%d || %d = %d\n", 10, 4, 10 || 4); }
+void testAddressOf(){ int a; printf("&a is %d\n", &a); }
+void testPointerIndirection(){ int a, b; a = &b; b = 17; printf("*%d  = %d =?= %d\n", a, * (int*) a, b); }
+void testNegation(){ printf("-%d = %d\n", 10, -10); }
+void testUnaryPlus(){ printf("+%d = %d\n", 10, +10); }
+void testUnaryNot(){ printf("!%d = %d\n", 10, !10); }
+void testBitNot(){ printf("~%d = %d\n", 10, ~10); }
+
+int main(int a, char** b) {
+    testInc();
+    testDec();
+    testTimes();
+    testDiv();
+    testMod();
+    testPlus();
+    testMinus();
+    testShiftLeft();
+    testShiftRight();
+    testLess();
+    testLesEqual();
+    testGreater();
+    testGreaterEqual();
+    testEqualTo();
+    testNotEqualTo();
+    testBitAnd();
+    testBinXor();
+    testBitOr();
+    testAssignment();
+    testLogicalAnd();
+    testLogicalOr();
+    testAddressOf();
+    testPointerIndirection();
+    testNegation();
+    testUnaryPlus();
+    testUnaryNot();
+    testBitNot();
+    return 0;
+}
diff --git a/libacc/tests/data/expr.c b/libacc/tests/data/expr.c
new file mode 100644
index 0000000..4f2d2e7
--- /dev/null
+++ b/libacc/tests/data/expr.c
@@ -0,0 +1,60 @@
+/* Test operators */
+
+testInc() { int a, b; a = 3; b = a++; printf("3++ = %d %d\n", b, a); }
+testDec() { int a, b; a = 3; b = a--; printf("3-- = %d %d\n", b, a); }
+testTimes(){ printf("%d * %d = %d\n", 10, 4, 10 * 4); }
+testDiv(){ printf("%d / %d = %d\n", 11, 4, 11 / 4); }
+testMod(){ printf("%d %% %d = %d\n", 11, 4, 11 % 4); }
+testPlus(){ printf("%d + %d = %d\n", 10, 4, 10 + 4); }
+testMinus(){ printf("%d - %d = %d\n", 10, 4, 10 - 4); }
+testShiftLeft(){ printf("%d << %d = %d\n", 10, 4, 10 << 4); }
+testShiftRight(){ printf("%d >> %d = %d\n", 100, 4, 100 >> 4); }
+testLess(){ printf("%d < %d = %d\n", 10, 4, 10 < 4); }
+testLesEqual(){ printf("%d <= %d = %d\n", 10, 4, 10 <= 4); }
+testGreater(){ printf("%d > %d = %d\n", 10, 4, 10 > 4); }
+testGreaterEqual(){ printf("%d >= %d = %d\n", 10, 4, 10 >= 4); }
+testEqualTo(){ printf("%d == %d = %d\n", 10, 4, 10 == 4); }
+testNotEqualTo(){ printf("%d != %d = %d\n", 10, 4, 10 != 4); }
+testBitAnd(){ printf("%d & %d = %d\n", 10, 7, 10 & 7); }
+testBitXor(){ printf("%d ^ %d = %d\n", 10, 7, 10 ^ 7); }
+testBitOr(){ printf("%d | %d = %d\n", 10, 4, 10 | 4); }
+testAssignment(){ int a, b; a = 3; b = a; printf("b == %d\n", b); }
+testLogicalAnd(){ printf("%d && %d = %d\n", 10, 4, 10 && 4); }
+testLogicalOr(){ printf("%d || %d = %d\n", 10, 4, 10 || 4); }
+testAddressOf(){ int a; printf("&a is %d\n", &a); }
+testPointerIndirection(){ int a, b; a = &b; b = 17; printf("*%d  = %d =?= %d\n", a, * (int*) a, b); }
+testNegation(){ printf("-%d = %d\n", 10, -10); }
+testUnaryPlus(){ printf("+%d = %d\n", 10, +10); }
+testUnaryNot(){ printf("!%d = %d\n", 10, !10); }
+testBitNot(){ printf("~%d = %d\n", 10, ~10); }
+
+main(a,b) {
+    testInc();
+    testDec();
+    testTimes();
+    testDiv();
+    testMod();
+    testPlus();
+    testMinus();
+    testShiftLeft();
+    testShiftRight();
+    testLess();
+    testLesEqual();
+    testGreater();
+    testGreaterEqual();
+    testEqualTo();
+    testNotEqualTo();
+    testBitAnd();
+    testBinXor();
+    testBitOr();
+    testAssignment();
+    testLogicalAnd();
+    testLogicalOr();
+    testAddressOf();
+    testPointerIndirection();
+    testNegation();
+    testUnaryPlus();
+    testUnaryNot();
+    testBitNot();
+    return 0;
+}
\ No newline at end of file
diff --git a/libacc/tests/data/expr2.c b/libacc/tests/data/expr2.c
new file mode 100644
index 0000000..04b6a38
--- /dev/null
+++ b/libacc/tests/data/expr2.c
@@ -0,0 +1,6 @@
+/* Test operators */
+
+main() {
+    int a;
+    a = a++;
+}
diff --git a/libacc/tests/data/film.c b/libacc/tests/data/film.c
new file mode 100644
index 0000000..00c2d36
--- /dev/null
+++ b/libacc/tests/data/film.c
@@ -0,0 +1,53 @@
+// Test logical and bitwise AND and OR
+
+int test(int x, int y) {
+    int v = x || y;
+    return v;
+}
+
+int test2(int x, int y) {
+    if(x | y) {
+        return 1;
+    } else {
+        return 0;
+    }
+}
+
+int test3(int x, int y) {
+    int v = x && y;
+    return v;
+}
+
+int test4(int x, int y) {
+    if(x & y) {
+        return 1;
+    } else {
+        return 0;
+    }
+}
+
+int main(int index)
+{
+    int x,y;
+    printf("testing...\n");
+    int totalBad = 0;
+    for(y = 0; y < 2; y++) {
+        for(x = 0; x < 2; x++) {
+            int a = test(x,y);
+            int b = test2(x,y);
+            if (a != b) {
+                printf("Results differ: OR x=%d y=%d a=%d b=%d\n", x, y, a, b);
+                totalBad++;
+            }
+            a = test3(x,y);
+            b = test4(x,y);
+            if (a != b) {
+                printf("Results differ: AND x=%d y=%d a=%d b=%d\n", x, y, a, b);
+                totalBad++;
+            }
+        }
+    }
+    printf("Total bad: %d\n", totalBad);
+    return 0;
+}
+
diff --git a/libacc/tests/data/float.c b/libacc/tests/data/float.c
new file mode 100644
index 0000000..f48b3d1
--- /dev/null
+++ b/libacc/tests/data/float.c
@@ -0,0 +1,57 @@
+int ftoi(float f) {
+    return f;
+}
+
+int dtoi(double d) {
+    return d;
+}
+
+float itof(int i) {
+    return i;
+}
+
+double itod(int i) {
+    return i;
+}
+
+float f0, f1;
+double d0, d1;
+
+void testParseConsts() {
+    printf("Constants: %g %g %g %g %g %g %g %g %g\n", 0e1, 0E1, 0.f, .01f,
+          .01e0f, 1.0e-1, 1.0e1, 1.0e+1,
+          .1f);
+}
+void testVars(float arg0, float arg1, double arg2, double arg3) {
+    float local0, local1;
+    double local2, local3;
+    f0 = arg0;
+    f1 = arg1;
+    d0 = arg2;
+    d1 = arg3;
+    local0 = arg0;
+    local1 = arg1;
+    local2 = arg2;
+    local3 = arg3;
+    printf("globals: %g %g %g %g\n", f0, f1, d0, d1);
+    printf("args: %g %g %g %g\n", arg0, arg1, arg2, arg3);
+    printf("locals: %g %g %g %g\n", local0, local1, local2, local3);
+
+
+    printf("cast rval: %g %g\n", * (float*) & f1, * (double*) & d1);
+
+    * (float*) & f0 = 1.1f;
+    * (double*) & d0 = 3.3;
+    printf("cast lval: %g %g %g %g\n", f0, f1, d0, d1);
+}
+
+int main() {
+    testParseConsts();
+    printf("int: %d float: %g double: %g\n", 1, 2.2f, 3.3);
+    printf(" ftoi(1.4f)=%d\n", ftoi(1.4f));
+    printf(" dtoi(2.4)=%d\n", dtoi(2.4));
+    printf(" itof(3)=%g\n", itof(3));
+    printf(" itod(4)=%g\n", itod(4));
+    testVars(1.0f, 2.0f, 3.0, 4.0);
+    return 0;
+}
diff --git a/libacc/tests/data/floatdouble.c b/libacc/tests/data/floatdouble.c
new file mode 100644
index 0000000..264c641
--- /dev/null
+++ b/libacc/tests/data/floatdouble.c
@@ -0,0 +1,9 @@
+int main()
+{
+    // Test coercing values when storing.
+    float a = 0.002;
+    double b = 0.1f;
+    int c = 10.002;
+    printf("%g %g %d\n", a, b, c);
+    return 0;
+}
diff --git a/libacc/tests/data/flops.c b/libacc/tests/data/flops.c
new file mode 100644
index 0000000..40b1b28
--- /dev/null
+++ b/libacc/tests/data/flops.c
@@ -0,0 +1,158 @@
+// Test floating point operations.
+
+void unaryOps() {
+    // Unary ops
+    printf("-%g = %g\n", 1.1, -1.1);
+    printf("!%g = %d\n", 1.2, !1.2);
+    printf("!%g = %d\n", 0.0, !0.0);
+}
+
+void binaryOps() {
+    printf("double op double:\n");
+    printf("%g + %g = %g\n", 1.0, 2.0, 1.0 + 2.0);
+    printf("%g - %g = %g\n", 1.0, 2.0, 1.0 - 2.0);
+    printf("%g * %g = %g\n", 1.0, 2.0, 1.0 * 2.0);
+    printf("%g / %g = %g\n", 1.0, 2.0, 1.0 / 2.0);
+
+    printf("float op float:\n");
+    printf("%g + %g = %g\n", 1.0f, 2.0f, 1.0f + 2.0f);
+    printf("%g - %g = %g\n", 1.0f, 2.0f, 1.0f - 2.0f);
+    printf("%g * %g = %g\n", 1.0f, 2.0f, 1.0f * 2.0f);
+    printf("%g / %g = %g\n", 1.0f, 2.0f, 1.0f / 2.0f);
+
+    printf("double op float:\n");
+    printf("%g + %g = %g\n", 1.0, 2.0f, 1.0 + 2.0f);
+    printf("%g - %g = %g\n", 1.0, 2.0f, 1.0 - 2.0f);
+    printf("%g * %g = %g\n", 1.0, 2.0f, 1.0 * 2.0f);
+    printf("%g / %g = %g\n", 1.0, 2.0f, 1.0 / 2.0f);
+
+    printf("double op int:\n");
+    printf("%g + %d = %g\n", 1.0, 2, 1.0 + 2);
+    printf("%g - %d = %g\n", 1.0, 2, 1.0 - 2);
+    printf("%g * %d = %g\n", 1.0, 2, 1.0 * 2);
+    printf("%g / %d = %g\n", 1.0, 2, 1.0 / 2);
+
+    printf("int op double:\n");
+    printf("%d + %g = %g\n", 1, 2.0, 1 + 2.0);
+    printf("%d - %g = %g\n", 1, 2.0, 1 - 2.0);
+    printf("%d * %g = %g\n", 1, 2.0, 1 * 2.0);
+    printf("%d / %g = %g\n", 1, 2.0, 1 / 2.0);
+}
+
+void comparisonTestdd(double a, double b) {
+    printf("%g op %g: < %d   <= %d   == %d   >= %d   > %d   != %d\n",
+           a, b, a < b, a <= b, a == b, a >= b, a > b, a != b);
+}
+
+void comparisonOpsdd() {
+    printf("double op double:\n");
+    comparisonTestdd(1.0, 2.0);
+    comparisonTestdd(1.0, 1.0);
+    comparisonTestdd(2.0, 1.0);
+}
+
+
+void comparisonTestdf(double a, float b) {
+    printf("%g op %g: < %d   <= %d   == %d   >= %d   > %d   != %d\n",
+           a, b, a < b, a <= b, a == b, a >= b, a > b, a != b);
+}
+
+void comparisonOpsdf() {
+    printf("double op float:\n");
+    comparisonTestdf(1.0, 2.0f);
+    comparisonTestdf(1.0, 1.0f);
+    comparisonTestdf(2.0, 1.0f);
+}
+
+void comparisonTestff(float a, float b) {
+    printf("%g op %g: < %d   <= %d   == %d   >= %d   > %d   != %d\n",
+           a, b, a < b, a <= b, a == b, a >= b, a > b, a != b);
+}
+
+void comparisonOpsff() {
+    printf("float op float:\n");
+    comparisonTestff(1.0f, 2.0f);
+    comparisonTestff(1.0f, 1.0f);
+    comparisonTestff(2.0f, 1.0f);
+}
+
+void comparisonTestid(int a, double b) {
+    printf("%d op %g: < %d   <= %d   == %d   >= %d   > %d   != %d\n",
+           a, b, a < b, a <= b, a == b, a >= b, a > b, a != b);
+}
+
+void comparisonOpsid() {
+    printf("int op double:\n");
+    comparisonTestid(1, 2.0);
+    comparisonTestid(1, 1.0);
+    comparisonTestid(2, 1.0);
+}
+void comparisonTestdi(double a, int b) {
+    printf("%g op %d: < %d   <= %d   == %d   >= %d   > %d   != %d\n",
+           a, b, a < b, a <= b, a == b, a >= b, a > b, a != b);
+}
+
+void comparisonOpsdi() {
+    printf("double op int:\n");
+    comparisonTestdi(1.0f, 2);
+    comparisonTestdi(1.0f, 1);
+    comparisonTestdi(2.0f, 1);
+}
+
+void comparisonOps() {
+    comparisonOpsdd();
+    comparisonOpsdf();
+    comparisonOpsff();
+    comparisonOpsid();
+    comparisonOpsdi();
+}
+
+int branch(double d) {
+    if (d) {
+        return 1;
+    }
+    return 0;
+}
+
+void testBranching() {
+    printf("branching: %d %d %d\n", branch(-1.0), branch(0.0), branch(1.0));
+}
+
+void testpassi(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int k, int l) {
+    printf("testpassi: %d %d %d %d %d %d %d %d %d %d %d %d\n", a, b, c, d, e, f, g, h, i, j, k, l);
+}
+
+void testpassf(float a, float b, float c, float d, float e, float f, float g, float h, float i, float j, float k, float l) {
+    printf("testpassf: %g %g %g %g %g %g %g %g %g %g %g %g\n", a, b, c, d, e, f, g, h, i, j, k, l);
+}
+
+void testpassd(double a, double b, double c, double d, double e, double f, double g, double h, double i, double j, double k, double l) {
+    printf("testpassd: %g %g %g %g %g %g %g %g %g %g %g %g\n", a, b, c, d, e, f, g, h, i, j, k, l);
+}
+
+void testpassidf(int i, double d, float f) {
+    printf("testpassidf: %d %g %g\n", i, d, f);
+}
+
+void testParameterPassing() {
+    float x;
+    testpassi(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12);
+    testpassf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12);
+    testpassd(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12);
+    testpassi(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f);
+    testpassf(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f);
+    testpassd(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f);
+    testpassi(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0);
+    testpassf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0);
+    testpassd(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0);
+    testpassidf(1, 2.0, 3.0f);
+}
+
+int main() {
+    unaryOps();
+    binaryOps();
+    comparisonOps();
+    testBranching();
+    testParameterPassing();
+    return 0;
+}
diff --git a/libacc/tests/data/funcargs.c b/libacc/tests/data/funcargs.c
new file mode 100644
index 0000000..1dce226
--- /dev/null
+++ b/libacc/tests/data/funcargs.c
@@ -0,0 +1,8 @@
+int f(int a,int, int c) {
+    return a + c;
+}
+
+int main() {
+    return f(1,2,3);
+}
+
diff --git a/libacc/tests/data/hello.c b/libacc/tests/data/hello.c
new file mode 100644
index 0000000..585ce6c
--- /dev/null
+++ b/libacc/tests/data/hello.c
@@ -0,0 +1,3 @@
+main(a,b) {
+    printf("Hello, world\n");
+}
diff --git a/libacc/tests/data/inc.c b/libacc/tests/data/inc.c
new file mode 100644
index 0000000..14c09d1
--- /dev/null
+++ b/libacc/tests/data/inc.c
@@ -0,0 +1,14 @@
+// Check integer operations
+
+int main() {
+    int a = 0;
+    printf("%d\n", a++);
+    printf("%d\n", a++);
+    printf("%d\n", a--);
+    printf("%d\n", a--);
+    printf("%d\n", ++a);
+    printf("%d\n", ++a);
+    printf("%d\n", --a);
+    printf("%d\n", --a);
+    return a;
+}
diff --git a/libacc/tests/data/iops.c b/libacc/tests/data/iops.c
new file mode 100644
index 0000000..780e95d
--- /dev/null
+++ b/libacc/tests/data/iops.c
@@ -0,0 +1,23 @@
+// Check integer operations
+
+void loops() {
+    int y;
+    printf("++\n");
+    for(y = 0; y < 10; y++) {
+        printf("%d\n", y);
+    }
+    printf("--\n");
+    for(y = 10; y >= 0; y--) {
+        printf("%d\n", y);
+    }
+}
+
+void checkLiterals() {
+    printf("Literals: %d %d\n", 1, -1);
+}
+
+int main() {
+    checkLiterals();
+    loops();
+    return 0;
+}
diff --git a/libacc/tests/data/locals.c b/libacc/tests/data/locals.c
new file mode 100644
index 0000000..f1ef363
--- /dev/null
+++ b/libacc/tests/data/locals.c
@@ -0,0 +1,71 @@
+int a;
+
+int f() {
+    int a;
+    // Undefined variable b
+    // printf("f 0: a = %d b = %d\n", a, b);
+    printf("f 0: a = %d\n", a);
+    a = 2;
+    printf("f 1: a = %d\n", a);
+}
+
+int g(int a) {
+    printf("g 0: a = %d\n", a);
+    a = 3;
+    printf("g 1: a = %d\n", a);
+}
+
+int h(int a) {
+    // int a; // gcc 4.3 says error: 'a' redeclared as different kind of symbol
+
+    printf("h 0: a = %d\n", a);
+    a = 4;
+    printf("h 1: a = %d\n", a);
+}
+
+// Already defined global 
+// int h() {}
+int globCheck() {
+    fprintf(stdout, "globCheck()\n");
+}
+
+int fwdCheck() {
+    b();
+    // Undefined forward reference
+    // c();
+}
+
+int b() {
+    printf("b()\n");
+}
+
+int nested() {
+    int a;
+    printf("nested 0: a = %d\n", a);
+    a = 50;
+    printf("nested 1: a = %d\n", a);
+    {
+        int a;
+        printf("nested 2: a = %d\n", a);
+        a = 51;
+        printf("nested 3: a = %d\n", a);
+    }
+    printf("nested 4: a = %d\n", a);
+}
+
+int main() {
+    globCheck();
+    fwdCheck();
+    printf("main 0: a = %d\n", a);
+    a = 5;
+    printf("main 1: a = %d\n", a);
+    f();
+    printf("main 2: a = %d\n", a);
+    g(77);
+    printf("main 3: a = %d\n", a);
+    h(30);
+    printf("main 4: a = %d\n", a);
+    nested();
+    printf("main 5: a = %d\n", a);
+    return 0;
+}
diff --git a/libacc/tests/data/missing-main.c b/libacc/tests/data/missing-main.c
new file mode 100644
index 0000000..e73eec4
--- /dev/null
+++ b/libacc/tests/data/missing-main.c
@@ -0,0 +1,4 @@
+/* No main. */
+
+a() {
+}
\ No newline at end of file
diff --git a/libacc/tests/data/otcc-ansi.c b/libacc/tests/data/otcc-ansi.c
new file mode 100644
index 0000000..72580e9
--- /dev/null
+++ b/libacc/tests/data/otcc-ansi.c
@@ -0,0 +1,466 @@
+// #include <stdio.h>
+int d, z, C, h, P, K, ac, q, G, v, Q, R, D, L, W, M;
+
+void E(int e) {
+    *(char*) D++ = e;
+}
+
+void o() {
+    if (L) {
+        h = *(char*) L++;
+        if (h == 2) {
+            L = 0;
+            h = W;
+        }
+    } else
+        h = fgetc(Q);
+}
+
+int X() {
+    return isalnum(h) | h == 95;
+}
+
+void Y() {
+    if (h == 92) {
+        o();
+        if (h == 110)
+            h = 10;
+    }
+}
+
+void ad() {
+    int e, j, m;
+    while (isspace(h) | h == 35) {
+        if (h == 35) {
+            o();
+            ad();
+            if (d == 536) {
+                ad();
+                E(32);
+                *(int*) d = 1;
+                *(int*) (d + 4) = D;
+            }
+            while (h != 10) {
+                E(h);
+                o();
+            }
+            E(h);
+            E(2);
+        }
+        o();
+    }
+    C = 0;
+    d = h;	
+    if (X()) {
+        E(32);
+        M = D;
+        while (X()) {
+            E(h);
+            o();
+        }
+        if (isdigit(d)) {
+            z = strtol(M, 0, 0);
+            d = 2;
+        } else {
+            *(char*) D = 32;
+            d = strstr(R, M - 1) - R;
+            *(char*) D = 0;
+            d = d * 8 + 256;
+            if (d > 536) {
+                d = P + d;
+                if (*(int*) d == 1) {
+                    L = *(int*) (d + 4);
+                    W = h;
+                    o();
+                    ad();
+                }
+            }
+        }
+    } else {
+        o();
+        if (d == 39) {
+            d = 2;
+            Y();
+            z = h;
+            o();
+            o();
+        } else if (d == 47 & h == 42) {
+            o();
+            while (h) {
+                while (h != 42)
+                    o();
+                o();
+                if (h == 47)
+                    h = 0;
+            }
+            o();
+            ad();
+        } else {
+            e
+                    = "++#m--%am*@R<^1c/@%[_[H3c%@%[_[H3c+@.B#d-@%:_^BKd<<Z/03e>>`/03e<=0f>=/f<@.f>@1f==&g!='g&&k||#l&@.BCh^@.BSi|@.B+j~@/%Yd!@&d*@b";
+            while (j = *(char*) e++) {
+                m = *(char*) e++;
+                z = 0;
+                while ((C = *(char*) e++ - 98) < 0)
+                    z = z * 64 + C + 64;
+                if (j == d & (m == h | m == 64)) {
+                    if (m == h) {
+                        o();
+                        d = 1;
+                    }
+                    break;
+                }
+            }
+        }
+    }
+}
+
+void ae(int g) {
+    while( g&&g!=-1) {
+        *(char*) q++=g;
+        g=g>>8;
+    }
+}
+
+void A(int e) {
+    int g;
+    while( e) {
+        g=*(int*) e;
+        *(int*) e=q-e-4;
+        e=g;
+    }
+}
+
+int s(int g, int e) {
+    ae(g);
+    *(int*) q = e;
+    e = q;
+    q = q + 4;
+    return e;
+}
+
+void H(int e) {
+    s(184,e);
+}
+
+int B(int e) {
+    return s(233,e);
+}
+
+int S(int j, int e) {
+    ae(1032325);
+    return s(132 + j, e);
+}
+
+void Z(int e) {
+    ae( 49465);
+    H(0);
+    ae( 15);
+    ae( e+144);
+    ae( 192);
+}
+
+void N(int j, int e) {
+    ae(j + 131);
+    s((e > -512 && e < 512) << 7 | 5, e);
+}
+
+void T (int j) {
+    int g,e,m,aa;
+    g=1;
+    if( d == 34) {
+        H(v);
+        while( h!=34) {
+            Y ();
+            *(char*) v++=h;
+            o ();
+        }
+        *(char*) v=0;
+        v=v +4&-4;
+        o ();
+        ad();
+    }
+    else {
+        aa=C;
+        m= z;
+        e=d;
+        ad();
+        if( e == 2) {
+            H(m);
+        }
+        else if( aa == 2) {
+            T(0);
+            s(185,0);
+            if( e == 33)Z(m);
+            else ae( m);
+        }
+        else if( e == 40) {
+            w ();
+            ad();
+        }
+        else if( e == 42) {
+            ad();
+            e=d;
+            ad();
+            ad();
+            if( d == 42) {
+                ad();
+                ad();
+                ad();
+                ad();
+                e=0;
+            }
+            ad();
+            T(0);
+            if( d == 61) {
+                ad();
+                ae( 80);
+                w ();
+                ae( 89);
+                ae( 392+(e == 256));
+            }
+            else if( e) {
+                if( e == 256)ae( 139);
+                else ae( 48655);
+                q++;
+            }
+        }
+        else if( e == 38) {
+            N(10,*(int*) d);
+            ad();
+        }
+        else {
+            g=*(int*) e;
+            if(!g)g=dlsym(0,M);
+            if( d == 61&j) {
+                ad();
+                w ();
+                N(6,g);
+            }
+            else if( d!= 40) {
+                N(8,g);
+                if( C == 11) {
+                    N(0,g);
+                    ae( z);
+                    ad();
+                }
+            }
+        }
+    }
+    if( d == 40) {
+        if( g == 1)ae( 80);
+        m= s(60545,0);
+        ad();
+        j=0;
+        while( d!= 41) {
+            w ();
+            s(2393225,j);
+            if( d == 44)ad();
+            j=j +4;
+        }
+        *(int*) m= j;
+        ad();
+        if(!g) {
+            e=e +4;
+            *(int*) e=s(232,*(int*) e);
+        }
+        else if( g == 1) {
+            s(2397439,j);
+            j=j +4;
+        }
+        else {
+            s(232,g-q-5);
+        }
+        if( j)s(50305,j);
+    }
+}
+
+void O (int j) {
+    int e,g,m;
+    if( j--== 1)T(1);
+    else {
+        O (j);
+        m= 0;
+        while( j == C) {
+            g=d;
+            e=z;
+            ad();
+            if( j>8) {
+                m= S(e,m);
+                O (j);
+            }
+            else {
+                ae( 80);
+                O (j);
+                ae( 89);
+                if( j == 4|j == 5) {
+                    Z(e);
+                }
+                else {
+                    ae( e);
+                    if( g == 37)ae( 146);
+                }
+            }
+        }
+        if( m&&j>8) {
+            m= S(e,m);
+            H(e^1);
+            B(5);
+            A(m);
+            H(e);
+        }
+    }
+}
+
+void w() {
+    O(11);
+}
+
+int U() {
+    w();
+    return S(0, 0);
+}
+
+void I (int j) {
+    int m,g,e;
+    if( d == 288) {
+        ad();
+        ad();
+        m= U ();
+        ad();
+        I (j);
+        if( d == 312) {
+            ad();
+            g=B(0);
+            A(m);
+            I (j);
+            A(g);
+        }
+        else {
+            A(m);
+        }
+    }
+    else if( d == 352|d == 504) {
+        e=d;
+        ad();
+        ad();
+        if( e == 352) {
+            g=q;
+            m= U ();
+        }
+        else {
+            if( d!= 59)w ();
+            ad();
+            g=q;
+            m= 0;
+            if( d!= 59)m= U ();
+            ad();
+            if( d!= 41) {
+                e=B(0);
+                w ();
+                B(g-q-5);
+                A(e);
+                g=e +4;
+            }
+        }
+        ad();
+        I(&m);
+        B(g-q-5);
+        A(m);
+    }
+    else if( d == 123) {
+        ad();
+        ab(1);
+        while( d!= 125)I (j);
+        ad();
+    }
+    else {
+        if( d == 448) {
+            ad();
+            if( d!= 59)w ();
+            K=B(K);
+        }
+        else if( d == 400) {
+            ad();
+            *(int*) j=B(*(int*) j);
+        }
+        else if( d!= 59)w ();
+        ad();
+    }
+}
+
+void ab (int j) {
+    int m;
+    while( d == 256|d!=-1&!j) {
+        if( d == 256) {
+            ad();
+            while( d!= 59) {
+                if( j) {
+                    G=G +4;
+                    *(int*) d=-G;
+                }
+                else {
+                    *(int*) d=v;
+                    v=v +4;
+                }
+                ad();
+                if( d == 44)ad()	;
+            }
+            ad();
+        }
+        else {
+            A(*(int*)(d +4));
+            *(int*) d=q;
+            ad();
+            ad();
+            m= 8;
+            while( d!= 41) {
+                *(int*) d=m;
+                m= m +4;
+                ad();
+                if( d == 44)ad();
+            }
+            ad();
+            K=G=0;
+            ae( 15042901);
+            m= s(60545,0);
+            I(0);
+            A(K);
+            ae( 50121);
+            *(int*) m= G;
+        }
+    }
+}
+
+int run(int g, int e) {
+    return (*(int(*)()) *(int*) (P + 592))(g, e);
+}
+
+int main(int g, int e) {
+    int result;
+    Q = stdin;
+    if (g-- > 1) {
+        e = e + 4;
+        Q = fopen(*(int*) e, "r");
+        if (!Q) {
+            fprintf(stderr, "otcc-ansi.c: could not open file %s\n", *(int*) e);
+            return -2;
+        }
+    }
+    D = strcpy(R = calloc(1, 99999), " int if else while break return for define main ") + 48;
+    v = calloc(1, 99999);
+    q = ac = calloc(1, 99999);
+    P = calloc(1, 99999);
+    o();
+    ad();
+    ab(0);
+    if (mprotect(ac & (~ 4095), (99999 + 4095) & (~ 4095), 7)) {
+        printf("Mprotect failed. %d\n", errno);
+        return -1;
+    }
+    fprintf(stderr, "otcc-ansi.c: About to execute compiled code:\n");
+    result = run(g, e);
+    fprintf(stderr, "atcc-ansi.c: result: %d\n", result);
+    return result;
+}
+
diff --git a/libacc/tests/data/otcc-noinclude.c b/libacc/tests/data/otcc-noinclude.c
new file mode 100644
index 0000000..530f9e2
--- /dev/null
+++ b/libacc/tests/data/otcc-noinclude.c
@@ -0,0 +1,446 @@
+// #include <stdio.h>
+#define k *(int*)
+#define a if(
+#define c ad()
+#define i else
+#define p while(
+#define x *(char*)
+#define b ==
+#define V =calloc(1,99999)
+#define f ()
+#define J return
+#define l ae(
+#define n e)
+#define u d!=
+#define F int 
+#define y (j)
+#define r m=
+#define t +4
+F d,z,C,h,P,K,ac,q,G,v,Q,R,D,L,W,M;
+E(n{
+x D++=e;
+}
+o f{
+a L){
+h=x L++;
+a h b 2){
+L=0;
+h=W;
+}
+}
+i h=fgetc(Q);
+}
+X f{
+J isalnum(h)|h b 95;
+}
+Y f{
+a h b 92){
+o f;
+a h b 110)h=10;
+}
+}
+c{
+F e,j,m;
+p isspace(h)|h b 35){
+a h b 35){
+o f;
+c;
+a d b 536){
+c;
+E(32);
+k d=1;
+k(d t)=D;
+}
+p h!=10){
+E(h);
+o f;
+}
+E(h);
+E(2);
+}
+o f;
+}
+C=0;
+d=h;
+a X f){
+E(32);
+M=D;
+p X f){
+E(h);
+o f;
+}
+a isdigit(d)){
+z=strtol(M,0,0);
+d=2;
+}
+i{
+x D=32;
+d=strstr(R,M-1)-R;
+x D=0;
+d=d*8+256;
+a d>536){
+d=P+d;
+a k d b 1){
+L=k(d t);
+W=h;
+o f;
+c;
+}
+}
+}
+}
+i{
+o f;
+a d b 39){
+d=2;
+Y f;
+z=h;
+o f;
+o f;
+}
+i a d b 47&h b 42){
+o f;
+p h){
+p h!=42)o f;
+o f;
+a h b 47)h=0;
+}
+o f;
+c;
+}
+i{
+e="++#m--%am*@R<^1c/@%[_[H3c%@%[_[H3c+@.B#d-@%:_^BKd<<Z/03e>>`/03e<=0f>=/f<@.f>@1f==&g!='g&&k||#l&@.BCh^@.BSi|@.B+j~@/%Yd!@&d*@b";
+p j=x e++){
+r x e++;
+z=0;
+p(C=x e++-98)<0)z=z*64+C+64;
+a j b d&(m b h|m b 64)){
+a m b h){
+o f;
+d=1;
+}
+break;
+}
+}
+}
+}
+}
+l g){
+p g&&g!=-1){
+x q++=g;
+g=g>>8;
+}
+}
+A(n{
+F g;
+p n{
+g=k e;
+k e=q-e-4;
+e=g;
+}
+}
+s(g,n{
+l g);
+k q=e;
+e=q;
+q=q t;
+J e;
+}
+H(n{
+s(184,n;
+}
+B(n{
+J s(233,n;
+}
+S(j,n{
+l 1032325);
+J s(132+j,n;
+}
+Z(n{
+l 49465);
+H(0);
+l 15);
+l e+144);
+l 192);
+}
+N(j,n{
+l j+131);
+s((e<512)<<7|5,n;
+}
+T y{
+F g,e,m,aa;
+g=1;
+a d b 34){
+H(v);
+p h!=34){
+Y f;
+x v++=h;
+o f;
+}
+x v=0;
+v=v t&-4;
+o f;
+c;
+}
+i{
+aa=C;
+r z;
+e=d;
+c;
+a e b 2){
+H(m);
+}
+i a aa b 2){
+T(0);
+s(185,0);
+a e b 33)Z(m);
+i l m);
+}
+i a e b 40){
+w f;
+c;
+}
+i a e b 42){
+c;
+e=d;
+c;
+c;
+a d b 42){
+c;
+c;
+c;
+c;
+e=0;
+}
+c;
+T(0);
+a d b 61){
+c;
+l 80);
+w f;
+l 89);
+l 392+(e b 256));
+}
+i a n{
+a e b 256)l 139);
+i l 48655);
+q++;
+}
+}
+i a e b 38){
+N(10,k d);
+c;
+}
+i{
+g=k e;
+a!g)g=dlsym(0,M);
+a d b 61&j){
+c;
+w f;
+N(6,g);
+}
+i a u 40){
+N(8,g);
+a C b 11){
+N(0,g);
+l z);
+c;
+}
+}
+}
+}
+a d b 40){
+a g b 1)l 80);
+r s(60545,0);
+c;
+j=0;
+p u 41){
+w f;
+s(2393225,j);
+a d b 44)c;
+j=j t;
+}
+k r j;
+c;
+a!g){
+e=e t;
+k e=s(232,k n;
+}
+i a g b 1){
+s(2397439,j);
+j=j t;
+}
+i{
+s(232,g-q-5);
+}
+a j)s(50305,j);
+}
+}
+O y{
+F e,g,m;
+a j--b 1)T(1);
+i{
+O y;
+r 0;
+p j b C){
+g=d;
+e=z;
+c;
+a j>8){
+r S(e,m);
+O y;
+}
+i{
+l 80);
+O y;
+l 89);
+a j b 4|j b 5){
+Z(n;
+}
+i{
+l n;
+a g b 37)l 146);
+}
+}
+}
+a m&&j>8){
+r S(e,m);
+H(e^1);
+B(5);
+A(m);
+H(n;
+}
+}
+}
+w f{
+O(11);
+}
+U f{
+w f;
+J S(0,0);
+}
+I y{
+F m,g,e;
+a d b 288){
+c;
+c;
+r U f;
+c;
+I y;
+a d b 312){
+c;
+g=B(0);
+A(m);
+I y;
+A(g);
+}
+i{
+A(m);
+}
+}
+i a d b 352|d b 504){
+e=d;
+c;
+c;
+a e b 352){
+g=q;
+r U f;
+}
+i{
+a u 59)w f;
+c;
+g=q;
+r 0;
+a u 59)r U f;
+c;
+a u 41){
+e=B(0);
+w f;
+B(g-q-5);
+A(n;
+g=e t;
+}
+}
+c;
+I(&m);
+B(g-q-5);
+A(m);
+}
+i a d b 123){
+c;
+ab(1);
+p u 125)I y;
+c;
+}
+i{
+a d b 448){
+c;
+a u 59)w f;
+K=B(K);
+}
+i a d b 400){
+c;
+k j=B(k j);
+}
+i a u 59)w f;
+c;
+}
+}
+ab y{
+F m;
+p d b 256|u-1&!j){
+a d b 256){
+c;
+p u 59){
+a j){
+G=G t;
+k d=-G;
+}
+i{
+k d=v;
+v=v t;
+}
+c;
+a d b 44)c;
+}
+c;
+}
+i{
+A(k(d t));
+k d=q;
+c;
+c;
+r 8;
+p u 41){
+k d=m;
+r m t;
+c;
+a d b 44)c;
+}
+c;
+K=G=0;
+l 15042901);
+r s(60545,0);
+I(0);
+A(K);
+l 50121);
+k r G;
+}
+}
+}
+main(g,n{
+Q=stdin;
+a g-->1){
+e=e t;
+Q=fopen(k e,"r");
+}
+D=strcpy(R V," int if else while break return for define main ")+48;
+v V;
+q=ac V;
+P V;
+o f;
+c;
+ab(0);
+J(*(int(*)f)k(P+592))(g,n;
+}
+
diff --git a/libacc/tests/data/otcc.c b/libacc/tests/data/otcc.c
new file mode 100644
index 0000000..433ae2e
--- /dev/null
+++ b/libacc/tests/data/otcc.c
@@ -0,0 +1,448 @@
+#include <stdio.h>
+#define k *(int*)
+#define a if(
+#define c ad()
+#define i else
+#define p while(
+#define x *(char*)
+#define b ==
+#define V =calloc(1,99999)
+#define f ()
+#define J return
+#define l ae(
+#define n e)
+#define u d!=
+#define F int 
+#define y (j)
+#define r m=
+#define t +4
+F d,z,C,h,P,K,ac,q,G,v,Q,R,D,L,W,M;
+E(n{
+x D++=e;
+}
+o f{
+a L){
+h=x L++;
+a h b 2){
+L=0;
+h=W;
+}
+}
+i h=fgetc(Q);
+}
+X f{
+J isalnum(h)|h b 95;
+}
+Y f{
+a h b 92){
+o f;
+a h b 110)h=10;
+}
+}
+c{
+F e,j,m;
+p isspace(h)|h b 35){
+a h b 35){
+o f;
+c;
+a d b 536){
+c;
+E(32);
+k d=1;
+k(d t)=D;
+}
+p h!=10){
+E(h);
+o f;
+}
+E(h);
+E(2);
+}
+o f;
+}
+C=0;
+d=h;
+a X f){
+E(32);
+M=D;
+p X f){
+E(h);
+o f;
+}
+a isdigit(d)){
+z=strtol(M,0,0);
+d=2;
+}
+i{
+x D=32;
+d=strstr(R,M-1)-R;
+x D=0;
+d=d*8+256;
+a d>536){
+d=P+d;
+a k d b 1){
+L=k(d t);
+W=h;
+o f;
+c;
+}
+}
+}
+}
+i{
+o f;
+a d b 39){
+d=2;
+Y f;
+z=h;
+o f;
+o f;
+}
+i a d b 47&h b 42){
+o f;
+p h){
+p h!=42)o f;
+o f;
+a h b 47)h=0;
+}
+o f;
+c;
+}
+i{
+e="++#m--%am*@R<^1c/@%[_[H3c%@%[_[H3c+@.B#d-@%:_^BKd<<Z/03e>>`/03e<=0f>=/f<@.f>@1f==&g!='g&&k||#l&@.BCh^@.BSi|@.B+j~@/%Yd!@&d*@b";
+p j=x e++){
+r x e++;
+z=0;
+p(C=x e++-98)<0)z=z*64+C+64;
+a j b d&(m b h|m b 64)){
+a m b h){
+o f;
+d=1;
+}
+break;
+}
+}
+}
+}
+}
+l g){
+p g&&g!=-1){
+x q++=g;
+g=g>>8;
+}
+}
+A(n{
+F g;
+p n{
+g=k e;
+k e=q-e-4;
+e=g;
+}
+}
+s(g,n{
+l g);
+k q=e;
+e=q;
+q=q t;
+J e;
+}
+H(n{
+s(184,n;
+}
+B(n{
+J s(233,n;
+}
+S(j,n{
+l 1032325);
+J s(132+j,n;
+}
+Z(n{
+l 49465);
+H(0);
+l 15);
+l e+144);
+l 192);
+}
+N(j,n{
+l j+131);
+s((e<512)<<7|5,n;
+}
+T y{
+F g,e,m,aa;
+g=1;
+a d b 34){
+H(v);
+p h!=34){
+Y f;
+x v++=h;
+o f;
+}
+x v=0;
+v=v t&-4;
+o f;
+c;
+}
+i{
+aa=C;
+r z;
+e=d;
+c;
+a e b 2){
+H(m);
+}
+i a aa b 2){
+T(0);
+s(185,0);
+a e b 33)Z(m);
+i l m);
+}
+i a e b 40){
+w f;
+c;
+}
+i a e b 42){
+c;
+e=d;
+c;
+c;
+a d b 42){
+c;
+c;
+c;
+c;
+e=0;
+}
+c;
+T(0);
+a d b 61){
+c;
+l 80);
+w f;
+l 89);
+l 392+(e b 256));
+}
+i a n{
+a e b 256)l 139);
+i l 48655);
+q++;
+}
+}
+i a e b 38){
+N(10,k d);
+c;
+}
+i{
+g=k e;
+a!g)g=dlsym(0,M);
+a d b 61&j){
+c;
+w f;
+N(6,g);
+}
+i a u 40){
+N(8,g);
+a C b 11){
+N(0,g);
+l z);
+c;
+}
+}
+}
+}
+a d b 40){
+a g b 1)l 80);
+r s(60545,0);
+c;
+j=0;
+p u 41){
+w f;
+s(2393225,j);
+a d b 44)c;
+j=j t;
+}
+k r j;
+c;
+a!g){
+e=e t;
+k e=s(232,k n;
+}
+i a g b 1){
+s(2397439,j);
+j=j t;
+}
+i{
+s(232,g-q-5);
+}
+a j)s(50305,j);
+}
+}
+O y{
+F e,g,m;
+a j--b 1)T(1);
+i{
+O y;
+r 0;
+p j b C){
+g=d;
+e=z;
+c;
+a j>8){
+r S(e,m);
+O y;
+}
+i{
+l 80);
+O y;
+l 89);
+a j b 4|j b 5){
+Z(n;
+}
+i{
+l n;
+a g b 37)l 146);
+}
+}
+}
+a m&&j>8){
+r S(e,m);
+H(e^1);
+B(5);
+A(m);
+H(n;
+}
+}
+}
+w f{
+O(11);
+}
+U f{
+w f;
+J S(0,0);
+}
+I y{
+F m,g,e;
+a d b 288){
+c;
+c;
+r U f;
+c;
+I y;
+a d b 312){
+c;
+g=B(0);
+A(m);
+I y;
+A(g);
+}
+i{
+A(m);
+}
+}
+i a d b 352|d b 504){
+e=d;
+c;
+c;
+a e b 352){
+g=q;
+r U f;
+}
+i{
+a u 59)w f;
+c;
+g=q;
+r 0;
+a u 59)r U f;
+c;
+a u 41){
+e=B(0);
+w f;
+B(g-q-5);
+A(n;
+g=e t;
+}
+}
+c;
+I(&m);
+B(g-q-5);
+A(m);
+}
+i a d b 123){
+c;
+ab(1);
+p u 125)I y;
+c;
+}
+i{
+a d b 448){
+c;
+a u 59)w f;
+K=B(K);
+}
+i a d b 400){
+c;
+k j=B(k j);
+}
+i a u 59)w f;
+c;
+}
+}
+ab y{
+F m;
+p d b 256|u-1&!j){
+a d b 256){
+c;
+p u 59){
+a j){
+G=G t;
+k d=-G;
+}
+i{
+k d=v;
+v=v t;
+}
+c;
+a d b 44)c;
+}
+c;
+}
+i{
+A(k(d t));
+k d=q;
+c;
+c;
+r 8;
+p u 41){
+k d=m;
+r m t;
+c;
+a d b 44)c;
+}
+c;
+K=G=0;
+l 15042901);
+r s(60545,0);
+I(0);
+A(K);
+l 50121);
+k r G;
+}
+}
+}
+main(g,n{
+Q=stdin;
+a g-->1){
+e=e t;
+Q=fopen(k e,"r");
+}
+D=strcpy(R V," int if else while break return for define main ")+48;
+v V;
+q=ac V;
+P V;
+o f;
+c;
+ab(0);
+mprotect(ac & (~ 4095), (99999 + 4095) & (~ 4095), 7);
+fprintf(stderr, "otcc.c: about to execute compiled code.\n");
+J(*(int(*)f)k(P+592))(g,n;
+}
+
diff --git a/libacc/tests/data/pointers.c b/libacc/tests/data/pointers.c
new file mode 100644
index 0000000..461ebeb
--- /dev/null
+++ b/libacc/tests/data/pointers.c
@@ -0,0 +1,15 @@
+int main() {
+    int* pa = (int*) malloc(100);
+    int* pb = pa + 1;
+    int* pc = (int*) 0;
+    *pa = 1;
+    *pb = 2;
+    printf("Pointer difference: %d %d\n", pb - pa, ((int) pb) - ((int) pa));
+    int c = * (pa + 1);
+    printf("Pointer addition: %d\n", c);
+    printf("Pointer comparison to zero: %d %d %d\n", pa == 0, pb == 0, pc == 0);
+    printf("Pointer comparison: %d %d %d %d %d\n", pa < pb, pa == pb, pa > pb, ! pb, ! pc);
+    free(pa);
+    return 0;
+}
+
diff --git a/libacc/tests/data/pointers2.c b/libacc/tests/data/pointers2.c
new file mode 100644
index 0000000..69e402f
--- /dev/null
+++ b/libacc/tests/data/pointers2.c
@@ -0,0 +1,35 @@
+// Test multiple levels of indirection
+
+void testsingle() {
+    int a = 0;
+    int* pa = &a;
+    printf("a = %d, *pa = %d\n", a, *pa);
+    *pa = 2;
+    printf("a = %d, *pa = %d\n", a, *pa);
+}
+
+void testdouble() {
+    int a = 0;
+    int* pa = &a;
+    int** ppa = &pa;
+    printf("a = %d, *pa = %d **ppa = %d\n", a, *pa, **ppa);
+    **ppa = 2;
+    printf("a = %d, *pa = %d **ppa = %d\n", a, *pa, **ppa);
+}
+
+void testtripple() {
+    int a = 0;
+    int* pa = &a;
+    int** ppa = &pa;
+    int*** pppa = &ppa;
+    printf("a = %d, *pa = %d **ppa = %d\n ***pppa = %d", a, *pa, **ppa, ***pppa);
+    ***pppa = 2;
+    printf("a = %d, *pa = %d **ppa = %d\n ***pppa = %d", a, *pa, **ppa, ***pppa);
+}
+
+int main() {
+    testsingle();
+    testdouble();
+    testdouble();
+    return 0;
+}
diff --git a/libacc/tests/data/returnval-ansi.c b/libacc/tests/data/returnval-ansi.c
new file mode 100644
index 0000000..6b53fd5
--- /dev/null
+++ b/libacc/tests/data/returnval-ansi.c
@@ -0,0 +1,8 @@
+
+int main(int argc, char** argv) {
+  return f();
+}
+
+int f() {
+    return 42;
+}
diff --git a/libacc/tests/data/returnval.c b/libacc/tests/data/returnval.c
new file mode 100644
index 0000000..1cf5bae
--- /dev/null
+++ b/libacc/tests/data/returnval.c
@@ -0,0 +1,4 @@
+main() {
+  return 42;
+}
+
diff --git a/libacc/tests/data/rollo3.c b/libacc/tests/data/rollo3.c
new file mode 100644
index 0000000..b21c12f
--- /dev/null
+++ b/libacc/tests/data/rollo3.c
@@ -0,0 +1,9 @@
+
+float fabsf(float);
+
+int main(void* con, int ft, int launchID)
+{
+   float f =  fabsf(-10.0f);
+   return f;
+}
+
diff --git a/libacc/tests/data/short.c b/libacc/tests/data/short.c
new file mode 100644
index 0000000..5e222f3
--- /dev/null
+++ b/libacc/tests/data/short.c
@@ -0,0 +1,6 @@
+short a = 3;
+int main() {
+    short* b = &a;
+    *b = *b - 5;
+    return a;
+}
diff --git a/libacc/tests/data/simplest.c b/libacc/tests/data/simplest.c
new file mode 100644
index 0000000..bae895a
--- /dev/null
+++ b/libacc/tests/data/simplest.c
@@ -0,0 +1 @@
+main() {}
diff --git a/libacc/tests/data/structs.c b/libacc/tests/data/structs.c
new file mode 100644
index 0000000..dd81af3
--- /dev/null
+++ b/libacc/tests/data/structs.c
@@ -0,0 +1,95 @@
+// struct definition and declaration
+struct a {
+    int a;
+    int b;
+} c;
+
+// Useless, but legal struct declaration
+struct {
+    int x;
+};
+
+// Useful anonymous struct declaration
+struct {
+    int y;
+} anon1, anon2;
+
+// forward declarations
+struct a;
+struct b;
+struct c;
+
+struct b {int a; int b; };
+
+// struct c {b g; }; // syntax error.
+
+// struct s {float c,a,b,c;} s; // duplicate struct member
+
+struct c {struct b g; };
+
+// struct a { int w; }; // error
+
+void testCopying() {
+    struct a {int a[10]; char c;} a, b;
+    a.c = 37;
+    b.c = 38;
+    b = a;
+    printf("testCopying: %d == %d\n", a.c, b.c);
+}
+
+void testUnion() {
+    union u;
+    union u {float f;int i;} u;
+    u.f = 1.0f;
+    printf("testUnion: %g == 0x%08x\n", u.f, u.i);
+}
+
+struct v {float x, y, z, w; };
+
+void add(struct v* result, struct v* a, struct v* b) {
+    result->x = a->x + b->x;
+    result->y = a->y + b->y;
+    result->z = a->z + b->z;
+    result->w = a->w + b->w;
+}
+
+void set(struct v* v, float x, float y, float z, float w) {
+    v->x = x;
+    v->y = y;
+    v->z = z;
+    v->w = w;
+}
+
+void print(struct v* v) {
+    printf("(%g, %g, %g, %g)\n", v->x, v->y, v->z, v->w);
+}
+
+void testArgs() {
+    struct v a, b, c;
+    set(&a, 1.0f, 2.0f, 3.0f, 4.0f);
+    set(&b, 5.0f, 6.0f, 7.0f, 8.0f);
+    add(&c, &a, &b);
+    printf("testArgs: ");
+    print(&c);
+}
+
+int main() {
+    anon1.y = 3;
+    anon2.y = anon1.y;
+
+    testCopying();
+    testUnion();
+    testArgs();
+
+    struct c cc;
+    cc.g.a = 3;
+    c.a = 1;
+    c.b = 3;
+    struct a {int x, y; } z;
+    // struct a {int x, y; } z2;
+    z.x = c.a;
+    struct a *pA;
+    pA = &z;
+    pA->x += 5;
+    return pA->x;
+}
diff --git a/libacc/tests/data/testStringConcat.c b/libacc/tests/data/testStringConcat.c
new file mode 100644
index 0000000..bf06ae1
--- /dev/null
+++ b/libacc/tests/data/testStringConcat.c
@@ -0,0 +1,4 @@
+int main() {
+    return printf("Hello" "," " world\n");
+}
+
diff --git a/libacc/tests/disassem.cpp b/libacc/tests/disassem.cpp
new file mode 100644
index 0000000..ac35342
--- /dev/null
+++ b/libacc/tests/disassem.cpp
@@ -0,0 +1,711 @@
+/*	$NetBSD: disassem.c,v 1.14 2003/03/27 16:58:36 mycroft Exp $	*/
+
+/*-
+ * Copyright (c) 1996 Mark Brinicombe.
+ * Copyright (c) 1996 Brini.
+ *
+ * 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. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``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 BRINI OR CONTRIBUTORS 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.
+ *
+ * RiscBSD kernel project
+ *
+ * db_disasm.c
+ *
+ * Kernel disassembler
+ *
+ * Created      : 10/02/96
+ *
+ * Structured after the sparc/sparc/db_disasm.c by David S. Miller &
+ * Paul Kranenburg
+ *
+ * This code is not complete. Not all instructions are disassembled.
+ */
+
+#include <sys/cdefs.h>
+//__FBSDID("$FreeBSD: /repoman/r/ncvs/src/sys/arm/arm/disassem.c,v 1.2 2005/01/05 21:58:47 imp Exp $");
+#include <sys/param.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#include "disassem.h"
+#include "armreg.h"
+//#include <ddb/ddb.h>
+
+/*
+ * General instruction format
+ *
+ *	insn[cc][mod]	[operands]
+ *
+ * Those fields with an uppercase format code indicate that the field
+ * follows directly after the instruction before the separator i.e.
+ * they modify the instruction rather than just being an operand to
+ * the instruction. The only exception is the writeback flag which
+ * follows a operand.
+ *
+ *
+ * 2 - print Operand 2 of a data processing instruction
+ * d - destination register (bits 12-15)
+ * n - n register (bits 16-19)
+ * s - s register (bits 8-11)
+ * o - indirect register rn (bits 16-19) (used by swap)
+ * m - m register (bits 0-3)
+ * a - address operand of ldr/str instruction
+ * e - address operand of ldrh/strh instruction
+ * l - register list for ldm/stm instruction
+ * f - 1st fp operand (register) (bits 12-14)
+ * g - 2nd fp operand (register) (bits 16-18)
+ * h - 3rd fp operand (register/immediate) (bits 0-4)
+ * b - branch address
+ * t - thumb branch address (bits 24, 0-23)
+ * k - breakpoint comment (bits 0-3, 8-19)
+ * X - block transfer type
+ * Y - block transfer type (r13 base)
+ * c - comment field bits(0-23)
+ * p - saved or current status register
+ * F - PSR transfer fields
+ * D - destination-is-r15 (P) flag on TST, TEQ, CMP, CMN
+ * L - co-processor transfer size
+ * S - set status flag
+ * P - fp precision
+ * Q - fp precision (for ldf/stf)
+ * R - fp rounding
+ * v - co-processor data transfer registers + addressing mode
+ * W - writeback flag
+ * x - instruction in hex
+ * # - co-processor number
+ * y - co-processor data processing registers
+ * z - co-processor register transfer registers
+ */
+
+struct arm32_insn {
+	u_int mask;
+	u_int pattern;
+	const char* name;
+	const char* format;
+};
+
+static const struct arm32_insn arm32_i[] = {
+    { 0x0fffffff, 0x0ff00000, "imb",	"c" },		/* Before swi */
+    { 0x0fffffff, 0x0ff00001, "imbrange",	"c" },	/* Before swi */
+    { 0x0f000000, 0x0f000000, "swi",	"c" },
+    { 0xfe000000, 0xfa000000, "blx",	"t" },		/* Before b and bl */
+    { 0x0f000000, 0x0a000000, "b",	"b" },
+    { 0x0f000000, 0x0b000000, "bl",	"b" },
+    { 0x0fe000f0, 0x00000090, "mul",	"Snms" },
+    { 0x0fe000f0, 0x00200090, "mla",	"Snmsd" },
+    { 0x0fe000f0, 0x00800090, "umull",	"Sdnms" },
+    { 0x0fe000f0, 0x00c00090, "smull",	"Sdnms" },
+    { 0x0fe000f0, 0x00a00090, "umlal",	"Sdnms" },
+    { 0x0fe000f0, 0x00e00090, "smlal",	"Sdnms" },
+    { 0x0d700000, 0x04200000, "strt",	"daW" },
+    { 0x0d700000, 0x04300000, "ldrt",	"daW" },
+    { 0x0d700000, 0x04600000, "strbt",	"daW" },
+    { 0x0d700000, 0x04700000, "ldrbt",	"daW" },
+    { 0x0c500000, 0x04000000, "str",	"daW" },
+    { 0x0c500000, 0x04100000, "ldr",	"daW" },
+    { 0x0c500000, 0x04400000, "strb",	"daW" },
+    { 0x0c500000, 0x04500000, "ldrb",	"daW" },
+    { 0x0e1f0000, 0x080d0000, "stm",	"YnWl" },/* separate out r13 base */
+    { 0x0e1f0000, 0x081d0000, "ldm",	"YnWl" },/* separate out r13 base */    
+    { 0x0e100000, 0x08000000, "stm",	"XnWl" },
+    { 0x0e100000, 0x08100000, "ldm",	"XnWl" },    
+    { 0x0e1000f0, 0x00100090, "ldrb",	"deW" },
+    { 0x0e1000f0, 0x00000090, "strb",	"deW" },
+    { 0x0e1000f0, 0x001000d0, "ldrsb",	"deW" },
+    { 0x0e1000f0, 0x001000b0, "ldrh",	"deW" },
+    { 0x0e1000f0, 0x000000b0, "strh",	"deW" },
+    { 0x0e1000f0, 0x001000f0, "ldrsh",	"deW" },
+    { 0x0f200090, 0x00200090, "und",	"x" },	/* Before data processing */
+    { 0x0e1000d0, 0x000000d0, "und",	"x" },	/* Before data processing */
+    { 0x0ff00ff0, 0x01000090, "swp",	"dmo" },
+    { 0x0ff00ff0, 0x01400090, "swpb",	"dmo" },
+    { 0x0fbf0fff, 0x010f0000, "mrs",	"dp" },	/* Before data processing */
+    { 0x0fb0fff0, 0x0120f000, "msr",	"pFm" },/* Before data processing */
+    { 0x0fb0f000, 0x0320f000, "msr",	"pF2" },/* Before data processing */
+    { 0x0ffffff0, 0x012fff10, "bx",     "m" },
+    { 0x0fff0ff0, 0x016f0f10, "clz",	"dm" },
+    { 0x0ffffff0, 0x012fff30, "blx",	"m" },
+    { 0xfff000f0, 0xe1200070, "bkpt",	"k" },
+    { 0x0de00000, 0x00000000, "and",	"Sdn2" },
+    { 0x0de00000, 0x00200000, "eor",	"Sdn2" },
+    { 0x0de00000, 0x00400000, "sub",	"Sdn2" },
+    { 0x0de00000, 0x00600000, "rsb",	"Sdn2" },
+    { 0x0de00000, 0x00800000, "add",	"Sdn2" },
+    { 0x0de00000, 0x00a00000, "adc",	"Sdn2" },
+    { 0x0de00000, 0x00c00000, "sbc",	"Sdn2" },
+    { 0x0de00000, 0x00e00000, "rsc",	"Sdn2" },
+    { 0x0df00000, 0x01100000, "tst",	"Dn2" },
+    { 0x0df00000, 0x01300000, "teq",	"Dn2" },
+    { 0x0df00000, 0x01500000, "cmp",	"Dn2" },
+    { 0x0df00000, 0x01700000, "cmn",	"Dn2" },
+    { 0x0de00000, 0x01800000, "orr",	"Sdn2" },
+    { 0x0de00000, 0x01a00000, "mov",	"Sd2" },
+    { 0x0de00000, 0x01c00000, "bic",	"Sdn2" },
+    { 0x0de00000, 0x01e00000, "mvn",	"Sd2" },
+    { 0x0ff08f10, 0x0e000100, "adf",	"PRfgh" },
+    { 0x0ff08f10, 0x0e100100, "muf",	"PRfgh" },
+    { 0x0ff08f10, 0x0e200100, "suf",	"PRfgh" },
+    { 0x0ff08f10, 0x0e300100, "rsf",	"PRfgh" },
+    { 0x0ff08f10, 0x0e400100, "dvf",	"PRfgh" },
+    { 0x0ff08f10, 0x0e500100, "rdf",	"PRfgh" },
+    { 0x0ff08f10, 0x0e600100, "pow",	"PRfgh" },
+    { 0x0ff08f10, 0x0e700100, "rpw",	"PRfgh" },
+    { 0x0ff08f10, 0x0e800100, "rmf",	"PRfgh" },
+    { 0x0ff08f10, 0x0e900100, "fml",	"PRfgh" },
+    { 0x0ff08f10, 0x0ea00100, "fdv",	"PRfgh" },
+    { 0x0ff08f10, 0x0eb00100, "frd",	"PRfgh" },
+    { 0x0ff08f10, 0x0ec00100, "pol",	"PRfgh" },
+    { 0x0f008f10, 0x0e000100, "fpbop",	"PRfgh" },
+    { 0x0ff08f10, 0x0e008100, "mvf",	"PRfh" },
+    { 0x0ff08f10, 0x0e108100, "mnf",	"PRfh" },
+    { 0x0ff08f10, 0x0e208100, "abs",	"PRfh" },
+    { 0x0ff08f10, 0x0e308100, "rnd",	"PRfh" },
+    { 0x0ff08f10, 0x0e408100, "sqt",	"PRfh" },
+    { 0x0ff08f10, 0x0e508100, "log",	"PRfh" },
+    { 0x0ff08f10, 0x0e608100, "lgn",	"PRfh" },
+    { 0x0ff08f10, 0x0e708100, "exp",	"PRfh" },
+    { 0x0ff08f10, 0x0e808100, "sin",	"PRfh" },
+    { 0x0ff08f10, 0x0e908100, "cos",	"PRfh" },
+    { 0x0ff08f10, 0x0ea08100, "tan",	"PRfh" },
+    { 0x0ff08f10, 0x0eb08100, "asn",	"PRfh" },
+    { 0x0ff08f10, 0x0ec08100, "acs",	"PRfh" },
+    { 0x0ff08f10, 0x0ed08100, "atn",	"PRfh" },
+    { 0x0f008f10, 0x0e008100, "fpuop",	"PRfh" },
+    { 0x0e100f00, 0x0c000100, "stf",	"QLv" },
+    { 0x0e100f00, 0x0c100100, "ldf",	"QLv" },
+    { 0x0ff00f10, 0x0e000110, "flt",	"PRgd" },
+    { 0x0ff00f10, 0x0e100110, "fix",	"PRdh" },
+    { 0x0ff00f10, 0x0e200110, "wfs",	"d" },
+    { 0x0ff00f10, 0x0e300110, "rfs",	"d" },
+    { 0x0ff00f10, 0x0e400110, "wfc",	"d" },
+    { 0x0ff00f10, 0x0e500110, "rfc",	"d" },
+    { 0x0ff0ff10, 0x0e90f110, "cmf",	"PRgh" },
+    { 0x0ff0ff10, 0x0eb0f110, "cnf",	"PRgh" },
+    { 0x0ff0ff10, 0x0ed0f110, "cmfe",	"PRgh" },
+    { 0x0ff0ff10, 0x0ef0f110, "cnfe",	"PRgh" },
+    { 0xff100010, 0xfe000010, "mcr2",	"#z" },
+    { 0x0f100010, 0x0e000010, "mcr",	"#z" },
+    { 0xff100010, 0xfe100010, "mrc2",	"#z" },
+    { 0x0f100010, 0x0e100010, "mrc",	"#z" },
+    { 0xff000010, 0xfe000000, "cdp2",	"#y" },
+    { 0x0f000010, 0x0e000000, "cdp",	"#y" },
+    { 0xfe100090, 0xfc100000, "ldc2",	"L#v" },
+    { 0x0e100090, 0x0c100000, "ldc",	"L#v" },
+    { 0xfe100090, 0xfc000000, "stc2",	"L#v" },
+    { 0x0e100090, 0x0c000000, "stc",	"L#v" },
+    { 0xf550f000, 0xf550f000, "pld",	"ne" },
+    { 0x0ff00ff0, 0x01000050, "qaad",	"dmn" },
+    { 0x0ff00ff0, 0x01400050, "qdaad",	"dmn" },
+    { 0x0ff00ff0, 0x01600050, "qdsub",	"dmn" },
+    { 0x0ff00ff0, 0x01200050, "dsub",	"dmn" },
+    { 0x0ff000f0, 0x01000080, "smlabb",	"nmsd" },   // d & n inverted!!
+    { 0x0ff000f0, 0x010000a0, "smlatb",	"nmsd" },   // d & n inverted!!
+    { 0x0ff000f0, 0x010000c0, "smlabt",	"nmsd" },   // d & n inverted!!
+    { 0x0ff000f0, 0x010000e0, "smlatt",	"nmsd" },   // d & n inverted!!
+    { 0x0ff000f0, 0x01400080, "smlalbb","ndms" },   // d & n inverted!!
+    { 0x0ff000f0, 0x014000a0, "smlaltb","ndms" },   // d & n inverted!!
+    { 0x0ff000f0, 0x014000c0, "smlalbt","ndms" },   // d & n inverted!!
+    { 0x0ff000f0, 0x014000e0, "smlaltt","ndms" },   // d & n inverted!!
+    { 0x0ff000f0, 0x01200080, "smlawb", "nmsd" },   // d & n inverted!!
+    { 0x0ff0f0f0, 0x012000a0, "smulwb","nms" },   // d & n inverted!!
+    { 0x0ff000f0, 0x012000c0, "smlawt", "nmsd" },   // d & n inverted!!
+    { 0x0ff0f0f0, 0x012000e0, "smulwt","nms" },   // d & n inverted!!
+    { 0x0ff0f0f0, 0x01600080, "smulbb","nms" },   // d & n inverted!!
+    { 0x0ff0f0f0, 0x016000a0, "smultb","nms" },   // d & n inverted!!
+    { 0x0ff0f0f0, 0x016000c0, "smulbt","nms" },   // d & n inverted!!
+    { 0x0ff0f0f0, 0x016000e0, "smultt","nms" },   // d & n inverted!!
+    { 0x00000000, 0x00000000, NULL,	NULL }
+};
+
+static char const arm32_insn_conditions[][4] = {
+	"eq", "ne", "cs", "cc",
+	"mi", "pl", "vs", "vc",
+	"hi", "ls", "ge", "lt",
+	"gt", "le", "",   "nv"
+};
+
+static char const insn_block_transfers[][4] = {
+	"da", "ia", "db", "ib"
+};
+
+static char const insn_stack_block_transfers[][4] = {
+	"ed", "ea", "fd", "fa"
+};
+
+static char const op_shifts[][4] = {
+	"lsl", "lsr", "asr", "ror"
+};
+
+static char const insn_fpa_rounding[][2] = {
+	"", "p", "m", "z"
+};
+
+static char const insn_fpa_precision[][2] = {
+	"s", "d", "e", "p"
+};
+
+static char const insn_fpaconstants[][8] = {
+	"0.0", "1.0", "2.0", "3.0",
+	"4.0", "5.0", "0.5", "10.0"
+};
+
+#define insn_condition(x)	arm32_insn_conditions[(x >> 28) & 0x0f]
+#define insn_blktrans(x)	insn_block_transfers[(x >> 23) & 3]
+#define insn_stkblktrans(x)	insn_stack_block_transfers[(x >> 23) & 3]
+#define op2_shift(x)		op_shifts[(x >> 5) & 3]
+#define insn_fparnd(x)		insn_fpa_rounding[(x >> 5) & 0x03]
+#define insn_fpaprec(x)		insn_fpa_precision[(((x >> 18) & 2)|(x >> 7)) & 1]
+#define insn_fpaprect(x)	insn_fpa_precision[(((x >> 21) & 2)|(x >> 15)) & 1]
+#define insn_fpaimm(x)		insn_fpaconstants[x & 0x07]
+
+/* Local prototypes */
+static void disasm_register_shift(const disasm_interface_t *di, u_int insn);
+static void disasm_print_reglist(const disasm_interface_t *di, u_int insn);
+static void disasm_insn_ldrstr(const disasm_interface_t *di, u_int insn,
+    u_int loc);
+static void disasm_insn_ldrhstrh(const disasm_interface_t *di, u_int insn,
+    u_int loc);
+static void disasm_insn_ldcstc(const disasm_interface_t *di, u_int insn,
+    u_int loc);
+static u_int disassemble_readword(u_int address);
+static void disassemble_printaddr(u_int address);
+
+u_int
+disasm(const disasm_interface_t *di, u_int loc, int altfmt)
+{
+	const struct arm32_insn *i_ptr = &arm32_i[0];
+
+	u_int insn;
+	int matchp;
+	int branch;
+	const char* f_ptr;
+	int fmt;
+
+	fmt = 0;
+	matchp = 0;
+	insn = di->di_readword(loc);
+
+/*	di->di_printf("loc=%08x insn=%08x : ", loc, insn);*/
+
+	while (i_ptr->name) {
+		if ((insn & i_ptr->mask) ==  i_ptr->pattern) {
+			matchp = 1;
+			break;
+		}
+		i_ptr++;
+	}
+
+	if (!matchp) {
+		di->di_printf("und%s\t%08x\n", insn_condition(insn), insn);
+		return(loc + INSN_SIZE);
+	}
+
+	/* If instruction forces condition code, don't print it. */
+	if ((i_ptr->mask & 0xf0000000) == 0xf0000000)
+		di->di_printf("%s", i_ptr->name);
+	else
+		di->di_printf("%s%s", i_ptr->name, insn_condition(insn));
+
+	f_ptr = i_ptr->format;
+
+	/* Insert tab if there are no instruction modifiers */
+
+	if (*(f_ptr) < 'A' || *(f_ptr) > 'Z') {
+		++fmt;
+		di->di_printf("\t");
+	}
+
+	while (*f_ptr) {
+		switch (*f_ptr) {
+		/* 2 - print Operand 2 of a data processing instruction */
+		case '2':
+			if (insn & 0x02000000) {
+				int rotate= ((insn >> 7) & 0x1e);
+
+				di->di_printf("#0x%08x",
+					      (insn & 0xff) << (32 - rotate) |
+					      (insn & 0xff) >> rotate);
+			} else {  
+				disasm_register_shift(di, insn);
+			}
+			break;
+		/* d - destination register (bits 12-15) */
+		case 'd':
+			di->di_printf("r%d", ((insn >> 12) & 0x0f));
+			break;
+		/* D - insert 'p' if Rd is R15 */
+		case 'D':
+			if (((insn >> 12) & 0x0f) == 15)
+				di->di_printf("p");
+			break;
+		/* n - n register (bits 16-19) */
+		case 'n':
+			di->di_printf("r%d", ((insn >> 16) & 0x0f));
+			break;
+		/* s - s register (bits 8-11) */
+		case 's':
+			di->di_printf("r%d", ((insn >> 8) & 0x0f));
+			break;
+		/* o - indirect register rn (bits 16-19) (used by swap) */
+		case 'o':
+			di->di_printf("[r%d]", ((insn >> 16) & 0x0f));
+			break;
+		/* m - m register (bits 0-4) */
+		case 'm':
+			di->di_printf("r%d", ((insn >> 0) & 0x0f));
+			break;
+		/* a - address operand of ldr/str instruction */
+		case 'a':
+			disasm_insn_ldrstr(di, insn, loc);
+			break;
+		/* e - address operand of ldrh/strh instruction */
+		case 'e':
+			disasm_insn_ldrhstrh(di, insn, loc);
+			break;
+		/* l - register list for ldm/stm instruction */
+		case 'l':
+			disasm_print_reglist(di, insn);
+			break;
+		/* f - 1st fp operand (register) (bits 12-14) */
+		case 'f':
+			di->di_printf("f%d", (insn >> 12) & 7);
+			break;
+		/* g - 2nd fp operand (register) (bits 16-18) */
+		case 'g':
+			di->di_printf("f%d", (insn >> 16) & 7);
+			break;
+		/* h - 3rd fp operand (register/immediate) (bits 0-4) */
+		case 'h':
+			if (insn & (1 << 3))
+				di->di_printf("#%s", insn_fpaimm(insn));
+			else
+				di->di_printf("f%d", insn & 7);
+			break;
+		/* b - branch address */
+		case 'b':
+			branch = ((insn << 2) & 0x03ffffff);
+			if (branch & 0x02000000)
+				branch |= 0xfc000000;
+			di->di_printaddr(loc + 8 + branch);
+			break;
+		/* t - blx address */
+		case 't':
+			branch = ((insn << 2) & 0x03ffffff) |
+			    (insn >> 23 & 0x00000002);
+			if (branch & 0x02000000)
+				branch |= 0xfc000000;
+			di->di_printaddr(loc + 8 + branch);
+			break;
+		/* X - block transfer type */
+		case 'X':
+			di->di_printf("%s", insn_blktrans(insn));
+			break;
+		/* Y - block transfer type (r13 base) */
+		case 'Y':
+			di->di_printf("%s", insn_stkblktrans(insn));
+			break;
+		/* c - comment field bits(0-23) */
+		case 'c':
+			di->di_printf("0x%08x", (insn & 0x00ffffff));
+			break;
+		/* k - breakpoint comment (bits 0-3, 8-19) */
+		case 'k':
+			di->di_printf("0x%04x",
+			    (insn & 0x000fff00) >> 4 | (insn & 0x0000000f));
+			break;
+		/* p - saved or current status register */
+		case 'p':
+			if (insn & 0x00400000)
+				di->di_printf("spsr");
+			else
+				di->di_printf("cpsr");
+			break;
+		/* F - PSR transfer fields */
+		case 'F':
+			di->di_printf("_");
+			if (insn & (1 << 16))
+				di->di_printf("c");
+			if (insn & (1 << 17))
+				di->di_printf("x");
+			if (insn & (1 << 18))
+				di->di_printf("s");
+			if (insn & (1 << 19))
+				di->di_printf("f");
+			break;
+		/* B - byte transfer flag */
+		case 'B':
+			if (insn & 0x00400000)
+				di->di_printf("b");
+			break;
+		/* L - co-processor transfer size */
+		case 'L':
+			if (insn & (1 << 22))
+				di->di_printf("l");
+			break;
+		/* S - set status flag */
+		case 'S':
+			if (insn & 0x00100000)
+				di->di_printf("s");
+			break;
+		/* P - fp precision */
+		case 'P':
+			di->di_printf("%s", insn_fpaprec(insn));
+			break;
+		/* Q - fp precision (for ldf/stf) */
+		case 'Q':
+			break;
+		/* R - fp rounding */
+		case 'R':
+			di->di_printf("%s", insn_fparnd(insn));
+			break;
+		/* W - writeback flag */
+		case 'W':
+			if (insn & (1 << 21))
+				di->di_printf("!");
+			break;
+		/* # - co-processor number */
+		case '#':
+			di->di_printf("p%d", (insn >> 8) & 0x0f);
+			break;
+		/* v - co-processor data transfer registers+addressing mode */
+		case 'v':
+			disasm_insn_ldcstc(di, insn, loc);
+			break;
+		/* x - instruction in hex */
+		case 'x':
+			di->di_printf("0x%08x", insn);
+			break;
+		/* y - co-processor data processing registers */
+		case 'y':
+			di->di_printf("%d, ", (insn >> 20) & 0x0f);
+
+			di->di_printf("c%d, c%d, c%d", (insn >> 12) & 0x0f,
+			    (insn >> 16) & 0x0f, insn & 0x0f);
+
+			di->di_printf(", %d", (insn >> 5) & 0x07);
+			break;
+		/* z - co-processor register transfer registers */
+		case 'z':
+			di->di_printf("%d, ", (insn >> 21) & 0x07);
+			di->di_printf("r%d, c%d, c%d, %d",
+			    (insn >> 12) & 0x0f, (insn >> 16) & 0x0f,
+			    insn & 0x0f, (insn >> 5) & 0x07);
+
+/*			if (((insn >> 5) & 0x07) != 0)
+				di->di_printf(", %d", (insn >> 5) & 0x07);*/
+			break;
+		default:
+			di->di_printf("[%c - unknown]", *f_ptr);
+			break;
+		}
+		if (*(f_ptr+1) >= 'A' && *(f_ptr+1) <= 'Z')
+			++f_ptr;
+		else if (*(++f_ptr)) {
+			++fmt;
+			if (fmt == 1)
+				di->di_printf("\t");
+			else
+				di->di_printf(", ");
+		}
+	};
+
+	di->di_printf("\n");
+
+	return(loc + INSN_SIZE);
+}
+
+
+static void
+disasm_register_shift(const disasm_interface_t *di, u_int insn)
+{
+	di->di_printf("r%d", (insn & 0x0f));
+	if ((insn & 0x00000ff0) == 0)
+		;
+	else if ((insn & 0x00000ff0) == 0x00000060)
+		di->di_printf(", rrx");
+	else {
+		if (insn & 0x10)
+			di->di_printf(", %s r%d", op2_shift(insn),
+			    (insn >> 8) & 0x0f);
+		else
+			di->di_printf(", %s #%d", op2_shift(insn),
+			    (insn >> 7) & 0x1f);
+	}
+}
+
+
+static void
+disasm_print_reglist(const disasm_interface_t *di, u_int insn)
+{
+	int loop;
+	int start;
+	int comma;
+
+	di->di_printf("{");
+	start = -1;
+	comma = 0;
+
+	for (loop = 0; loop < 17; ++loop) {
+		if (start != -1) {
+			if (loop == 16 || !(insn & (1 << loop))) {
+				if (comma)
+					di->di_printf(", ");
+				else
+					comma = 1;
+        			if (start == loop - 1)
+        				di->di_printf("r%d", start);
+        			else
+        				di->di_printf("r%d-r%d", start, loop - 1);
+        			start = -1;
+        		}
+        	} else {
+        		if (insn & (1 << loop))
+        			start = loop;
+        	}
+        }
+	di->di_printf("}");
+
+	if (insn & (1 << 22))
+		di->di_printf("^");
+}
+
+static void
+disasm_insn_ldrstr(const disasm_interface_t *di, u_int insn, u_int loc)
+{
+	int offset;
+
+	offset = insn & 0xfff;
+	if ((insn & 0x032f0000) == 0x010f0000) {
+		/* rA = pc, immediate index */
+		if (insn & 0x00800000)
+			loc += offset;
+		else
+			loc -= offset;
+		di->di_printaddr(loc + 8);
+ 	} else {
+		di->di_printf("[r%d", (insn >> 16) & 0x0f);
+		if ((insn & 0x03000fff) != 0x01000000) {
+			di->di_printf("%s, ", (insn & (1 << 24)) ? "" : "]");
+			if (!(insn & 0x00800000))
+				di->di_printf("-");
+			if (insn & (1 << 25))
+				disasm_register_shift(di, insn);
+			else
+				di->di_printf("#0x%03x", offset);
+		}
+		if (insn & (1 << 24))
+			di->di_printf("]");
+	}
+}
+
+static void
+disasm_insn_ldrhstrh(const disasm_interface_t *di, u_int insn, u_int loc)
+{
+	int offset;
+
+	offset = ((insn & 0xf00) >> 4) | (insn & 0xf);
+	if ((insn & 0x004f0000) == 0x004f0000) {
+		/* rA = pc, immediate index */
+		if (insn & 0x00800000)
+			loc += offset;
+		else
+			loc -= offset;
+		di->di_printaddr(loc + 8);
+ 	} else {
+		di->di_printf("[r%d", (insn >> 16) & 0x0f);
+		if ((insn & 0x01400f0f) != 0x01400000) {
+			di->di_printf("%s, ", (insn & (1 << 24)) ? "" : "]");
+			if (!(insn & 0x00800000))
+				di->di_printf("-");
+			if (insn & (1 << 22))
+				di->di_printf("#0x%02x", offset);
+			else
+				di->di_printf("r%d", (insn & 0x0f));
+		}
+		if (insn & (1 << 24))
+			di->di_printf("]");
+	}
+}
+
+static void
+disasm_insn_ldcstc(const disasm_interface_t *di, u_int insn, u_int loc)
+{
+	if (((insn >> 8) & 0xf) == 1)
+		di->di_printf("f%d, ", (insn >> 12) & 0x07);
+	else
+		di->di_printf("c%d, ", (insn >> 12) & 0x0f);
+
+	di->di_printf("[r%d", (insn >> 16) & 0x0f);
+
+	di->di_printf("%s, ", (insn & (1 << 24)) ? "" : "]");
+
+	if (!(insn & (1 << 23)))
+		di->di_printf("-");
+
+	di->di_printf("#0x%03x", (insn & 0xff) << 2);
+
+	if (insn & (1 << 24))
+		di->di_printf("]");
+
+	if (insn & (1 << 21))
+		di->di_printf("!");
+}
+
+static u_int
+disassemble_readword(u_int address)
+{
+	return(*((u_int *)address));
+}
+
+static void
+disassemble_printaddr(u_int address)
+{
+	printf("0x%08x", address);
+}
+
+static void
+disassemble_printf(const char *fmt, ...) {
+	va_list ap;
+	va_start(ap, fmt);
+	vprintf(fmt, ap);
+	va_end(ap);
+}
+
+static const disasm_interface_t disassemble_di = {
+	disassemble_readword, disassemble_printaddr, disassemble_printf
+};
+
+void
+disassemble(u_int address)
+{
+
+	(void)disasm(&disassemble_di, address, 0);
+}
+
+/* End of disassem.c */
diff --git a/libacc/tests/disassem.h b/libacc/tests/disassem.h
new file mode 100644
index 0000000..02747cd
--- /dev/null
+++ b/libacc/tests/disassem.h
@@ -0,0 +1,65 @@
+/*	$NetBSD: disassem.h,v 1.4 2001/03/04 04:15:58 matt Exp $	*/
+
+/*-
+ * Copyright (c) 1997 Mark Brinicombe.
+ * Copyright (c) 1997 Causality Limited.
+ *
+ * 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. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by Mark Brinicombe.
+ * 4. The name of the company nor the name of the author may 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 OR CONTRIBUTORS 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.
+ *
+ * Define the interface structure required by the disassembler.
+ *
+ * $FreeBSD: /repoman/r/ncvs/src/sys/arm/include/disassem.h,v 1.2 2005/01/05 21:58:48 imp Exp $
+ */
+
+#ifndef ANDROID_MACHINE_DISASSEM_H
+#define ANDROID_MACHINE_DISASSEM_H
+
+#include <sys/types.h>
+
+#if __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+	u_int	(*di_readword)(u_int);
+	void	(*di_printaddr)(u_int);	
+	void	(*di_printf)(const char *, ...);
+} disasm_interface_t;
+
+/* Prototypes for callable functions */
+
+u_int disasm(const disasm_interface_t *, u_int, int);
+void disassemble(u_int);
+
+#if __cplusplus
+}
+#endif
+
+#endif /* !ANDROID_MACHINE_DISASSEM_H */
diff --git a/libacc/tests/main.cpp b/libacc/tests/main.cpp
new file mode 100644
index 0000000..e4e386f
--- /dev/null
+++ b/libacc/tests/main.cpp
@@ -0,0 +1,207 @@
+/*
+ * Android "Almost" C Compiler.
+ * This is a compiler for a small subset of the C language, intended for use
+ * in scripting environments where speed and memory footprint are important.
+ *
+ * This code is based upon the "unobfuscated" version of the
+ * Obfuscated Tiny C compiler, see the file LICENSE for details.
+ *
+ */
+
+#include <ctype.h>
+#include <dlfcn.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if defined(__arm__)
+#include <unistd.h>
+#endif
+
+#if defined(__arm__)
+#define PROVIDE_ARM_DISASSEMBLY
+#endif
+
+#ifdef PROVIDE_ARM_DISASSEMBLY
+#include "disassem.h"
+#endif
+
+#include <acc/acc.h>
+
+
+typedef int (*MainPtr)(int, char**);
+// This is a separate function so it can easily be set by breakpoint in gdb.
+int run(MainPtr mainFunc, int argc, char** argv) {
+    return mainFunc(argc, argv);
+}
+
+ACCvoid* symbolLookup(ACCvoid* pContext, const ACCchar* name) {
+    return (ACCvoid*) dlsym(RTLD_DEFAULT, name);
+}
+
+#ifdef PROVIDE_ARM_DISASSEMBLY
+
+static FILE* disasmOut;
+
+static u_int
+disassemble_readword(u_int address)
+{
+    return(*((u_int *)address));
+}
+
+static void
+disassemble_printaddr(u_int address)
+{
+    fprintf(disasmOut, "0x%08x", address);
+}
+
+static void
+disassemble_printf(const char *fmt, ...) {
+    va_list ap;
+    va_start(ap, fmt);
+    vfprintf(disasmOut, fmt, ap);
+    va_end(ap);
+}
+
+static int disassemble(ACCscript* script, FILE* out) {
+    disasmOut = out;
+    disasm_interface_t  di;
+    di.di_readword = disassemble_readword;
+    di.di_printaddr = disassemble_printaddr;
+    di.di_printf = disassemble_printf;
+
+    ACCvoid* base;
+    ACCsizei length;
+
+    accGetProgramBinary(script, &base, &length);
+    unsigned long* pBase = (unsigned long*) base;
+    unsigned long* pEnd = (unsigned long*) (((unsigned char*) base) + length);
+
+    for(unsigned long* pInstruction = pBase; pInstruction < pEnd; pInstruction++) {
+        fprintf(out, "%08x: %08x  ", (int) pInstruction, (int) *pInstruction);
+        ::disasm(&di, (uint) pInstruction, 0);
+    }
+    return 0;
+}
+
+#endif // PROVIDE_ARM_DISASSEMBLY
+
+int main(int argc, char** argv) {
+    const char* inFile = NULL;
+    bool printListing;
+    bool runResults = false;
+    FILE* in = stdin;
+    int i;
+    for (i = 1; i < argc; i++) {
+        char* arg = argv[i];
+        if (arg[0] == '-') {
+            switch (arg[1]) {
+                case 'S':
+                    printListing = true;
+                    break;
+                case 'R':
+                    runResults = true;
+                    break;
+            default:
+                fprintf(stderr, "Unrecognized flag %s\n", arg);
+                return 3;
+            }
+        } else if (inFile == NULL) {
+            inFile = arg;
+        } else {
+            break;
+        }
+    }
+
+    if (! inFile) {
+        fprintf(stderr, "input file required\n");
+        return 2;
+    }
+
+    if (inFile) {
+        in = fopen(inFile, "r");
+        if (!in) {
+            fprintf(stderr, "Could not open input file %s\n", inFile);
+            return 1;
+        }
+    }
+
+    fseek(in, 0, SEEK_END);
+    size_t fileSize = (size_t) ftell(in);
+    rewind(in);
+    ACCchar* text = new ACCchar[fileSize + 1];
+    size_t bytesRead = fread(text, 1, fileSize, in);
+    if (bytesRead != fileSize) {
+        fprintf(stderr, "Could not read all of file %s\n", inFile);
+    }
+
+    text[fileSize] = '\0';
+
+    ACCscript* script = accCreateScript();
+
+    const ACCchar* scriptSource[] = {text};
+    accScriptSource(script, 1, scriptSource, NULL);
+    delete[] text;
+
+    accRegisterSymbolCallback(script, symbolLookup, NULL);
+
+    accCompileScript(script);
+    int result = accGetError(script);
+    MainPtr mainPointer = 0;
+    if (result != 0) {
+        ACCsizei bufferLength;
+        accGetScriptInfoLog(script, 0, &bufferLength, NULL);
+        char* buf = (char*) malloc(bufferLength + 1);
+        if (buf != NULL) {
+            accGetScriptInfoLog(script, bufferLength + 1, NULL, buf);
+            fprintf(stderr, "%s", buf);
+            free(buf);
+        } else {
+            fprintf(stderr, "Out of memory.\n");
+        }
+        goto exit;
+    }
+
+    {
+        ACCsizei numPragmaStrings;
+        accGetPragmas(script, &numPragmaStrings, 0, NULL);
+        if (numPragmaStrings) {
+            char** strings = new char*[numPragmaStrings];
+            accGetPragmas(script, NULL, numPragmaStrings, strings);
+            for(ACCsizei i = 0; i < numPragmaStrings; i += 2) {
+                fprintf(stderr, "#pragma %s(%s)\n", strings[i], strings[i+1]);
+            }
+            delete[] strings;
+        }
+    }
+
+    if (printListing) {
+#ifdef PROVIDE_ARM_DISASSEMBLY
+        disassemble(script, stderr);
+#endif
+    }
+
+    if (runResults) {
+        accGetScriptLabel(script, "main", (ACCvoid**) & mainPointer);
+
+        result = accGetError(script);
+        if (result != ACC_NO_ERROR) {
+            fprintf(stderr, "Could not find main: %d\n", result);
+        } else {
+            fprintf(stderr, "Executing compiled code:\n");
+            int codeArgc = argc - i + 1;
+            char** codeArgv = argv + i - 1;
+            codeArgv[0] = (char*) (inFile ? inFile : "stdin");
+            result = run(mainPointer, codeArgc, codeArgv);
+            fprintf(stderr, "result: %d\n", result);
+        }
+    }
+
+exit:
+
+    accDeleteScript(script);
+
+    return result;
+}
diff --git a/libacc/tests/runtimeTest.cpp b/libacc/tests/runtimeTest.cpp
new file mode 100644
index 0000000..55bf877
--- /dev/null
+++ b/libacc/tests/runtimeTest.cpp
@@ -0,0 +1,118 @@
+/*
+ * RuntimeTest for ACC compiler.
+ *
+ */
+
+#include <ctype.h>
+#include <dlfcn.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if defined(__arm__)
+#include <unistd.h>
+#endif
+
+#include <acc/acc.h>
+
+
+typedef void (*ScriptPtr)();
+
+// This is a separate function so it can easily be set by breakpoint in gdb.
+void run(ScriptPtr scriptFn) {
+    scriptFn();
+}
+
+// Private API for development:
+
+extern "C"
+void accDisassemble(ACCscript* script);
+
+int globalVar;
+
+void op_int(int a) {
+    printf("op_int(%d)\n", a);
+}
+
+void op_float12(float a, float b, float c, float d,
+                float e, float f, float g, float h,
+                float i, float j, float k, float l) {
+    printf("op_float12(%g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g)\n",
+           a, b, c, d, e, f, g, h, i, j, k, l);
+}
+
+const char* text = "void op_int(int a);\n"
+    "void op_float12(float a, float b, float c, float d,\n"
+    "           float e, float f, float g, float h,\n"
+    "           float i, float j, float k, float l);\n"
+    "void script() {\n"
+    "  globalVar += 3;\n"
+    "  op_int(123);\n"
+    "  op_float12(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0);\n"
+    "}\n";
+
+ACCvoid* symbolLookup(ACCvoid* pContext, const ACCchar* name) {
+    if (strcmp("op_int", name) == 0) {
+        return (ACCvoid*) op_int;
+    }
+    if (strcmp("op_float12", name) == 0) {
+        return (ACCvoid*) op_float12;
+    }
+    if (strcmp("globalVar", name) == 0) {
+        return (ACCvoid*) &globalVar;
+    }
+    return (ACCvoid*) dlsym(RTLD_DEFAULT, name);
+}
+
+int main(int argc, char** argv) {
+    ACCscript* script = accCreateScript();
+
+    accRegisterSymbolCallback(script, symbolLookup, NULL);
+
+    const ACCchar* scriptSource[] = {text};
+    accScriptSource(script, 1, scriptSource, NULL);
+
+    accCompileScript(script);
+    int result = accGetError(script);
+    ScriptPtr scriptPointer = 0;
+    if (result != 0) {
+        char buf[1024];
+        accGetScriptInfoLog(script, sizeof(buf), NULL, buf);
+        fprintf(stderr, "%s", buf);
+        goto exit;
+    }
+
+    {
+        ACCsizei numPragmaStrings;
+        accGetPragmas(script, &numPragmaStrings, 0, NULL);
+        if (numPragmaStrings) {
+            char** strings = new char*[numPragmaStrings];
+            accGetPragmas(script, NULL, numPragmaStrings, strings);
+            for(ACCsizei i = 0; i < numPragmaStrings; i += 2) {
+                fprintf(stderr, "#pragma %s(%s)\n", strings[i], strings[i+1]);
+            }
+            delete[] strings;
+        }
+    }
+
+    accGetScriptLabel(script, "script", (ACCvoid**) & scriptPointer);
+
+    result = accGetError(script);
+    if (result != ACC_NO_ERROR) {
+        fprintf(stderr, "Could not find script: %d\n", result);
+    } else {
+        fprintf(stderr, "Executing script:\n");
+        globalVar = 17;
+        run(scriptPointer);
+        fprintf(stderr, "After script globalVar = %d\n", globalVar);
+    }
+
+
+exit:
+
+    accDeleteScript(script);
+
+    return result;
+}
diff --git a/libacc/tests/test b/libacc/tests/test
new file mode 100755
index 0000000..8fd6916
--- /dev/null
+++ b/libacc/tests/test
@@ -0,0 +1,6 @@
+#!/bin/bash
+
+SCRIPT_DIR=`dirname $BASH_SOURCE`
+cd $SCRIPT_DIR
+python test.py "$@"
+
diff --git a/libacc/tests/test.py b/libacc/tests/test.py
new file mode 100644
index 0000000..d984301
--- /dev/null
+++ b/libacc/tests/test.py
@@ -0,0 +1,493 @@
+#
+# Test the acc compiler
+
+import unittest
+import subprocess
+import os
+import sys
+
+gArmInitialized = False
+gUseArm = True
+gUseX86 = True
+gRunOTCCOutput = True
+
+
+def parseArgv():
+    global gUseArm
+    global gUseX86
+    global gRunOTCCOutput
+    for arg in sys.argv[1:]:
+        if arg == "--noarm":
+            print "--noarm: not testing ARM"
+            gUseArm = False
+        elif arg == "--nox86":
+            print "--nox86: not testing x86"
+            gUseX86 = False
+        elif arg == "--norunotcc":
+            print "--norunotcc detected, not running OTCC output"
+            gRunOTCCOutput = False
+        else:
+            print "Unknown parameter: ", arg
+            raise "Unknown parameter"
+    sys.argv = sys.argv[0:1]
+
+def compile(args):
+    proc = subprocess.Popen(["acc"] + args, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
+    result = proc.communicate()
+    return result
+
+def runCmd(args):
+    proc = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+    result = proc.communicate()
+    return result[0].strip()
+
+def uname():
+    return runCmd(["uname"])
+
+def unameM():
+    return runCmd(["uname", "-m"])
+
+def which(item):
+    return runCmd(["which", item])
+
+def fileType(item):
+    return runCmd(["file", item])
+
+def outputCanRun():
+    ft = fileType(which("acc"))
+    return ft.find("ELF 32-bit LSB executable, Intel 80386") >= 0
+
+def checkEnvironment():
+    global gRunOTCCOutput
+    gRunOTCCOutput = uname() == "Linux" and unameM() != "x86_64" and outputCanRun()
+
+def adb(args):
+    return runCmd(["adb"] + args)
+
+def setupArm():
+    global gArmInitialized
+    if gArmInitialized:
+        return
+    print "Setting up arm"
+    adb(["remount"])
+    adb(["shell", "rm", "/system/bin/acc"])
+    adb(["shell", "mkdir", "/system/bin/accdata"])
+    adb(["shell", "mkdir", "/system/bin/accdata/data"])
+    # Clear out old data TODO: handle recursion
+    adb(["shell", "rm", "/system/bin/accdata/data/*"])
+    # Copy over data
+    for root, dirs, files in os.walk("data"):
+        for d in dirs:
+            adb(["shell", "mkdir", os.path.join(root, d)])
+        for f in files:
+            adb(["push", os.path.join(root, f), os.path.join("/system/bin/accdata", root, f)])
+    # Copy over compiler
+    adb(["sync"])
+    gArmInitialized = True
+
+def compileArm(args):
+    setupArm()
+    proc = subprocess.Popen(["adb", "shell", "/system/bin/acc"] + args, stdout=subprocess.PIPE)
+    result = proc.communicate()
+    return result[0].replace("\r","")
+
+def compare(a, b):
+    if a != b:
+        firstDiff = firstDifference(a, b)
+        print "Strings differ at character %d. Common: %s. Difference '%s' != '%s'" % (
+            firstDiff, a[0:firstDiff], safeAccess(a, firstDiff), safeAccess(b, firstDiff))
+
+def safeAccess(s, i):
+    if 0 <= i < len(s):
+        return s[i]
+    else:
+        return '?'
+
+def firstDifference(a, b):
+    commonLen = min(len(a), len(b))
+    for i in xrange(0, commonLen):
+        if a[i] != b[i]:
+            return i
+    return commonLen
+
+# a1 and a2 are the expected stdout and stderr.
+# b1 and b2 are the actual stdout and stderr.
+# Compare the two, sets. Allow any individual line
+# to appear in either stdout or stderr. This is because
+# the way we obtain output on the ARM combines both
+# streams into one sequence.
+
+def compareOuput(a1,a2,b1,b2):
+    while True:
+        totalLen = len(a1) + len(a2) + len(b1) + len(b2)
+        a1, b1 = matchCommon(a1, b1)
+        a1, b2 = matchCommon(a1, b2)
+        a2, b1 = matchCommon(a2, b1)
+        a2, b2 = matchCommon(a2, b2)
+        newTotalLen = len(a1) + len(a2) + len(b1) + len(b2)
+        if newTotalLen == 0:
+            return True
+        if newTotalLen == totalLen:
+            print "Failed at %d %d %d %d" % (len(a1), len(a2), len(b1), len(b2))
+            print "a1", a1
+            print "a2", a2
+            print "b1", b1
+            print "b2", b2
+            return False
+
+def matchCommon(a, b):
+    """Remove common items from the beginning of a and b,
+       return just the tails that are different."""
+    while len(a) > 0 and len(b) > 0 and a[0] == b[0]:
+        a = a[1:]
+        b = b[1:]
+    return a, b
+
+def rewritePaths(args):
+    return [rewritePath(x) for x in args]
+
+def rewritePath(p):
+    """Take a path that's correct on the x86 and convert to a path
+       that's correct on ARM."""
+    if p.startswith("data/"):
+        p = "/system/bin/accdata/" + p
+    return p
+
+class TestACC(unittest.TestCase):
+
+    def checkResult(self, out, err, stdErrResult, stdOutResult=""):
+        a1 = out.splitlines()
+        a2 = err.splitlines()
+        b2 = stdErrResult.splitlines()
+        b1 = stdOutResult.splitlines()
+        self.assertEqual(True, compareOuput(a1,a2,b1,b2))
+
+    def compileCheck(self, args, stdErrResult, stdOutResult="",
+                     targets=['arm', 'x86']):
+        global gUseArm
+        global gUseX86
+        targetSet = frozenset(targets)
+        if gUseX86 and 'x86' in targetSet:
+            out, err = compile(args)
+            self.checkResult(out, err, stdErrResult, stdOutResult)
+        if gUseArm and 'arm' in targetSet:
+            out = compileArm(rewritePaths(args))
+            self.checkResult(out, "", stdErrResult, stdOutResult)
+
+    def compileCheckArm(self, args, result):
+        self.assertEqual(compileArm(args), result)
+
+    def testCompileReturnVal(self):
+        self.compileCheck(["data/returnval-ansi.c"], "")
+
+    def testCompileOTCCANSII(self):
+        self.compileCheck(["data/otcc-ansi.c"], "", "", ['x86'])
+
+    def testRunReturnVal(self):
+        self.compileCheck(["-R", "data/returnval-ansi.c"],
+        "Executing compiled code:\nresult: 42\n")
+
+    def testStringLiteralConcatenation(self):
+        self.compileCheck(["-R", "data/testStringConcat.c"],
+        "Executing compiled code:\nresult: 13\n", "Hello, world\n")
+
+    def testRunOTCCANSI(self):
+        global gRunOTCCOutput
+        if gRunOTCCOutput:
+            self.compileCheck(["-R", "data/otcc-ansi.c", "data/returnval.c"],
+                "Executing compiled code:\notcc-ansi.c: About to execute compiled code:\natcc-ansi.c: result: 42\nresult: 42\n", "",
+                 ['x86'])
+
+    def testRunOTCCANSI2(self):
+        global gRunOTCCOutput
+        if gRunOTCCOutput:
+            self.compileCheck(["-R", "data/otcc-ansi.c", "data/otcc.c", "data/returnval.c"],
+                "Executing compiled code:\notcc-ansi.c: About to execute compiled code:\notcc.c: about to execute compiled code.\natcc-ansi.c: result: 42\nresult: 42\n", "",['x86'])
+
+    def testRunConstants(self):
+        self.compileCheck(["-R", "data/constants.c"],
+            "Executing compiled code:\nresult: 12\n",
+            "0 = 0\n010 = 8\n0x10 = 16\n'\\a' = 7\n'\\b' = 8\n'\\f' = 12\n'\\n' = 10\n'\\r' = 13\n'\\t' = 9\n'\\v' = 11\n'\\\\' = 92\n'\\'' = 39\n" +
+            "'\\\"' = 34\n'\\?' = 63\n'\\0' = 0\n'\\1' = 1\n'\\12' = 10\n'\\123' = 83\n'\\x0' = 0\n'\\x1' = 1\n'\\x12' = 18\n'\\x123' = 291\n'\\x1f' = 31\n'\\x1F' = 31\n")
+
+    def testRunFloat(self):
+        self.compileCheck(["-R", "data/float.c"],
+            "Executing compiled code:\nresult: 0\n",
+            """Constants: 0 0 0 0.01 0.01 0.1 10 10 0.1
+int: 1 float: 2.2 double: 3.3
+ ftoi(1.4f)=1
+ dtoi(2.4)=2
+ itof(3)=3
+ itod(4)=4
+globals: 1 2 3 4
+args: 1 2 3 4
+locals: 1 2 3 4
+cast rval: 2 4
+cast lval: 1.1 2 3.3 4
+""")
+
+    def testRunFlops(self):
+        self.compileCheck(["-R", "data/flops.c"],
+            """Executing compiled code:
+result: 0""",
+"""-1.1 = -1.1
+!1.2 = 0
+!0 = 1
+double op double:
+1 + 2 = 3
+1 - 2 = -1
+1 * 2 = 2
+1 / 2 = 0.5
+float op float:
+1 + 2 = 3
+1 - 2 = -1
+1 * 2 = 2
+1 / 2 = 0.5
+double op float:
+1 + 2 = 3
+1 - 2 = -1
+1 * 2 = 2
+1 / 2 = 0.5
+double op int:
+1 + 2 = 3
+1 - 2 = -1
+1 * 2 = 2
+1 / 2 = 0.5
+int op double:
+1 + 2 = 3
+1 - 2 = -1
+1 * 2 = 2
+1 / 2 = 0.5
+double op double:
+1 op 2: < 1   <= 1   == 0   >= 0   > 0   != 1
+1 op 1: < 0   <= 1   == 1   >= 1   > 0   != 0
+2 op 1: < 0   <= 0   == 0   >= 1   > 1   != 1
+double op float:
+1 op 2: < 1   <= 1   == 0   >= 0   > 0   != 1
+1 op 1: < 0   <= 1   == 1   >= 1   > 0   != 0
+2 op 1: < 0   <= 0   == 0   >= 1   > 1   != 1
+float op float:
+1 op 2: < 1   <= 1   == 0   >= 0   > 0   != 1
+1 op 1: < 0   <= 1   == 1   >= 1   > 0   != 0
+2 op 1: < 0   <= 0   == 0   >= 1   > 1   != 1
+int op double:
+1 op 2: < 1   <= 1   == 0   >= 0   > 0   != 1
+1 op 1: < 0   <= 1   == 1   >= 1   > 0   != 0
+2 op 1: < 0   <= 0   == 0   >= 1   > 1   != 1
+double op int:
+1 op 2: < 1   <= 1   == 0   >= 0   > 0   != 1
+1 op 1: < 0   <= 1   == 1   >= 1   > 0   != 0
+2 op 1: < 0   <= 0   == 0   >= 1   > 1   != 1
+branching: 1 0 1
+testpassi: 1 2 3 4 5 6 7 8 9 10 11 12
+testpassf: 1 2 3 4 5 6 7 8 9 10 11 12
+testpassd: 1 2 3 4 5 6 7 8 9 10 11 12
+testpassi: 1 2 3 4 5 6 7 8 9 10 11 12
+testpassf: 1 2 3 4 5 6 7 8 9 10 11 12
+testpassd: 1 2 3 4 5 6 7 8 9 10 11 12
+testpassi: 1 2 3 4 5 6 7 8 9 10 11 12
+testpassf: 1 2 3 4 5 6 7 8 9 10 11 12
+testpassd: 1 2 3 4 5 6 7 8 9 10 11 12
+testpassidf: 1 2 3
+""")
+    def testCasts(self):
+        self.compileCheck(["-R", "data/casts.c"],
+            """Executing compiled code:
+result: 0""", """Reading from a pointer: 3 3
+Writing to a pointer: 4
+Testing casts: 3 3 4.5 4
+Testing reading (int*): 4
+Testing writing (int*): 8 9
+Testing reading (char*): 0x78 0x56 0x34 0x12
+Testing writing (char*): 0x87654321
+f(10)
+Function pointer result: 70
+Testing read/write (float*): 8.8 9.9
+Testing read/write (double*): 8.8 9.9
+""")
+
+    def testChar(self):
+        self.compileCheck(["-R", "data/char.c"], """Executing compiled code:
+result: 0""", """a = 99, b = 41
+ga = 100, gb = 44""")
+
+    def testPointerArithmetic(self):
+        self.compileCheck(["-R", "data/pointers.c"], """Executing compiled code:
+result: 0""", """Pointer difference: 1 4
+Pointer addition: 2
+Pointer comparison to zero: 0 0 1
+Pointer comparison: 1 0 0 0 1
+""")
+    def testRollo3(self):
+        self.compileCheck(["-R", "data/rollo3.c"], """Executing compiled code:
+result: 10""", """""")
+
+    def testFloatDouble(self):
+        self.compileCheck(["-R", "data/floatdouble.c"], """Executing compiled code:
+result: 0""", """0.002 0.1 10""")
+
+    def testIncDec(self):
+        self.compileCheck(["-R", "data/inc.c"], """Executing compiled code:
+0
+1
+2
+1
+1
+2
+1
+0
+result: 0
+""","""""")
+
+    def testIops(self):
+        self.compileCheck(["-R", "data/iops.c"], """Executing compiled code:
+result: 0""", """Literals: 1 -1
+++
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9
+--
+10
+9
+8
+7
+6
+5
+4
+3
+2
+1
+0
+""")
+
+    def testFilm(self):
+        self.compileCheck(["-R", "data/film.c"], """Executing compiled code:
+result: 0""", """testing...
+Total bad: 0
+""")
+
+    def testpointers2(self):
+        self.compileCheck(["-R", "data/pointers2.c"], """Executing compiled code:
+result: 0""", """a = 0, *pa = 0
+a = 2, *pa = 2
+a = 0, *pa = 0 **ppa = 0
+a = 2, *pa = 2 **ppa = 2
+a = 0, *pa = 0 **ppa = 0
+a = 2, *pa = 2 **ppa = 2
+""")
+
+    def testassignmentop(self):
+        self.compileCheck(["-R", "data/assignmentop.c"], """Executing compiled code:
+result: 0""", """2 *= 5  10
+20 /= 5  4
+17 %= 5  2
+17 += 5  22
+17 -= 5  12
+17<<= 1  34
+17>>= 1  8
+17&= 1  1
+17^= 1  16
+16|= 1  17
+*f() = *f() + 10;
+f()
+f()
+a = 10
+*f() += 10;
+f()
+a = 10
+""")
+
+    def testcomma(self):
+        self.compileCheck(["-R", "data/comma.c"], """Executing compiled code:
+result: 0""", """statement: 10
+if: a = 0
+while: b = 11
+for: b = 22
+return: 30
+arg: 12
+""")
+
+    def testBrackets(self):
+        self.compileCheck(["-R", "data/brackets.c"], """Executing compiled code:
+Errors: 0
+2D Errors: 0
+result: 0
+""","""""")
+
+    def testShort(self):
+        self.compileCheck(["-R", "data/short.c"], """Executing compiled code:
+result: -2
+""","""""")
+
+    def testAssignment(self):
+        self.compileCheck(["-R", "data/assignment.c"], """Executing compiled code:
+result: 7
+""","""""")
+
+    def testArray(self):
+        self.compileCheck(["-R", "data/array.c"], """Executing compiled code:
+localInt: 3
+localDouble: 3 3
+globalChar: 3
+globalDouble: 3
+testArgs: 0 2 4
+testDecay: Hi!
+test2D:
+abcdefghijdefghijklm
+defghijklmghijklmnop
+ghijklmnopjklmnopabc
+jklmnopabcmnopabcdef
+mnopabcdefpabcdefghi
+pabcdefghicdefghijkl
+cdefghijklfghijklmno
+fghijklmnoijklmnopab
+ijklmnopablmnopabcde
+lmnopabcdefghijklmno
+result: 0
+""","""""")
+
+    def testDefines(self):
+        self.compileCheck(["-R", "data/defines.c"], """Executing compiled code:
+result: 3
+""","""""")
+
+    def testFuncArgs(self):
+        self.compileCheck(["-R", "data/funcargs.c"], """Executing compiled code:
+result: 4
+""","""""")
+
+    def testB2071670(self):
+        self.compileCheck(["-R", "data/b2071670.c"], """Executing compiled code:
+result: 1092616192
+""","""""")
+
+    def testStructs(self):
+        self.compileCheck(["-R", "data/structs.c"], """Executing compiled code:
+testCopying: 37 == 37
+testUnion: 1 == 0x3f800000
+testArgs: (6, 8, 10, 12)
+result: 6
+""","""""")
+
+    def testAddressOf(self):
+        self.compileCheck(["-R", "data/addressOf.c"], """Executing compiled code:
+testStruct: 10 10 10
+testArray: 1 1 1
+result: 0
+""","""""")
+
+def main():
+    checkEnvironment()
+    parseArgv()
+    unittest.main()
+
+if __name__ == '__main__':
+    main()
+