diff -ruN libjit/.cvsignore libjit-mikyt/.cvsignore
--- libjit/.cvsignore	2008-04-22 09:10:31.000000000 +0200
+++ libjit-mikyt/.cvsignore	1970-01-01 01:00:00.000000000 +0100
@@ -1,25 +0,0 @@
-INSTALL
-Makefile
-Makefile.in
-.deps
-configure
-config.log
-config.cache
-config.status
-config.guess
-config.sub
-depcomp
-missing
-install-sh
-aclocal.m4
-confdefs.h
-config.h
-config.h.in
-stamp-h
-stamp-h.in
-libtool
-ltconfig
-ltmain.sh
-autom4te.cache
-stamp-h1
-ylwrap
diff -ruN libjit/ChangeLog libjit-mikyt/ChangeLog
--- libjit/ChangeLog	2009-01-01 19:35:38.000000000 +0100
+++ libjit-mikyt/ChangeLog	2008-12-11 08:52:18.000000000 +0100
@@ -1,28 +1,8 @@
-2009-01-01  Klaus Treichel  <ktreichel@web.de>
-
-	* jit/jit-rules-x86-64.ins (JIT_OP_NFLOAT_TO_FLOAT32,
-	JIT_OP_NFLOAT_TO_FLOAT64): Add rules for the case that the
-	destination value is in the stack frame.
-	(JIT_OP_BR_ILT, JIT_OP_BR_ILE, JIT_OP_BR_IGT, JIT_OP_BR_IGE):
-	Handle the comparision with a constant 0 with a test opcode instead
-	of a cmp.
-	(JIT_OP_ISIGN, JIT_OP_LSIGN): Add handling of the integer sign
-	opcodes.
-
-2008-12-21  Aleksey Demakov  <ademakov@gmail.com>
-
-	* jit/jit-dump.c (jit_dump_function): dump undefined labels as such
-	rather than generating new labels for them.
-
-2008-12-12  Aleksey Demakov  <ademakov@gmail.com>
-
-	* jitruby/*: add Paul Brannan's ruby-libjit.
-
 2008-12-11  Juan Jesus Garcia de Soria  <juanj.g_soria@grupobbva.com>
 
 	* jit/jit-insn.c (jit_insn_call_native): extend small int return
 	values to full ints as native calls sometimes return garbage in MSB
-	of the return register.
+	of the return rigister.
 
 2008-12-11  Aleksey Demakov  <ademakov@gmail.com>
 
diff -ruN libjit/TODO libjit-mikyt/TODO
--- libjit/TODO	2008-12-19 15:03:32.000000000 +0100
+++ libjit-mikyt/TODO	2008-12-11 08:52:18.000000000 +0100
@@ -1,9 +1,7 @@
 Target release: 0.1.4
 =====================
 
-* CFG-based liveness analysis and dead code elimination
-* global copy and constant propagation
-* jitruby (in case copyright issues are resolved)
+* jitruby
 * sync jitplus with jit (jump tables, compile driver, debug)
 * fix catch/throw within finally
 * get rid of manual rules
@@ -14,7 +12,9 @@
 Target Release: 0.2.0
 =====================
 
+* CFG-based liveness analysis and dead code elimination
 * linear scan register allocation
+* global copy and constant propagation
 * improve exception handling
 * align function prolog and basic blocks
 * support cross-compilation 
diff -ruN libjit/doc/.cvsignore libjit-mikyt/doc/.cvsignore
--- libjit/doc/.cvsignore	2008-04-22 09:10:31.000000000 +0200
+++ libjit-mikyt/doc/.cvsignore	1970-01-01 01:00:00.000000000 +0100
@@ -1,10 +0,0 @@
-Makefile
-Makefile.in
-.deps
-.libs
-libjit.info*
-libjitext-*
-texinfo.tex
-*.pdf
-*.lo
-*.la
diff -ruN libjit/dpas/.cvsignore libjit-mikyt/dpas/.cvsignore
--- libjit/dpas/.cvsignore	2004-05-11 12:23:14.000000000 +0200
+++ libjit-mikyt/dpas/.cvsignore	1970-01-01 01:00:00.000000000 +0100
@@ -1,10 +0,0 @@
-Makefile
-Makefile.in
-.deps
-.libs
-dpas-parser.h
-dpas-parser.c
-dpas-scanner.c
-dpas
-*.lo
-*.la
diff -ruN libjit/include/.cvsignore libjit-mikyt/include/.cvsignore
--- libjit/include/.cvsignore	2004-05-11 12:23:14.000000000 +0200
+++ libjit-mikyt/include/.cvsignore	1970-01-01 01:00:00.000000000 +0100
@@ -1,6 +0,0 @@
-Makefile
-Makefile.in
-.deps
-.libs
-*.lo
-*.la
diff -ruN libjit/include/jit/.cvsignore libjit-mikyt/include/jit/.cvsignore
--- libjit/include/jit/.cvsignore	2004-05-01 01:29:53.000000000 +0200
+++ libjit-mikyt/include/jit/.cvsignore	1970-01-01 01:00:00.000000000 +0100
@@ -1,4 +0,0 @@
-Makefile
-Makefile.in
-.deps
-jit-defs.h
diff -ruN libjit/include/jit/jit-arch-arm.h libjit-mikyt/include/jit/jit-arch-arm.h
--- libjit/include/jit/jit-arch-arm.h	1970-01-01 01:00:00.000000000 +0100
+++ libjit-mikyt/include/jit/jit-arch-arm.h	2009-01-23 14:28:23.000000000 +0100
@@ -0,0 +1,64 @@
+/*
+ * jit-arch-arm.h - Architecture-specific definitions.
+ *
+ * Copyright (C) 2006  Southern Storm Software, Pty Ltd.
+ *
+ * The libjit library is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation, either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * The libjit library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the libjit library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef	_JIT_ARCH_ARM_H
+#define	_JIT_ARCH_ARM_H
+
+/*
+ * If defined _JIT_ARCH_GET_CURRENT_FRAME() macro assigns the current frame
+ * pointer to the supplied argument that has to be a void pointer.
+ */
+#if defined(__GNUC__)
+#define _JIT_ARCH_GET_CURRENT_FRAME(f)		\
+	do {					\
+		register void *__f asm("fp");	\
+		f = __f;			\
+	} while(0)
+#else
+#undef _JIT_ARCH_GET_CURRENT_FRAME
+#endif
+
+/*
+ * If defined _JIT_ARCH_GET_NEXT_FRAME() assigns the frame address following
+ * the frame supplied as second arg to the value supplied as first argument.
+ *
+#define _JIT_ARCH_GET_NEXT_FRAME(n, f)							\
+	do {										\
+		int count=0;	\
+		char found=0;	\
+		void *address;	\
+		do {	\
+			address= __builtin_frame_address(1);	\
+			if(address==f)	\
+			{	\
+				\
+				address = __builtin_frame_address(count);	\
+				found=1;	\
+			}	\
+			else	\
+			{	\
+				count++;	\
+			}	\
+		} while (address!=0 && !found);	\
+		n=address;	\
+	} while(0)
+*/
+
+#endif /* _JIT_ARCH_ARM_H */
diff -ruN libjit/jit/.cvsignore libjit-mikyt/jit/.cvsignore
--- libjit/jit/.cvsignore	2006-06-07 18:29:05.000000000 +0200
+++ libjit-mikyt/jit/.cvsignore	1970-01-01 01:00:00.000000000 +0100
@@ -1,10 +0,0 @@
-Makefile
-Makefile.in
-.deps
-.libs
-jit-apply-rules.h
-jit-interp-labels.h
-*.inc
-*.slc
-*.lo
-*.la
diff -ruN libjit/jit/Makefile.am libjit-mikyt/jit/Makefile.am
--- libjit/jit/Makefile.am	2008-05-29 23:03:30.000000000 +0200
+++ libjit-mikyt/jit/Makefile.am	2008-10-15 18:12:29.000000000 +0200
@@ -78,7 +78,7 @@
 EXTRA_DIST = \
 	mklabel.sh \
 	jit-rules-alpha.ins \
-	jit-rules-arm.sel \
+	jit-rules-arm.ins \
 	jit-rules-x86.ins \
 	jit-rules-x86-64.ins
 
@@ -100,11 +100,11 @@
 	$(top_builddir)/tools/gen-rules$(EXEEXT) $(srcdir)/jit-rules-x86.ins \
 			>jit-rules-x86.inc
 
-jit-rules-arm.lo: jit-rules-arm.slc
+jit-rules-arm.lo: jit-rules-arm.inc
 
-jit-rules-arm.slc: jit-rules-arm.sel $(top_builddir)/tools/gen-sel$(EXEEXT)
-	$(top_builddir)/tools/gen-sel$(EXEEXT) $(srcdir)/jit-rules-arm.sel \
-			>jit-rules-arm.slc
+jit-rules-arm.inc: jit-rules-arm.ins $(top_builddir)/tools/gen-rules$(EXEEXT)
+	$(top_builddir)/tools/gen-rules$(EXEEXT) $(srcdir)/jit-rules-arm.ins \
+			>jit-rules-arm.inc
 
 jit-rules-alpha.lo: jit-rules-alpha.inc
 
@@ -121,6 +121,6 @@
 CLEANFILES = \
 	jit-interp-labels.h \
 	jit-rules-alpha.inc \
-	jit-rules-arm.slc \
+	jit-rules-arm.inc \
 	jit-rules-x86.inc \
 	jit-rules-x86-64.inc
diff -ruN libjit/jit/jit-apply-arm.c libjit-mikyt/jit/jit-apply-arm.c
--- libjit/jit/jit-apply-arm.c	2008-01-24 21:12:50.000000000 +0100
+++ libjit-mikyt/jit/jit-apply-arm.c	2009-01-17 16:30:23.000000000 +0100
@@ -97,4 +97,47 @@
 	return (void *)buf;
 }
 
+/**
+ * Creates the indirector, that is the trampoline that permits the Just In Time 
+ * compilation of a method the first time that it is executed and its direct execution
+ * the following times
+ */
+void *_jit_create_indirector(unsigned char *buf, void **entry)
+{
+	arm_inst_buf inst;
+	void *start = (void *)buf;
+
+	/* Initialize the instruction buffer */
+	arm_inst_buf_init(inst, buf, buf + jit_indirector_size);
+
+	//Load the content of memory at address "entry", that is, the entry point of the function
+	arm_mov_reg_imm(inst,ARM_WORK,entry);
+	arm_mov_reg_membase(inst,ARM_WORK,ARM_WORK,0,4);
+	
+	/* Jump to the entry point. */
+	arm_mov_reg_reg(inst, ARM_PC, ARM_WORK);
+
+	/* Flush the cache lines that we just wrote */
+	jit_flush_exec(buf, ((unsigned char *)(inst.current)) - buf);
+	
+	return start;
+}
+
+void _jit_pad_buffer(unsigned char *buf, int len)
+{
+	arm_inst_buf inst;
+	
+	/* Initialize the instruction buffer */
+	arm_inst_buf_init(inst, buf, buf + len*4);
+	while(len > 0)
+	{
+		/* Traditional arm NOP */
+		arm_nop(inst);
+		--len;
+	}
+	
+	/* Flush the cache lines that we just wrote */
+	jit_flush_exec(buf, ((unsigned char *)(inst.current)) - buf);
+}
+
 #endif /* arm */
diff -ruN libjit/jit/jit-apply-arm.h libjit-mikyt/jit/jit-apply-arm.h
--- libjit/jit/jit-apply-arm.h	2008-01-24 21:12:50.000000000 +0100
+++ libjit-mikyt/jit/jit-apply-arm.h	2009-01-17 16:30:23.000000000 +0100
@@ -36,4 +36,37 @@
  */
 #define	jit_redirector_size		128
 
+/*
+ * The number of bytes that are needed for a indirector stub.
+ * This includes any extra bytes that are needed for alignment.
+ */
+#define	jit_indirector_size		24
+
+/*
+* Defines the alignment for the stack pointer at a public interface.
+* As of the "Procedure Call Standard for the ARM Architecture" (AAPCS release 2.07)
+*    SP mod 8 = 0
+* must always be true at every public interface (function calls, etc)
+*/
+#define JIT_SP_ALIGN_PUBLIC 8
+
+/* Redefine jit_builtin_apply in order to correctly align the stack pointer
+* to JIT_SP_ALING_PUBLIC bytes before calling __builtin_apply to execute the jit-compiled function
+*/
+#define	jit_builtin_apply(func,args,size,return_float,return_buf)	\
+do { \
+	register void *sp asm("sp");	\
+	while(((unsigned int)sp) % JIT_SP_ALIGN_PUBLIC != 0)	\
+	{	\
+		sp=(void *)(((unsigned int) sp)+1);	\
+	}	\
+	(return_buf) = __builtin_apply \
+	((void (*)())(func), (args), (size)); \
+} while (0)
+
+/*
+ * We should pad unused code space with NOP's.
+ */
+#define	jit_should_pad			1
+
 #endif	/* _JIT_APPLY_ARM_H */
diff -ruN libjit/jit/jit-apply-func.h libjit-mikyt/jit/jit-apply-func.h
--- libjit/jit/jit-apply-func.h	2008-05-26 23:06:29.000000000 +0200
+++ libjit-mikyt/jit/jit-apply-func.h	2008-12-20 19:09:52.000000000 +0100
@@ -48,32 +48,44 @@
 			(return_buf) = __builtin_apply \
 					((void (*)())(func), (args), (size)); \
 		} while (0)
+#endif
 
+#if !defined(jit_builtin_apply_args)
 #define	jit_builtin_apply_args(type,args)	\
 		do { \
 			(args) = (type)__builtin_apply_args(); \
 		} while (0)
+#endif
 
+#if !defined(jit_builtin_return_int)
 #define	jit_builtin_return_int(return_buf)	\
 		do { \
 			__builtin_return((return_buf)); \
 		} while (0)
+#endif
 
+#if !defined(jit_builtin_return_long)
 #define	jit_builtin_return_long(return_buf)	\
 		do { \
 			__builtin_return((return_buf)); \
 		} while (0)
+#endif
 
+#if !defined(jit_builtin_return_float)
 #define	jit_builtin_return_float(return_buf)	\
 		do { \
 			__builtin_return((return_buf)); \
 		} while (0)
+#endif
 
+#if !defined(jit_builtin_return_double)
 #define	jit_builtin_return_double(return_buf)	\
 		do { \
 			__builtin_return((return_buf)); \
 		} while (0)
+#endif
 
+#if !defined(jit_builtin_return_nfloat)
 #define	jit_builtin_return_nfloat(return_buf)	\
 		do { \
 			__builtin_return((return_buf)); \
diff -ruN libjit/jit/jit-cache.c libjit-mikyt/jit/jit-cache.c
--- libjit/jit/jit-cache.c	2008-03-03 15:49:06.000000000 +0100
+++ libjit-mikyt/jit/jit-cache.c	2009-01-23 14:22:59.000000000 +0100
@@ -27,6 +27,7 @@
 #include "jit-internal.h"
 #include "jit-cache.h"
 #include "jit-apply-func.h"
+//#include <stdio.h>
 
 #ifdef	__cplusplus
 extern	"C" {
diff -ruN libjit/jit/jit-dump.c libjit-mikyt/jit/jit-dump.c
--- libjit/jit/jit-dump.c	2008-12-22 19:49:47.000000000 +0100
+++ libjit-mikyt/jit/jit-dump.c	2008-01-25 08:27:00.000000000 +0100
@@ -846,14 +846,17 @@
 		while((block = jit_block_next(func, block)) != 0)
 		{
 			/* Output the block's label, if it has one */
-			if(block->label != jit_label_undefined)
+			if(prev_block && block->label == jit_label_undefined)
 			{
-				fprintf(stream, ".L%ld:\n", (long)(block->label));
+				/* A new block was started, but it doesn't have a label yet */
+				if(_jit_block_get_last(block) != 0)
+				{
+					block->label = (func->builder->next_label)++;
+				}
 			}
-			else if (prev_block && _jit_block_get_last(block) != 0)
+			if(block->label != jit_label_undefined)
 			{
-				/* A new block was started, but it doesn't have a label yet */
-				fprintf(stream, ".L:\n");
+				fprintf(stream, ".L%ld:\n", (long)(block->label));
 			}
 			prev_block = 1;
 
diff -ruN libjit/jit/jit-function.c libjit-mikyt/jit/jit-function.c
--- libjit/jit/jit-function.c	2008-05-28 08:13:48.000000000 +0200
+++ libjit-mikyt/jit/jit-function.c	2009-01-23 14:23:41.000000000 +0100
@@ -26,6 +26,7 @@
 #include "jit-reg-alloc.h"
 #include "jit-apply-func.h"
 #include "jit-setjmp.h"
+#include "jit-cache.h"
 #ifdef _JIT_COMPILE_DEBUG
 #include <stdio.h>
 #endif
@@ -1207,7 +1208,7 @@
 	func = (jit_function_t)_jit_cache_get_method(context->cache, pc, &cookie);
 	if(!func)
 	{
-		return 0;
+        return 0;
 	}
 
 	/* Convert the cookie into a handler address */
@@ -1598,3 +1599,4 @@
 
 	return (func->builder->next_label)++;
 }
+
diff -ruN libjit/jit/jit-gen-arm.h libjit-mikyt/jit/jit-gen-arm.h
--- libjit/jit/jit-gen-arm.h	2008-01-24 21:12:52.000000000 +0100
+++ libjit-mikyt/jit/jit-gen-arm.h	2009-01-16 13:18:11.000000000 +0100
@@ -2,6 +2,7 @@
  * arm_codegen.h - Code generation macros for the ARM processor.
  *
  * Copyright (C) 2003, 2004  Southern Storm Software, Pty Ltd.
+ * Copyright (C) 2008  Michele Tartara  <mikyt@users.sourceforge.net>
  *
  * This file is part of the libjit library.
  *
@@ -22,7 +23,7 @@
 
 #ifndef	_ARM_CODEGEN_H
 #define	_ARM_CODEGEN_H
-
+#include <assert.h>
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -139,43 +140,85 @@
 /*
  * Floating-point unary operators.
  */
+/* Old FP-based implementation
+// typedef enum
+// {
+// 	ARM_MVF		= 0,			/* Move */
+// 	ARM_MNF		= 1,			/* Move negative */
+// 	ARM_ABS		= 2,			/* Absolute value */
+// 	ARM_RND		= 3,			/* Round */
+// 	ARM_SQT		= 4,			/* Square root */
+// 	ARM_LOG		= 5,			/* log10 */
+// 	ARM_LGN		= 6,			/* ln */
+// 	ARM_EXP		= 7,			/* exp */
+// 	ARM_SIN		= 8,			/* sin */
+// 	ARM_COS		= 9,			/* cos */
+// 	ARM_TAN		= 10,			/* tan */
+// 	ARM_ASN		= 11,			/* asin */
+// 	ARM_ACS		= 12,			/* acos */
+// 	ARM_ATN		= 13			/* atan */
+// 
+// } ARM_FUNARY;
 typedef enum
 {
-	ARM_MVF		= 0,			/* Move */
-	ARM_MNF		= 1,			/* Move negative */
-	ARM_ABS		= 2,			/* Absolute value */
-	ARM_RND		= 3,			/* Round */
-	ARM_SQT		= 4,			/* Square root */
-	ARM_LOG		= 5,			/* log10 */
-	ARM_LGN		= 6,			/* ln */
-	ARM_EXP		= 7,			/* exp */
-	ARM_SIN		= 8,			/* sin */
-	ARM_COS		= 9,			/* cos */
-	ARM_TAN		= 10,			/* tan */
-	ARM_ASN		= 11,			/* asin */
-	ARM_ACS		= 12,			/* acos */
-	ARM_ATN		= 13			/* atan */
-
+	ARM_MVF		= 0,			/* Move - FCPY */
+	ARM_MNF		= 1,			/* Move negative - FNEG */
+	ARM_ABS		= 2			/* Absolute value - FABS */
+	//TODO
+// 	ARM_RND		= 3,			/* Round */
+// 	ARM_SQT		= 4,			/* Square root */
+// 	ARM_LOG		= 5,			/* log10 */
+// 	ARM_LGN		= 6,			/* ln */
+// 	ARM_EXP		= 7,			/* exp */
+// 	ARM_SIN		= 8,			/* sin */
+// 	ARM_COS		= 9,			/* cos */
+// 	ARM_TAN		= 10,			/* tan */
+// 	ARM_ASN		= 11,			/* asin */
+// 	ARM_ACS		= 12,			/* acos */
+// 	ARM_ATN		= 13			/* atan */
 } ARM_FUNARY;
 
 /*
  * Floating-point binary operators.
  */
+/* Old FP-based implementation */
+// typedef enum
+// {
+// 	ARM_ADF		= 0,			/* Add */
+// 	ARM_MUF		= 1,			/* Multiply */
+// 	ARM_SUF		= 2,			/* Subtract */
+// 	ARM_RSF		= 3,			/* Reverse subtract */
+// 	ARM_DVF		= 4,			/* Divide */
+// 	ARM_RDF		= 5,			/* Reverse divide */
+// 	ARM_POW		= 6,			/* pow */
+// 	ARM_RPW		= 7,			/* Reverse pow */
+// 	ARM_RMF		= 8,			/* Remainder */
+// 	ARM_FML		= 9,			/* Fast multiply (32-bit only) */
+// 	ARM_FDV		= 10,			/* Fast divide (32-bit only) */
+// 	ARM_FRD		= 11,			/* Fast reverse divide (32-bit only) */
+// 	ARM_POL		= 12			/* Polar angle */
+// 
+// } ARM_FBINARY;
+
+/* VFP version */
 typedef enum
 {
-	ARM_ADF		= 0,			/* Add */
-	ARM_MUF		= 1,			/* Multiply */
-	ARM_SUF		= 2,			/* Subtract */
-	ARM_RSF		= 3,			/* Reverse subtract */
-	ARM_DVF		= 4,			/* Divide */
-	ARM_RDF		= 5,			/* Reverse divide */
-	ARM_POW		= 6,			/* pow */
-	ARM_RPW		= 7,			/* Reverse pow */
-	ARM_RMF		= 8,			/* Remainder */
-	ARM_FML		= 9,			/* Fast multiply (32-bit only) */
-	ARM_FDV		= 10,			/* Fast divide (32-bit only) */
-	ARM_FRD		= 11,			/* Fast reverse divide (32-bit only) */
-	ARM_POL		= 12			/* Polar angle */
+	//OK
+	ARM_FADD	= 0,			/* Add */	
+	ARM_FMUL	= 1,			/* Multiply */
+	ARM_FSUB	= 2,			/* Subtract */
+	ARM_FDIV	= 4			/* Divide */
+	
+	//TODO
+// 	ARM_RSF		= 3,			/* Reverse subtract */	
+// 	ARM_RDF		= 5,			/* Reverse divide */
+// 	ARM_POW		= 6,			/* pow */
+// 	ARM_RPW		= 7,			/* Reverse pow */
+// 	ARM_RMF		= 8,			/* Remainder */
+// 	ARM_FML		= 9,			/* Fast multiply (32-bit only) */
+// 	ARM_FDV		= 10,			/* Fast divide (32-bit only) */
+// 	ARM_FRD		= 11,			/* Fast reverse divide (32-bit only) */
+// 	ARM_POL		= 12			/* Polar angle */
 
 } ARM_FBINARY;
 
@@ -265,6 +308,7 @@
 							(((unsigned int)(sreg)) << 16) | \
 							 ((unsigned int)((imm) & 0xFF))); \
 			} while (0)
+
 #define	arm_alu_reg_imm8_cond(inst,opc,dreg,sreg,imm,cond)	\
 			do { \
 				arm_inst_add((inst), arm_build_prefix((cond), (1 << 25)) | \
@@ -382,6 +426,14 @@
 				} \
 			} while (0)
 
+#define arm_test_reg_membase(inst,opc,reg,basereg,disp,scratchreg)	\
+			do {	\
+				assert(reg!=scratchreg);	\
+				assert(basereg!=scratchreg);	\
+				arm_load_membase((inst), (tmpreg),(basereg),(disp));	\
+				arm_test_reg_reg((inst), (opc), (reg), (tmpreg));	\
+} while (0)
+
 /*
  * Move a value between registers.
  */
@@ -389,6 +441,17 @@
 			do { \
 				arm_alu_reg((inst), ARM_MOV, (dreg), (sreg)); \
 			} while (0)
+			
+/**
+ * Move a value between floating point registers.
+ * @var inst is the pointer to the location of memory at which the instruction will be put
+ * @var dreg is the destination register
+ * @var freg is the source register
+ */
+#define	arm_mov_freg_freg(inst,dreg,sreg)	\
+			do { \
+				arm_alu_freg((inst), ARM_MVF, (dreg), (sreg)); \
+			} while (0)
 
 /*
  * Move an immediate value into a register.  This is hard because
@@ -431,6 +494,172 @@
 				} \
 			} while (0)
 
+#define ARM_NOBASEREG (-1)
+
+/**
+ * LDR (Load Register), LDRB (Load Register Byte)
+ * Load the content of the memory area of size "size" at position basereg+disp+(indexreg<<shift) into the 32-bit "reg", with zero-extension.
+ * "scratchreg" is a scratch register that has to be asked to the register allocator; it is 
+ * used only when disp!=0; if disp==0, it can have whatever value, since it won't be used
+ */
+#define arm_mov_reg_memindex(inst,reg,basereg,disp,indexreg,shift,size,scratchreg)	\
+do {	\
+	if (basereg==ARM_NOBASEREG)	\
+	{	\
+		fprintf(stderr, "TODO(NOBASEREG) at %s, %d\n", __FILE__, (int)__LINE__);	\
+	}	\
+	else	\
+	{	\
+		/* Add the displacement (only if needed)*/\
+		int tempreg=(basereg);	\
+		if (disp!=0)	\
+		{	\
+			tempreg=(scratchreg);	\
+			assert(tempreg!=basereg);	\
+			assert(tempreg!=indexreg);	\
+			arm_alu_reg_imm((inst), ARM_ADD, (tempreg), (basereg), (disp)); \
+		}	\
+		/* Load the content, depending on its size */	\
+		switch ((size)) {	\
+			case 1: arm_load_memindex_either(inst,reg,(tempreg),indexreg,shift,0x00400000); break;	\
+			case 2: arm_load_memindex_either(inst,reg,tempreg,indexreg,shift,0);	\
+				arm_shift_reg_imm8((inst), ARM_SHL, (reg), (reg), 16);	\
+				arm_shift_reg_imm8((inst), ARM_SHR, (reg), (reg), 16);	\
+				break; \
+			case 4: arm_load_memindex_either(inst,reg,tempreg,indexreg,shift,0); break;	\
+			default: assert (0);	\
+		}	\
+	}	\
+} while (0)
+
+/**
+ * Store the content of "reg" into a memory area of size "size" at position basereg+disp+(indexreg<<shift)
+ * NB: the scratch register has to be asked to the register allocator.
+ *     It can't be ARM_WORK, since it's already used
+ */
+#define arm_mov_memindex_reg(inst,basereg,disp,indexreg,shift,reg,size,scratchreg)	\
+do {	\
+	if (basereg==ARM_NOBASEREG)	\
+	{	\
+		fprintf(stderr, "TODO(NOBASEREG) at %s, %d\n", __FILE__, (int)__LINE__);	\
+	}	\
+	else	\
+	{	\
+		arm_shift_reg_imm8((inst), ARM_SHL, (ARM_WORK), (indexreg), (shift));	\
+		arm_alu_reg_reg((inst), ARM_ADD, (scratchreg), (basereg), ARM_WORK);	\
+		arm_mov_membase_reg((inst),(scratchreg),(disp),(reg),(size))	\
+	}	\
+} while (0);
+#if 0
+define arm_mov_reg_memindex(inst,reg,basereg,disp,indexreg,shift,size)	\
+do {	\
+	if (basereg==ARM_NOBASEREG)	\
+	{	\
+		fprintf(stderr, "TODO(NOBASEREG) at %s, %d\n", __FILE__, (int)__LINE__);	\
+	}	\
+	else	\
+	{	\
+		/* Add the displacement (only if needed)*/\
+		int tempreg=(basereg);	\
+		if (disp!=0)	\
+		{	\
+			arm_alu_reg_imm((inst), ARM_ADD, (reg), (basereg), (disp)); \
+			tempreg=(reg);	\
+		}	\
+		/* Load the content, depending on its size */	\
+		switch ((size)) {	\
+			case 1: arm_load_memindex_either(inst,reg,(tempreg),indexreg,shift,0x00400000); break;	\
+			case 2: arm_alu_reg_imm8((inst), ARM_SHL, ARM_WORK, (indexreg), (shift));	\
+				arm_alu_reg_reg((inst), ARM_ADD, ARM_WORK, ARM_WORK, \
+				ARM_WORK); \
+				arm_alu_reg_reg((inst), ARM_ADD, ARM_WORK, (tempreg), \
+				ARM_WORK); \
+				arm_load_membase_byte((inst), (reg), ARM_WORK, 0); \
+				arm_load_membase_byte((inst), ARM_WORK, ARM_WORK, 1); \
+				arm_shift_reg_imm8((inst), ARM_SHL, ARM_WORK, ARM_WORK, 24); \
+				arm_shift_reg_imm8((inst), ARM_SAR, ARM_WORK, ARM_WORK, 16); \
+				arm_alu_reg_reg((inst), ARM_ORR, (reg), (reg), ARM_WORK); \
+				break; \
+			case 4: arm_load_memindex_either(inst,reg,basereg,indexreg,shift,0); break;	\
+			default: assert (0);	\
+		}	\
+	}	\
+} while (0)
+#endif
+
+/*
+ * Stores the content of register "reg" in memory, at position "mem" with size "size"
+ * NB: destroys the content of ARM_WORK
+ */
+#define arm_mov_mem_reg(inst,mem,reg,size)	\
+do {	\
+	arm_mov_reg_imm((inst), ARM_WORK, (mem));	\
+	switch ((size)) {	\
+		case 1: arm_store_membase_byte((inst), (reg), ARM_WORK, 0); break;	\
+		case 2: arm_store_membase_short((inst), (reg), ARM_WORK, 0); break;	\
+		case 4: arm_store_membase((inst), (reg), ARM_WORK, 0); break;	\
+		default: jit_assert(0);	\
+	}	\
+} while (0)
+
+/*
+ * Stores the content of "imm" in memory, at position "mem" with size "size". Uses a scratch register (scratchreg),
+ * that has to be asked to the register allocator via the [scratch reg] parameter in the definition of the OPCODE.
+ * NB: destroys the content of ARM_WORK
+ */
+#define arm_mov_mem_imm(inst,mem,imm,size,scratchreg)	\
+do {	\
+	arm_mov_reg_imm((inst), (scratchreg), (imm));	\
+	arm_mov_reg_imm((inst), ARM_WORK, (mem));	\
+	switch ((size)) {	\
+		case 1: arm_store_membase_byte((inst), (scratchreg), ARM_WORK, 0); break;	\
+		case 2: arm_store_membase_short((inst), (scratchreg), ARM_WORK, 0); break;	\
+		case 4: arm_store_membase((inst), (scratchreg), ARM_WORK, 0); break;	\
+		default: assert(0);	\
+	}	\
+} while (0)
+
+/**
+ * Set "size" bytes at position basereg+disp at the value of imm
+ * NB: destroys the content of scratchreg. A good choice for scratchreg is ARM_WORK,
+ * unless the value of disp is too big to be handled by arm_store_membase_either. In that case,
+ * it's better to require the allocation of a scratch reg by adding the parameter [scratch reg] at the end
+ * of the parameters of the rule inside jit-rules-arm.ins that's calling this function.
+ */
+#define arm_mov_membase_imm(inst,basereg,disp,imm,size,scratchreg)	\
+do {	\
+	arm_mov_reg_imm((inst), (scratchreg), imm);	\
+	arm_mov_membase_reg((inst), (basereg), (disp), (scratchreg), (size));	\
+} while(0);
+
+/**
+ * Set "size" bytes at position basereg+disp at the value of reg
+ * NB: might destroy the content of ARM_WORK because of arm_store_membase
+ */
+#define arm_mov_membase_reg(inst,basereg,disp,reg,size)	\
+do {	\
+	switch ((size)) {	\
+		case 1: arm_store_membase_byte((inst), (reg), (basereg), (disp)); break;	\
+		case 2: arm_store_membase_short((inst), (reg), (basereg), (disp)); break;	\
+		case 4: arm_store_membase((inst), (reg), (basereg), (disp)); break;	\
+		default: jit_assert(0);	\
+	}	\
+} while(0);
+
+/**
+* Set the value of "reg" to the "size"-bytes-long value held in memory at position basereg+disp
+* NB: can destroys the content of ARM_WORK because of arm_store_membase_short
+*/
+#define arm_mov_reg_membase(inst,reg,basereg,disp,size)	\
+do {	\
+	switch ((size)) {	\
+		case 1: arm_load_membase_byte((inst), (reg), (basereg), (disp)); break;	\
+		case 2: arm_load_membase_short((inst), (reg), (basereg), (disp)); break;	\
+		case 4: arm_load_membase((inst), (reg), (basereg), (disp)); break;	\
+		default: jit_assert(0);	\
+}	\
+} while(0);
+
 /*
  * Clear a register to zero.
  */
@@ -491,42 +720,142 @@
 				} \
 			} while (0)
 
-/*
- * Perform a binary operation on floating-point arguments.
+/**
+ * Perform a binary operation on double-precision floating-point arguments.
+ * OPC is the number indicating the operation to execute (taken from enum ARM_FBINARY)
+ * sreg1 and sreg2 are the registers containing the first and second operand
+ * dreg is the destination register
  */
 #define	arm_alu_freg_freg(inst,opc,dreg,sreg1,sreg2)	\
 			do { \
-				arm_inst_add((inst), arm_prefix(0x0E000180) | \
-							(((unsigned int)(opc)) << 20) | \
-							(((unsigned int)(dreg)) << 12) | \
-							(((unsigned int)(sreg1)) << 16) | \
-							 ((unsigned int)(sreg2))); \
-			} while (0)
-#define	arm_alu_freg_freg_32(inst,opc,dreg,sreg1,sreg2)	\
-			do { \
-				arm_inst_add((inst), arm_prefix(0x0E000100) | \
-							(((unsigned int)(opc)) << 20) | \
+				unsigned int mask;	\
+				switch(opc)	\
+				{	\
+					case ARM_FADD:	\
+						mask=0x0E300B00;	\
+						break;	\
+					case ARM_FMUL:	\
+						mask=0x0E200B00;	\
+						break;	\
+					case ARM_FSUB:	\
+						mask=0x0E300B40;	\
+						break;	\
+					case ARM_FDIV:	\
+						mask=0x0E800B00;	\
+						break;	\
+					default:	\
+						printf("Unimplemented binary operation %d in %s\n", opc,  __FILE__);	\
+						abort();	\
+				}	\
+				arm_inst_add((inst), arm_prefix(mask) | \
 							(((unsigned int)(dreg)) << 12) | \
 							(((unsigned int)(sreg1)) << 16) | \
-							 ((unsigned int)(sreg2))); \
+							((unsigned int)(sreg2))); \
 			} while (0)
-
-/*
- * Perform a unary operation on floating-point arguments.
+/**
+ * Perform a binary operation on single-precision floating-point arguments.
+ * OPC is the number indicating the operation to execute (taken from enum ARM_FBINARY)
+ * sreg1 and sreg2 are the registers containing the first and second operand
+ * dreg is the destination register
  */
+#define	arm_alu_freg_freg_32(inst,opc,dreg,sreg1,sreg2)	\
+do { \
+	unsigned int mask;	\
+	switch(opc)	\
+	{	\
+		case ARM_FADD:	\
+			mask=0x0E300A00;	\
+			break;	\
+		case ARM_FMUL:	\
+			mask=0x0E200A00;	\
+			break;	\
+		case ARM_FSUB:	\
+			mask=0x0E300A40;	\
+			break;	\
+		case ARM_FDIV:	\
+			mask=0x0E800A00;	\
+			break;	\
+		default:	\
+			printf("Unimplemented binary operation %d in %s\n", opc,  __FILE__);	\
+			abort();	\
+	}	\
+	unsigned int dreg_top_4_bits = (dreg & 0x1E) >> 1;	\
+	unsigned int dreg_bottom_bit = (dreg & 0x01);	\
+	unsigned int sreg1_top_4_bits = (sreg1 & 0x1E) >> 1;	\
+	unsigned int sreg1_bottom_bit = (sreg1 & 0x01);	\
+	unsigned int sreg2_top_4_bits = (sreg2 & 0x1E) >> 1;	\
+	unsigned int sreg2_bottom_bit = (sreg2 & 0x01);	\
+	arm_inst_add((inst), arm_prefix(mask) | \
+				(((unsigned int)(dreg_top_4_bits)) << 12) |	\
+				(((unsigned int)(dreg_bottom_bit)) << 22) |	\
+				(((unsigned int)(sreg1_top_4_bits)) << 16) |	\
+				(((unsigned int)(sreg1_bottom_bit)) << 7) |	\
+				(((unsigned int)(sreg2_bottom_bit)) << 5) |	\
+				((unsigned int)(sreg2_top_4_bits))); \
+} while (0)
+
+/**
+* Perform a unary operation on a double-precision floating-point argument.
+* OPC is the number indicating the operation to execute (taken from enum ARM_FUNARY)
+* sreg is the register containing the operand
+* dreg is the destination register
+*/
 #define	arm_alu_freg(inst,opc,dreg,sreg)	\
 			do { \
-				arm_inst_add((inst), arm_prefix(0x0E008180) | \
-							(((unsigned int)(opc)) << 20) | \
-							(((unsigned int)(dreg)) << 12) | \
+				unsigned int mask;	\
+				switch(opc)	\
+				{	\
+					case ARM_MVF:	\
+						mask=0xEB00B40;	\
+						break;	\
+					case ARM_MNF:	\
+						mask=0xEB10B40;	\
+						break;	\
+					case ARM_ABS:	\
+						mask=0xEB00BC0;	\
+						break;	\
+					default:	\
+						printf("Unimplemented unary operation %d in %s\n", opc,  __FILE__);	\
+						abort();	\
+				}	\
+				arm_inst_add((inst), arm_prefix(mask) | \
+							(((unsigned int)(dreg)) << 12) |	\
 							 ((unsigned int)(sreg))); \
 			} while (0)
+			
+/**
+ * Perform a unary operation on a single-precision floating-point argument.
+ * OPC is the number indicating the operation to execute (taken from enum ARM_FUNARY)
+ * sreg is the register containing the operand
+ * dreg is the destination register
+ */			
 #define	arm_alu_freg_32(inst,opc,dreg,sreg)	\
 			do { \
-				arm_inst_add((inst), arm_prefix(0x0E008100) | \
-							(((unsigned int)(opc)) << 20) | \
-							(((unsigned int)(dreg)) << 12) | \
-							 ((unsigned int)(sreg))); \
+				unsigned int mask;	\
+				switch(opc)	\
+				{	\
+					case ARM_MVF:	\
+						mask=0xEB00A40;	\
+						break;	\
+					case ARM_MNF:	\
+						mask=0xEB10A40;	\
+						break;	\
+					case ARM_ABS:	\
+						mask=0xEB00AC0;	\
+						break;	\
+					default:	\
+						printf("Unimplemented OPCODE in %s\n", __FILE__);	\
+						abort();	\
+				}	\
+				unsigned int dreg_top_4_bits = (dreg & 0x1E) >> 1;	\
+				unsigned int dreg_bottom_bit = (dreg & 0x01);	\
+				unsigned int sreg_top_4_bits = (sreg & 0x1E) >> 1;	\
+				unsigned int sreg_bottom_bit = (sreg & 0x01);	\
+				arm_inst_add((inst), arm_prefix(mask) | \
+							(((unsigned int)(dreg_top_4_bits)) << 12) |	\
+							(((unsigned int)(dreg_bottom_bit)) << 22) |	\
+							(((unsigned int)(sreg_bottom_bit)) << 5)  |	\
+							 ((unsigned int)(sreg_top_4_bits))); \
 			} while (0)
 
 /*
@@ -598,6 +927,7 @@
 
 /*
  * Call a subroutine at a specific target location.
+ * (Equivalent to x86_call_code)
  */
 #define	arm_call(inst,target)	\
 			do { \
@@ -645,6 +975,15 @@
 			} while (0)
 
 /*
+ * Pop the top of the system stack and put it at a given offset from the position specified by basereg (that is, usually, the frame pointer). NB: This macro thrashes the content of ARM_WORK
+ */
+#define arm_pop_membase(inst,basereg,offset)	\
+			do {	\
+				arm_pop_reg((inst), ARM_WORK);	\
+				arm_store_membase((inst),ARM_WORK,basereg,offset);	\
+			} while (0)
+			
+/*
  * Set up a local variable frame, and save the registers in "regset".
  */
 #define	arm_setup_frame(inst,regset)	\
@@ -710,6 +1049,7 @@
 				} \
 				else \
 				{ \
+					assert(basereg!=ARM_WORK);	\
 					arm_mov_reg_imm((inst), ARM_WORK, __mb_offset); \
 					arm_inst_add((inst), arm_prefix(0x07900000 | (mask)) | \
 								(((unsigned int)(basereg)) << 16) | \
@@ -721,6 +1061,43 @@
 			do { \
 				arm_load_membase_either((inst), (reg), (basereg), (imm), 0); \
 			} while (0)
+
+/* Load Effective Address */
+#define arm_lea_membase(inst,reg,imm)	\
+			do { \
+				arm_alu_reg_imm((inst), ARM_ADD, (reg), ARM_FP, (imm));\
+			} while (0)
+
+/**
+ * Moves the content of 1 byte (is_half==0) or 2 bytes (is_half==1) from memory address basereg+disp+(indexreg<<shift) into dreg, with sign extension (is_signed==1) or zero extension (is_signed==0)
+ */
+#define arm_widen_memindex(inst,dreg,basereg,disp,indexreg,shift,is_signed,is_half)	\
+do {	\
+	int scratchreg=ARM_WORK;	\
+	if(is_half)	\
+	{	\
+		arm_mov_reg_memindex((inst),(dreg),(basereg),(disp),(indexreg),(shift),2, scratchreg);	\
+	}	\
+	else	\
+	{	\
+		arm_mov_reg_memindex((inst),(dreg),(basereg),(disp),(indexreg),(shift),1, scratchreg);	\
+	}	\
+	if(is_signed)	\
+	{	\
+		int shiftSize;	\
+		if (is_half)	\
+		{	\
+			shiftSize=16;	\
+		}	\
+		else	\
+		{	\
+			shiftSize=24;	\
+		}	\
+		arm_shift_reg_imm8((inst), ARM_SHL, (dreg), (dreg), shiftSize); \
+		arm_shift_reg_imm8((inst), ARM_SAR, (dreg), (dreg), shiftSize);	\
+	}	\
+} while (0)
+
 #define	arm_load_membase_byte(inst,reg,basereg,imm)	\
 			do { \
 				arm_load_membase_either((inst), (reg), (basereg), (imm), \
@@ -752,7 +1129,7 @@
 /*
  * Load a floating-point value from an address into a register.
  */
-#define	arm_load_membase_float(inst,reg,basereg,imm,mask)	\
+/* #define	arm_load_membase_float(inst,reg,basereg,imm,mask)	\
 			do { \
 				int __mb_offset = (int)(imm); \
 				if(__mb_offset >= 0 && __mb_offset < (1 << 10) && \
@@ -780,21 +1157,206 @@
 							(((unsigned int)ARM_WORK) << 16) | \
 							(((unsigned int)(reg)) << 12)); \
 				} \
+			} while (0)*/
+
+/**
+ * FLDS (Floating-point Load, Single-precision)
+ * Loads a word from memory address basereg+imm to 
+ * the single precision floating point register reg.
+ * "mask" is usually set to 0
+ */
+#define	arm_load_membase_float(inst,reg,basereg,imm,mask)	\
+do { \
+	unsigned int reg_top_4_bits = (reg & 0x1E) >> 1;	\
+	unsigned int reg_bottom_bit = (reg & 0x01);	\
+	int __mb_offset = (int)(imm); \
+	if(__mb_offset >= 0 && __mb_offset < (1 << 10) && \
+		(__mb_offset & 3) == 0) \
+	{ \
+		arm_inst_add((inst), arm_prefix(0x0D900A00 | (mask)) | \
+			(((unsigned int)(basereg)) << 16) | \
+			(((unsigned int)(reg_top_4_bits)) << 12) | \
+			(((unsigned int)(reg_bottom_bit)) << 22) | \
+			((unsigned int)((__mb_offset / 4) & 0xFF))); \
+	} \
+	else if(__mb_offset > -(1 << 10) && __mb_offset < 0 && \
+		(__mb_offset & 3) == 0) \
+	{ \
+		arm_inst_add((inst), arm_prefix(0x0D100A00 | (mask)) | \
+			(((unsigned int)(basereg)) << 16) | \
+			(((unsigned int)(reg_top_4_bits)) << 12) | \
+			(((unsigned int)(reg_bottom_bit)) << 22) | \
+			((unsigned int)(((-__mb_offset) / 4) & 0xFF)));\
+	} \
+	else \
+	{ \
+		assert(reg != ARM_WORK);	\
+		assert(basereg!=ARM_WORK);	\
+		if(__mb_offset > 0)	\
+		{	\
+			arm_mov_reg_imm((inst), ARM_WORK, __mb_offset);	\
+			arm_alu_reg_reg((inst), ARM_ADD, ARM_WORK, (basereg), ARM_WORK);	\
+		}	\
+		else	\
+		{	\
+			arm_mov_reg_imm((inst), ARM_WORK, -__mb_offset);	\
+			arm_alu_reg_reg((inst), ARM_SUB, ARM_WORK, (basereg), ARM_WORK);	\
+		}	\
+		arm_inst_add((inst), arm_prefix(0x0D900A00 | (mask)) | \
+			(((unsigned int)ARM_WORK) << 16) | \
+			(((unsigned int)(reg_top_4_bits)) << 12) | \
+			(((unsigned int)(reg_bottom_bit)) << 22)); \
+	} \
+} while (0)
+
+/**
+ * FLDD
+ */
+#define	arm_load_membase_float64(inst,reg,basereg,imm)	\
+			do { \
+				int __mb_offset = (int)(imm); \
+				if(__mb_offset >= 0 && __mb_offset < (1 << 10) && \
+				   (__mb_offset & 3) == 0) \
+				{ \
+					arm_inst_add((inst), arm_prefix(0x0D900B00) | \
+							(((unsigned int)(basereg)) << 16) | \
+							(((unsigned int)(reg)) << 12) | \
+							 ((unsigned int)((__mb_offset / 4) & 0xFF))); \
+				} \
+				else if(__mb_offset > -(1 << 10) && __mb_offset < 0 && \
+				        (__mb_offset & 3) == 0) \
+				{ \
+					arm_inst_add((inst), arm_prefix(0x0D100B00) | \
+							(((unsigned int)(basereg)) << 16) | \
+							(((unsigned int)(reg)) << 12) | \
+							 ((unsigned int)(((-__mb_offset) / 4) & 0xFF)));\
+				} \
+				else \
+				{ \
+					assert(reg != ARM_WORK);	\
+					assert(basereg!=ARM_WORK);	\
+					if(__mb_offset > 0)	\
+					{	\
+						arm_mov_reg_imm((inst), ARM_WORK, __mb_offset);	\
+						arm_alu_reg_reg((inst), ARM_ADD, ARM_WORK, (basereg), ARM_WORK);	\
+					}	\
+					else	\
+					{	\
+						arm_mov_reg_imm((inst), ARM_WORK, -__mb_offset);	\
+						arm_alu_reg_reg((inst), ARM_SUB, ARM_WORK, (basereg), ARM_WORK);	\
+					}	\
+					arm_inst_add((inst), arm_prefix(0x0D900B00) | \
+							(((unsigned int)ARM_WORK) << 16) | \
+							(((unsigned int)(reg)) << 12)); \
+				} \
 			} while (0)
+
 #define	arm_load_membase_float32(inst,reg,basereg,imm)	\
 			do { \
 				arm_load_membase_float((inst), (reg), (basereg), (imm), 0); \
 			} while (0)
-#define	arm_load_membase_float64(inst,reg,basereg,imm)	\
-			do { \
-				arm_load_membase_float((inst), (reg), (basereg), \
-									   (imm), 0x00008000); \
-			} while (0)
 
-/*
- * Store a value from a register into an address.
+/**
+* Load the content of the memory area at position basereg+disp into the float register "dfreg",
+* using the appropriate instruction depending whether the value to be loaded is_double (1 => 64 bits) or not (0 => 32 bits)
+* (it's similar to x86_fld_membase)
+*/
+#define arm_fld_membase(inst,dfreg,basereg,disp,is_double)	\
+do {	\
+	if (is_double)	\
+	{	\
+		arm_load_membase_float64((inst), (dfreg), (basereg), (disp));	\
+	}	\
+	else	\
+	{	\
+		arm_load_membase_float32((inst), (dfreg), (basereg), (disp));	\
+	}\
+} while(0)
+
+/**
+ * Load the content of the memory area at position basereg+disp+(indexreg<<shift) into the float register "dfreg",
+ * using the appropriate instruction depending whether the value to be loaded is_double (1 => 64 bits) or not (0 => 32 bits)
+ * (it's similar to x86_fld_memindex)
+ */
+#define arm_fld_memindex(inst,dfreg,basereg,disp,indexreg,shift,is_double,scratchreg) \
+	do {	\
+		if (is_double)	\
+		{	\
+			arm_load_memindex_float64((inst), (dfreg), (basereg), (disp), (indexreg), (shift), (scratchreg));	\
+		}	\
+		else	\
+		{	\
+			arm_load_memindex_float32((inst), (dfreg), (basereg), (disp), (indexreg), (shift), (scratchreg));	\
+		}\
+	} while(0)
+/**
+ * Load the content of the 64-bits memory area at position basereg+disp+(indexreg<<shift) into the double register "dfreg"
+ * NB: the scratch register has to be asked to the register allocator.
+ *     It can't be ARM_WORK, since it's already used
+ */
+#define arm_load_memindex_float64(inst,dfreg,basereg,disp,indexreg,shift,scratchreg)	\
+	do {	\
+		arm_shift_reg_imm8((inst), ARM_SHL, ARM_WORK, (indexreg), (shift));	\
+		arm_alu_reg_reg((inst), ARM_ADD, (scratchreg), (basereg), ARM_WORK);	\
+		arm_load_membase_float64((inst), (dfreg), (scratchreg), (disp));	\
+	} while (0)
+	
+/**
+ * Load the content of the 32-bits memory area at position basereg+disp+(indexreg<<shift) into the single float register "dfreg"
+ * NB: the scratch register has to be asked to the register allocator.
+ *     It can't be ARM_WORK, since it's already used
+ */
+#define arm_load_memindex_float32(inst,dfreg,basereg,disp,indexreg,shift,scratchreg)	\
+do {	\
+	arm_shift_reg_imm8((inst), ARM_SHL, ARM_WORK, (indexreg), (shift));	\
+	arm_alu_reg_reg((inst), ARM_ADD, (scratchreg), (basereg), ARM_WORK);	\
+	arm_load_membase_float32((inst), (dfreg), (scratchreg), (disp));	\
+	} while (0)
+
+/**
+ * Store the content of the float register "sfreg" into the memory area at position basereg+disp+(indexreg<<shift)
+ * using the appropriate instruction depending whether the value to be loaded is_double (1 => 64 bits) or not (0 => 32 bits)
+ * (it's similar to x86_fst_memindex)
+ */
+#define arm_fst_memindex(inst,sfreg,basereg,disp,indexreg,shift,is_double,scratchreg) \
+do {	\
+	if (is_double)	\
+	{	\
+		arm_store_memindex_float64((inst), (sfreg), (basereg), (disp), (indexreg), (shift), (scratchreg));	\
+	}	\
+	else	\
+	{	\
+		arm_store_memindex_float32((inst), (sfreg), (basereg), (disp), (indexreg), (shift), (scratchreg));	\
+	}\
+} while(0)
+
+/**
+ * Store the content of the double float register "dfreg" into the 64-bits memory area at position basereg+disp+(indexreg<<shift)
+ * NB: the scratch register has to be asked to the register allocator.
+ *     It can't be ARM_WORK, since it's already used
+ */
+#define arm_store_memindex_float64(inst,dfreg,basereg,disp,indexreg,shift,scratchreg)	\
+do {	\
+	arm_shift_reg_imm8((inst), ARM_SHL, ARM_WORK, (indexreg), (shift));	\
+	arm_alu_reg_reg((inst), ARM_ADD, (scratchreg), (basereg), ARM_WORK);	\
+	arm_store_membase_float64((inst), (dfreg), (scratchreg), (disp));	\
+} while (0)
+
+/**
+ * Store the content of the single float register "dfreg" into the 32-bits memory area at position basereg+disp+(indexreg<<shift)
+ * NB: the scratch register has to be asked to the register allocator.
+ *     It can't be ARM_WORK, since it's already used
+ */
+#define arm_store_memindex_float32(inst,dfreg,basereg,disp,indexreg,shift,scratchreg)	\
+do {	\
+	arm_shift_reg_imm8((inst), ARM_SHL, ARM_WORK, (indexreg), (shift));	\
+	arm_alu_reg_reg((inst), ARM_ADD, (scratchreg), (basereg), ARM_WORK);	\
+	arm_store_membase_float32((inst), (dfreg), (scratchreg), (disp));	\
+} while (0)
+
+/**
+ * Store a value from a register (reg) into an address (basereg+imm).
  *
- * Note: storing a 16-bit value destroys the value in the register.
  */
 #define arm_store_membase_either(inst,reg,basereg,imm,mask)	\
 			do { \
@@ -815,6 +1377,8 @@
 				} \
 				else \
 				{ \
+					assert(reg != ARM_WORK);	\
+					assert(basereg!=ARM_WORK);	\
 					arm_mov_reg_imm((inst), ARM_WORK, __sm_offset); \
 					arm_inst_add((inst), arm_prefix(0x07800000 | (mask)) | \
 								(((unsigned int)(basereg)) << 16) | \
@@ -822,6 +1386,10 @@
 								 ((unsigned int)ARM_WORK)); \
 				} \
 			} while (0)
+
+/*
+ * The ARM STR instruction. The content of "reg" will be put in memory at the address given by the content of basereg + imm
+ */
 #define	arm_store_membase(inst,reg,basereg,imm)	\
 			do { \
 				arm_store_membase_either((inst), (reg), (basereg), (imm), 0); \
@@ -851,7 +1419,7 @@
 /*
  * Store a floating-point value to a memory address.
  */
-#define	arm_store_membase_float(inst,reg,basereg,imm,mask)	\
+/*#define	arm_store_membase_float(inst,reg,basereg,imm,mask)	\
 			do { \
 				int __mb_offset = (int)(imm); \
 				if(__mb_offset >= 0 && __mb_offset < (1 << 10) && \
@@ -879,18 +1447,159 @@
 							(((unsigned int)ARM_WORK) << 16) | \
 							(((unsigned int)(reg)) << 12)); \
 				} \
-			} while (0)
-#define	arm_store_membase_float32(inst,reg,basereg,imm)	\
+			} while (0)*/
+
+/**
+ * FSTS
+ */
+#if 0
+define	arm_store_membase_float(inst,reg,basereg,imm,mask)	\
+do { \
+	unsigned int reg_top_4_bits = (reg & 0x1E) >> 1;	\
+	unsigned int reg_bottom_bit = (reg & 0x01);	\
+	int __mb_offset = (int)(imm); \
+	if(__mb_offset >= 0 && __mb_offset < (1 << 10) && \
+		(__mb_offset & 3) == 0) \
+	{ \
+		arm_inst_add((inst), arm_prefix(0x0D800A00 | (mask)) | \
+			(((unsigned int)(basereg)) << 16) | \
+			(((unsigned int)(reg_top_4_bits)) << 12) | \
+			(((unsigned int)(reg_bottom_bit)) << 22) | \
+			((unsigned int)((__mb_offset / 4) & 0xFF))); \
+	} \
+	else if(__mb_offset > -(1 << 10) && __mb_offset < 0 && \
+		(__mb_offset & 3) == 0) \
+	{ \
+		arm_inst_add((inst), arm_prefix(0x0D080A00 | (mask)) | \
+			(((unsigned int)(basereg)) << 16) | \
+			(((unsigned int)(reg_top_4_bits)) << 12) | \
+			(((unsigned int)(reg_bottom_bit)) << 22) | \
+			((unsigned int)(((-__mb_offset) / 4) & 0xFF)));\
+	} \
+	else \
+	{ \
+		arm_mov_reg_imm((inst), ARM_WORK, __mb_offset); \
+		arm_alu_reg_reg((inst), ARM_ADD, ARM_WORK, \
+			(basereg), ARM_WORK); \
+		arm_inst_add((inst), arm_prefix(0x0D800A00 | (mask)) | \
+			(((unsigned int)ARM_WORK) << 16) | \
+			(((unsigned int)(reg_top_4_bits)) << 12) |	\
+			(((unsigned int)(reg_bottom_bit)) << 22));	\
+	} \
+} while (0)
+#endif
+#define arm_store_membase_float32(inst,reg,basereg,imm)	\
+do { \
+	unsigned int reg_top_4_bits = (reg & 0x1E) >> 1;	\
+	unsigned int reg_bottom_bit = (reg & 0x01);	\
+	int __mb_offset = (int)(imm);	\
+	if(__mb_offset >= 0 && __mb_offset < (1 << 10) && (__mb_offset & 3) == 0)	\
+	{	\
+		arm_inst_add((inst), arm_prefix(0x0D800A00) |	\
+			(((unsigned int)(basereg)) << 16) | 	\
+			(((unsigned int)(reg_top_4_bits)) << 12) |	\
+			(((unsigned int)(reg_bottom_bit)) << 22) |	\
+			((unsigned int)((__mb_offset / 4) & 0xFF)));	\
+	}	\
+	else if(__mb_offset > -(1 << 10) && __mb_offset < 0 && (__mb_offset & 3) == 0)	\
+	{	\
+		arm_inst_add((inst), arm_prefix(0x0D000A00) |	\
+			(((unsigned int)(basereg)) << 16) |	\
+			(((unsigned int)(reg_top_4_bits)) << 12) |	\
+			(((unsigned int)(reg_bottom_bit)) << 22) |	\
+			((unsigned int)(((-__mb_offset) / 4) & 0xFF)));	\
+	}	\
+	else	\
+	{ \
+		assert(reg != ARM_WORK);	\
+		assert(basereg!=ARM_WORK);	\
+		if(__mb_offset > 0)	\
+		{	\
+			arm_mov_reg_imm((inst), ARM_WORK, __mb_offset); \
+			arm_alu_reg_reg((inst), ARM_ADD, ARM_WORK, (basereg), ARM_WORK); \
+		}	\
+		else	\
+		{	\
+			arm_mov_reg_imm((inst), ARM_WORK, -__mb_offset); \
+			arm_alu_reg_reg((inst), ARM_SUB, ARM_WORK, (basereg), ARM_WORK); \
+		}	\
+		arm_inst_add((inst), arm_prefix(0x0D800A00) |	\
+			(((unsigned int)ARM_WORK) << 16) | 	\
+			(((unsigned int)(reg_top_4_bits)) << 12) |	\
+			(((unsigned int)(reg_bottom_bit)) << 22));	\
+	} \
+} while (0)
+
+/**
+* FSTD
+*/
+#define	arm_store_membase_float64(inst,reg,basereg,imm)	\
+do { \
+	int __mb_offset = (int)(imm); \
+	if(__mb_offset >= 0 && __mb_offset < (1 << 10) && \
+		(__mb_offset & 3) == 0) \
+	{ \
+		arm_inst_add((inst), arm_prefix(0x0D800B00 |	\
+			(((unsigned int)(basereg)) << 16) | \
+			(((unsigned int)(reg)) << 12) | 	\
+			((unsigned int)((__mb_offset / 4) & 0xFF)))); \
+	} \
+	else if(__mb_offset > -(1 << 10) && __mb_offset < 0 && \
+		(__mb_offset & 3) == 0) \
+	{ \
+		arm_inst_add((inst), arm_prefix(0x0D000B00 |	\
+			(((unsigned int)(basereg)) << 16) | \
+			(((unsigned int)(reg)) << 12) | 	\
+			((unsigned int)(((-__mb_offset) / 4) & 0xFF))));\
+	} \
+	else \
+	{ \
+		assert(reg != ARM_WORK);	\
+		assert(basereg!=ARM_WORK);	\
+		if(__mb_offset > 0)	\
+		{	\
+			arm_mov_reg_imm((inst), ARM_WORK, __mb_offset);	\
+			arm_alu_reg_reg((inst), ARM_ADD, ARM_WORK, (basereg), ARM_WORK);	\
+		}	\
+		else	\
+		{	\
+			arm_mov_reg_imm((inst), ARM_WORK, -__mb_offset);	\
+			arm_alu_reg_reg((inst), ARM_SUB, ARM_WORK, (basereg), ARM_WORK);\
+		}	\
+		arm_inst_add((inst), arm_prefix(0x0D800B00 |	\
+			(((unsigned int)ARM_WORK) << 16) | \
+			(((unsigned int)(reg)) << 12)));\
+	} \
+} while (0)
+
+#if 0
+define	arm_store_membase_float32(inst,reg,basereg,imm)	\
 			do { \
 				arm_store_membase_float((inst), (reg), (basereg), (imm), 0); \
 			} while (0)
-#define	arm_store_membase_float64(inst,reg,basereg,imm)	\
+#endif
+/*#define	arm_store_membase_float64(inst,reg,basereg,imm)	\
 			do { \
 				arm_store_membase_float((inst), (reg), (basereg), \
 									    (imm), 0x00008000); \
 			} while (0)
+*/
+/*
+ * Floating point push/pop operations
+ */
+#define	arm_push_reg_float64(inst,reg)	\
+			do { \
+				arm_store_membase_float64((inst), (reg), ARM_SP, -8); \
+				arm_alu_reg_imm(inst, ARM_SUB, ARM_SP, ARM_SP, 8);	\
+			} while (0)
+			
 #define	arm_push_reg_float32(inst,reg)	\
 			do { \
+				arm_store_membase_float32((inst), (reg), ARM_SP, -4); \
+				arm_alu_reg_imm(inst, ARM_SUB, ARM_SP, ARM_SP, 4);	\
+			} while (0)
+/*#define	arm_push_reg_float32(inst,reg)	\
+			do { \
 				arm_store_membase_float((inst), (reg), ARM_SP, \
 									    -4, 0x00200000); \
 			} while (0)
@@ -899,7 +1608,18 @@
 				arm_store_membase_float((inst), (reg), ARM_SP, \
 									    -4, 0x00208000); \
 			} while (0)
-
+			
+#define	arm_pop_reg_float32(inst,reg)	\
+			do { \
+				arm_load_membase_float((inst), (reg), ARM_SP, \
+									    4, 0x00200000); \
+			} while (0)
+#define	arm_pop_reg_float64(inst,reg)	\
+			do { \
+				arm_load_membase_float((inst), (reg), ARM_SP, \
+									    4, 0x00208000); \
+			} while (0)
+*/
 /*
  * Load a value from an indexed address into a register.
  */
@@ -996,6 +1716,103 @@
 										 (basereg), (indexreg)); \
 			} while (0)
 
+
+/**
+ * FMDRR (Floating-point Move to Double-precision Register from two Registers)
+ * Move a value from two ARM registers (lowsreg, highsreg) to a double-precision floating point register (dreg)
+ */
+#define arm_mov_double_reg_reg(inst,dreg,lowsreg,highsreg)	\
+do { \
+	arm_inst_add((inst), arm_prefix(0x0C400B10) | \
+	(((unsigned int)(lowsreg)) << 12) | \
+	(((unsigned int)(highsreg)) << 16) | \
+	((unsigned int)(dreg))); \
+} while(0)
+
+/**
+* FMRRD (Floating-point Move to two registers from Double-precision Register)
+* Move a value from a double-precision floating point register (sreg) to two ARM registers (lowsreg, highsreg) 
+*/
+#define arm_mov_reg_reg_double(inst,lowsreg,highsreg,sreg)	\
+do { \
+	arm_inst_add((inst), arm_prefix(0x0C500B10) | \
+	(((unsigned int)(lowsreg)) << 12) | \
+	(((unsigned int)(highsreg)) << 16) | \
+	((unsigned int)(sreg))); \
+} while(0)
+
+/**
+ * FMSR (Floating-point Move to Single-precision from Register)
+ * Move a value from one ARM registers (sreg) to a single-precision floating point register (dreg)
+ */
+#define arm_mov_float_reg(inst,dreg,sreg)	\
+do { \
+	char dreg_top_4_bits = (dreg & 0x1E) >> 1;	\
+	char dreg_bottom_bit = (dreg & 0x01);	\
+	arm_inst_add((inst), arm_prefix(0x0E000A10) | 	\
+	(((unsigned int)(sreg)) << 12) | 	\
+	(((unsigned int)(dreg_top_4_bits)) << 16) |	\
+	(((unsigned int)(dreg_bottom_bit)) << 7)); \
+} while(0)
+
+/**
+* FMRS (Floating-point Move to Register from Single-precision)
+* Move a value from a single-precision floating point register (sreg) to an ARM registers (dreg) 
+*/
+#define arm_mov_reg_float(inst,dreg,sreg)	\
+do { \
+	char sreg_top_4_bits = (dreg & 0x1E) >> 1;	\
+	char sreg_bottom_bit = (dreg & 0x01);	\
+	arm_inst_add((inst), arm_prefix(0x0E100A10) | 	\
+	(((unsigned int)(dreg)) << 12) | 	\
+	(((unsigned int)(sreg_top_4_bits)) << 16) |	\
+	(((unsigned int)(sreg_bottom_bit)) << 7)); \
+} while(0)
+
+/**
+* FCVTDS (Floating-point Convert to Double-precision from Single-precision)
+* dreg is the double precision destination register
+* sreg is the single precision source register
+*/
+#define arm_convert_float_double_single(inst,dreg,sreg)	\
+{	\
+	unsigned char sreg_top_4_bits = (sreg & 0x1E) >> 1;	\
+	unsigned char sreg_bottom_bit = (sreg & 0x01);	\
+	arm_inst_add((inst), arm_prefix(0x0EB70AC0) |	\
+		(((unsigned int)(sreg_top_4_bits))) |	\
+		(((unsigned int)(sreg_bottom_bit)) << 5) |	\
+		(((unsigned int)(dreg)) << 12));	\
+}
+
+/**
+ * FCVTSD (Floating-point Convert to Single-precision from Double-precision)
+ * dreg is the single precision destination register
+ * sreg is the double precision source register
+ */
+#define arm_convert_float_single_double(inst,dreg,sreg)	\
+{	\
+	unsigned char dreg_top_4_bits = (dreg & 0x1E) >> 1;	\
+	unsigned char dreg_bottom_bit = (dreg & 0x01);	\
+	arm_inst_add((inst), arm_prefix(0x0EB70BC0) |	\
+		(((unsigned int)(dreg_top_4_bits)) << 12) |	\
+		(((unsigned int)(dreg_bottom_bit)) << 22) |	\
+		((unsigned int)(sreg)));	\
+}
+
+/**
+ * FSITOD (Floating-point Convert Signed Integer to Double-precision)
+ * sreg is the single precision register containing the integer value to be converted
+ * dreg is the double precision destination register
+ */
+#define arm_convert_float_signed_integer_double(inst,dreg,sreg)	\
+	unsigned char sreg_top_4_bits = (sreg & 0x1E) >> 1;	\
+	unsigned char sreg_bottom_bit = (sreg & 0x01);	\
+	arm_inst_add((inst), arm_prefix(0x0EB80BC0) |	\
+		(((unsigned int)(dreg)) << 12) |	\
+		(((unsigned int)(sreg_bottom_bit)) << 5) |	\
+		((unsigned int)(sreg_top_4_bits)));
+
+
 #ifdef __cplusplus
 };
 #endif
diff -ruN libjit/jit/jit-reg-alloc.c libjit-mikyt/jit/jit-reg-alloc.c
--- libjit/jit/jit-reg-alloc.c	2008-07-06 11:07:18.000000000 +0200
+++ libjit-mikyt/jit/jit-reg-alloc.c	2009-01-17 16:30:23.000000000 +0100
@@ -160,6 +160,28 @@
 	return -1;
 }
 
+/**
+ * Given the only register known, returns both the registers (if coupled) or the register and -1
+ *
+ * @var reg The register known (on entry). The same value or the value of the first register in the couple (on exit).
+ * @var other_reg The content is ignored on entry. On exit, it contains the second register in a couple or -1 if there is no second register.
+ */
+void get_reg_and_other_reg(jit_gencode_t gen, int *reg, int *other_reg)
+{
+	if(gen->contents[*reg].is_long_start)
+	{
+		*other_reg = OTHER_REG(*reg);
+	}
+	else if(gen->contents[*reg].is_long_end)
+	{
+		*other_reg = *reg;
+		*reg = get_long_pair_start(*reg);
+	}
+	else
+	{
+		*other_reg = -1;
+	}
+}
 /*
  * Determine the type of register that we need.
  */
@@ -1829,27 +1851,36 @@
 		abort();
 	}
 #endif
-
-	gen->contents[reg].values[gen->contents[reg].num_values] = value;
-	++(gen->contents[reg].num_values);
-	gen->contents[reg].age = gen->current_age;
-	gen->contents[reg].used_for_temp = 0;
-	gen->contents[reg].is_long_end = 0;
-	if(other_reg == -1)
-	{
-		gen->contents[reg].is_long_start = 0;
-	}
-	else
-	{
-		gen->contents[reg].is_long_start = 1;
-		gen->contents[other_reg].num_values = 0;
-		gen->contents[other_reg].age = gen->current_age;
-		gen->contents[other_reg].used_for_temp = 0;
-		gen->contents[other_reg].is_long_start = 0;
-		gen->contents[other_reg].is_long_end = 1;
+// #if defined(JIT_BACKEND_ARM) && !defined(JIT_REG_STACK)
+// 	if(value->in_register && value->reg==reg && gen->contents[reg].values[gen->contents[reg].num_values - 1] == value) 
+// 	{
+// 			//The value is already bound to this register!!
+// 			//Just update its age
+// 			gen->contents[reg].age = gen->current_age;
+// 	}
+// 	else
+// #endif
+	{
+		gen->contents[reg].values[gen->contents[reg].num_values] = value;
+		++(gen->contents[reg].num_values);
+		gen->contents[reg].age = gen->current_age;
+		gen->contents[reg].used_for_temp = 0;
+		gen->contents[reg].is_long_end = 0;
+		if(other_reg == -1)
+		{
+			gen->contents[reg].is_long_start = 0;
+		}
+		else
+		{
+			gen->contents[reg].is_long_start = 1;
+			gen->contents[other_reg].num_values = 0;
+			gen->contents[other_reg].age = gen->current_age;
+			gen->contents[other_reg].used_for_temp = 0;
+			gen->contents[other_reg].is_long_start = 0;
+			gen->contents[other_reg].is_long_end = 1;
+		}
+		++(gen->current_age);
 	}
-	++(gen->current_age);
-
 	/* Adjust the value to reflect that it is in "reg", and maybe the frame */
 	value->in_register = 1;
 	if(value->has_global_register)
@@ -2964,6 +2995,14 @@
 		++(gen->reg_stack_top);
 	}
 #endif
+#if defined(JIT_BACKEND_ARM) && defined(JIT_ARM_HAS_FLOAT_REGS)
+	/*
+	 * On the ARM platform, the results of a function call are always in r0-r3,
+	 * even when the result is float or double.
+	 * so we must take care of handling this situation correctly
+	 */
+	return_to_float(gen, value, reg);
+#endif
 	bind_value(gen, value, reg, other_reg, 0);
 }
 
@@ -3033,6 +3072,14 @@
 		}
 
 		_jit_gen_load_value(gen, reg, other_reg, value);
+#ifdef JIT_BACKEND_ARM
+		if(jit_type_get_kind(jit_value_get_type(value))==JIT_TYPE_STRUCT)
+		{
+			//_jit_gen_load_value doesn't handle structs
+			_jit_gen_load_value_struct (gen, reg, value);
+		}
+#endif
+
 	}
 
 	jit_reg_set_used(gen->inhibit, reg);
@@ -3808,8 +3855,8 @@
 		}
 		commit_output_value(gen, regs, 0);
 	}
-	else
 #endif
+	else
 	{
 		commit_input_value(gen, regs, 2, 0);
 		commit_input_value(gen, regs, 1, 0);
diff -ruN libjit/jit/jit-reg-alloc.h libjit-mikyt/jit/jit-reg-alloc.h
--- libjit/jit/jit-reg-alloc.h	2008-01-24 21:12:53.000000000 +0100
+++ libjit-mikyt/jit/jit-reg-alloc.h	2008-12-05 10:32:16.000000000 +0100
@@ -190,6 +190,7 @@
 unsigned char *_jit_regs_begin(jit_gencode_t gen, _jit_regs_t *regs, int space);
 void _jit_regs_end(jit_gencode_t gen, _jit_regs_t *regs, unsigned char *inst);
 
+void get_reg_and_other_reg(jit_gencode_t gen, int *reg, int *other_reg);
 #ifdef	__cplusplus
 };
 #endif
diff -ruN libjit/jit/jit-rules-arm.c libjit-mikyt/jit/jit-rules-arm.c
--- libjit/jit/jit-rules-arm.c	2008-01-24 21:12:53.000000000 +0100
+++ libjit-mikyt/jit/jit-rules-arm.c	2009-01-17 16:30:23.000000000 +0100
@@ -32,40 +32,189 @@
 #include <stdio.h>
 
 /*
+ * Pseudo register numbers for the ARM registers.  These are not the
+ * same as the CPU instruction register numbers.  The order of these
+ * values must match the order in "JIT_REG_INFO".
+ */
+#define	ARM_REG_R0			0
+#define	ARM_REG_R1			1
+#define	ARM_REG_R2			2
+#define	ARM_REG_R3			3
+#define	ARM_REG_R4			4
+#define	ARM_REG_R5			5
+#define	ARM_REG_R6			6
+#define	ARM_REG_R7			7
+#define	ARM_REG_R8			8
+#define	ARM_REG_R9			9
+#define	ARM_REG_R10			10
+#define	ARM_REG_FP			11
+#define	ARM_REG_R12			12
+#define	ARM_REG_SP			13
+#define	ARM_REG_LR			14
+#define	ARM_REG_PC			15
+#define	ARM_REG_S0			16
+#define	ARM_REG_S1			17
+#define	ARM_REG_S2			18
+#define ARM_REG_S3			19
+#define	ARM_REG_D10			20
+#define	ARM_REG_D11			21
+#define	ARM_REG_D12			22
+#define ARM_REG_D13			23
+ 
+ /*
+ * Determine if a pseudo register number is word-based or float-based.
+ */
+#define	IS_WORD_REG(reg)	((reg) < ARM_REG_S0)
+#define	IS_FLOAT_REG(reg)	((reg) >= ARM_REG_S0)
+
+/*
  * Round a size up to a multiple of the stack word size.
  */
 #define	ROUND_STACK(size)	\
 		(((size) + (sizeof(void *) - 1)) & ~(sizeof(void *) - 1))
 
+/* 
+ * Define the classes of registers
+ */
+static _jit_regclass_t *arm_reg;
+static _jit_regclass_t *arm_freg32;
+static _jit_regclass_t *arm_freg64;
+static _jit_regclass_t *arm_lreg;
+static _jit_regclass_t *arm_breg;
+
 /*
+ * -------------------- Helper functions --------------------------
+ */
+/**
  * Load the instruction pointer from the generation context.
  */
 #define	jit_gen_load_inst_ptr(gen,inst)	\
 		do { \
 			arm_inst_buf_init((inst), (gen)->posn.ptr, (gen)->posn.limit); \
-		} while (0)
+} while (0)
 
-/*
+/**
  * Save the instruction pointer back to the generation context.
  */
 #define	jit_gen_save_inst_ptr(gen,inst)	\
 		do { \
 			(gen)->posn.ptr = (unsigned char *)arm_inst_get_posn(inst); \
-		} while (0)
+} while (0)
 
-void _jit_init_backend(void)
+/*
+* Get a temporary register that isn't one of the specified registers.
+* When this function is used EVERY REGISTER COULD BE DESTROYED!!!
+* TODO: this function is only used by JIT_OP_STORE_RELATIVE_STRUCT, through memory copy: remove
+* the need of using it by sustituting it with register allocation with [scratch reg]
+*/
+static int get_temp_reg(int reg1, int reg2, int reg3)
 {
-	/* Nothing to do here */
+	/* 
+	 * R0-R3 are not used because they could be needed for parameter passing.
+	 * R4 is not used because it's used by jit_apply to store the base of the frame where
+	 * it saves all the data it needs in order to restart execution after calling a compiled function.
+	 * R9 is not used because it's the platform register and could have special
+	 * uses on some ARM platform
+	 * R11, R13-R15 are not used because they have special meaning on the ARM platform.
+	 * The other registers are candidates for 
+	 */
+	if(reg1 != ARM_R5 && reg2 != ARM_R5 && reg3 != ARM_R5)
+	{
+		return ARM_R5;
+	}
+	if(reg1 != ARM_R6 && reg2 != ARM_R6 && reg3 != ARM_R6)
+	{
+		return ARM_R6;
+	}
+	if(reg1 != ARM_R7 && reg2 != ARM_R7 && reg3 != ARM_R7)
+	{
+		return ARM_R7;
+	}
+	if(reg1 != ARM_R8 && reg2 != ARM_R8 && reg3 != ARM_R8)
+	{
+		return ARM_R8;
+	}
+	if(reg1 != ARM_R10 && reg2 != ARM_R10 && reg3 != ARM_R10)
+	{
+		return ARM_R10;
+	}
+	return ARM_R12;
 }
 
-void _jit_gen_get_elf_info(jit_elf_info_t *info)
-{
-	info->machine = 40;		/* EM_ARM */
-	info->abi = 0;			/* ELFOSABI_SYSV */
-	info->abi_version = 0;
+/*
+* Copy a block of memory that has a specific size.  Other than
+* the parameter pointers, all registers must be unused at this point.
+*/
+static arm_inst_buf memory_copy (jit_gencode_t gen, arm_inst_buf inst, int dreg, jit_nint doffset, int sreg, jit_nint soffset, jit_nuint size, int temp_reg)
+{
+	//int temp_reg = get_temp_reg(dreg, sreg, -1);
+	if (temp_reg==-1) temp_reg = get_temp_reg(dreg, sreg, -1);
+	if(size <= 4 * sizeof(void *))
+	{
+		/* Use direct copies to copy the memory */
+		int offset = 0;
+		while(size >= sizeof(void *))
+		{
+			arm_mov_reg_membase(inst, temp_reg, sreg, soffset + offset, sizeof(void *));
+			arm_mov_membase_reg(inst, dreg, doffset + offset, temp_reg, sizeof(void *));
+			size -= sizeof(void *);
+			offset += sizeof(void *);
+		}
+		if(size >= 2)
+		{
+			arm_mov_reg_membase(inst, temp_reg, sreg, soffset + offset, 2);
+			arm_mov_membase_reg(inst, dreg, doffset + offset, temp_reg, 2);
+			size -= 2;
+			offset += 2;
+		}
+		if(size >= 1)
+		{
+			arm_mov_reg_membase(inst, temp_reg, sreg, soffset + offset, 1);
+			arm_mov_membase_reg(inst, dreg, doffset + offset, temp_reg, 1);
+		}
+	}
+	else
+	{
+		/* Call out to "jit_memcpy" to effect the copy */
+		//Load the parameters in the right registers
+		//R2 <- size
+		arm_mov_reg_imm(inst, ARM_R2, size);
+		//R1 <- source pointer
+		if(soffset == 0)
+		{
+			arm_mov_reg_reg(inst, ARM_R1, sreg);
+		}
+		else
+		{
+			arm_alu_reg_imm(inst, ARM_ADD, temp_reg, sreg, soffset);
+			arm_mov_reg_reg(inst, ARM_R1, temp_reg);
+		}
+		//R0 <- destination pointer
+		//if(dreg != ARM_SP) /* On ARM, the stack doesn't need special treatment, since parameters are passed using registers, not using the stack as it's done on x86 */
+		//{
+			if(doffset == 0)
+			{
+				arm_mov_reg_reg(inst, ARM_R0, dreg);
+			}
+			else
+			{
+				arm_alu_reg_imm(inst, ARM_ADD, temp_reg, dreg, doffset);
+				arm_mov_reg_reg(inst, ARM_R0, temp_reg);
+			}
+			//}
+			//else
+			//{
+				//	/* Copying a structure value onto the stack */
+		//	x86_lea_membase(inst, temp_reg, X86_ESP,
+		//			 doffset + 2 * sizeof(void *));
+		//			 x86_push_reg(inst, temp_reg);
+		//}
+		arm_call(inst, jit_memcpy);
+	}
+	return inst;
 }
 
-/*
+/**
  * Flush the contents of the constant pool.
  */
 static void flush_constants(jit_gencode_t gen, int after_epilog)
@@ -126,7 +275,7 @@
 			}
 			if(value)
 			{
-				fixup -= value;
+				fixup -= value / sizeof(void *);
 			}
 			else
 			{
@@ -148,14 +297,14 @@
 	jit_gen_save_inst_ptr(gen, inst);
 }
 
-/*
+/**
  * Perform a constant pool flush if we are too far from the starting point.
  */
 static int flush_if_too_far(jit_gencode_t gen)
 {
 	if(gen->first_constant_use &&
-	   (((arm_inst_word *)(gen->posn.ptr)) -
-	   		((arm_inst_word *)(gen->first_constant_use))) >= 100)
+		  (((arm_inst_word *)(gen->posn.ptr)) -
+		  ((arm_inst_word *)(gen->first_constant_use))) >= 100)
 	{
 		flush_constants(gen, 0);
 		return 1;
@@ -170,7 +319,7 @@
  * Add a fixup for a particular constant pool entry.
  */
 static void add_constant_fixup
-	(jit_gencode_t gen, int index, arm_inst_word *fixup)
+		(jit_gencode_t gen, int index, arm_inst_word *fixup)
 {
 	arm_inst_word *prev;
 	int value;
@@ -182,7 +331,7 @@
 	prev = gen->fixup_constants[index];
 	if(prev)
 	{
-		value = fixup - prev;
+		value = (fixup - prev) * sizeof(void *);
 	}
 	else
 	{
@@ -190,10 +339,12 @@
 	}
 	if((*fixup & 0x0F000000) == 0x05000000)
 	{
+		//Word fixup
 		*fixup = ((*fixup & ~0x0FFF) | value);
 	}
 	else
 	{
+		//Float fixup
 		*fixup = ((*fixup & ~0x00FF) | (value / 4));
 	}
 	gen->fixup_constants[index] = fixup;
@@ -235,10 +386,10 @@
 }
 
 /*
- * Add a double-word immedite value to the constant pool.
+ * Add a double-word immediate value to the constant pool.
  */
 static void add_constant_dword
-	(jit_gencode_t gen, int value1, int value2, arm_inst_word *fixup, int align)
+		(jit_gencode_t gen, int value1, int value2, arm_inst_word *fixup, int align)
 {
 	int index;
 
@@ -252,7 +403,7 @@
 	for(index = 0; index < (gen->num_constants - 1); ++index)
 	{
 		if(gen->constants[index] == value1 &&
-		   gen->constants[index + 1] == value2)
+				 gen->constants[index + 1] == value2)
 		{
 			if(!align || (index % 2) == 0)
 			{
@@ -279,8 +430,8 @@
 	/* Add the double word constant value to the pool */
 	gen->constants[gen->num_constants] = value1;
 	gen->fixup_constants[gen->num_constants] = 0;
-	gen->constants[gen->num_constants] = value2;
-	gen->fixup_constants[gen->num_constants] = 0;
+	gen->constants[gen->num_constants+1] = value2;
+	gen->fixup_constants[gen->num_constants+1] = 0;
 	gen->num_constants += 2;
 	add_constant_fixup(gen, gen->num_constants - 2, fixup);
 }
@@ -290,7 +441,7 @@
  * complicated, then add an entry to the constant pool.
  */
 static void mov_reg_imm
-	(jit_gencode_t gen, arm_inst_buf *inst, int reg, int value)
+		(jit_gencode_t gen, arm_inst_buf *inst, int reg, int value)
 {
 	arm_inst_word *fixup;
 
@@ -316,7 +467,7 @@
  * complicated, then add an entry to the constant pool.
  */
 static void mov_freg_imm_32
-	(jit_gencode_t gen, arm_inst_buf *inst, int reg, int value)
+		(jit_gencode_t gen, arm_inst_buf *inst, int reg, int value)
 {
 	arm_inst_word *fixup;
 
@@ -335,7 +486,7 @@
  * complicated, then add an entry to the constant pool.
  */
 static void mov_freg_imm_64
-	(jit_gencode_t gen, arm_inst_buf *inst, int reg, int value1, int value2)
+		(jit_gencode_t gen, arm_inst_buf *inst, int reg, int value1, int value2)
 {
 	arm_inst_word *fixup;
 
@@ -349,6 +500,190 @@
 	jit_gen_load_inst_ptr(gen, *inst);
 }
 
+/*
+ * Output a branch instruction.
+ */
+static void output_branch
+		(jit_function_t func, arm_inst_buf *inst, int cond, jit_insn_t insn)
+{
+	jit_block_t block;
+	int offset;
+	//block = jit_block_from_label(func, (jit_label_t)(insn->dest));
+	if((insn->flags & JIT_INSN_VALUE1_IS_LABEL) != 0)
+	{
+		/* "address_of_label" instruction */
+		block = jit_block_from_label(func, (jit_label_t)(insn->value1));
+	}
+	else
+	{
+		block = jit_block_from_label(func, (jit_label_t)(insn->dest));
+	}
+	if(!block)
+	{
+		return;
+	}
+	if(arm_inst_get_posn(*inst) >= arm_inst_get_limit(*inst))
+	{
+		/* The buffer has overflowed, so don't worry about fixups */
+		return;
+	}
+	if(block->address)
+	{
+		/* We already know the address of the block */
+		arm_branch(*inst, cond, block->address);
+	}
+	else
+	{
+		/* Output a placeholder and record on the block's fixup list */
+		if(block->fixup_list)
+		{
+			offset = (int)(((unsigned char *)arm_inst_get_posn(*inst)) -
+					((unsigned char *)(block->fixup_list)));
+		}
+		else
+		{
+			offset = 0;
+		}
+		arm_branch_imm(*inst, cond, offset);
+		block->fixup_list = (void *)(arm_inst_get_posn(*inst) - 1);
+	}
+}
+
+/*
+ * Throw a builtin exception.
+ */
+static void throw_builtin
+		(arm_inst_buf *inst, jit_function_t func, int cond, int type)
+{
+	arm_inst_word *patch;
+
+	/* Branch past the following code if "cond" is not true */
+	patch = arm_inst_get_posn(*inst);
+	arm_branch_imm(*inst, cond ^ 0x01, 0);
+
+	/* We need to update "catch_pc" if we have a "try" block */
+	if(func->builder->setjmp_value != 0)
+	{
+		_jit_gen_fix_value(func->builder->setjmp_value);
+		arm_mov_reg_reg(*inst, ARM_WORK, ARM_PC);
+		arm_store_membase(*inst, ARM_WORK, ARM_FP,
+				   func->builder->setjmp_value->frame_offset +
+						   jit_jmp_catch_pc_offset);
+	}
+
+	/* Push the exception type onto the stack */
+	arm_mov_reg_imm(*inst, ARM_WORK, type);
+	arm_push_reg(*inst, ARM_WORK);
+
+	/* Call the "jit_exception_builtin" function, which will never return */
+	arm_call(*inst, jit_exception_builtin);
+
+	/* Back-patch the previous branch instruction */
+	arm_patch(*inst, patch, arm_inst_get_posn(*inst));
+}
+
+/*
+ * Jump to the current function's epilog.
+ */
+static void jump_to_epilog
+		(jit_gencode_t gen, arm_inst_buf *inst, jit_block_t block)
+{
+	int offset;
+
+	/* If the epilog is the next thing that we will output,
+	then fall through to the epilog directly */
+	block = block->next;
+	while(block != 0 && block->first_insn > block->last_insn)
+	{
+		block = block->next;
+	}
+	if(!block)
+	{
+		return;
+	}
+
+	/* Bail out if the instruction buffer has overflowed */
+	if(arm_inst_get_posn(*inst) >= arm_inst_get_limit(*inst))
+	{
+		return;
+	}
+
+	/* Output a placeholder for the jump and add it to the fixup list */
+	if(gen->epilog_fixup)
+	{
+		offset = (int)(((unsigned char *)arm_inst_get_posn(*inst)) -
+				((unsigned char *)(gen->epilog_fixup)));
+	}
+	else
+	{
+		offset = 0;
+	}
+	arm_branch_imm(*inst, ARM_CC_AL, offset);
+	gen->epilog_fixup = (void *)(arm_inst_get_posn(*inst) - 1);
+}
+
+#define	TODO()		\
+	do { \
+		fprintf(stderr, "TODO at %s, %d\n", __FILE__, (int)__LINE__); \
+} while (0)
+
+/*
+ * -------------------- End of helper functions ------------------------
+ */
+ 
+
+
+/**
+ * Initialize the backend.
+ */
+void _jit_init_backend(void)
+{
+	/*
+	 * Init the various classes of registers
+	 */
+	/** WORD registers */
+	arm_reg = _jit_regclass_create(
+		"reg", JIT_REG_WORD, 9,
+		ARM_REG_R0, ARM_REG_R1,
+		ARM_REG_R2, ARM_REG_R3,
+		ARM_REG_R4, ARM_REG_R5,
+		ARM_REG_R6, ARM_REG_R7,
+		ARM_REG_R8);
+
+	/** 32-bits float registers */
+	arm_freg32 = _jit_regclass_create(
+		"freg32", JIT_REG_ARM_FLOAT32, 4,
+		ARM_REG_S0, ARM_REG_S1,
+		ARM_REG_S2, ARM_REG_S3);
+	
+	/** 64-bits float registers */
+	arm_freg64 = _jit_regclass_create(
+		"freg64", JIT_REG_ARM_FLOAT64, 4,
+		ARM_REG_D10, ARM_REG_D11,
+		ARM_REG_D12, ARM_REG_D12);
+
+	/** Long registers */
+	arm_lreg = _jit_regclass_create(
+		"lreg", JIT_REG_LONG, 2,
+		ARM_REG_R0, ARM_REG_R2);
+		
+	/** ??? registers */ //TODO: check this definition
+	arm_breg = _jit_regclass_create(
+	"breg", JIT_REG_WORD, 9,
+				       ARM_REG_R0, ARM_REG_R1,
+				       ARM_REG_R2, ARM_REG_R3,
+				       ARM_REG_R4, ARM_REG_R5,
+				       ARM_REG_R6, ARM_REG_R7,
+				       ARM_REG_R8);
+}
+
+void _jit_gen_get_elf_info(jit_elf_info_t *info)
+{
+	info->machine = 40;		/* EM_ARM */
+	info->abi = 0;			/* ELFOSABI_SYSV */
+	info->abi_version = 0;
+}
+
 int _jit_setup_indirect_pointer(jit_function_t func, jit_value_t value)
 {
 	return jit_insn_outgoing_reg(func, value, ARM_WORK);
@@ -367,7 +702,7 @@
 	ptr_return = jit_type_return_via_pointer(return_type);
 	if(!return_value || ptr_return)
 	{
-		return 0;
+		return 1;
 	}
 
 	/* Structure values must be flushed into the frame, and
@@ -380,11 +715,18 @@
 		}
 	}
 #ifdef JIT_ARM_HAS_FLOAT_REGS
-	else if(return_type->kind == JIT_TYPE_FLOAT32 ||
-			return_type->kind == JIT_TYPE_FLOAT64 ||
+	//TODO: check that this works when the handling of the float registers changes
+	else if(return_type->kind == JIT_TYPE_FLOAT32)
+	{
+		if(!jit_insn_return_reg(func, return_value, ARM_REG_S0))
+		{
+			return 0;
+		}
+	}
+	else if(return_type->kind == JIT_TYPE_FLOAT64 ||
 			return_type->kind == JIT_TYPE_NFLOAT)
 	{
-		if(!jit_insn_return_reg(func, return_value, 16 /* f0 */))
+		if(!jit_insn_return_reg(func, return_value, ARM_REG_D10))
 		{
 			return 0;
 		}
@@ -392,7 +734,7 @@
 #endif
 	else if(return_type->kind != JIT_TYPE_VOID)
 	{
-		if(!jit_insn_return_reg(func, return_value, 0 /* r0 */))
+		if(!jit_insn_return_reg(func, return_value, ARM_REG_R0))
 		{
 			return 0;
 		}
@@ -407,7 +749,7 @@
 	switch(opcode)
 	{
 		#define JIT_INCLUDE_SUPPORTED
-		#include "jit-rules-arm.slc"
+		#include "jit-rules-arm.inc"
 		#undef JIT_INCLUDE_SUPPORTED
 	}
 	return 0;
@@ -420,7 +762,8 @@
 	int reg, regset;
 	unsigned int saved;
 	unsigned int frame_size;
-
+	unsigned int stack_growth;
+	
 	/* Initialize the instruction buffer */
 	arm_inst_buf_init(inst, prolog, prolog + JIT_PROLOG_SIZE / sizeof(int));
 
@@ -443,8 +786,26 @@
 	/* Allocate space for the local variable frame.  Subtract off
 	   the space for the registers that we just saved.  The pc, lr,
 	   and fp registers are always saved, so account for them too */
+	stack_growth=(saved + 4 * sizeof(void *));
+	frame_size = func->builder->frame_size - stack_growth;
 	frame_size = func->builder->frame_size - (saved + 3 * sizeof(void *));
 	frame_size += (unsigned int)(func->builder->param_area_size);
+	while(frame_size % JIT_SP_ALIGN_PUBLIC != 0)
+	{
+		//Pad to reach the required stacl pointer alignment
+		frame_size++;
+	}
+	
+	/* If the registers that get saved on the stack make it grow of a odd number
+	 * of words, the preceding while isn't able anymore to compute the correct
+	 * allignment. The following adds a correction when needed.
+	 */
+	if (stack_growth % JIT_SP_ALIGN_PUBLIC != 0)
+	{
+		//Pad to reach the required stack pointer alignment
+		frame_size += (stack_growth % JIT_SP_ALIGN_PUBLIC);
+	}
+	
 	if(frame_size > 0)
 	{
 		arm_alu_reg_imm(inst, ARM_SUB, ARM_SP, ARM_SP, frame_size);
@@ -504,6 +865,11 @@
 	flush_constants(gen, 1);
 }
 
+#if 0
+/*
+ * The ARM backend does not need this function because it uses
+ * _jit_create_indirector() instead.
+ */
 void *_jit_gen_redirector(jit_gencode_t gen, jit_function_t func)
 {
 	void *ptr, *entry;
@@ -517,7 +883,7 @@
 	jit_gen_save_inst_ptr(gen, inst);
 	return entry;
 }
-
+#endif 
 /*
  * Setup or teardown the ARM code output process.
  */
@@ -527,6 +893,12 @@
 #define	jit_cache_end_output()	\
 	jit_gen_save_inst_ptr(gen, inst)
 
+/** 
+ * Spill the content of register "reg" (and "other_reg", if it's different from -1) 
+ * into the global register or the memory area associated with "value"
+ * NB: it doesn't set value->in_global_register or value->in_frame. The caller has to
+ * take care of that.
+ */
 void _jit_gen_spill_reg(jit_gencode_t gen, int reg,
 						int other_reg, jit_value_t value)
 {
@@ -542,14 +914,21 @@
 	/* Output an appropriate instruction to spill the value */
 	if(value->has_global_register)
 	{
-		arm_mov_reg_reg(inst, _jit_reg_info[value->global_reg].cpu_reg,
-						_jit_reg_info[reg].cpu_reg);
+		if (IS_FLOAT_REG(reg))
+		{
+			printf("TODO:Copy from float reg to global reg is not handled properly in %s\n", __FILE__);
+			abort();
+		}
+		else
+		{
+			arm_mov_reg_reg(inst, _jit_reg_info[value->global_reg].cpu_reg, _jit_reg_info[reg].cpu_reg);
+		}
 	}
 	else
 	{
 		_jit_gen_fix_value(value);
 		offset = (int)(value->frame_offset);
-		if(reg < 16)
+		if(IS_WORD_REG(reg))
 		{
 			arm_store_membase(inst, reg, ARM_FP, offset);
 			if(other_reg != -1)
@@ -561,11 +940,11 @@
 		}
 		else if(jit_type_normalize(value->type)->kind == JIT_TYPE_FLOAT32)
 		{
-			arm_store_membase_float32(inst, reg - 16, ARM_FP, offset);
+			arm_store_membase_float32(inst, _jit_reg_info[value->reg].cpu_reg, ARM_FP, offset);
 		}
 		else
 		{
-			arm_store_membase_float64(inst, reg - 16, ARM_FP, offset);
+			arm_store_membase_float64(inst, _jit_reg_info[value->reg].cpu_reg, ARM_FP, offset);
 		}
 	}
 
@@ -579,6 +958,101 @@
 	/* We don't have to do anything to free ARM registers */
 }
 
+#ifdef JIT_REG_STACK
+static int fp_stack_index(jit_gencode_t gen, int reg)
+{
+	return gen->reg_stack_top - reg - 1;
+}
+
+void _jit_gen_exch_top(jit_gencode_t gen, int reg)
+{
+	if(IS_FLOAT_REG(reg))
+	{
+		jit_cache_setup_output(2);
+		
+		/* Swap using a temporary register */
+		int tmpreg;
+		if (reg!=ARM_F0)
+		{
+			tmpreg=ARM_F0;
+		}
+		else
+		{
+			tmpreg=ARM_F1;
+		}
+		arm_push_reg_float64(inst, tmpreg);
+		
+		int top=gen->reg_stack_top-1;
+		arm_mov_freg_freg(inst, fp_stack_index(gen, tmpreg), top);
+		arm_mov_freg_freg(inst, top, fp_stack_index(gen, reg));
+		arm_mov_freg_freg(inst, fp_stack_index(gen, reg), fp_stack_index(gen, tmpreg));
+		
+		arm_pop_reg_float64(inst, tmpreg);
+		
+		jit_cache_end_output();
+	}
+}
+
+void _jit_gen_move_top(jit_gencode_t gen, int reg)
+{
+	if(IS_FLOAT_REG(reg))
+	{
+		jit_cache_setup_output(2);
+		int top=gen->reg_stack_top-1;
+		arm_mov_freg_freg(inst, fp_stack_index(gen, reg), top);
+		jit_cache_end_output();
+	}
+}
+
+void _jit_gen_spill_top(jit_gencode_t gen, int reg, jit_value_t value, int pop)
+{
+	int offset;
+	if(IS_FLOAT_REG(reg))
+	{
+		/* Make sure that we have sufficient space */
+		jit_cache_setup_output(16);
+		
+		/* Fix the value in place within the local variable frame */
+		_jit_gen_fix_value(value);
+		
+		/* Output an appropriate instruction to spill the value */
+		offset = (int)(value->frame_offset);
+		
+		/* Spill the top of the floating-point register stack */
+		switch(jit_type_normalize(value->type)->kind)
+		{
+			case JIT_TYPE_FLOAT32:
+			{
+				arm_store_membase_float32(inst,reg,ARM_FP,offset);
+			}
+			break;
+			
+			case JIT_TYPE_FLOAT64:
+			{
+				arm_store_membase_float64(inst,reg,ARM_FP,offset);
+			}
+			break;
+			
+			case JIT_TYPE_NFLOAT:
+			{
+				printf("JIT_TYPE_NFLOAT unimplemented in file %s at line %d", __FILE__, __LINE__);
+				abort();
+				//TODO: store float64 or float32?
+				
+				/*x86_fst80_membase(inst, X86_EBP, offset);
+				if(!pop)
+				{
+					x86_fld80_membase(inst, X86_EBP, offset);
+				}*/
+			}
+			break;
+		}
+		
+		/* End the code output process */
+		jit_cache_end_output();
+	}
+}
+#endif
 void _jit_gen_load_value
 	(jit_gencode_t gen, int reg, int other_reg, jit_value_t value)
 {
@@ -624,7 +1098,7 @@
 			{
 				jit_float32 float32_value;
 				float32_value = jit_value_get_float32_constant(value);
-				if(reg < 16)
+				if(IS_WORD_REG(reg))
 				{
 					mov_reg_imm(gen, &inst, _jit_reg_info[reg].cpu_reg,
 							    *((int *)&float32_value));
@@ -643,7 +1117,7 @@
 			{
 				jit_float64 float64_value;
 				float64_value = jit_value_get_float64_constant(value);
-				if(reg < 16)
+				if(IS_WORD_REG(reg))
 				{
 					mov_reg_imm
 						(gen, &inst, _jit_reg_info[reg].cpu_reg,
@@ -665,6 +1139,26 @@
 	}
 	else if(value->has_global_register)
 	{
+		/*
+		 * This value has been assinged a global register. This means
+		 * that it can use that register, but not necessarily that it's
+		 * already in it!!
+		 */
+		
+		/* Ensure that the value is already in the global_register */
+		if (!value->in_global_register)
+		{	
+			/* Find the other register in a long pair */
+			int reg=value->reg;
+			int other_reg;
+			get_reg_and_other_reg(gen, &reg, &other_reg);
+			//Spill to the global register
+			_jit_gen_spill_reg(gen, reg, other_reg, value);
+			value->in_global_register=1;
+			
+			/* A new instruction has probably been generated by _jit_gen_spill_reg: reload the inst pointer */
+			jit_gen_load_inst_ptr(gen, inst);
+		}
 		/* Load the value out of a global register */
 		arm_mov_reg_reg(inst, _jit_reg_info[reg].cpu_reg,
 						_jit_reg_info[value->global_reg].cpu_reg);
@@ -675,34 +1169,47 @@
 		_jit_gen_fix_value(value);
 		offset = (int)(value->frame_offset);
 
-		/* Load the value into the specified register */
+		/* Ensure that the value is already in the stack frame */
+		if(value->in_register)
+		{
+			/* Find the other register in a long pair */
+			int reg=value->reg;
+			int other_reg;
+			get_reg_and_other_reg(gen, &reg, &other_reg);
+			_jit_gen_spill_reg(gen, reg, other_reg, value);
+			value->in_frame=1;
+			
+			/* A new instruction has probably been generated by _jit_gen_spill_reg: reload the inst pointer */
+			jit_gen_load_inst_ptr(gen, inst);
+		}
+		
 		switch(jit_type_normalize(value->type)->kind)
 		{
 			case JIT_TYPE_SBYTE:
 			{
 				arm_load_membase_sbyte(inst, _jit_reg_info[reg].cpu_reg,
-								       ARM_FP, offset);
+								ARM_FP, offset);
 			}
 			break;
 
 			case JIT_TYPE_UBYTE:
 			{
 				arm_load_membase_byte(inst, _jit_reg_info[reg].cpu_reg,
-								      ARM_FP, offset);
+								ARM_FP, offset);
 			}
 			break;
 
 			case JIT_TYPE_SHORT:
 			{
 				arm_load_membase_short(inst, _jit_reg_info[reg].cpu_reg,
-								       ARM_FP, offset);
+								ARM_FP, offset);
 			}
 			break;
 
 			case JIT_TYPE_USHORT:
 			{
 				arm_load_membase_ushort(inst, _jit_reg_info[reg].cpu_reg,
-								        ARM_FP, offset);
+									ARM_FP, offset);
 			}
 			break;
 
@@ -710,7 +1217,7 @@
 			case JIT_TYPE_UINT:
 			{
 				arm_load_membase(inst, _jit_reg_info[reg].cpu_reg,
-								 ARM_FP, offset);
+								ARM_FP, offset);
 			}
 			break;
 
@@ -718,18 +1225,18 @@
 			case JIT_TYPE_ULONG:
 			{
 				arm_load_membase(inst, _jit_reg_info[reg].cpu_reg,
-								 ARM_FP, offset);
+								ARM_FP, offset);
 				arm_load_membase(inst, _jit_reg_info[reg].cpu_reg + 1,
-								 ARM_FP, offset + 4);
+								ARM_FP, offset + 4);
 			}
 			break;
 
 			case JIT_TYPE_FLOAT32:
 			{
-				if(reg < 16)
+				if(IS_WORD_REG(reg))
 				{
 					arm_load_membase(inst, _jit_reg_info[reg].cpu_reg,
-									 ARM_FP, offset);
+									ARM_FP, offset);
 				}
 				else
 				{
@@ -742,12 +1249,12 @@
 			case JIT_TYPE_FLOAT64:
 			case JIT_TYPE_NFLOAT:
 			{
-				if(reg < 16)
+				if(IS_WORD_REG(reg))
 				{
 					arm_load_membase(inst, _jit_reg_info[reg].cpu_reg,
-									 ARM_FP, offset);
+									ARM_FP, offset);
 					arm_load_membase(inst, _jit_reg_info[reg].cpu_reg + 1,
-									 ARM_FP, offset + 4);
+									ARM_FP, offset + 4);
 				}
 				else
 				{
@@ -763,160 +1270,110 @@
 	jit_cache_end_output();
 }
 
-void _jit_gen_spill_global(jit_gencode_t gen, int reg, jit_value_t value)
+/**
+ * Loads a struct indicated by "value" into the given register reg
+ */
+void _jit_gen_load_value_struct (jit_gencode_t gen, int reg, jit_value_t value)
 {
-	/* TODO: Implement if ARM needs it. */
-}
+	int offset;
 
-void _jit_gen_load_global(jit_gencode_t gen, int reg, jit_value_t value)
-{
+	/* Make sure that we have sufficient space */
 	jit_cache_setup_output(32);
-	arm_load_membase(inst, _jit_reg_info[value->global_reg].cpu_reg,
-					 ARM_FP, value->frame_offset);
-	jit_cache_end_output();
-}
-
-void _jit_gen_exch_top(jit_gencode_t gen, int reg)
-{
-}
-
-void _jit_gen_move_top(jit_gencode_t gen, int reg)
-{
-}
-
-void _jit_gen_spill_top(jit_gencode_t gen, int reg, jit_value_t value, int pop)
-{
-}
-
-void _jit_gen_fix_value(jit_value_t value)
-{
-	if(!(value->has_frame_offset) && !(value->is_constant))
+	if(flush_if_too_far(gen))
 	{
-		jit_nint size = (jit_nint)(ROUND_STACK(jit_type_get_size(value->type)));
-		value->block->func->builder->frame_size += size;
-		value->frame_offset = -(value->block->func->builder->frame_size);
-		value->has_frame_offset = 1;
+		jit_gen_load_inst_ptr(gen, inst);
 	}
-}
 
-/*
- * Output a branch instruction.
- */
-static void output_branch
-	(jit_function_t func, arm_inst_buf *inst, int cond, jit_insn_t insn)
-{
-	jit_block_t block;
-	int offset;
-	block = jit_block_from_label(func, (jit_label_t)(insn->dest));
-	if(!block)
-	{
-		return;
-	}
-	if(arm_inst_get_posn(*inst) >= arm_inst_get_limit(*inst))
+	if(value->is_constant)
 	{
-		/* The buffer has overflowed, so don't worry about fixups */
-		return;
+		TODO();
+		abort();
 	}
-	if(block->address)
+	else if(value->has_global_register)
 	{
-		/* We already know the address of the block */
-		arm_branch(*inst, cond, block->address);
+		/*
+		 * This value has been assinged a global register. This means
+		 * that it can use that register, but not necessarily that it's
+		 * already in it!!
+		 */
+		
+		/* Ensure that the value is already in the global_register */
+		if (!value->in_global_register)
+		{	
+			/* Find the other register in a long pair */
+			int reg=value->reg;
+			int other_reg;
+			get_reg_and_other_reg(gen, &reg, &other_reg);
+			//Spill to the global register
+			_jit_gen_spill_reg(gen, reg, other_reg, value);
+			value->in_global_register=1;
+			
+			/* A new instruction has probably been generated by _jit_gen_spill_reg: reload the inst pointer */
+			jit_gen_load_inst_ptr(gen, inst);
+		}
+		/* Load the value out of a global register */
+		arm_mov_reg_reg(inst, _jit_reg_info[reg].cpu_reg,
+						_jit_reg_info[value->global_reg].cpu_reg);
 	}
 	else
 	{
-		/* Output a placeholder and record on the block's fixup list */
-		if(block->fixup_list)
+		/* Fix the position of the value in the stack frame */
+		_jit_gen_fix_value(value);
+		offset = (int)(value->frame_offset);
+
+		/* Ensure that the value is already in the stack frame */
+		if(value->in_register)
 		{
-			offset = (int)(((unsigned char *)arm_inst_get_posn(*inst)) -
-						   ((unsigned char *)(block->fixup_list)));
+			/* Find the other register in a long pair */
+			int reg=value->reg;
+			int other_reg;
+			get_reg_and_other_reg(gen, &reg, &other_reg);
+			_jit_gen_spill_reg(gen, reg, other_reg, value);
+			value->in_frame=1;
+			
+			/* A new instruction has probably been generated by _jit_gen_spill_reg: reload the inst pointer */
+			jit_gen_load_inst_ptr(gen, inst);
 		}
-		else
+		
+		assert(jit_type_normalize(value->type)->kind==JIT_TYPE_STRUCT);
+		
+		arm_load_membase(inst, _jit_reg_info[reg].cpu_reg, ARM_FP, offset);
+		if (jit_type_get_size(jit_value_get_type(value)) > 4)
 		{
-			offset = 0;
+			TODO();
+			abort();
 		}
-		arm_branch_imm(*inst, cond, offset);
-		block->fixup_list = (void *)(arm_inst_get_posn(*inst) - 1);
+		
 	}
+
+	/* End the code output process */
+	jit_cache_end_output();
 }
 
-/*
- * Throw a builtin exception.
- */
-static void throw_builtin
-		(arm_inst_buf *inst, jit_function_t func, int cond, int type)
+void _jit_gen_spill_global(jit_gencode_t gen, int reg, jit_value_t value)
 {
-	arm_inst_word *patch;
-
-	/* Branch past the following code if "cond" is not true */
-	patch = arm_inst_get_posn(*inst);
-	arm_branch_imm(*inst, cond ^ 0x01, 0);
-
-	/* We need to update "catch_pc" if we have a "try" block */
-	if(func->builder->setjmp_value != 0)
-	{
-		_jit_gen_fix_value(func->builder->setjmp_value);
-		arm_mov_reg_reg(*inst, ARM_WORK, ARM_PC);
-		arm_store_membase(*inst, ARM_WORK, ARM_FP,
-						  func->builder->setjmp_value->frame_offset +
-						  jit_jmp_catch_pc_offset);
-	}
-
-	/* Push the exception type onto the stack */
-	arm_mov_reg_imm(*inst, ARM_WORK, type);
-	arm_push_reg(*inst, ARM_WORK);
-
-	/* Call the "jit_exception_builtin" function, which will never return */
-	arm_call(*inst, jit_exception_builtin);
-
-	/* Back-patch the previous branch instruction */
-	arm_patch(*inst, patch, arm_inst_get_posn(*inst));
+	/* TODO: Implement if ARM needs it. */
 }
 
-/*
- * Jump to the current function's epilog.
- */
-static void jump_to_epilog
-	(jit_gencode_t gen, arm_inst_buf *inst, jit_block_t block)
+void _jit_gen_load_global(jit_gencode_t gen, int reg, jit_value_t value)
 {
-	int offset;
-
-	/* If the epilog is the next thing that we will output,
-	   then fall through to the epilog directly */
-	block = block->next;
-	while(block != 0 && block->first_insn > block->last_insn)
-	{
-		block = block->next;
-	}
-	if(!block)
-	{
-		return;
-	}
-
-	/* Bail out if the instruction buffer has overflowed */
-	if(arm_inst_get_posn(*inst) >= arm_inst_get_limit(*inst))
-	{
-		return;
-	}
+	jit_cache_setup_output(32);
+	arm_load_membase(inst, _jit_reg_info[value->global_reg].cpu_reg,
+					 ARM_FP, value->frame_offset);
+	jit_cache_end_output();
+}
 
-	/* Output a placeholder for the jump and add it to the fixup list */
-	if(gen->epilog_fixup)
-	{
-		offset = (int)(((unsigned char *)arm_inst_get_posn(*inst)) -
-					   ((unsigned char *)(gen->epilog_fixup)));
-	}
-	else
+void _jit_gen_fix_value(jit_value_t value)
+{
+	if(!(value->has_frame_offset) && !(value->is_constant))
 	{
-		offset = 0;
+		jit_nint size = (jit_nint)(ROUND_STACK(jit_type_get_size(value->type)));
+		value->block->func->builder->frame_size += size;
+		value->frame_offset = -(value->block->func->builder->frame_size);
+		value->has_frame_offset = 1;
 	}
-	arm_branch_imm(*inst, ARM_CC_AL, offset);
-	gen->epilog_fixup = (void *)(arm_inst_get_posn(*inst) - 1);
 }
 
-#define	TODO()		\
-	do { \
-		fprintf(stderr, "TODO at %s, %d\n", __FILE__, (int)__LINE__); \
-	} while (0)
-
 void _jit_gen_insn(jit_gencode_t gen, jit_function_t func,
 				   jit_block_t block, jit_insn_t insn)
 {
@@ -924,7 +1381,7 @@
 	switch(insn->opcode)
 	{
 		#define JIT_INCLUDE_RULES
-		#include "jit-rules-arm.slc"
+		#include "jit-rules-arm.inc"
 		#undef JIT_INCLUDE_RULES
 
 		default:
@@ -985,4 +1442,28 @@
 	return 0;
 }
 
+/** "value" is a float value (single or double) that has just been returned 
+ * by a function and is in r0 (and, if needed, r1).
+ * If it is a float value, this function puts it back where it should be, in the float register reg
+ * (of appropriate size)
+ */
+void return_to_float(jit_gencode_t gen, jit_value_t value, int reg)
+{
+	if (IS_FLOAT_REG(reg))
+	{
+		arm_inst_buf inst;
+		jit_gen_load_inst_ptr(gen, inst);
+		//arm_push_reg(inst, 0);
+		//arm_push_reg(inst, 1);
+		if (value->type->kind==JIT_TYPE_FLOAT64||value->type->kind==JIT_TYPE_NFLOAT)
+		{
+			arm_mov_double_reg_reg(inst, _jit_reg_info[reg].cpu_reg,0,1);
+		}
+		else if (value->type->kind==JIT_TYPE_FLOAT32)
+		{
+			arm_mov_float_reg(inst, _jit_reg_info[reg].cpu_reg,0);
+		}
+		jit_gen_save_inst_ptr(gen, inst);
+	}
+}
 #endif /* JIT_BACKEND_ARM */
diff -ruN libjit/jit/jit-rules-arm.h libjit-mikyt/jit/jit-rules-arm.h
--- libjit/jit/jit-rules-arm.h	2008-01-24 21:12:53.000000000 +0100
+++ libjit-mikyt/jit/jit-rules-arm.h	2009-01-03 22:12:08.000000000 +0100
@@ -2,6 +2,7 @@
  * jit-rules-arm.h - Rules that define the characteristics of the ARM.
  *
  * Copyright (C) 2004  Southern Storm Software, Pty Ltd.
+ * Copyright (C) 2008  Michele Tartara <mikyt@users.sourceforge.net>
  *
  * This file is part of the libjit library.
  *
@@ -43,13 +44,17 @@
  * Of the floating-point registers, we only use f0-f3 at present,
  * so that we don't have to worry about saving the values of f4-f7.
  * The floating-point registers are only present on some ARM cores.
+ *
+ * The definitions of the used flags are in jit-rules.h
  */
 #ifdef JIT_ARM_HAS_FLOAT_REGS
-	#define	JIT_REG_ARM_FLOAT	\
-	  (JIT_REG_FLOAT32 | JIT_REG_FLOAT64 | JIT_REG_NFLOAT | JIT_REG_CALL_USED)
+	#define	JIT_REG_ARM_FLOAT32	(JIT_REG_FLOAT32)
+	#define	JIT_REG_ARM_FLOAT64	(JIT_REG_FLOAT64 | JIT_REG_NFLOAT)
 #else
-	#define	JIT_REG_ARM_FLOAT	JIT_REG_FIXED
+	#define	JIT_REG_ARM_FLOAT32	(JIT_REG_FIXED | JIT_REG_CALL_USED)
+	#define	JIT_REG_ARM_FLOAT64	(JIT_REG_FIXED | JIT_REG_CALL_USED)
 #endif
+
 #define	JIT_REG_INFO	\
 	{"r0",   0,  1, JIT_REG_WORD | JIT_REG_LONG | JIT_REG_CALL_USED}, \
 	{"r1",   1, -1, JIT_REG_WORD | JIT_REG_CALL_USED}, \
@@ -67,13 +72,24 @@
 	{"sp",  13, -1, JIT_REG_FIXED | JIT_REG_STACK_PTR}, \
 	{"lr",  14, -1, JIT_REG_FIXED}, \
 	{"pc",  15, -1, JIT_REG_FIXED}, \
-	{"f0",   0, -1, JIT_REG_ARM_FLOAT}, \
-	{"f1",   1, -1, JIT_REG_ARM_FLOAT}, \
-	{"f2",   2, -1, JIT_REG_ARM_FLOAT}, \
-	{"f3",   3, -1, JIT_REG_ARM_FLOAT},
-#define	JIT_NUM_REGS		20
+	{"s0",   0, -1, JIT_REG_ARM_FLOAT32}, \
+	{"s1",   1, -1, JIT_REG_ARM_FLOAT32}, \
+	{"s2",   2, -1, JIT_REG_ARM_FLOAT32}, \
+	{"s3",   3, -1, JIT_REG_ARM_FLOAT32}, \
+	{"d10",   10, -1, JIT_REG_ARM_FLOAT64},	\
+	{"d11",   11, -1, JIT_REG_ARM_FLOAT64},	\
+	{"d12",   11, -1, JIT_REG_ARM_FLOAT64},	\
+	{"d13",   13, -1, JIT_REG_ARM_FLOAT64},
+	
+//JIT_NUM_REGS is the total number of registers, including stack registers
+#define	JIT_NUM_REGS		24
 #define	JIT_NUM_GLOBAL_REGS	3
 
+//#define JIT_REG_STACK		1
+#undef JIT_REG_STACK
+//#define JIT_REG_STACK_START	16
+//#define JIT_REG_STACK_END	19
+
 /*
  * Define to 1 if we should always load values into registers
  * before operating on them.  i.e. the CPU does not have reg-mem
@@ -90,7 +106,7 @@
 /*
  * Preferred alignment for the start of functions.
  */
-#define	JIT_FUNCTION_ALIGNMENT	4
+#define	JIT_FUNCTION_ALIGNMENT	8
 
 /*
  * Define this to 1 if the platform allows reads and writes on
diff -ruN libjit/jit/jit-rules-arm.ins libjit-mikyt/jit/jit-rules-arm.ins
--- libjit/jit/jit-rules-arm.ins	1970-01-01 01:00:00.000000000 +0100
+++ libjit-mikyt/jit/jit-rules-arm.ins	2009-01-19 21:02:44.000000000 +0100
@@ -0,0 +1,2158 @@
+/* * jit-rules-arm.sel - Instruction selector for ARM.
+ *
+ * Copyright (C) 2004  Southern Storm Software, Pty Ltd.
+ * Copyright (C) 2008  Michele Tartara  <mikyt@users.sourceforge.net>
+ *
+ * This file is part of the libjit library.
+ *
+ * The libjit library is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation, either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * The libjit library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the libjit library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+%inst_type arm_inst_buf
+
+/*
+ * Register classes
+ */
+%regclass reg arm_reg
+%regclass freg32 arm_freg32
+%regclass freg64 arm_freg64
+%lregclass lreg arm_lreg
+%regclass breg arm_breg
+
+/*
+ * Conversion opcodes.
+ */
+
+JIT_OP_TRUNC_SBYTE: /*unary*/
+	[reg] -> {
+		arm_shift_reg_imm8(inst, ARM_SHL, $1, $1, 24);
+		arm_shift_reg_imm8(inst, ARM_SAR, $1, $1, 24);
+	}
+
+JIT_OP_TRUNC_UBYTE: /*unary*/
+	[reg] -> {
+		arm_alu_reg_imm8(inst, ARM_AND, $1, $1, 0xFF);
+	}
+
+JIT_OP_TRUNC_SHORT: /*unary*/
+	[reg] -> {
+		arm_shift_reg_imm8(inst, ARM_SHL, $1, $1, 16);
+		arm_shift_reg_imm8(inst, ARM_SAR, $1, $1, 16);
+	}
+
+JIT_OP_TRUNC_USHORT: /*unary*/
+	[reg] -> {
+		arm_shift_reg_imm8(inst, ARM_SHL, $1, $1, 16);
+		arm_shift_reg_imm8(inst, ARM_SHR, $1, $1, 16);
+	}
+
+JIT_OP_INT_TO_NFLOAT:
+	[=freg64, local, scratch freg32] -> {
+		//Load int from a local variable stored in memory
+		arm_load_membase_float(inst, $3, ARM_FP, $2, 0);
+		arm_convert_float_signed_integer_double(inst, $1, $3);
+}
+	[=freg64, reg, scratch freg32] -> {
+		//The int value is in a register
+		arm_mov_float_reg(inst, $3, $2);
+		arm_convert_float_signed_integer_double(inst, $1, $3)
+}
+
+JIT_OP_NFLOAT_TO_FLOAT32:
+	[=freg32, freg64] -> {
+		arm_convert_float_single_double(inst, $1, $2);
+}
+
+JIT_OP_NFLOAT_TO_FLOAT64, JIT_OP_FLOAT64_TO_NFLOAT: copy
+	[freg64] -> {
+		/* Nothing to do: float64 and nfloat are the same thing on ARM linux. Just copy the value */
+}
+
+JIT_OP_FLOAT32_TO_NFLOAT:
+	[=freg64, freg32] -> {
+		arm_convert_float_double_single(inst, $1, $2);
+}
+
+/*
+ * Arithmetic opcodes.
+ */
+
+JIT_OP_IADD: /*binary*/
+	[reg, immu8] -> {
+		arm_alu_reg_imm8(inst, ARM_ADD, $1, $1, $2);
+	}
+	[reg, reg] -> {
+		arm_alu_reg_reg(inst, ARM_ADD, $1, $1, $2);
+	}
+
+JIT_OP_ISUB: /*binary*/
+	[reg, immu8] -> {
+		arm_alu_reg_imm8(inst, ARM_SUB, $1, $1, $2);
+	}
+	[reg, reg] -> {
+		arm_alu_reg_reg(inst, ARM_SUB, $1, $1, $2);
+	}
+
+JIT_OP_IMUL: /*binary*/
+	[reg, immu8] -> {
+		/* Handle special cases of immediate multiplies */
+		switch($2)
+		{
+			case 0:
+			{
+				arm_mov_reg_imm8(inst, $1, 0);
+			}
+			break;
+
+			case 1: break;
+
+			case 2:
+			{
+				arm_shift_reg_imm8(inst, ARM_SHL, $1, $1, 1);
+			}
+			break;
+
+			case 4:
+			{
+				arm_shift_reg_imm8(inst, ARM_SHL, $1, $1, 2);
+			}
+			break;
+
+			case 8:
+			{
+				arm_shift_reg_imm8(inst, ARM_SHL, $1, $1, 3);
+			}
+			break;
+
+			case 16:
+			{
+				arm_shift_reg_imm8(inst, ARM_SHL, $1, $1, 4);
+			}
+			break;
+
+			case 32:
+			{
+				arm_shift_reg_imm8(inst, ARM_SHL, $1, $1, 5);
+			}
+			break;
+
+			case 64:
+			{
+				arm_shift_reg_imm8(inst, ARM_SHL, $1, $1, 6);
+			}
+			break;
+
+			case 128:
+			{
+				arm_shift_reg_imm8(inst, ARM_SHL, $1, $1, 7);
+			}
+			break;
+
+			default:
+			{
+				arm_mov_reg_imm8(inst, ARM_WORK, $2);
+				arm_mul_reg_reg(inst, $1, $1, ARM_WORK);
+			}
+			break;
+		}
+	}
+	[reg, reg] -> {
+		if($1 != $2)
+		{
+			arm_mul_reg_reg(inst, $1, $1, $2);
+		}
+		else
+		{
+			/* Cannot use the same register for both arguments */
+			arm_mov_reg_reg(inst, ARM_WORK, $2);
+			arm_mul_reg_reg(inst, $1, $1, ARM_WORK);
+		}
+	}
+
+JIT_OP_INEG: /*unary*/
+	[reg] -> {
+		/* -x is the same as (0 - x) */
+		arm_alu_reg_imm8(inst, ARM_RSB, $1, $1, 0);
+	}
+
+JIT_OP_LADD: /*binary*/
+	[lreg, lreg] -> {
+		arm_alu_cc_reg_reg(inst, ARM_ADD, $1, $1, $2);
+		arm_alu_reg_reg(inst, ARM_ADC, %1, %1, %2);
+	}
+
+JIT_OP_LSUB: /*binary*/
+	[lreg, lreg] -> {
+		arm_alu_cc_reg_reg(inst, ARM_SUB, $1, $1, $2);
+		arm_alu_reg_reg(inst, ARM_SBC, %1, %1, %2);
+	}
+
+JIT_OP_LNEG: /*unary*/
+	[lreg] -> {
+		arm_alu_reg(inst, ARM_MVN, $1, $1);
+		arm_alu_reg(inst, ARM_MVN, %1, %1);
+		arm_alu_cc_reg_imm8(inst, ARM_ADD, $1, $1, 1);
+		arm_alu_reg_imm8(inst, ARM_ADC, %1, %1, 0);
+	}
+
+JIT_OP_FADD (JIT_ARM_HAS_FLOAT_REGS): /*binary*/
+	[freg32, freg32] -> {
+		arm_alu_freg_freg_32(inst, ARM_FADD, $1, $1, $2);
+	}
+
+JIT_OP_FSUB (JIT_ARM_HAS_FLOAT_REGS): /*binary*/
+	[freg32, freg32] -> {
+		arm_alu_freg_freg_32(inst, ARM_FSUB, $1, $1, $2);
+	}
+
+JIT_OP_FMUL (JIT_ARM_HAS_FLOAT_REGS): /*binary*/
+	[freg32, freg32] -> {
+		arm_alu_freg_freg_32(inst, ARM_FMUL, $1, $1, $2);
+	}
+
+JIT_OP_FDIV (JIT_ARM_HAS_FLOAT_REGS): /*binary*/
+	[freg32, freg32] -> {
+		arm_alu_freg_freg_32(inst, ARM_FDIV, $1, $1, $2);
+	}
+
+JIT_OP_FNEG (JIT_ARM_HAS_FLOAT_REGS): /*unary*/
+	[freg32] -> {
+		arm_alu_freg_32(inst, ARM_MNF, $1, $1);
+	}
+
+JIT_OP_DADD, JIT_OP_NFADD (JIT_ARM_HAS_FLOAT_REGS): /*binary*/
+	[freg64, freg64] -> {
+		arm_alu_freg_freg(inst, ARM_FADD, $1, $1, $2);
+	}
+
+JIT_OP_DSUB, JIT_OP_NFSUB (JIT_ARM_HAS_FLOAT_REGS): /*binary*/
+	[freg64, freg64] -> {
+		arm_alu_freg_freg(inst, ARM_FSUB, $1, $1, $2);
+	}
+
+JIT_OP_DMUL, JIT_OP_NFMUL (JIT_ARM_HAS_FLOAT_REGS): /*binary*/
+	[freg64, freg64] -> {
+		arm_alu_freg_freg(inst, ARM_FMUL, $1, $1, $2);
+	}
+
+JIT_OP_DDIV, JIT_OP_NFDIV (JIT_ARM_HAS_FLOAT_REGS): /*binary*/
+	[freg64, freg64] -> {
+		arm_alu_freg_freg(inst, ARM_FDIV, $1, $1, $2);
+	}
+
+JIT_OP_DNEG, JIT_OP_NFNEG (JIT_ARM_HAS_FLOAT_REGS): /*unary*/
+	[freg64] -> {
+		arm_alu_freg(inst, ARM_MNF, $1, $1);
+	}
+
+/*
+ * Bitwise opcodes.
+ */
+
+JIT_OP_IAND: /*binary*/
+	[reg, immu8] -> {
+		arm_alu_reg_imm8(inst, ARM_AND, $1, $1, $2);
+	}
+	[reg, reg] -> {
+		arm_alu_reg_reg(inst, ARM_AND, $1, $1, $2);
+	}
+
+JIT_OP_IOR: /*binary*/
+	[reg, immu8] -> {
+		arm_alu_reg_imm8(inst, ARM_ORR, $1, $1, $2);
+	}
+	[reg, reg] -> {
+		arm_alu_reg_reg(inst, ARM_ORR, $1, $1, $2);
+	}
+
+JIT_OP_IXOR: /*binary*/
+	[reg, immu8] -> {
+		arm_alu_reg_imm8(inst, ARM_EOR, $1, $1, $2);
+	}
+	[reg, reg] -> {
+		arm_alu_reg_reg(inst, ARM_EOR, $1, $1, $2);
+	}
+
+JIT_OP_INOT: /*unary*/
+	[reg] -> {
+		/* MVN == "move not" */
+		arm_alu_reg(inst, ARM_MVN, $1, $1);
+	}
+
+JIT_OP_ISHL: /*binary*/
+	[reg, imm] -> {
+		arm_shift_reg_imm8(inst, ARM_SHL, $1, $1, ($2 & 0x1F));
+	}
+	[reg, reg] -> {
+		arm_alu_reg_imm8(inst, ARM_AND, ARM_WORK, $2, 0x1F);
+		arm_shift_reg_reg(inst, ARM_SHL, $1, $1, ARM_WORK);
+	}
+
+JIT_OP_ISHR: /*binary*/
+	[reg, imm] -> {
+		arm_shift_reg_imm8(inst, ARM_SAR, $1, $1, ($2 & 0x1F));
+	}
+	[reg, reg] -> {
+		arm_alu_reg_imm8(inst, ARM_AND, ARM_WORK, $2, 0x1F);
+		arm_shift_reg_reg(inst, ARM_SAR, $1, $1, ARM_WORK);
+	}
+
+JIT_OP_ISHR_UN: /*binary*/
+	[reg, imm] -> {
+		arm_shift_reg_imm8(inst, ARM_SHR, $1, $1, ($2 & 0x1F));
+	}
+	[reg, reg] -> {
+		arm_alu_reg_imm8(inst, ARM_AND, ARM_WORK, $2, 0x1F);
+		arm_shift_reg_reg(inst, ARM_SHR, $1, $1, ARM_WORK);
+	}
+
+JIT_OP_LAND: /*binary*/
+	[lreg, lreg] -> {
+		arm_alu_reg_reg(inst, ARM_AND, $1, $1, $2);
+		arm_alu_reg_reg(inst, ARM_AND, %1, %1, %2);
+	}
+
+JIT_OP_LOR: /*binary*/
+	[lreg, lreg] -> {
+		arm_alu_reg_reg(inst, ARM_ORR, $1, $1, $2);
+		arm_alu_reg_reg(inst, ARM_ORR, %1, %1, %2);
+	}
+
+JIT_OP_LXOR: /*binary*/
+	[lreg, lreg] -> {
+		arm_alu_reg_reg(inst, ARM_EOR, $1, $1, $2);
+		arm_alu_reg_reg(inst, ARM_EOR, %1, %1, %2);
+	}
+
+JIT_OP_LNOT: /*unary*/
+	[lreg] -> {
+		arm_alu_reg(inst, ARM_MVN, $1, $1);
+		arm_alu_reg(inst, ARM_MVN, %1, %1);
+	}
+
+/*
+ * Branch opcodes.
+ */
+
+JIT_OP_BR: branch /*spill_before*/
+	[] -> {
+		/* ARM_CC_AL == "always branch" */
+		output_branch(func, &inst, ARM_CC_AL, insn);
+
+		/* Flush the constant pool now, to minimize the probability that
+		   it is accidentally flushed in the middle of a loop body */
+		jit_gen_save_inst_ptr(gen, inst);
+		flush_constants(gen, 1);
+		jit_gen_load_inst_ptr(gen, inst);
+	}
+
+JIT_OP_BR_IFALSE: branch /*unary_branch*/
+	[reg] -> {
+		arm_test_reg_imm8(inst, ARM_CMP, $1, 0);
+		output_branch(func, &inst, ARM_CC_EQ, insn);
+	}
+
+JIT_OP_BR_ITRUE: branch /*unary_branch*/
+	[reg] -> {
+		arm_test_reg_imm8(inst, ARM_CMP, $1, 0);
+		output_branch(func, &inst, ARM_CC_NE, insn);
+	}
+
+JIT_OP_BR_IEQ: branch /*binary_branch*/
+	[reg, immu8] -> {
+		arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
+		output_branch(func, &inst, ARM_CC_EQ, insn);
+	}
+	[reg, reg] -> {
+		arm_test_reg_reg(inst, ARM_CMP, $1, $2);
+		output_branch(func, &inst, ARM_CC_EQ, insn);
+	}
+
+JIT_OP_BR_INE: branch /*binary_branch*/
+	[reg, immu8] -> {
+		arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
+		output_branch(func, &inst, ARM_CC_NE, insn);
+	}
+	[reg, reg] -> {
+		arm_test_reg_reg(inst, ARM_CMP, $1, $2);
+		output_branch(func, &inst, ARM_CC_NE, insn);
+	}
+
+JIT_OP_BR_ILT: branch /*binary_branch*/
+	[reg, immu8] -> {
+		arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
+		output_branch(func, &inst, ARM_CC_LT, insn);
+	}
+	[reg, reg] -> {
+		arm_test_reg_reg(inst, ARM_CMP, $1, $2);
+		output_branch(func, &inst, ARM_CC_LT, insn);
+	}
+
+JIT_OP_BR_ILT_UN: branch /*binary_branch*/
+	[reg, immu8] -> {
+		arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
+		output_branch(func, &inst, ARM_CC_LT_UN, insn);
+	}
+	[reg, reg] -> {
+		arm_test_reg_reg(inst, ARM_CMP, $1, $2);
+		output_branch(func, &inst, ARM_CC_LT_UN, insn);
+	}
+
+JIT_OP_BR_ILE: branch /*binary_branch*/
+	[reg, immu8] -> {
+		arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
+		output_branch(func, &inst, ARM_CC_LE, insn);
+	}
+	[reg, reg] -> {
+		arm_test_reg_reg(inst, ARM_CMP, $1, $2);
+		output_branch(func, &inst, ARM_CC_LE, insn);
+	}
+
+JIT_OP_BR_ILE_UN: branch /*binary_branch*/
+	[reg, immu8] -> {
+		arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
+		output_branch(func, &inst, ARM_CC_LE_UN, insn);
+	}
+	[reg, reg] -> {
+		arm_test_reg_reg(inst, ARM_CMP, $1, $2);
+		output_branch(func, &inst, ARM_CC_LE_UN, insn);
+	}
+
+JIT_OP_BR_IGT: branch /*binary_branch*/
+	[reg, immu8] -> {
+		arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
+		output_branch(func, &inst, ARM_CC_GT, insn);
+	}
+	[reg, reg] -> {
+		arm_test_reg_reg(inst, ARM_CMP, $1, $2);
+		output_branch(func, &inst, ARM_CC_GT, insn);
+	}
+
+JIT_OP_BR_IGT_UN: branch /*binary_branch*/
+	[reg, immu8] -> {
+		arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
+		output_branch(func, &inst, ARM_CC_GT_UN, insn);
+	}
+	[reg, reg] -> {
+		arm_test_reg_reg(inst, ARM_CMP, $1, $2);
+		output_branch(func, &inst, ARM_CC_GT_UN, insn);
+	}
+
+JIT_OP_BR_IGE: branch /*binary_branch*/
+	[reg, immu8] -> {
+		arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
+		output_branch(func, &inst, ARM_CC_GE, insn);
+	}
+	[reg, reg] -> {
+		arm_test_reg_reg(inst, ARM_CMP, $1, $2);
+		output_branch(func, &inst, ARM_CC_GE, insn);
+	}
+
+JIT_OP_BR_IGE_UN: branch /*binary_branch*/
+	[reg, immu8] -> {
+		arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
+		output_branch(func, &inst, ARM_CC_GE_UN, insn);
+	}
+	[reg, reg] -> {
+		arm_test_reg_reg(inst, ARM_CMP, $1, $2);
+		output_branch(func, &inst, ARM_CC_GE_UN, insn);
+	}
+
+/*
+ * Comparison opcodes.
+ */
+
+JIT_OP_ICMP: /*binary*/
+	[reg, immu8] -> {
+		arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
+		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GT);
+		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LE);
+		arm_alu_reg_cond(inst, ARM_MVN, $1, $1, ARM_CC_LT);
+	}
+	[reg, reg] -> {
+		arm_test_reg_reg(inst, ARM_CMP, $1, $2);
+		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GT);
+		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LE);
+		arm_alu_reg_cond(inst, ARM_MVN, $1, $1, ARM_CC_LT);
+	}
+
+JIT_OP_ICMP_UN: /*binary*/
+	[reg, immu8] -> {
+		arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
+		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GT_UN);
+		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LE_UN);
+		arm_alu_reg_cond(inst, ARM_MVN, $1, $1, ARM_CC_LT_UN);
+	}
+	[reg, reg] -> {
+		arm_test_reg_reg(inst, ARM_CMP, $1, $2);
+		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GT_UN);
+		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LE_UN);
+		arm_alu_reg_cond(inst, ARM_MVN, $1, $1, ARM_CC_LT_UN);
+	}
+
+JIT_OP_IEQ: /*binary*/
+	[reg, immu8] -> {
+		arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
+		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_EQ);
+		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_NE);
+	}
+	[reg, reg] -> {
+		arm_test_reg_reg(inst, ARM_CMP, $1, $2);
+		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_EQ);
+		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_NE);
+	}
+
+JIT_OP_INE: /*binary*/
+	[reg, immu8] -> {
+		arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
+		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_NE);
+		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_EQ);
+	}
+	[reg, reg] -> {
+		arm_test_reg_reg(inst, ARM_CMP, $1, $2);
+		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_NE);
+		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_EQ);
+	}
+
+JIT_OP_ILT: /*binary*/
+	[reg, immu8] -> {
+		arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
+		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_LT);
+		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_GE);
+	}
+	[reg, reg] -> {
+		arm_test_reg_reg(inst, ARM_CMP, $1, $2);
+		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_LT);
+		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_GE);
+	}
+
+JIT_OP_ILT_UN: /*binary*/
+	[reg, immu8] -> {
+		arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
+		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_LT_UN);
+		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_GE_UN);
+	}
+	[reg, reg] -> {
+		arm_test_reg_reg(inst, ARM_CMP, $1, $2);
+		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_LT_UN);
+		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_GE_UN);
+	}
+
+JIT_OP_ILE: /*binary*/
+	[reg, immu8] -> {
+		arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
+		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_LE);
+		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_GT);
+	}
+	[reg, reg] -> {
+		arm_test_reg_reg(inst, ARM_CMP, $1, $2);
+		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_LE);
+		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_GT);
+	}
+
+JIT_OP_ILE_UN: /*binary*/
+	[reg, immu8] -> {
+		arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
+		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_LE_UN);
+		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_GT_UN);
+	}
+	[reg, reg] -> {
+		arm_test_reg_reg(inst, ARM_CMP, $1, $2);
+		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_LE_UN);
+		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_GT_UN);
+	}
+
+JIT_OP_IGT: /*binary*/
+	[reg, immu8] -> {
+		arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
+		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GT);
+		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LE);
+	}
+	[reg, reg] -> {
+		arm_test_reg_reg(inst, ARM_CMP, $1, $2);
+		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GT);
+		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LE);
+	}
+/* NEW	- Seems to work, but pgm02_05.exe fails if this is activated
+	[=reg, reg, imm] -> {
+		arm_test_reg_imm(inst, ARM_CMP, $2, $3);
+		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GT);
+		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LE);
+	}
+	[=reg, reg, local] -> {
+		arm_test_reg_membase(inst, ARM_CMP, $2, ARM_FP, $3, ARM_WORK);
+		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GT);
+		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LE);
+	}
+	[=reg, reg, reg] -> {
+		arm_test_reg_reg(inst, ARM_CMP, $2, $3);
+		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GT);
+		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LE);
+	} */
+
+JIT_OP_IGT_UN: /*binary*/
+	[reg, immu8] -> {
+		arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
+		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GT_UN);
+		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LE_UN);
+	}
+	[reg, reg] -> {
+		arm_test_reg_reg(inst, ARM_CMP, $1, $2);
+		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GT_UN);
+		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LE_UN);
+	}
+
+JIT_OP_IGE: /*binary*/
+	[reg, immu8] -> {
+		arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
+		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GE);
+		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LT);
+	}
+	[reg, reg] -> {
+		arm_test_reg_reg(inst, ARM_CMP, $1, $2);
+		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GE);
+		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LT);
+	}
+
+JIT_OP_IGE_UN: /*binary*/
+	[reg, immu8] -> {
+		arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
+		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GE_UN);
+		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LT_UN);
+	}
+	[reg, reg] -> {
+		arm_test_reg_reg(inst, ARM_CMP, $1, $2);
+		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GE_UN);
+		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LT_UN);
+	}
+
+/*
+ * Pointer check opcodes.
+ */
+
+JIT_OP_CHECK_NULL: note /*unary_note*/
+	[reg] -> {
+		arm_test_reg_imm8(inst, ARM_CMP, $1, 0);
+		throw_builtin(&inst, func, ARM_CC_EQ, JIT_RESULT_NULL_REFERENCE);
+	}
+
+/*
+ * Function calls.
+ */
+
+JIT_OP_CALL:
+	[] -> {
+		jit_function_t func = (jit_function_t)(insn->dest);
+		arm_call(inst, jit_function_to_closure(func));
+	}
+
+JIT_OP_CALL_TAIL:
+	[] -> {
+		jit_function_t func = (jit_function_t)(insn->dest);
+		arm_pop_frame_tail(inst, 0);
+		arm_jump(inst, jit_function_to_closure(func));
+	}
+
+JIT_OP_CALL_INDIRECT:
+	[] -> {
+		arm_mov_reg_reg((inst), ARM_LINK, ARM_PC);
+		arm_mov_reg_reg((inst), ARM_PC, ARM_WORK);
+	}
+
+JIT_OP_CALL_VTABLE_PTR:
+	[] -> {
+		arm_mov_reg_reg((inst), ARM_LINK, ARM_PC);
+		arm_mov_reg_reg((inst), ARM_PC, ARM_WORK);
+	}
+
+JIT_OP_CALL_EXTERNAL:
+	[] -> {
+		arm_call(inst, (void *)(insn->dest));
+	}
+
+JIT_OP_RETURN:
+	[] -> {
+		jump_to_epilog(gen, &inst, block);
+	}
+
+JIT_OP_RETURN_INT: /*unary_branch*/
+	[reg] -> {
+		int cpu_reg = $1;
+		if(cpu_reg != ARM_R0)
+		{
+			arm_mov_reg_reg(inst, ARM_R0, cpu_reg);
+		}
+		jump_to_epilog(gen, &inst, block);
+	}
+
+JIT_OP_RETURN_LONG: /*unary_branch*/
+	[imm] -> {
+		mov_reg_imm(gen, &inst, ARM_R0, ((jit_int *)($1))[0]);
+		mov_reg_imm(gen, &inst, ARM_R1, ((jit_int *)($1))[1]);
+		jump_to_epilog(gen, &inst, block);
+	}
+	[local] -> {
+		arm_load_membase(inst, ARM_R0, ARM_FP, $1);
+		arm_load_membase(inst, ARM_R1, ARM_FP, $1 + 4);
+		jump_to_epilog(gen, &inst, block);
+	}
+	[lreg] -> {
+		if($1 != 0)
+		{
+			arm_mov_reg_reg(inst, ARM_R0, $1);
+			arm_mov_reg_reg(inst, ARM_R1, %1);
+		}
+		jump_to_epilog(gen, &inst, block);
+	}
+
+JIT_OP_RETURN_FLOAT32 (JIT_ARM_HAS_FLOAT_REGS): branch /*unary_branch*/
+	[freg32, clobber("r0")] -> {
+		/* OLD implementation if($1 != 0)
+		{
+			arm_alu_freg_32(inst, ARM_MVF, ARM_F0, $1);
+		} */
+		arm_mov_reg_float(inst, ARM_R0, $1); //NEW Implementation
+		jump_to_epilog(gen, &inst, block);
+	}
+
+JIT_OP_RETURN_FLOAT32 (!JIT_ARM_HAS_FLOAT_REGS): manual
+	[] -> {
+		arm_inst_buf inst;
+		_jit_regs_spill_all(gen);
+		_jit_gen_fix_value(insn->value1);
+		jit_gen_load_inst_ptr(gen, inst);
+		if(insn->value1->is_constant)
+		{
+			mov_reg_imm
+				(gen, &inst, ARM_R0, ((int *)(insn->value1->address))[0]);
+		}
+		else
+		{
+			arm_load_membase(inst, ARM_R0, ARM_FP, insn->value1->frame_offset);
+		}
+		jump_to_epilog(gen, &inst, block);
+		jit_gen_save_inst_ptr(gen, inst);
+	}
+
+JIT_OP_RETURN_FLOAT64, JIT_OP_RETURN_NFLOAT
+		(JIT_ARM_HAS_FLOAT_REGS): branch /*unary_branch*/
+	[freg64, clobber("r0", "r1")] -> {
+		/* OLD Implementation if($1 != 0)
+		{
+			arm_alu_freg(inst, ARM_MVF, ARM_F0, $1);
+		}*/
+		arm_mov_reg_reg_double(inst,ARM_R0,ARM_R1, $1); //NEW impl;
+		jump_to_epilog(gen, &inst, block);
+	}
+
+JIT_OP_RETURN_FLOAT64, JIT_OP_RETURN_NFLOAT (!JIT_ARM_HAS_FLOAT_REGS): manual
+	[] -> {
+		arm_inst_buf inst;
+		_jit_regs_spill_all(gen);
+		_jit_gen_fix_value(insn->value1);
+		jit_gen_load_inst_ptr(gen, inst);
+		if(insn->value1->is_constant)
+		{
+			mov_reg_imm
+				(gen, &inst, ARM_R0, ((int *)(insn->value1->address))[0]);
+			mov_reg_imm
+				(gen, &inst, ARM_R1, ((int *)(insn->value1->address))[1]);
+		}
+		else
+		{
+			arm_load_membase(inst, ARM_R0, ARM_FP, insn->value1->frame_offset);
+			arm_load_membase(inst, ARM_R1, ARM_FP,
+							 insn->value1->frame_offset + 4);
+		}
+		jump_to_epilog(gen, &inst, block);
+		jit_gen_save_inst_ptr(gen, inst);
+	}
+
+JIT_OP_RETURN_SMALL_STRUCT: note
+	[reg, imm, clobber("r0", "r1")] -> {
+		//$1: address of the struct to be returned
+		//$2: size of the struct to be returned
+		
+		//Prevent the accidental overwriting of the address
+		int temp_reg = $1;
+		if(temp_reg < 3)
+		{
+			arm_mov_reg_reg(inst, ARM_WORK, temp_reg);
+			temp_reg = ARM_WORK;
+		}
+		
+		//Copy the struct to the return register in a way that's appropriate to its size
+		switch($2)
+		{
+		case 1:
+			arm_load_membase_byte(inst, ARM_R0, temp_reg, 0);
+			break;
+
+		case 2:
+			arm_load_membase_ushort(inst, ARM_R0, temp_reg, 0);
+			break;
+
+		case 3:
+			arm_load_membase_ushort(inst, ARM_R0, temp_reg, 0);
+			arm_load_membase_byte(inst, ARM_R1, temp_reg, 2);
+			arm_shift_reg_imm8(inst, ARM_SHL, ARM_R1, ARM_R1, 16);
+			arm_alu_reg_reg(inst, ARM_ORR, ARM_R0, ARM_R0, ARM_R1);
+			break;
+
+		case 4:
+			arm_load_membase(inst, ARM_R0, temp_reg, 0);
+			break;
+
+		/*TODO: is this the right way to return a struct > 4 bytes?
+		* Or should it be returned by address? Look at the Procedure Call Standard!
+		*/
+		
+		case 5:
+			arm_load_membase(inst, ARM_R0, temp_reg, 0);
+			arm_load_membase_byte(inst, ARM_R1, temp_reg, 4);
+			break;
+
+		case 6:
+			arm_load_membase(inst, ARM_R0, temp_reg, 0);
+			arm_load_membase_ushort(inst, ARM_R1, temp_reg, 4);
+			break;
+
+		case 7:
+			arm_load_membase(inst, ARM_R0, temp_reg, 0);
+			arm_load_membase_ushort(inst, ARM_R1, temp_reg, 4);
+			arm_load_membase_byte(inst, ARM_R2, temp_reg, 6);
+			arm_shift_reg_imm8(inst, ARM_SHL, ARM_R2, ARM_R2, 16);
+			arm_alu_reg_reg(inst, ARM_ORR, ARM_R1, ARM_R1, ARM_R2);
+			break;
+
+		case 8:
+			arm_load_membase(inst, ARM_R0, temp_reg, 0);
+			arm_load_membase(inst, ARM_R1, temp_reg, 4);
+			break;
+		}
+
+		jump_to_epilog(gen, &inst, block);
+	}
+	
+/* OLD Impl
+JIT_OP_RETURN_SMALL_STRUCT: /*unary_branch
+	[reg] -> {
+		int temp_reg = $1;
+		if(temp_reg < 3)
+		{
+			arm_mov_reg_reg(inst, ARM_WORK, temp_reg);
+			temp_reg = ARM_WORK;
+		}
+		switch(insn->value2->address)
+		{
+			case 1:
+			{
+				arm_load_membase_byte(inst, ARM_R0, temp_reg, 0);
+			}
+			break;
+
+			case 2:
+			{
+				arm_load_membase_ushort(inst, ARM_R0, temp_reg, 0);
+			}
+			break;
+
+			case 3:
+			{
+				arm_load_membase_ushort(inst, ARM_R0, temp_reg, 0);
+				arm_load_membase_byte(inst, ARM_R1, temp_reg, 2);
+				arm_shift_reg_imm8(inst, ARM_SHL, ARM_R1, ARM_R1, 16);
+				arm_alu_reg_reg(inst, ARM_ORR, ARM_R0, ARM_R0, ARM_R1);
+			}
+			break;
+
+			case 4:
+			{
+				arm_load_membase(inst, ARM_R0, temp_reg, 0);
+			}
+			break;
+
+			case 5:
+			{
+				arm_load_membase(inst, ARM_R0, temp_reg, 0);
+				arm_load_membase_byte(inst, ARM_R1, temp_reg, 4);
+			}
+			break;
+
+			case 6:
+			{
+				arm_load_membase(inst, ARM_R0, temp_reg, 0);
+				arm_load_membase_ushort(inst, ARM_R1, temp_reg, 4);
+			}
+			break;
+
+			case 7:
+			{
+				arm_load_membase(inst, ARM_R0, temp_reg, 0);
+				arm_load_membase_ushort(inst, ARM_R1, temp_reg, 4);
+				arm_load_membase_byte(inst, ARM_R2, temp_reg, 6);
+				arm_shift_reg_imm8(inst, ARM_SHL, ARM_R2, ARM_R2, 16);
+				arm_alu_reg_reg(inst, ARM_ORR, ARM_R1, ARM_R1, ARM_R2);
+			}
+			break;
+
+			case 8:
+			{
+				arm_load_membase(inst, ARM_R0, temp_reg, 0);
+				arm_load_membase(inst, ARM_R1, temp_reg, 4);
+			}
+			break;
+		}
+		jump_to_epilog(gen, &inst, block);
+	}*/
+
+JIT_OP_SETUP_FOR_NESTED: /*spill_before*/
+	[] -> {
+		jit_nint nest_reg = jit_value_get_nint_constant(insn->value1);
+		if(nest_reg == -1)
+		{
+			arm_push_reg(inst, ARM_FP);
+		}
+		else
+		{
+			arm_mov_reg_reg(inst, _jit_reg_info[nest_reg].cpu_reg, ARM_FP);
+		}
+	}
+
+JIT_OP_SETUP_FOR_SIBLING: /*spill_before*/
+	[] -> {
+		jit_nint level = jit_value_get_nint_constant(insn->value1);
+		jit_nint nest_reg = jit_value_get_nint_constant(insn->value2);
+		int cpu_reg;
+		if(nest_reg == -1)
+		{
+			cpu_reg = ARM_R0;
+		}
+		else
+		{
+			cpu_reg = _jit_reg_info[nest_reg].cpu_reg;
+		}
+		arm_load_membase(inst, cpu_reg, ARM_FP, JIT_APPLY_PARENT_FRAME_OFFSET);
+		while(level > 0)
+		{
+			arm_load_membase(inst, cpu_reg, cpu_reg,
+							 JIT_APPLY_PARENT_FRAME_OFFSET);
+			--level;
+		}
+		if(nest_reg == -1)
+		{
+			arm_push_reg(inst, cpu_reg);
+		}
+	}
+
+JIT_OP_IMPORT:
+	[] -> {
+		/* TODO */
+		TODO();
+	}
+
+/*
+ * Exception handling
+ */
+JIT_OP_THROW: branch
+	[reg] -> {
+
+		arm_push_reg(inst, $1);
+		if(func->builder->setjmp_value != 0)
+		{
+			/* We have a "setjmp" block in the current function,
+			   so we must record the location of the throw first */
+			jit_nint pc_offset;
+		
+			_jit_gen_fix_value(func->builder->setjmp_value);
+			
+			pc_offset = func->builder->setjmp_value->frame_offset +
+							jit_jmp_catch_pc_offset;
+							
+			/*if(func->builder->position_independent)
+			{
+				arm_call_imm(inst, 0);
+				arm_pop_membase(inst, ARM_FP,
+						pc_offset);
+			}*/
+			if(func->builder->position_independent)
+			{
+				arm_call_imm(inst, 0);
+				arm_pop_membase(inst, ARM_FP, pc_offset);
+			}
+			else
+			{
+				int pc = (int) (unsigned char *) arm_inst_get_posn(inst);
+				arm_mov_membase_imm(inst, ARM_FP, pc_offset, pc, 4, ARM_WORK);
+			}
+		}
+		arm_call(inst, (void *)jit_exception_throw);
+	}
+/* [reg] -> {
+	/* Prepare parameters for the call to jit_exception_throw *
+	arm_mov_reg_reg(inst, ARM_R0, $1); //x86_push_reg(inst, $1); //From X86
+	
+	if(func->builder->setjmp_value != 0)
+	{
+		/* We have a "setjmp" block in the current function,
+		so we must record the location of the throw first *
+		
+		_jit_gen_fix_value(func->builder->setjmp_value);
+		
+		//Store the value of the program counter at the time when the exception is thrown
+		arm_mov_reg_reg(inst, ARM_WORK, ARM_PC);
+		arm_store_membase(inst, ARM_WORK, ARM_FP,
+				   func->builder->setjmp_value->frame_offset +
+				   jit_jmp_catch_pc_offset);
+	}
+	
+	//Throw the exception
+	arm_call(inst, (void *)jit_exception_throw);
+} */
+
+JIT_OP_LOAD_PC:
+[=reg] -> {
+	if(func->builder->position_independent)
+	{
+		arm_call_imm(inst, 0);
+		arm_pop_reg(inst, $1);
+	}
+	else
+	{
+		int pc = inst.current; /*(int) inst;*/
+		arm_mov_reg_imm(inst, $1, pc);
+	}
+}
+
+JIT_OP_ENTER_FINALLY:
+[] -> { /* 
+	 * The return address is in the link register
+	 * We must save it on the stack in case it will be overwritten by the content
+	 * of the "finally" block.
+	 * In order to respect the ABI of the ARM architecture, that prescribes an 8-byte
+	 * alignment for the stack at a public interface, we save the value twice, 
+	 * in order to move the current SP by 8 bytes 
+	 * (we could have just saved the value once and then moved the SP by 4 bytes)
+	 */
+	arm_push_reg(inst, ARM_LINK);
+	arm_push_reg(inst, ARM_LINK);
+}
+
+JIT_OP_LEAVE_FINALLY: branch
+[] -> {
+	/* The "finally" return address is on the stack (twice, just for padding)*/
+		arm_pop_reg(inst, ARM_LINK);
+		arm_pop_reg(inst, ARM_LINK);
+		arm_return(inst);
+}
+
+JIT_OP_CALL_FINALLY: branch
+[] -> {
+	/* Adapted from x86 version
+	jit_block_t block;
+	
+	block = jit_block_from_label(func, (jit_label_t)(insn->dest));
+	if(!block)
+	{
+		return;
+	}
+	
+	if(block->address)
+	{
+		arm_call(inst, block->address);
+	}
+	else
+	{
+		arm_call_imm(inst, block->fixup_list);
+		block->fixup_list = (inst.current - 4); //TODO: check if inst.current is correct
+	} */
+	
+	/* My ARM implementation */
+	//output_branch(func, &inst, ARM_CC_AL, insn);
+	jit_block_t block;
+	int offset;
+	block = jit_block_from_label(func, (jit_label_t)(insn->dest));
+	if(!block)
+	{
+		return;
+	}
+	if(arm_inst_get_posn(inst) >= arm_inst_get_limit(inst))
+	{
+		/* The buffer has overflowed, so don't worry about fixups */
+		return;
+	}
+	if(block->address)
+	{
+		/* We already know the address of the block */
+		arm_call(inst, block->address);
+	}
+	else
+	{
+		/* Output a placeholder and record on the block's fixup list */
+		if(block->fixup_list)
+		{
+			offset = (int)(((unsigned char *)arm_inst_get_posn(inst)) -
+			((unsigned char *)(block->fixup_list)));
+		}
+		else
+		{
+			offset = 0;
+		}
+		arm_call_imm(inst, offset);
+		block->fixup_list = (void *)(arm_inst_get_posn(inst) - 1);
+	}
+}
+
+JIT_OP_ADDRESS_OF_LABEL:
+[=reg] -> {
+	block = jit_block_from_label(func, (jit_label_t)(insn->value1));
+	if(func->builder->position_independent)
+	{
+		/* TODO */
+			TODO();
+	}
+	else
+	{
+		if(block->address)
+		{
+			arm_mov_reg_imm(inst, $1, block->address);
+		}
+		else
+		{
+			/* Output a placeholder and record on the block's fixup list */
+				arm_mov_reg_imm(inst, $1, (int)(block->fixup_absolute_list));
+				block->fixup_absolute_list = (void *)(inst.current - 1); //TODO: check if -1 is correct, or if it should be -4
+		}
+	}
+}
+
+/*
+ * Data manipulation.
+ */
+
+JIT_OP_COPY_LOAD_SBYTE: /*unary*/
+	[reg] -> {}
+
+JIT_OP_COPY_LOAD_UBYTE: /*unary*/
+	[reg] -> {}
+
+JIT_OP_COPY_LOAD_SHORT: /*unary*/
+	[reg] -> {}
+
+JIT_OP_COPY_LOAD_USHORT: /*unary*/
+	[reg] -> {}
+
+JIT_OP_COPY_INT: copy /*unary*/
+	[=local, imm, scratch reg] -> {
+		arm_mov_membase_imm(inst, ARM_FP, $1, $2, 4, $3);
+	}
+	/*[=reg, local] -> {
+		arm_mov_reg_membase(inst, $1, ARM_FP, $2, 4)
+	}*/
+	[reg] -> {}
+	
+
+JIT_OP_COPY_LONG: copy /*unary*/
+	[lreg] -> {}
+
+JIT_OP_COPY_FLOAT32 (JIT_ARM_HAS_FLOAT_REGS): copy, stack /*unary*/
+	[freg32] -> {}
+
+JIT_OP_COPY_FLOAT32 (!JIT_ARM_HAS_FLOAT_REGS): manual
+	[] -> {
+		arm_inst_buf inst;
+		_jit_regs_force_out(gen, insn->value1, 0);
+		_jit_regs_force_out(gen, insn->dest, 1);
+		_jit_gen_fix_value(insn->value1);
+		_jit_gen_fix_value(insn->dest);
+		jit_gen_load_inst_ptr(gen, inst);
+		if(insn->value1->is_constant)
+		{
+			mov_reg_imm
+				(gen, &inst, ARM_WORK, ((int *)(insn->value1->address))[0]);
+		}
+		else
+		{
+			arm_load_membase(inst, ARM_WORK, ARM_FP,
+							 insn->value1->frame_offset);
+		}
+		arm_store_membase(inst, ARM_WORK, ARM_FP, insn->dest->frame_offset);
+		jit_gen_save_inst_ptr(gen, inst);
+	}
+
+JIT_OP_COPY_FLOAT64, JIT_OP_COPY_NFLOAT (JIT_ARM_HAS_FLOAT_REGS): copy, stack /*unary*/
+	[freg64] -> {}
+
+JIT_OP_COPY_FLOAT64, JIT_OP_COPY_NFLOAT (!JIT_ARM_HAS_FLOAT_REGS): manual
+	[] -> {
+		arm_inst_buf inst;
+		_jit_regs_force_out(gen, insn->value1, 0);
+		_jit_regs_force_out(gen, insn->dest, 1);
+		_jit_gen_fix_value(insn->value1);
+		_jit_gen_fix_value(insn->dest);
+		jit_gen_load_inst_ptr(gen, inst);
+		if(insn->value1->is_constant)
+		{
+			mov_reg_imm
+				(gen, &inst, ARM_WORK, ((int *)(insn->value1->address))[0]);
+			arm_store_membase(inst, ARM_WORK, ARM_FP,
+							  insn->dest->frame_offset);
+			mov_reg_imm
+				(gen, &inst, ARM_WORK, ((int *)(insn->value1->address))[1]);
+			arm_store_membase(inst, ARM_WORK, ARM_FP,
+							  insn->dest->frame_offset + 4);
+		}
+		else
+		{
+			arm_load_membase(inst, ARM_WORK, ARM_FP,
+							 insn->value1->frame_offset);
+			arm_store_membase(inst, ARM_WORK, ARM_FP,
+							  insn->dest->frame_offset);
+			arm_load_membase(inst, ARM_WORK, ARM_FP,
+							 insn->value1->frame_offset + 4);
+			arm_store_membase(inst, ARM_WORK, ARM_FP,
+							  insn->dest->frame_offset + 4);
+		}
+		jit_gen_save_inst_ptr(gen, inst);
+	}
+
+JIT_OP_COPY_STRUCT:
+	/*[=frame, frame, clobber(reg)] -> {
+		inst = memory_copy(gen, inst, ARM_FP, $1, ARM_FP, $2,
+				jit_type_get_size(jit_value_get_type(insn->dest)));
+	}*/
+	[=frame, frame, scratch reg] -> {
+		inst = memory_copy(gen, inst, ARM_FP, $1, ARM_FP, $2,
+				jit_type_get_size(jit_value_get_type(insn->dest)), $3);
+	}
+
+JIT_OP_COPY_STORE_BYTE: manual
+	[] -> {
+		arm_inst_buf inst;
+		int reg;
+		_jit_regs_force_out(gen, insn->dest, 1);
+		_jit_gen_fix_value(insn->dest);
+		reg = _jit_regs_load_value
+			(gen, insn->value1, 0,
+			 (insn->flags & (JIT_INSN_VALUE1_NEXT_USE |
+			 				 JIT_INSN_VALUE1_LIVE)));
+		jit_gen_load_inst_ptr(gen, inst);
+		arm_store_membase_byte(inst, _jit_reg_info[reg].cpu_reg,
+							   ARM_FP, insn->dest->frame_offset);
+		jit_gen_save_inst_ptr(gen, inst);
+	}
+
+JIT_OP_COPY_STORE_SHORT: manual
+	[] -> {
+		arm_inst_buf inst;
+		int reg;
+		_jit_regs_force_out(gen, insn->dest, 1);
+		_jit_gen_fix_value(insn->dest);
+		reg = _jit_regs_load_value
+			(gen, insn->value1, 1,
+			 (insn->flags & (JIT_INSN_VALUE1_NEXT_USE |
+			 				 JIT_INSN_VALUE1_LIVE)));
+		jit_gen_load_inst_ptr(gen, inst);
+		arm_store_membase_short(inst, _jit_reg_info[reg].cpu_reg,
+							    ARM_FP, insn->dest->frame_offset);
+		jit_gen_save_inst_ptr(gen, inst);
+		//_jit_regs_free_reg(gen, reg, 1); //TODO: check if it's needed
+	}
+
+JIT_OP_ADDRESS_OF: /*manual*/
+	[=reg, frame] -> {
+		/* New implementation 
+		arm_lea_membase(inst, $1, $2); */
+	
+		/* Old implementation
+		arm_inst_buf inst;
+		int reg, offset;
+		_jit_regs_force_out(gen, insn->value1, 0);
+		_jit_gen_fix_value(insn->value1);
+		jit_gen_load_inst_ptr(gen, inst);
+		reg = _jit_regs_dest_value(gen, insn->dest);
+		reg = _jit_reg_info[reg].cpu_reg;
+		offset = insn->value1->frame_offset;
+		if(offset > 0)
+		{
+			arm_alu_reg_imm(inst, ARM_ADD, reg, ARM_FP, offset);
+		}
+		else if(offset < 0)
+		{
+			arm_alu_reg_imm(inst, ARM_SUB, reg, ARM_FP, -offset);
+		}
+		else
+		{
+			arm_mov_reg_reg(inst, reg, ARM_FP);
+		}
+		jit_gen_save_inst_ptr(gen, inst); */
+		
+		if($2 > 0)
+		{
+			arm_alu_reg_imm(inst, ARM_ADD, $1, ARM_FP, $2);
+		}
+		else if($2 < 0)
+		{
+			arm_alu_reg_imm(inst, ARM_SUB, $1, ARM_FP, -$2);
+		}
+		else
+		{
+			arm_mov_reg_reg(inst, $1, ARM_FP);
+		}
+
+	}
+
+/*
+ * Stack pushes and pops.
+ */
+
+JIT_OP_INCOMING_REG, JIT_OP_RETURN_REG: note
+        [reg] -> {
+		/*
+		 * This rule does nothing itself. Also at this point
+		 * the value is supposed to be already in the register
+		 * so the "reg" pattern does not load it either. But
+		 * it allows the allocator to check the liveness flags
+		 * and free the register if the value is dead.
+		 */
+	}
+	
+JIT_OP_PUSH_INT: note /*unary_note*/
+	[reg] -> {
+		arm_push_reg(inst, $1);
+	}
+
+JIT_OP_PUSH_LONG: note /*unary_note*/
+	[lreg] -> {
+		arm_push_reg(inst, %1);
+		arm_push_reg(inst, $1);
+		gen->stack_changed=1;
+	}
+
+JIT_OP_PUSH_FLOAT32 (JIT_ARM_HAS_FLOAT_REGS): note
+	[freg32] -> {
+		arm_push_reg_float32(inst, $1);
+	}
+
+JIT_OP_PUSH_FLOAT32 (!JIT_ARM_HAS_FLOAT_REGS): manual
+	[] -> {
+		arm_inst_buf inst;
+		_jit_regs_force_out(gen, insn->value1, 0);
+		_jit_gen_fix_value(insn->value1);
+		jit_gen_load_inst_ptr(gen, inst);
+		if(insn->value1->is_constant)
+		{
+			mov_reg_imm
+				(gen, &inst, ARM_WORK, ((int *)(insn->value1->address))[0]);
+		}
+		else
+		{
+			arm_load_membase(inst, ARM_WORK, ARM_FP,
+							 insn->value1->frame_offset);
+		}
+		arm_push_reg(inst, ARM_WORK);
+		jit_gen_save_inst_ptr(gen, inst);
+	}
+
+JIT_OP_PUSH_FLOAT64, JIT_OP_PUSH_NFLOAT (JIT_ARM_HAS_FLOAT_REGS): note
+	[freg64] -> {
+		arm_push_reg_float64(inst, $1);
+	}
+
+JIT_OP_PUSH_FLOAT64, JIT_OP_PUSH_NFLOAT (!JIT_ARM_HAS_FLOAT_REGS): manual
+	[] -> {
+		arm_inst_buf inst;
+		_jit_regs_force_out(gen, insn->value1, 0);
+		_jit_gen_fix_value(insn->value1);
+		jit_gen_load_inst_ptr(gen, inst);
+		if(insn->value1->is_constant)
+		{
+			mov_reg_imm
+				(gen, &inst, ARM_WORK, ((int *)(insn->value1->address))[1]);
+			arm_push_reg(inst, ARM_WORK);
+			mov_reg_imm
+				(gen, &inst, ARM_WORK, ((int *)(insn->value1->address))[0]);
+			arm_push_reg(inst, ARM_WORK);
+		}
+		else
+		{
+			arm_load_membase(inst, ARM_WORK, ARM_FP,
+							 insn->value1->frame_offset + 4);
+			arm_push_reg(inst, ARM_WORK);
+			arm_load_membase(inst, ARM_WORK, ARM_FP,
+							 insn->value1->frame_offset);
+			arm_push_reg(inst, ARM_WORK);
+		}
+		jit_gen_save_inst_ptr(gen, inst);
+	}
+
+JIT_OP_PUSH_STRUCT: /*unary_note*/
+	[reg] -> {
+		/* TODO */
+		TODO();
+	}
+
+JIT_OP_POP_STACK:
+	[] -> {
+		arm_alu_reg_imm(inst, ARM_ADD, ARM_SP, ARM_SP, insn->value1->address);
+	}
+
+JIT_OP_FLUSH_SMALL_STRUCT:
+	[] -> {
+		jit_nuint size;
+		jit_nint offset;
+		_jit_gen_fix_value(insn->value1);
+		size = jit_type_get_size(jit_value_get_type(insn->value1));
+		offset = insn->value1->frame_offset;
+		switch(size)
+		{
+			case 1:
+			{
+				arm_store_membase_byte(inst, ARM_R0, ARM_FP, offset);
+			}
+			break;
+
+			case 2:
+			{
+				arm_store_membase_short(inst, ARM_R0, ARM_FP, offset);
+			}
+			break;
+
+			case 3:
+			{
+				arm_mov_reg_reg(inst, ARM_R1, ARM_R0);
+				arm_store_membase_short(inst, ARM_R0, ARM_FP, offset);
+				arm_shift_reg_imm8(inst, ARM_SHR, ARM_R0, ARM_R1, 16);
+				arm_store_membase_byte(inst, ARM_R0, ARM_FP, offset + 2);
+			}
+			break;
+
+			case 4:
+			{
+				arm_store_membase(inst, ARM_R0, ARM_FP, offset);
+			}
+			break;
+
+			case 5:
+			{
+				arm_store_membase(inst, ARM_R0, ARM_FP, offset);
+				arm_store_membase_byte(inst, ARM_R1, ARM_FP, offset + 4);
+			}
+			break;
+
+			case 6:
+			{
+				arm_store_membase(inst, ARM_R0, ARM_FP, offset);
+				arm_store_membase_short(inst, ARM_R1, ARM_FP, offset + 4);
+			}
+			break;
+
+			case 7:
+			{
+				arm_store_membase(inst, ARM_R0, ARM_FP, offset);
+				arm_mov_reg_reg(inst, ARM_R2, ARM_R1);
+				arm_store_membase_short(inst, ARM_R1, ARM_FP, offset + 4);
+				arm_shift_reg_imm8(inst, ARM_SHR, ARM_R1, ARM_R2, 16);
+				arm_store_membase_byte(inst, ARM_R1, ARM_FP, offset + 6);
+			}
+			break;
+
+			case 8:
+			{
+				arm_store_membase(inst, ARM_R0, ARM_FP, offset);
+				arm_store_membase(inst, ARM_R1, ARM_FP, offset + 4);
+			}
+			break;
+		}
+	}
+
+JIT_OP_SET_PARAM_INT: note
+/* OLD	[reg] -> {
+		arm_store_membase(inst, $1, ARM_SP, insn->value2->address);
+	}*/
+	[imm, imm] -> {
+		arm_mov_membase_imm(inst, ARM_SP, $2, $1, 4, ARM_WORK);
+	}
+	[reg, imm] -> {
+		arm_mov_membase_reg(inst, ARM_SP, $2, $1, 4);
+	}
+
+JIT_OP_SET_PARAM_LONG: /*unary_note*/
+	[lreg] -> {
+		arm_store_membase(inst, $1, ARM_SP, insn->value2->address);
+		arm_store_membase(inst, %1, ARM_SP, insn->value2->address + 4);
+	}
+
+JIT_OP_SET_PARAM_FLOAT32 (JIT_ARM_HAS_FLOAT_REGS): /*unary_note*/
+	[freg32] -> {
+		arm_store_membase_float32(inst, $1, ARM_SP, insn->value2->address);
+	}
+
+JIT_OP_SET_PARAM_FLOAT32 (!JIT_ARM_HAS_FLOAT_REGS): manual
+	[] -> {
+		arm_inst_buf inst;
+		_jit_regs_force_out(gen, insn->value1, 0);
+		_jit_gen_fix_value(insn->value1);
+		jit_gen_load_inst_ptr(gen, inst);
+		if(insn->value1->is_constant)
+		{
+			mov_reg_imm
+				(gen, &inst, ARM_WORK, ((int *)(insn->value1->address))[0]);
+			arm_store_membase
+				(inst, ARM_WORK, ARM_SP, insn->value2->address);
+		}
+		else
+		{
+			arm_load_membase(inst, ARM_WORK, ARM_FP,
+							 insn->value1->frame_offset);
+			arm_store_membase
+				(inst, ARM_WORK, ARM_SP, insn->value2->address);
+		}
+		jit_gen_save_inst_ptr(gen, inst);
+	}
+
+JIT_OP_SET_PARAM_FLOAT64, JIT_OP_SET_PARAM_NFLOAT
+		(JIT_ARM_HAS_FLOAT_REGS): /*unary_note*/
+	[freg64] -> {
+		arm_store_membase_float64(inst, $1, ARM_SP, insn->value2->address);
+	}
+
+JIT_OP_SET_PARAM_FLOAT64, JIT_OP_SET_PARAM_NFLOAT
+		(!JIT_ARM_HAS_FLOAT_REGS): manual
+	[] -> {
+		arm_inst_buf inst;
+		_jit_regs_force_out(gen, insn->value1, 0);
+		_jit_gen_fix_value(insn->value1);
+		jit_gen_load_inst_ptr(gen, inst);
+		if(insn->value1->is_constant)
+		{
+			mov_reg_imm
+				(gen, &inst, ARM_WORK, ((int *)(insn->value1->address))[0]);
+			arm_store_membase
+				(inst, ARM_WORK, ARM_SP, insn->value2->address);
+			mov_reg_imm
+				(gen, &inst, ARM_WORK, ((int *)(insn->value1->address))[1]);
+			arm_store_membase
+				(inst, ARM_WORK, ARM_SP, insn->value2->address + 4);
+		}
+		else
+		{
+			arm_load_membase(inst, ARM_WORK, ARM_FP,
+							 insn->value1->frame_offset);
+			arm_store_membase
+				(inst, ARM_WORK, ARM_SP, insn->value2->address);
+			arm_load_membase(inst, ARM_WORK, ARM_FP,
+							 insn->value1->frame_offset + 4);
+			arm_store_membase
+				(inst, ARM_WORK, ARM_SP, insn->value2->address + 4);
+		}
+		jit_gen_save_inst_ptr(gen, inst);
+	}
+
+/*JIT_OP_SET_PARAM_STRUCT: /*unary_note
+	[reg] -> {
+		/* TODO 
+		TODO();
+	}*/
+JIT_OP_SET_PARAM_STRUCT: note
+[reg, imm, scratch reg] -> {
+	/* Handle arbitrary-sized structures */
+	jit_nint offset = jit_value_get_nint_constant(insn->dest);
+	inst = memory_copy(gen, inst, ARM_SP, offset, $1, 0, $2, $3);
+}
+		
+/*
+ * Pointer-relative loads and stores.
+ */
+
+JIT_OP_LOAD_RELATIVE_SBYTE: /*unary*/
+	[reg] -> {
+		arm_load_membase_sbyte(inst, $1, $1, insn->value2->address);
+	}
+
+JIT_OP_LOAD_RELATIVE_UBYTE: /*unary*/
+	[reg] -> {
+		arm_load_membase_byte(inst, $1, $1, insn->value2->address);
+	}
+
+JIT_OP_LOAD_RELATIVE_SHORT: /*unary*/
+	[reg] -> {
+		arm_load_membase_short(inst, $1, $1, insn->value2->address);
+	}
+
+JIT_OP_LOAD_RELATIVE_USHORT: /*unary*/
+	[reg] -> {
+		arm_load_membase_ushort(inst, $1, $1, insn->value2->address);
+	}
+
+JIT_OP_LOAD_RELATIVE_INT: /*unary*/
+	[reg] -> {
+		arm_load_membase(inst, $1, $1, insn->value2->address);
+	}
+
+JIT_OP_LOAD_RELATIVE_LONG: /*manual*/
+	[=lreg, reg, imm] -> {
+		if($1 == $2)
+		{
+			arm_mov_reg_membase(inst, %1, $2, $3 + 4, 4);
+			arm_mov_reg_membase(inst, $1, $2, $3, 4);
+		}
+		else
+		{
+			arm_mov_reg_membase(inst, $1, $2, $3, 4);
+			arm_mov_reg_membase(inst, %1, $2, $3 + 4, 4);
+		}
+	}
+	/*[=lreg, reg, imm] -> {
+		if ($1 == $2)
+		{
+			_arm_mov_reg_imm(&inst, %1, $2, $3 + 4);
+			_arm_mov_reg_imm(&inst, $1, $2, $3);
+		}
+		else
+		{
+			_arm_mov_reg_imm(&inst, $1, $2, $3);
+			_arm_mov_reg_imm(&inst, %1, $2, $3 + 4);
+		}
+		
+		/* Old implementation
+		arm_inst_buf inst;
+		int reg = _jit_regs_load_value
+			(gen, insn->value1, 0,
+			 (insn->flags & (JIT_INSN_VALUE1_NEXT_USE |
+			 				 JIT_INSN_VALUE1_LIVE)));
+		int reg2, reg3;
+		int frame_offset;
+		_jit_gen_fix_value(insn->dest);
+		_jit_regs_get_reg_pair(gen, reg, -1, -1, &reg2, &reg3);
+		reg  = _jit_reg_info[reg].cpu_reg;
+		reg2 = _jit_reg_info[reg2].cpu_reg;
+		reg3 = _jit_reg_info[reg3].cpu_reg;
+		frame_offset = insn->dest->frame_offset;
+		jit_gen_load_inst_ptr(gen, inst);
+		arm_load_membase(inst, reg2, reg, insn->value2->address);
+		arm_load_membase(inst, reg3, reg, insn->value2->address + 4);
+		arm_store_membase(inst, reg2, ARM_FP, frame_offset);
+		arm_store_membase(inst, reg3, ARM_FP, frame_offset + 4);
+		insn->dest->in_frame = 1;
+		jit_gen_save_inst_ptr(gen, inst);
+	}*/
+
+JIT_OP_LOAD_RELATIVE_FLOAT32:
+[=freg32, reg, imm] -> {
+	arm_fld_membase(inst, $1, $2, $3, 0);
+}
+
+JIT_OP_LOAD_RELATIVE_FLOAT64:
+[=freg64, reg, imm] -> {
+	//x86_fld_membase(inst, $2, $3, 1);
+	arm_fld_membase(inst, $1, $2, $3, 1);
+}
+
+JIT_OP_LOAD_RELATIVE_NFLOAT: manual
+	[] -> {
+		/* TODO */
+		TODO();
+		abort();
+	}
+
+JIT_OP_LOAD_RELATIVE_STRUCT: more_space
+/*[=frame, reg, imm, clobber(reg)] -> {
+	inst = memory_copy(gen, inst, ARM_FP, $1, $2, $3, jit_type_get_size(jit_value_get_type(insn->dest)));
+}*/
+[=frame, reg, imm, scratch reg] -> {
+	inst = memory_copy(gen, inst, ARM_FP, $1, $2, $3, jit_type_get_size(jit_value_get_type(insn->dest)), $4);
+}
+
+JIT_OP_STORE_RELATIVE_BYTE: ternary
+[imm, imm, imm, scratch reg] -> {
+	arm_mov_mem_imm(inst, $1 + $3, $2, 1, $4);
+}
+[imm, breg, imm] -> {
+	arm_mov_mem_reg(inst, $1 + $3, $2, 1);
+}
+[reg, imm, imm] -> {
+	arm_mov_membase_imm(inst, $1, $3, $2, 1, ARM_WORK);
+}
+[reg, breg, imm] -> {
+	arm_mov_membase_reg(inst, $1, $3, $2, 1);
+}
+
+JIT_OP_STORE_RELATIVE_SHORT: ternary
+[imm, imm, imm, scratch reg] -> {
+	arm_mov_mem_imm(inst, $1 + $3, $2, 2, $4);
+}
+[imm, reg, imm] -> {
+	arm_mov_mem_reg(inst, $1 + $3, $2, 2);
+}
+[reg, imm, imm] -> {
+	arm_mov_membase_imm(inst, $1, $3, $2, 2, ARM_WORK);
+}
+[reg, reg, imm] -> {
+	arm_mov_membase_reg(inst, $1, $3, $2, 2);
+}
+
+JIT_OP_STORE_RELATIVE_INT: ternary
+	[imm, imm, imm, scratch reg] -> {
+		arm_mov_mem_imm(inst, $1 + $3, $2, 4, $4);
+	}
+	[imm, reg, imm] -> {
+		arm_mov_mem_reg(inst, $1 + $3, $2, 4);
+	}
+	[reg, imm, imm] -> {
+		arm_mov_membase_imm(inst, $1, $3, $2, 4, ARM_WORK);
+	}
+	[reg, reg, imm] -> {
+		arm_mov_membase_reg(inst, $1, $3, $2, 4);
+	}
+
+JIT_OP_STORE_RELATIVE_LONG: ternary /*manual*/
+	[reg, imm, imm] -> {
+		arm_mov_membase_imm(inst, $1, $3, *(int *)($2), 4, ARM_WORK);
+		arm_mov_membase_imm(inst, $1, $3 + 4, *(int *)($2 + 4), 4, ARM_WORK);
+	}
+	[reg, local, imm, scratch reg] -> {
+		arm_mov_reg_membase(inst, $4, ARM_FP, $2, 4);
+		arm_mov_membase_reg(inst, $1, $3, $4, 4);
+		arm_mov_reg_membase(inst, $4, ARM_FP, $2 + 4, 4);
+		arm_mov_membase_reg(inst, $1, $3 + 4, $4, 4);
+	}
+	[reg, lreg, imm] -> {
+		arm_mov_membase_reg(inst, $1, $3, $2, 4);
+		arm_mov_membase_reg(inst, $1, $3 + 4, %2, 4);
+	}
+	/*[reg, imm, imm] -> {
+		_arm_mov_reg_imm(&inst, $1, $3, *(int *)($2));
+		_arm_mov_reg_imm(&inst, $1, $3 + 4, *(int *)($2 + 4));
+		
+		/* Old implementation
+		arm_inst_buf inst;
+		int reg = _jit_regs_load_value
+			(gen, insn->dest, 0,
+			 (insn->flags & (JIT_INSN_DEST_NEXT_USE |
+			 				 JIT_INSN_DEST_LIVE)));
+		int reg2, reg3;
+		int frame_offset;
+		_jit_regs_get_reg_pair(gen, reg, -1, -1, &reg2, &reg3);
+		_jit_gen_fix_value(insn->value1);
+		jit_gen_load_inst_ptr(gen, inst);
+		reg  = _jit_reg_info[reg].cpu_reg;
+		reg2 = _jit_reg_info[reg2].cpu_reg;
+		reg3 = _jit_reg_info[reg3].cpu_reg;
+		frame_offset = insn->value1->frame_offset;
+		arm_load_membase(inst, reg2, ARM_FP, frame_offset);
+		arm_load_membase(inst, reg3, ARM_FP, frame_offset + 4);
+		arm_store_membase(inst, reg2, reg, insn->value2->address);
+		arm_store_membase(inst, reg3, reg, insn->value2->address + 4);
+		jit_gen_save_inst_ptr(gen, inst); 
+	}*/
+
+JIT_OP_STORE_RELATIVE_FLOAT32: ternary
+	[reg, imm, imm] -> {
+		arm_mov_membase_imm(inst, $1, $3, ((int *)($2))[0], 4, ARM_WORK);
+	}
+	[reg, freg32, imm] -> {
+		//x86_fst_membase(inst, $1, $3, 0, 1);
+		arm_store_membase_float32(inst, $2, $1, $3);
+	}
+
+JIT_OP_STORE_RELATIVE_FLOAT64: ternary
+	[reg, imm, imm, scratch reg] -> {
+		arm_mov_membase_imm(inst, $1, $3, ((int *)($2))[0], 4, $4);
+		arm_mov_membase_imm(inst, $1, $3 + 4, ((int *)($2))[1], 4, $4);
+	}
+	[reg, freg64, imm] -> {
+		//x86_fst_membase(inst, $1, $3, 1, 1);
+		arm_store_membase_float64(inst, $2, $1, $3);
+	}
+
+JIT_OP_STORE_RELATIVE_NFLOAT: manual
+	[] -> {
+		/* TODO */
+		TODO();
+		abort();
+	}
+
+JIT_OP_STORE_RELATIVE_STRUCT: manual
+[] -> {
+	arm_inst_buf inst;
+	int reg = _jit_regs_load_value(gen, insn->dest, 0,
+	  (insn->flags & (JIT_INSN_DEST_NEXT_USE |
+	  JIT_INSN_DEST_LIVE)));
+	_jit_regs_spill_all(gen);
+	_jit_gen_fix_value(insn->value1);
+	jit_gen_load_inst_ptr(gen, inst);
+	if(!jit_cache_check_for_n(&(gen->posn), 128))
+	{
+		jit_cache_mark_full(&(gen->posn));
+		return;
+	}
+	reg = _jit_reg_info[reg].cpu_reg;
+	inst = memory_copy(gen, inst, reg, (int)(insn->value2->address),
+			ARM_FP, insn->value1->frame_offset,
+			jit_type_get_size(jit_value_get_type(insn->value1)), -1);
+	jit_gen_save_inst_ptr(gen, inst);
+}
+
+JIT_OP_ADD_RELATIVE: /*unary*/
+	[reg] -> {
+		if(insn->value2->address != 0)
+		{
+			arm_alu_reg_imm(inst, ARM_ADD, $1, $1, insn->value2->address);
+		}
+	}
+
+/*
+* Array element loads and stores.
+*/
+
+JIT_OP_LOAD_ELEMENT_UBYTE:
+[=reg, reg, reg] -> {
+	arm_widen_memindex(inst, $1, $2, 0, $3, 0, 0, 0);
+}
+
+JIT_OP_LOAD_ELEMENT_USHORT:
+[=reg, reg, reg] -> {
+	arm_widen_memindex(inst, $1, $2, 0, $3, 1, 0, 1);
+}
+
+JIT_OP_LOAD_ELEMENT_INT:
+[=reg, reg, reg] -> {
+	/* The last parameter is unimportant: it's not used, 
+	since the displacement (4th param) is 0 */
+	arm_mov_reg_memindex(inst, $1, $2, 0, $3, 2, 4, 0);
+}
+
+JIT_OP_LOAD_ELEMENT_LONG:
+[=lreg, reg, reg, scratch reg, scratch reg] -> {
+	//$1=destination long register (1-st word, LSB)
+	//%1=destination long register (2-nd word, MSB)
+	//$2=base register
+	//$3=index register
+	//$4=scratch register for arm_mov_reg_memindex
+	//$5=scratch register for overwriting prevention
+	
+	assert($2 != $3);
+	
+	int basereg=$2;
+	int indexreg=$3;
+	
+	//Write the 1-st word
+	if($1 == basereg)
+	{
+		//Prevent base reg from being overwritten
+		arm_mov_reg_reg(inst, $5, basereg);
+		basereg=$5;
+	}
+	else if ($1 == indexreg)
+	{	
+		//Prevent index reg from being overwritten
+		arm_mov_reg_reg(inst, $5, indexreg);
+		indexreg=$5;
+	}
+	arm_mov_reg_memindex(inst, $1, basereg, 0, indexreg, 3, 4, $4);
+	
+	//Write the 2-nd word
+// 	if(%1 == basereg)
+// 	{
+// 		//Prevent base reg from being overwritten
+// 		assert(basereg!=$5);
+// 		arm_mov_reg_reg(inst, $5, basereg);
+// 		basereg=$5;
+// 	}
+// 	else if (%1 == indexreg)
+// 	{
+// 		//Prevent index reg from being overwritten
+// 		assert(indexreg!=$5);
+// 		arm_mov_reg_reg(inst, $5, indexreg);
+// 		indexreg=$5;
+// 	}
+	arm_mov_reg_memindex(inst, %1, basereg, 4, indexreg, 3, 4, $4);
+}
+
+JIT_OP_LOAD_ELEMENT_FLOAT64:
+[=freg64, reg, reg, scratch reg] -> {
+	//x86_fld_memindex(inst, $2, 0, $3, 3, 1);
+	arm_fld_memindex(inst, $1, $2, 0, $3, 3, 1, $4);
+}
+
+JIT_OP_STORE_ELEMENT_BYTE: ternary
+[reg, reg, breg, scratch reg] -> {
+	arm_mov_memindex_reg(inst, $1, 0, $2, 0, $3, 1, $4);
+}
+
+JIT_OP_STORE_ELEMENT_SHORT: ternary
+[reg, reg, reg, scratch reg] -> {
+	arm_mov_memindex_reg(inst, $1, 0, $2, 1, $3, 2, $4);
+}
+
+JIT_OP_STORE_ELEMENT_INT: ternary
+[reg, reg, reg, scratch reg] -> {
+	arm_mov_memindex_reg(inst, $1, 0, $2, 2, $3, 4, $4);
+}
+
+JIT_OP_STORE_ELEMENT_FLOAT64: ternary, stack
+[reg, reg, freg64, scratch reg] -> {
+	//x86_fst_memindex(inst, $1, 0, $2, 3, 1, 1);
+	arm_fst_memindex(inst, $3, $1, 0, $2, 3, 1, $4);
+}
+
+/*
+* Allocate memory from the stack.
+*/
+JIT_OP_ALLOCA:
+[reg] -> {
+	//The ARM stack must always be 4-byte aligned and must be 8-byte aligned at a public interface.
+	//Since we don't know when this function will be called, let's align to 8 bytes.
+	arm_alu_reg_imm(inst, ARM_ADD, $1, $1, 7);
+	arm_alu_reg_imm(inst, ARM_AND, $1, $1, ~7);
+	arm_alu_reg_reg(inst, ARM_SUB, ARM_SP, ARM_SP, $1);
+	arm_mov_reg_reg(inst, $1, ARM_SP);
+	gen->stack_changed = 1;
+}
+
+/*
+ * Block operations
+ */
+JIT_OP_MEMCPY: ternary
+	[any, any, imm, if("$3 <= 0")] -> { }
+	/*[reg, reg, imm, scratch breg, if("$3 <= 32"), space("32 + $3 * 4")] -> {
+		int disp;
+		disp = 0;
+		while($3 >= (disp + 4))
+		{
+			arm_mov_reg_membase(inst, $4, $2, disp, 4);
+			arm_mov_membase_reg(inst, $1, disp, $4, 4);
+			disp += 4;
+		}
+		if($3 >= (disp + 2))
+		{
+			arm_mov_reg_membase(inst, $4, $2, disp, 2);
+			arm_mov_membase_reg(inst, $1, disp, $4, 2);
+			disp += 2;
+		}
+		if($3 > disp)
+		{
+			arm_mov_reg_membase(inst, $4, $2, disp, 1);
+			arm_mov_membase_reg(inst, $1, disp, $4, 1);
+		}
+	}*/
+	[reg, reg, imm, scratch reg, clobber("r0", "r1", "r2")] ->
+	{
+		/* 
+		 * Call jit_memcpy(dest,src,size).
+		 * $1=dest, $2=src, $3=size
+		 */
+		int dest=$1;
+		int src=$2;
+		
+		if (dest != ARM_R0) {
+			if(src==ARM_R0)
+			{
+				//Prevent overwriting useful data
+				arm_mov_reg_reg(inst, $4, src);
+				src=$4;
+			}
+			arm_mov_reg_reg((inst), ARM_R0, dest);
+		}
+		if (src != ARM_R1) {
+			//Move the "src" from wherever it is to where it should be
+			arm_mov_reg_reg(inst, ARM_R1, src);
+		}
+		arm_mov_reg_imm((inst), ARM_R2, $3);
+	    
+		//Call the function
+		arm_call(inst, jit_memcpy);
+	}
+	[reg, reg, reg, scratch breg, clobber("r0", "r1", "r2")] -> {
+		/* 
+		* Call jit_memcpy(dest,src,size).
+		* $1=dest, $2=src, $3=size
+		*/
+		if ($1 != ARM_R0) {
+			if($2==ARM_R0)
+			{
+				//Prevent overwriting useful data
+				arm_mov_reg_reg(inst, $4, $2);
+			}
+			arm_mov_reg_reg((inst), ARM_R0, $1);
+		}
+		if ($2 != ARM_R1) {
+			if ($2==ARM_R0)
+			{
+				//Recover previously saved data
+				arm_mov_reg_reg(inst, ARM_R1, $4);
+			}
+			else
+			{
+				arm_mov_reg_reg((inst), ARM_R1, $2);
+			}
+		}
+		if ($3 != ARM_R2) {
+			arm_mov_reg_reg((inst), ARM_R2, $3);
+		}
+	    
+		//Call the function
+		arm_call(inst, jit_memcpy);
+
+	}
+
+JIT_OP_MEMSET: ternary
+[any, any, imm, if("$3 <= 0")] -> { }
+/* Funzionante, con chiamata a funzione
+[reg, imm, imm, clobber("r0", "r1", "r2"), if("$3 <= 32"), space("32 + $3 * 4")] -> {
+	arm_nop(inst);
+	// Store actual parameters in registers
+	if ($1 != ARM_R0) {
+		arm_mov_reg_reg((inst), ARM_R0, $1);
+	}
+	arm_mov_reg_imm((inst), ARM_R1, $2);
+	arm_mov_reg_imm((inst), ARM_R2, $3);
+	
+	arm_call(inst, jit_memset);
+} */
+[reg, imm, imm, if("$3 <= 32"), space("32 + $3 * 4")] -> {
+	// $1 = pointer to the initial memory location
+	// $2 = value to be written in memory
+	// $3 = length in bytes
+	int disp;
+	disp = 0;
+	while($3 >= (disp + 4))
+	{
+		//NB: if 0<A<255, then A*0x01010101 = a 32-bit value where each of its four bytes is A.
+		arm_mov_membase_imm(inst, $1, disp, $2 * 0x01010101, 4, ARM_WORK);
+		disp += 4;
+	}
+	if($3 >= (disp + 2))
+	{
+		arm_mov_membase_imm(inst, $1, disp, $2 * 0x0101, 2, ARM_WORK);
+		disp += 2;
+	}
+	if(insn->value2->address > disp)
+	{
+		arm_mov_membase_imm(inst, $1, disp, $2, 1, ARM_WORK);
+	}
+}
+[reg, breg, imm, if("$3 < 4")] -> {
+	//0
+	TODO();
+	abort();
+}
+[reg, +reg, imm, scratch reg, if("$3 <= 32 && ($3 % 2) == 0"), space("32 + $3 * 4")] -> {
+	// $1 = pointer to the initial memory location
+	// $2 = value to be written in memory
+	// $3 = length in bytes
+	// $4 = scratch register
+	int disp;
+	arm_mov_reg_reg(inst, $4, $2);
+	arm_shift_reg_imm8(inst, ARM_SHL, $2, $2, 8);
+	arm_alu_reg_reg(inst, ARM_ORR, $2, $2, $4);
+	arm_mov_reg_reg(inst, $4, $2);
+	arm_shift_reg_imm8(inst, ARM_SHL, $2, $2, 16);
+	arm_alu_reg_reg(inst, ARM_ORR, $2, $2, $4);
+	disp = 0;
+	while($3 >= (disp + 4))
+	{
+		arm_mov_membase_reg(inst, $1, disp, $2, 4);
+		disp += 4;
+	}
+	if($3 > disp)
+	{
+		arm_mov_membase_reg(inst, $1, disp, $2, 2);
+	}
+}
+[reg, +breg, imm, scratch reg,
+if("$3 <= 32 && ($3 % 2) != 0"), space("32 + $3 * 4")] -> {
+	//2
+	TODO();
+	abort();
+}
+[reg, reg, reg, clobber("r0", "r1", "r2"), scratch reg] -> {
+	// $1 = pointer to the initial memory location
+	// $2 = value to be written in memory
+	// $3 = length in bytes
+	// $4 = scratch register
+	
+	int scratchContains=0; //< Number of the parameter in the scratch register. 0 means no param in scratch reg.
+	int allOk=0;
+
+	/* Move the outgoing parameters in the right registers (if they are not already where they should be */
+	if ($1 != ARM_R0) {
+		if($2 == ARM_R0)
+		{
+			arm_mov_reg_reg((inst), $4, ARM_R0);
+			scratchContains=2;
+		}
+		else if($3==ARM_R0)
+		{
+			arm_mov_reg_reg((inst), $4, ARM_R0);
+			scratchContains=3;
+		}
+		arm_mov_reg_reg((inst), ARM_R0, $1);
+	}
+	
+	if ($2 != ARM_R1)
+	{
+		if ($3 == ARM_R1)
+		{
+			//We must save param 3, that's in ARM_R1
+			if(scratchContains==2)
+			{
+				/*scratch reg contains the parameter that will go in ARM_R1 and can't be overwritten. Copy param 3 directly to its register. */
+				arm_mov_reg_reg(inst, ARM_R2, ARM_R1);
+				allOk=1;
+			}
+			else
+			{
+				assert(scratchContains==0);
+				//Scratch reg is free. Use it to store param 3
+				arm_mov_reg_reg(inst, $4, ARM_R1);
+				scratchContains=3;
+			}
+		}
+		
+		//Set param 2
+		if(scratchContains==2)
+		{
+			arm_mov_reg_reg((inst), ARM_R1, $4);
+		}
+		else
+		{
+			arm_mov_reg_reg((inst), ARM_R1, $2);
+		}
+	}
+	
+	if(!allOk)
+	{
+		if($3 != ARM_R1)
+		{
+			//Param 3 still isn't in place
+			if(scratchContains==3)
+			{
+				//Get param 3 from the scratch reg
+				arm_mov_reg_reg(inst, ARM_R2, $4);
+			}
+			else 
+			{
+				//Get param 3 from wherever it is
+				arm_mov_reg_reg(inst, ARM_R2, $3);
+			}
+			
+			allOk=1;
+		}
+	}
+	
+	arm_call(inst, jit_memset);
+}
diff -ruN libjit/jit/jit-rules-arm.sel libjit-mikyt/jit/jit-rules-arm.sel
--- libjit/jit/jit-rules-arm.sel	2008-01-24 21:12:53.000000000 +0100
+++ libjit-mikyt/jit/jit-rules-arm.sel	1970-01-01 01:00:00.000000000 +0100
@@ -1,1403 +0,0 @@
-/*
- * jit-rules-arm.sel - Instruction selector for ARM.
- *
- * Copyright (C) 2004  Southern Storm Software, Pty Ltd.
- *
- * This file is part of the libjit library.
- *
- * The libjit library is free software: you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation, either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * The libjit library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the libjit library.  If not, see
- * <http://www.gnu.org/licenses/>.
- */
-
-%inst_type arm_inst_buf
-
-/*
- * Conversion opcodes.
- */
-
-JIT_OP_TRUNC_SBYTE: unary
-	[reg] -> {
-		arm_shift_reg_imm8(inst, ARM_SHL, $1, $1, 24);
-		arm_shift_reg_imm8(inst, ARM_SAR, $1, $1, 24);
-	}
-
-JIT_OP_TRUNC_UBYTE: unary
-	[reg] -> {
-		arm_alu_reg_imm8(inst, ARM_AND, $1, $1, 0xFF);
-	}
-
-JIT_OP_TRUNC_SHORT: unary
-	[reg] -> {
-		arm_shift_reg_imm8(inst, ARM_SHL, $1, $1, 16);
-		arm_shift_reg_imm8(inst, ARM_SAR, $1, $1, 16);
-	}
-
-JIT_OP_TRUNC_USHORT: unary
-	[reg] -> {
-		arm_shift_reg_imm8(inst, ARM_SHL, $1, $1, 16);
-		arm_shift_reg_imm8(inst, ARM_SHR, $1, $1, 16);
-	}
-
-/*
- * Arithmetic opcodes.
- */
-
-JIT_OP_IADD: binary
-	[reg, immu8] -> {
-		arm_alu_reg_imm8(inst, ARM_ADD, $1, $1, $2);
-	}
-	[reg, reg] -> {
-		arm_alu_reg_reg(inst, ARM_ADD, $1, $1, $2);
-	}
-
-JIT_OP_ISUB: binary
-	[reg, immu8] -> {
-		arm_alu_reg_imm8(inst, ARM_SUB, $1, $1, $2);
-	}
-	[reg, reg] -> {
-		arm_alu_reg_reg(inst, ARM_SUB, $1, $1, $2);
-	}
-
-JIT_OP_IMUL: binary
-	[reg, immu8] -> {
-		/* Handle special cases of immediate multiplies */
-		switch($2)
-		{
-			case 0:
-			{
-				arm_mov_reg_imm8(inst, $1, 0);
-			}
-			break;
-
-			case 1: break;
-
-			case 2:
-			{
-				arm_shift_reg_imm8(inst, ARM_SHL, $1, $1, 1);
-			}
-			break;
-
-			case 4:
-			{
-				arm_shift_reg_imm8(inst, ARM_SHL, $1, $1, 2);
-			}
-			break;
-
-			case 8:
-			{
-				arm_shift_reg_imm8(inst, ARM_SHL, $1, $1, 3);
-			}
-			break;
-
-			case 16:
-			{
-				arm_shift_reg_imm8(inst, ARM_SHL, $1, $1, 4);
-			}
-			break;
-
-			case 32:
-			{
-				arm_shift_reg_imm8(inst, ARM_SHL, $1, $1, 5);
-			}
-			break;
-
-			case 64:
-			{
-				arm_shift_reg_imm8(inst, ARM_SHL, $1, $1, 6);
-			}
-			break;
-
-			case 128:
-			{
-				arm_shift_reg_imm8(inst, ARM_SHL, $1, $1, 7);
-			}
-			break;
-
-			default:
-			{
-				arm_mov_reg_imm8(inst, ARM_WORK, $2);
-				arm_mul_reg_reg(inst, $1, $1, ARM_WORK);
-			}
-			break;
-		}
-	}
-	[reg, reg] -> {
-		if($1 != $2)
-		{
-			arm_mul_reg_reg(inst, $1, $1, $2);
-		}
-		else
-		{
-			/* Cannot use the same register for both arguments */
-			arm_mov_reg_reg(inst, ARM_WORK, $2);
-			arm_mul_reg_reg(inst, $1, $1, ARM_WORK);
-		}
-	}
-
-JIT_OP_INEG: unary
-	[reg] -> {
-		/* -x is the same as (0 - x) */
-		arm_alu_reg_imm8(inst, ARM_RSB, $1, $1, 0);
-	}
-
-JIT_OP_LADD: binary
-	[lreg, lreg] -> {
-		arm_alu_cc_reg_reg(inst, ARM_ADD, $1, $1, $2);
-		arm_alu_reg_reg(inst, ARM_ADC, %1, %1, %2);
-	}
-
-JIT_OP_LSUB: binary
-	[lreg, lreg] -> {
-		arm_alu_cc_reg_reg(inst, ARM_SUB, $1, $1, $2);
-		arm_alu_reg_reg(inst, ARM_SBC, %1, %1, %2);
-	}
-
-JIT_OP_LNEG: unary
-	[lreg] -> {
-		arm_alu_reg(inst, ARM_MVN, $1, $1);
-		arm_alu_reg(inst, ARM_MVN, %1, %1);
-		arm_alu_cc_reg_imm8(inst, ARM_ADD, $1, $1, 1);
-		arm_alu_reg_imm8(inst, ARM_ADC, %1, %1, 0);
-	}
-
-JIT_OP_FADD (JIT_ARM_HAS_FLOAT_REGS): binary
-	[freg, freg] -> {
-		arm_alu_freg_freg_32(inst, ARM_ADF, $1, $1, $2);
-	}
-
-JIT_OP_FSUB (JIT_ARM_HAS_FLOAT_REGS): binary
-	[freg, freg] -> {
-		arm_alu_freg_freg_32(inst, ARM_SUF, $1, $1, $2);
-	}
-
-JIT_OP_FMUL (JIT_ARM_HAS_FLOAT_REGS): binary
-	[freg, freg] -> {
-		arm_alu_freg_freg_32(inst, ARM_MUF, $1, $1, $2);
-	}
-
-JIT_OP_FDIV (JIT_ARM_HAS_FLOAT_REGS): binary
-	[freg, freg] -> {
-		arm_alu_freg_freg_32(inst, ARM_DVF, $1, $1, $2);
-	}
-
-JIT_OP_FNEG (JIT_ARM_HAS_FLOAT_REGS): unary
-	[freg] -> {
-		arm_alu_freg_32(inst, ARM_MNF, $1, $1);
-	}
-
-JIT_OP_DADD, JIT_OP_NFADD (JIT_ARM_HAS_FLOAT_REGS): binary
-	[freg, freg] -> {
-		arm_alu_freg_freg(inst, ARM_ADF, $1, $1, $2);
-	}
-
-JIT_OP_DSUB, JIT_OP_NFSUB (JIT_ARM_HAS_FLOAT_REGS): binary
-	[freg, freg] -> {
-		arm_alu_freg_freg(inst, ARM_SUF, $1, $1, $2);
-	}
-
-JIT_OP_DMUL, JIT_OP_NFMUL (JIT_ARM_HAS_FLOAT_REGS): binary
-	[freg, freg] -> {
-		arm_alu_freg_freg(inst, ARM_MUF, $1, $1, $2);
-	}
-
-JIT_OP_DDIV, JIT_OP_NFDIV (JIT_ARM_HAS_FLOAT_REGS): binary
-	[freg, freg] -> {
-		arm_alu_freg_freg(inst, ARM_DVF, $1, $1, $2);
-	}
-
-JIT_OP_DNEG, JIT_OP_NFNEG (JIT_ARM_HAS_FLOAT_REGS): unary
-	[freg] -> {
-		arm_alu_freg(inst, ARM_MNF, $1, $1);
-	}
-
-/*
- * Bitwise opcodes.
- */
-
-JIT_OP_IAND: binary
-	[reg, immu8] -> {
-		arm_alu_reg_imm8(inst, ARM_AND, $1, $1, $2);
-	}
-	[reg, reg] -> {
-		arm_alu_reg_reg(inst, ARM_AND, $1, $1, $2);
-	}
-
-JIT_OP_IOR: binary
-	[reg, immu8] -> {
-		arm_alu_reg_imm8(inst, ARM_ORR, $1, $1, $2);
-	}
-	[reg, reg] -> {
-		arm_alu_reg_reg(inst, ARM_ORR, $1, $1, $2);
-	}
-
-JIT_OP_IXOR: binary
-	[reg, immu8] -> {
-		arm_alu_reg_imm8(inst, ARM_EOR, $1, $1, $2);
-	}
-	[reg, reg] -> {
-		arm_alu_reg_reg(inst, ARM_EOR, $1, $1, $2);
-	}
-
-JIT_OP_INOT: unary
-	[reg] -> {
-		/* MVN == "move not" */
-		arm_alu_reg(inst, ARM_MVN, $1, $1);
-	}
-
-JIT_OP_ISHL: binary
-	[reg, imm] -> {
-		arm_shift_reg_imm8(inst, ARM_SHL, $1, $1, ($2 & 0x1F));
-	}
-	[reg, reg] -> {
-		arm_alu_reg_imm8(inst, ARM_AND, ARM_WORK, $2, 0x1F);
-		arm_shift_reg_reg(inst, ARM_SHL, $1, $1, ARM_WORK);
-	}
-
-JIT_OP_ISHR: binary
-	[reg, imm] -> {
-		arm_shift_reg_imm8(inst, ARM_SAR, $1, $1, ($2 & 0x1F));
-	}
-	[reg, reg] -> {
-		arm_alu_reg_imm8(inst, ARM_AND, ARM_WORK, $2, 0x1F);
-		arm_shift_reg_reg(inst, ARM_SAR, $1, $1, ARM_WORK);
-	}
-
-JIT_OP_ISHR_UN: binary
-	[reg, imm] -> {
-		arm_shift_reg_imm8(inst, ARM_SHR, $1, $1, ($2 & 0x1F));
-	}
-	[reg, reg] -> {
-		arm_alu_reg_imm8(inst, ARM_AND, ARM_WORK, $2, 0x1F);
-		arm_shift_reg_reg(inst, ARM_SHR, $1, $1, ARM_WORK);
-	}
-
-JIT_OP_LAND: binary
-	[lreg, lreg] -> {
-		arm_alu_reg_reg(inst, ARM_AND, $1, $1, $2);
-		arm_alu_reg_reg(inst, ARM_AND, %1, %1, %2);
-	}
-
-JIT_OP_LOR: binary
-	[lreg, lreg] -> {
-		arm_alu_reg_reg(inst, ARM_ORR, $1, $1, $2);
-		arm_alu_reg_reg(inst, ARM_ORR, %1, %1, %2);
-	}
-
-JIT_OP_LXOR: binary
-	[lreg, lreg] -> {
-		arm_alu_reg_reg(inst, ARM_EOR, $1, $1, $2);
-		arm_alu_reg_reg(inst, ARM_EOR, %1, %1, %2);
-	}
-
-JIT_OP_LNOT: unary
-	[lreg] -> {
-		arm_alu_reg(inst, ARM_MVN, $1, $1);
-		arm_alu_reg(inst, ARM_MVN, %1, %1);
-	}
-
-/*
- * Branch opcodes.
- */
-
-JIT_OP_BR: spill_before
-	[] -> {
-		/* ARM_CC_AL == "always branch" */
-		output_branch(func, &inst, ARM_CC_AL, insn);
-
-		/* Flush the constant pool now, to minimize the probability that
-		   it is accidentally flushed in the middle of a loop body */
-		jit_gen_save_inst_ptr(gen, inst);
-		flush_constants(gen, 1);
-		jit_gen_load_inst_ptr(gen, inst);
-	}
-
-JIT_OP_BR_IFALSE: unary_branch
-	[reg] -> {
-		arm_test_reg_imm8(inst, ARM_CMP, $1, 0);
-		output_branch(func, &inst, ARM_CC_EQ, insn);
-	}
-
-JIT_OP_BR_ITRUE: unary_branch
-	[reg] -> {
-		arm_test_reg_imm8(inst, ARM_CMP, $1, 0);
-		output_branch(func, &inst, ARM_CC_NE, insn);
-	}
-
-JIT_OP_BR_IEQ: binary_branch
-	[reg, immu8] -> {
-		arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
-		output_branch(func, &inst, ARM_CC_EQ, insn);
-	}
-	[reg, reg] -> {
-		arm_test_reg_reg(inst, ARM_CMP, $1, $2);
-		output_branch(func, &inst, ARM_CC_EQ, insn);
-	}
-
-JIT_OP_BR_INE: binary_branch
-	[reg, immu8] -> {
-		arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
-		output_branch(func, &inst, ARM_CC_NE, insn);
-	}
-	[reg, reg] -> {
-		arm_test_reg_reg(inst, ARM_CMP, $1, $2);
-		output_branch(func, &inst, ARM_CC_NE, insn);
-	}
-
-JIT_OP_BR_ILT: binary_branch
-	[reg, immu8] -> {
-		arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
-		output_branch(func, &inst, ARM_CC_LT, insn);
-	}
-	[reg, reg] -> {
-		arm_test_reg_reg(inst, ARM_CMP, $1, $2);
-		output_branch(func, &inst, ARM_CC_LT, insn);
-	}
-
-JIT_OP_BR_ILT_UN: binary_branch
-	[reg, immu8] -> {
-		arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
-		output_branch(func, &inst, ARM_CC_LT_UN, insn);
-	}
-	[reg, reg] -> {
-		arm_test_reg_reg(inst, ARM_CMP, $1, $2);
-		output_branch(func, &inst, ARM_CC_LT_UN, insn);
-	}
-
-JIT_OP_BR_ILE: binary_branch
-	[reg, immu8] -> {
-		arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
-		output_branch(func, &inst, ARM_CC_LE, insn);
-	}
-	[reg, reg] -> {
-		arm_test_reg_reg(inst, ARM_CMP, $1, $2);
-		output_branch(func, &inst, ARM_CC_LE, insn);
-	}
-
-JIT_OP_BR_ILE_UN: binary_branch
-	[reg, immu8] -> {
-		arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
-		output_branch(func, &inst, ARM_CC_LE_UN, insn);
-	}
-	[reg, reg] -> {
-		arm_test_reg_reg(inst, ARM_CMP, $1, $2);
-		output_branch(func, &inst, ARM_CC_LE_UN, insn);
-	}
-
-JIT_OP_BR_IGT: binary_branch
-	[reg, immu8] -> {
-		arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
-		output_branch(func, &inst, ARM_CC_GT, insn);
-	}
-	[reg, reg] -> {
-		arm_test_reg_reg(inst, ARM_CMP, $1, $2);
-		output_branch(func, &inst, ARM_CC_GT, insn);
-	}
-
-JIT_OP_BR_IGT_UN: binary_branch
-	[reg, immu8] -> {
-		arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
-		output_branch(func, &inst, ARM_CC_GT_UN, insn);
-	}
-	[reg, reg] -> {
-		arm_test_reg_reg(inst, ARM_CMP, $1, $2);
-		output_branch(func, &inst, ARM_CC_GT_UN, insn);
-	}
-
-JIT_OP_BR_IGE: binary_branch
-	[reg, immu8] -> {
-		arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
-		output_branch(func, &inst, ARM_CC_GE, insn);
-	}
-	[reg, reg] -> {
-		arm_test_reg_reg(inst, ARM_CMP, $1, $2);
-		output_branch(func, &inst, ARM_CC_GE, insn);
-	}
-
-JIT_OP_BR_IGE_UN: binary_branch
-	[reg, immu8] -> {
-		arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
-		output_branch(func, &inst, ARM_CC_GE_UN, insn);
-	}
-	[reg, reg] -> {
-		arm_test_reg_reg(inst, ARM_CMP, $1, $2);
-		output_branch(func, &inst, ARM_CC_GE_UN, insn);
-	}
-
-/*
- * Comparison opcodes.
- */
-
-JIT_OP_ICMP: binary
-	[reg, immu8] -> {
-		arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
-		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GT);
-		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LE);
-		arm_alu_reg_cond(inst, ARM_MVN, $1, $1, ARM_CC_LT);
-	}
-	[reg, reg] -> {
-		arm_test_reg_reg(inst, ARM_CMP, $1, $2);
-		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GT);
-		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LE);
-		arm_alu_reg_cond(inst, ARM_MVN, $1, $1, ARM_CC_LT);
-	}
-
-JIT_OP_ICMP_UN: binary
-	[reg, immu8] -> {
-		arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
-		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GT_UN);
-		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LE_UN);
-		arm_alu_reg_cond(inst, ARM_MVN, $1, $1, ARM_CC_LT_UN);
-	}
-	[reg, reg] -> {
-		arm_test_reg_reg(inst, ARM_CMP, $1, $2);
-		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GT_UN);
-		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LE_UN);
-		arm_alu_reg_cond(inst, ARM_MVN, $1, $1, ARM_CC_LT_UN);
-	}
-
-JIT_OP_IEQ: binary
-	[reg, immu8] -> {
-		arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
-		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_EQ);
-		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_NE);
-	}
-	[reg, reg] -> {
-		arm_test_reg_reg(inst, ARM_CMP, $1, $2);
-		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_EQ);
-		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_NE);
-	}
-
-JIT_OP_INE: binary
-	[reg, immu8] -> {
-		arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
-		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_NE);
-		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_EQ);
-	}
-	[reg, reg] -> {
-		arm_test_reg_reg(inst, ARM_CMP, $1, $2);
-		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_NE);
-		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_EQ);
-	}
-
-JIT_OP_ILT: binary
-	[reg, immu8] -> {
-		arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
-		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_LT);
-		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_GE);
-	}
-	[reg, reg] -> {
-		arm_test_reg_reg(inst, ARM_CMP, $1, $2);
-		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_LT);
-		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_GE);
-	}
-
-JIT_OP_ILT_UN: binary
-	[reg, immu8] -> {
-		arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
-		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_LT_UN);
-		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_GE_UN);
-	}
-	[reg, reg] -> {
-		arm_test_reg_reg(inst, ARM_CMP, $1, $2);
-		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_LT_UN);
-		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_GE_UN);
-	}
-
-JIT_OP_ILE: binary
-	[reg, immu8] -> {
-		arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
-		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_LE);
-		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_GT);
-	}
-	[reg, reg] -> {
-		arm_test_reg_reg(inst, ARM_CMP, $1, $2);
-		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_LE);
-		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_GT);
-	}
-
-JIT_OP_ILE_UN: binary
-	[reg, immu8] -> {
-		arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
-		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_LE_UN);
-		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_GT_UN);
-	}
-	[reg, reg] -> {
-		arm_test_reg_reg(inst, ARM_CMP, $1, $2);
-		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_LE_UN);
-		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_GT_UN);
-	}
-
-JIT_OP_IGT: binary
-	[reg, immu8] -> {
-		arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
-		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GT);
-		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LE);
-	}
-	[reg, reg] -> {
-		arm_test_reg_reg(inst, ARM_CMP, $1, $2);
-		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GT);
-		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LE);
-	}
-
-JIT_OP_IGT_UN: binary
-	[reg, immu8] -> {
-		arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
-		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GT_UN);
-		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LE_UN);
-	}
-	[reg, reg] -> {
-		arm_test_reg_reg(inst, ARM_CMP, $1, $2);
-		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GT_UN);
-		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LE_UN);
-	}
-
-JIT_OP_IGE: binary
-	[reg, immu8] -> {
-		arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
-		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GE);
-		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LT);
-	}
-	[reg, reg] -> {
-		arm_test_reg_reg(inst, ARM_CMP, $1, $2);
-		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GE);
-		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LT);
-	}
-
-JIT_OP_IGE_UN: binary
-	[reg, immu8] -> {
-		arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
-		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GE_UN);
-		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LT_UN);
-	}
-	[reg, reg] -> {
-		arm_test_reg_reg(inst, ARM_CMP, $1, $2);
-		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GE_UN);
-		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LT_UN);
-	}
-
-/*
- * Pointer check opcodes.
- */
-
-JIT_OP_CHECK_NULL: unary_note
-	[reg] -> {
-		arm_test_reg_imm8(inst, ARM_CMP, $1, 0);
-		throw_builtin(&inst, func, ARM_CC_EQ, JIT_RESULT_NULL_REFERENCE);
-	}
-
-/*
- * Function calls.
- */
-
-JIT_OP_CALL:
-	[] -> {
-		jit_function_t func = (jit_function_t)(insn->dest);
-		arm_call(inst, func->closure_entry);
-	}
-
-JIT_OP_CALL_TAIL:
-	[] -> {
-		jit_function_t func = (jit_function_t)(insn->dest);
-		arm_pop_frame_tail(inst, 0);
-		arm_jump(inst, func->closure_entry);
-	}
-
-JIT_OP_CALL_INDIRECT:
-	[] -> {
-		arm_mov_reg_reg((inst), ARM_LINK, ARM_PC);
-		arm_mov_reg_reg((inst), ARM_PC, ARM_WORK);
-	}
-
-JIT_OP_CALL_VTABLE_PTR:
-	[] -> {
-		arm_mov_reg_reg((inst), ARM_LINK, ARM_PC);
-		arm_mov_reg_reg((inst), ARM_PC, ARM_WORK);
-	}
-
-JIT_OP_CALL_EXTERNAL:
-	[] -> {
-		arm_call(inst, (void *)(insn->dest));
-	}
-
-JIT_OP_RETURN:
-	[] -> {
-		jump_to_epilog(gen, &inst, block);
-	}
-
-JIT_OP_RETURN_INT: unary_branch
-	[reg] -> {
-		int cpu_reg = $1;
-		if(cpu_reg != ARM_R0)
-		{
-			arm_mov_reg_reg(inst, ARM_R0, cpu_reg);
-		}
-		jump_to_epilog(gen, &inst, block);
-	}
-
-JIT_OP_RETURN_LONG: unary_branch
-	[imm] -> {
-		mov_reg_imm(gen, &inst, ARM_R0, ((jit_int *)($1))[0]);
-		mov_reg_imm(gen, &inst, ARM_R1, ((jit_int *)($1))[1]);
-		jump_to_epilog(gen, &inst, block);
-	}
-	[local] -> {
-		arm_load_membase(inst, ARM_R0, ARM_FP, $1);
-		arm_load_membase(inst, ARM_R1, ARM_FP, $1 + 4);
-		jump_to_epilog(gen, &inst, block);
-	}
-	[lreg] -> {
-		if($1 != 0)
-		{
-			arm_mov_reg_reg(inst, ARM_R0, $1);
-			arm_mov_reg_reg(inst, ARM_R1, %1);
-		}
-		jump_to_epilog(gen, &inst, block);
-	}
-
-JIT_OP_RETURN_FLOAT32 (JIT_ARM_HAS_FLOAT_REGS): unary_branch
-	[freg] -> {
-		if($1 != 0)
-		{
-			arm_alu_freg_32(inst, ARM_MVF, ARM_F0, $1);
-		}
-		jump_to_epilog(gen, &inst, block);
-	}
-
-JIT_OP_RETURN_FLOAT32 (!JIT_ARM_HAS_FLOAT_REGS): manual
-	[] -> {
-		arm_inst_buf inst;
-		_jit_regs_spill_all(gen);
-		_jit_gen_fix_value(insn->value1);
-		jit_gen_load_inst_ptr(gen, inst);
-		if(insn->value1->is_constant)
-		{
-			mov_reg_imm
-				(gen, &inst, ARM_R0, ((int *)(insn->value1->address))[0]);
-		}
-		else
-		{
-			arm_load_membase(inst, ARM_R0, ARM_FP, insn->value1->frame_offset);
-		}
-		jump_to_epilog(gen, &inst, block);
-		jit_gen_save_inst_ptr(gen, inst);
-	}
-
-JIT_OP_RETURN_FLOAT64, JIT_OP_RETURN_NFLOAT
-		(JIT_ARM_HAS_FLOAT_REGS): unary_branch
-	[freg] -> {
-		if($1 != 0)
-		{
-			arm_alu_freg(inst, ARM_MVF, ARM_F0, $1);
-		}
-		jump_to_epilog(gen, &inst, block);
-	}
-
-JIT_OP_RETURN_FLOAT64, JIT_OP_RETURN_NFLOAT (!JIT_ARM_HAS_FLOAT_REGS): manual
-	[] -> {
-		arm_inst_buf inst;
-		_jit_regs_spill_all(gen);
-		_jit_gen_fix_value(insn->value1);
-		jit_gen_load_inst_ptr(gen, inst);
-		if(insn->value1->is_constant)
-		{
-			mov_reg_imm
-				(gen, &inst, ARM_R0, ((int *)(insn->value1->address))[0]);
-			mov_reg_imm
-				(gen, &inst, ARM_R1, ((int *)(insn->value1->address))[1]);
-		}
-		else
-		{
-			arm_load_membase(inst, ARM_R0, ARM_FP, insn->value1->frame_offset);
-			arm_load_membase(inst, ARM_R1, ARM_FP,
-							 insn->value1->frame_offset + 4);
-		}
-		jump_to_epilog(gen, &inst, block);
-		jit_gen_save_inst_ptr(gen, inst);
-	}
-
-JIT_OP_RETURN_SMALL_STRUCT: unary_branch
-	[reg] -> {
-		int temp_reg = $1;
-		if(temp_reg < 3)
-		{
-			arm_mov_reg_reg(inst, ARM_WORK, temp_reg);
-			temp_reg = ARM_WORK;
-		}
-		switch(insn->value2->address)
-		{
-			case 1:
-			{
-				arm_load_membase_byte(inst, ARM_R0, temp_reg, 0);
-			}
-			break;
-
-			case 2:
-			{
-				arm_load_membase_ushort(inst, ARM_R0, temp_reg, 0);
-			}
-			break;
-
-			case 3:
-			{
-				arm_load_membase_ushort(inst, ARM_R0, temp_reg, 0);
-				arm_load_membase_byte(inst, ARM_R1, temp_reg, 2);
-				arm_shift_reg_imm8(inst, ARM_SHL, ARM_R1, ARM_R1, 16);
-				arm_alu_reg_reg(inst, ARM_ORR, ARM_R0, ARM_R0, ARM_R1);
-			}
-			break;
-
-			case 4:
-			{
-				arm_load_membase(inst, ARM_R0, temp_reg, 0);
-			}
-			break;
-
-			case 5:
-			{
-				arm_load_membase(inst, ARM_R0, temp_reg, 0);
-				arm_load_membase_byte(inst, ARM_R1, temp_reg, 4);
-			}
-			break;
-
-			case 6:
-			{
-				arm_load_membase(inst, ARM_R0, temp_reg, 0);
-				arm_load_membase_ushort(inst, ARM_R1, temp_reg, 4);
-			}
-			break;
-
-			case 7:
-			{
-				arm_load_membase(inst, ARM_R0, temp_reg, 0);
-				arm_load_membase_ushort(inst, ARM_R1, temp_reg, 4);
-				arm_load_membase_byte(inst, ARM_R2, temp_reg, 6);
-				arm_shift_reg_imm8(inst, ARM_SHL, ARM_R2, ARM_R2, 16);
-				arm_alu_reg_reg(inst, ARM_ORR, ARM_R1, ARM_R1, ARM_R2);
-			}
-			break;
-
-			case 8:
-			{
-				arm_load_membase(inst, ARM_R0, temp_reg, 0);
-				arm_load_membase(inst, ARM_R1, temp_reg, 4);
-			}
-			break;
-		}
-		jump_to_epilog(gen, &inst, block);
-	}
-
-JIT_OP_SETUP_FOR_NESTED: spill_before
-	[] -> {
-		jit_nint nest_reg = jit_value_get_nint_constant(insn->value1);
-		if(nest_reg == -1)
-		{
-			arm_push_reg(inst, ARM_FP);
-		}
-		else
-		{
-			arm_mov_reg_reg(inst, _jit_reg_info[nest_reg].cpu_reg, ARM_FP);
-		}
-	}
-
-JIT_OP_SETUP_FOR_SIBLING: spill_before
-	[] -> {
-		jit_nint level = jit_value_get_nint_constant(insn->value1);
-		jit_nint nest_reg = jit_value_get_nint_constant(insn->value2);
-		int cpu_reg;
-		if(nest_reg == -1)
-		{
-			cpu_reg = ARM_R0;
-		}
-		else
-		{
-			cpu_reg = _jit_reg_info[nest_reg].cpu_reg;
-		}
-		arm_load_membase(inst, cpu_reg, ARM_FP, JIT_APPLY_PARENT_FRAME_OFFSET);
-		while(level > 0)
-		{
-			arm_load_membase(inst, cpu_reg, cpu_reg,
-							 JIT_APPLY_PARENT_FRAME_OFFSET);
-			--level;
-		}
-		if(nest_reg == -1)
-		{
-			arm_push_reg(inst, cpu_reg);
-		}
-	}
-
-JIT_OP_IMPORT:
-	[] -> {
-		/* TODO */
-		TODO();
-	}
-
-/*
- * Data manipulation.
- */
-
-JIT_OP_COPY_LOAD_SBYTE: unary
-	[reg] -> {}
-
-JIT_OP_COPY_LOAD_UBYTE: unary
-	[reg] -> {}
-
-JIT_OP_COPY_LOAD_SHORT: unary
-	[reg] -> {}
-
-JIT_OP_COPY_LOAD_USHORT: unary
-	[reg] -> {}
-
-JIT_OP_COPY_INT: unary
-	[reg] -> {}
-
-JIT_OP_COPY_LONG: unary
-	[lreg] -> {}
-
-JIT_OP_COPY_FLOAT32 (JIT_ARM_HAS_FLOAT_REGS): unary
-	[freg] -> {}
-
-JIT_OP_COPY_FLOAT32 (!JIT_ARM_HAS_FLOAT_REGS): manual
-	[] -> {
-		arm_inst_buf inst;
-		_jit_regs_force_out(gen, insn->value1, 0);
-		_jit_regs_force_out(gen, insn->dest, 1);
-		_jit_gen_fix_value(insn->value1);
-		_jit_gen_fix_value(insn->dest);
-		jit_gen_load_inst_ptr(gen, inst);
-		if(insn->value1->is_constant)
-		{
-			mov_reg_imm
-				(gen, &inst, ARM_WORK, ((int *)(insn->value1->address))[0]);
-		}
-		else
-		{
-			arm_load_membase(inst, ARM_WORK, ARM_FP,
-							 insn->value1->frame_offset);
-		}
-		arm_store_membase(inst, ARM_WORK, ARM_FP, insn->dest->frame_offset);
-		jit_gen_save_inst_ptr(gen, inst);
-	}
-
-JIT_OP_COPY_FLOAT64, JIT_OP_COPY_NFLOAT (JIT_ARM_HAS_FLOAT_REGS): unary
-	[freg] -> {}
-
-JIT_OP_COPY_FLOAT64, JIT_OP_COPY_NFLOAT (!JIT_ARM_HAS_FLOAT_REGS): manual
-	[] -> {
-		arm_inst_buf inst;
-		_jit_regs_force_out(gen, insn->value1, 0);
-		_jit_regs_force_out(gen, insn->dest, 1);
-		_jit_gen_fix_value(insn->value1);
-		_jit_gen_fix_value(insn->dest);
-		jit_gen_load_inst_ptr(gen, inst);
-		if(insn->value1->is_constant)
-		{
-			mov_reg_imm
-				(gen, &inst, ARM_WORK, ((int *)(insn->value1->address))[0]);
-			arm_store_membase(inst, ARM_WORK, ARM_FP,
-							  insn->dest->frame_offset);
-			mov_reg_imm
-				(gen, &inst, ARM_WORK, ((int *)(insn->value1->address))[1]);
-			arm_store_membase(inst, ARM_WORK, ARM_FP,
-							  insn->dest->frame_offset + 4);
-		}
-		else
-		{
-			arm_load_membase(inst, ARM_WORK, ARM_FP,
-							 insn->value1->frame_offset);
-			arm_store_membase(inst, ARM_WORK, ARM_FP,
-							  insn->dest->frame_offset);
-			arm_load_membase(inst, ARM_WORK, ARM_FP,
-							 insn->value1->frame_offset + 4);
-			arm_store_membase(inst, ARM_WORK, ARM_FP,
-							  insn->dest->frame_offset + 4);
-		}
-		jit_gen_save_inst_ptr(gen, inst);
-	}
-
-JIT_OP_COPY_STRUCT: manual
-	[] -> {
-		/* TODO */
-		TODO();
-	}
-
-JIT_OP_COPY_STORE_BYTE: manual
-	[] -> {
-		arm_inst_buf inst;
-		int reg;
-		_jit_regs_force_out(gen, insn->dest, 1);
-		_jit_gen_fix_value(insn->dest);
-		reg = _jit_regs_load_value
-			(gen, insn->value1, 0,
-			 (insn->flags & (JIT_INSN_VALUE1_NEXT_USE |
-			 				 JIT_INSN_VALUE1_LIVE)));
-		jit_gen_load_inst_ptr(gen, inst);
-		arm_store_membase_byte(inst, _jit_reg_info[reg].cpu_reg,
-							   ARM_FP, insn->dest->frame_offset);
-		jit_gen_save_inst_ptr(gen, inst);
-	}
-
-JIT_OP_COPY_STORE_SHORT: manual
-	[] -> {
-		arm_inst_buf inst;
-		int reg;
-		_jit_regs_force_out(gen, insn->dest, 1);
-		_jit_gen_fix_value(insn->dest);
-		reg = _jit_regs_load_value
-			(gen, insn->value1, 1,
-			 (insn->flags & (JIT_INSN_VALUE1_NEXT_USE |
-			 				 JIT_INSN_VALUE1_LIVE)));
-		jit_gen_load_inst_ptr(gen, inst);
-		arm_store_membase_short(inst, _jit_reg_info[reg].cpu_reg,
-							    ARM_FP, insn->dest->frame_offset);
-		jit_gen_save_inst_ptr(gen, inst);
-		_jit_regs_free_reg(gen, reg, 1);
-	}
-
-JIT_OP_ADDRESS_OF: manual
-	[] -> {
-		arm_inst_buf inst;
-		int reg, offset;
-		_jit_regs_force_out(gen, insn->value1, 0);
-		_jit_gen_fix_value(insn->value1);
-		jit_gen_load_inst_ptr(gen, inst);
-		reg = _jit_regs_dest_value(gen, insn->dest);
-		reg = _jit_reg_info[reg].cpu_reg;
-		offset = insn->value1->frame_offset;
-		if(offset > 0)
-		{
-			arm_alu_reg_imm(inst, ARM_ADD, reg, ARM_FP, offset);
-		}
-		else if(offset < 0)
-		{
-			arm_alu_reg_imm(inst, ARM_SUB, reg, ARM_FP, -offset);
-		}
-		else
-		{
-			arm_mov_reg_reg(inst, reg, ARM_FP);
-		}
-		jit_gen_save_inst_ptr(gen, inst);
-	}
-
-/*
- * Stack pushes and pops.
- */
-
-JIT_OP_RETURN_REG: manual
-	[] -> { /* Nothing to do here */ }
-
-JIT_OP_PUSH_INT: unary_note
-	[reg] -> {
-		arm_push_reg(inst, $1);
-	}
-
-JIT_OP_PUSH_LONG: unary_note
-	[lreg] -> {
-		arm_push_reg(inst, %1);
-		arm_push_reg(inst, $1);
-	}
-
-JIT_OP_PUSH_FLOAT32 (JIT_ARM_HAS_FLOAT_REGS): unary_note
-	[freg] -> {
-		arm_push_reg_float32(inst, $1);
-	}
-
-JIT_OP_PUSH_FLOAT32 (!JIT_ARM_HAS_FLOAT_REGS): manual
-	[] -> {
-		arm_inst_buf inst;
-		_jit_regs_force_out(gen, insn->value1, 0);
-		_jit_gen_fix_value(insn->value1);
-		jit_gen_load_inst_ptr(gen, inst);
-		if(insn->value1->is_constant)
-		{
-			mov_reg_imm
-				(gen, &inst, ARM_WORK, ((int *)(insn->value1->address))[0]);
-		}
-		else
-		{
-			arm_load_membase(inst, ARM_WORK, ARM_FP,
-							 insn->value1->frame_offset);
-		}
-		arm_push_reg(inst, ARM_WORK);
-		jit_gen_save_inst_ptr(gen, inst);
-	}
-
-JIT_OP_PUSH_FLOAT64, JIT_OP_PUSH_NFLOAT (JIT_ARM_HAS_FLOAT_REGS): unary_note
-	[freg] -> {
-		arm_push_reg_float64(inst, $1);
-	}
-
-JIT_OP_PUSH_FLOAT64, JIT_OP_PUSH_NFLOAT (!JIT_ARM_HAS_FLOAT_REGS): manual
-	[] -> {
-		arm_inst_buf inst;
-		_jit_regs_force_out(gen, insn->value1, 0);
-		_jit_gen_fix_value(insn->value1);
-		jit_gen_load_inst_ptr(gen, inst);
-		if(insn->value1->is_constant)
-		{
-			mov_reg_imm
-				(gen, &inst, ARM_WORK, ((int *)(insn->value1->address))[1]);
-			arm_push_reg(inst, ARM_WORK);
-			mov_reg_imm
-				(gen, &inst, ARM_WORK, ((int *)(insn->value1->address))[0]);
-			arm_push_reg(inst, ARM_WORK);
-		}
-		else
-		{
-			arm_load_membase(inst, ARM_WORK, ARM_FP,
-							 insn->value1->frame_offset + 4);
-			arm_push_reg(inst, ARM_WORK);
-			arm_load_membase(inst, ARM_WORK, ARM_FP,
-							 insn->value1->frame_offset);
-			arm_push_reg(inst, ARM_WORK);
-		}
-		jit_gen_save_inst_ptr(gen, inst);
-	}
-
-JIT_OP_PUSH_STRUCT: unary_note
-	[reg] -> {
-		/* TODO */
-		TODO();
-	}
-
-JIT_OP_POP_STACK:
-	[] -> {
-		arm_alu_reg_imm(inst, ARM_ADD, ARM_SP, ARM_SP, insn->value1->address);
-	}
-
-JIT_OP_FLUSH_SMALL_STRUCT:
-	[] -> {
-		jit_nuint size;
-		jit_nint offset;
-		_jit_gen_fix_value(insn->value1);
-		size = jit_type_get_size(jit_value_get_type(insn->value1));
-		offset = insn->value1->frame_offset;
-		switch(size)
-		{
-			case 1:
-			{
-				arm_store_membase_byte(inst, ARM_R0, ARM_FP, offset);
-			}
-			break;
-
-			case 2:
-			{
-				arm_store_membase_short(inst, ARM_R0, ARM_FP, offset);
-			}
-			break;
-
-			case 3:
-			{
-				arm_mov_reg_reg(inst, ARM_R1, ARM_R0);
-				arm_store_membase_short(inst, ARM_R0, ARM_FP, offset);
-				arm_shift_reg_imm8(inst, ARM_SHR, ARM_R0, ARM_R1, 16);
-				arm_store_membase_byte(inst, ARM_R0, ARM_FP, offset + 2);
-			}
-			break;
-
-			case 4:
-			{
-				arm_store_membase(inst, ARM_R0, ARM_FP, offset);
-			}
-			break;
-
-			case 5:
-			{
-				arm_store_membase(inst, ARM_R0, ARM_FP, offset);
-				arm_store_membase_byte(inst, ARM_R1, ARM_FP, offset + 4);
-			}
-			break;
-
-			case 6:
-			{
-				arm_store_membase(inst, ARM_R0, ARM_FP, offset);
-				arm_store_membase_short(inst, ARM_R1, ARM_FP, offset + 4);
-			}
-			break;
-
-			case 7:
-			{
-				arm_store_membase(inst, ARM_R0, ARM_FP, offset);
-				arm_mov_reg_reg(inst, ARM_R2, ARM_R1);
-				arm_store_membase_short(inst, ARM_R1, ARM_FP, offset + 4);
-				arm_shift_reg_imm8(inst, ARM_SHR, ARM_R1, ARM_R2, 16);
-				arm_store_membase_byte(inst, ARM_R1, ARM_FP, offset + 6);
-			}
-			break;
-
-			case 8:
-			{
-				arm_store_membase(inst, ARM_R0, ARM_FP, offset);
-				arm_store_membase(inst, ARM_R1, ARM_FP, offset + 4);
-			}
-			break;
-		}
-	}
-
-JIT_OP_SET_PARAM_INT: unary_note
-	[reg] -> {
-		arm_store_membase(inst, $1, ARM_SP, insn->value2->address);
-	}
-
-JIT_OP_SET_PARAM_LONG: unary_note
-	[lreg] -> {
-		arm_store_membase(inst, $1, ARM_SP, insn->value2->address);
-		arm_store_membase(inst, %1, ARM_SP, insn->value2->address + 4);
-	}
-
-JIT_OP_SET_PARAM_FLOAT32 (JIT_ARM_HAS_FLOAT_REGS): unary_note
-	[freg] -> {
-		arm_store_membase_float32(inst, $1, ARM_SP, insn->value2->address);
-	}
-
-JIT_OP_SET_PARAM_FLOAT32 (!JIT_ARM_HAS_FLOAT_REGS): manual
-	[] -> {
-		arm_inst_buf inst;
-		_jit_regs_force_out(gen, insn->value1, 0);
-		_jit_gen_fix_value(insn->value1);
-		jit_gen_load_inst_ptr(gen, inst);
-		if(insn->value1->is_constant)
-		{
-			mov_reg_imm
-				(gen, &inst, ARM_WORK, ((int *)(insn->value1->address))[0]);
-			arm_store_membase
-				(inst, ARM_WORK, ARM_SP, insn->value2->address);
-		}
-		else
-		{
-			arm_load_membase(inst, ARM_WORK, ARM_FP,
-							 insn->value1->frame_offset);
-			arm_store_membase
-				(inst, ARM_WORK, ARM_SP, insn->value2->address);
-		}
-		jit_gen_save_inst_ptr(gen, inst);
-	}
-
-JIT_OP_SET_PARAM_FLOAT64, JIT_OP_SET_PARAM_NFLOAT
-		(JIT_ARM_HAS_FLOAT_REGS): unary_note
-	[freg] -> {
-		arm_store_membase_float64(inst, $1, ARM_SP, insn->value2->address);
-	}
-
-JIT_OP_SET_PARAM_FLOAT64, JIT_OP_SET_PARAM_NFLOAT
-		(!JIT_ARM_HAS_FLOAT_REGS): manual
-	[] -> {
-		arm_inst_buf inst;
-		_jit_regs_force_out(gen, insn->value1, 0);
-		_jit_gen_fix_value(insn->value1);
-		jit_gen_load_inst_ptr(gen, inst);
-		if(insn->value1->is_constant)
-		{
-			mov_reg_imm
-				(gen, &inst, ARM_WORK, ((int *)(insn->value1->address))[0]);
-			arm_store_membase
-				(inst, ARM_WORK, ARM_SP, insn->value2->address);
-			mov_reg_imm
-				(gen, &inst, ARM_WORK, ((int *)(insn->value1->address))[1]);
-			arm_store_membase
-				(inst, ARM_WORK, ARM_SP, insn->value2->address + 4);
-		}
-		else
-		{
-			arm_load_membase(inst, ARM_WORK, ARM_FP,
-							 insn->value1->frame_offset);
-			arm_store_membase
-				(inst, ARM_WORK, ARM_SP, insn->value2->address);
-			arm_load_membase(inst, ARM_WORK, ARM_FP,
-							 insn->value1->frame_offset + 4);
-			arm_store_membase
-				(inst, ARM_WORK, ARM_SP, insn->value2->address + 4);
-		}
-		jit_gen_save_inst_ptr(gen, inst);
-	}
-
-JIT_OP_SET_PARAM_STRUCT: unary_note
-	[reg] -> {
-		/* TODO */
-		TODO();
-	}
-
-/*
- * Pointer-relative loads and stores.
- */
-
-JIT_OP_LOAD_RELATIVE_SBYTE: unary
-	[reg] -> {
-		arm_load_membase_sbyte(inst, $1, $1, insn->value2->address);
-	}
-
-JIT_OP_LOAD_RELATIVE_UBYTE: unary
-	[reg] -> {
-		arm_load_membase_byte(inst, $1, $1, insn->value2->address);
-	}
-
-JIT_OP_LOAD_RELATIVE_SHORT: unary
-	[reg] -> {
-		arm_load_membase_short(inst, $1, $1, insn->value2->address);
-	}
-
-JIT_OP_LOAD_RELATIVE_USHORT: unary
-	[reg] -> {
-		arm_load_membase_ushort(inst, $1, $1, insn->value2->address);
-	}
-
-JIT_OP_LOAD_RELATIVE_INT: unary
-	[reg] -> {
-		arm_load_membase(inst, $1, $1, insn->value2->address);
-	}
-
-JIT_OP_LOAD_RELATIVE_LONG: manual
-	[] -> {
-		arm_inst_buf inst;
-		int reg = _jit_regs_load_value
-			(gen, insn->value1, 0,
-			 (insn->flags & (JIT_INSN_VALUE1_NEXT_USE |
-			 				 JIT_INSN_VALUE1_LIVE)));
-		int reg2, reg3;
-		int frame_offset;
-		_jit_gen_fix_value(insn->dest);
-		_jit_regs_get_reg_pair(gen, reg, -1, -1, &reg2, &reg3);
-		reg  = _jit_reg_info[reg].cpu_reg;
-		reg2 = _jit_reg_info[reg2].cpu_reg;
-		reg3 = _jit_reg_info[reg3].cpu_reg;
-		frame_offset = insn->dest->frame_offset;
-		jit_gen_load_inst_ptr(gen, inst);
-		arm_load_membase(inst, reg2, reg, insn->value2->address);
-		arm_load_membase(inst, reg3, reg, insn->value2->address + 4);
-		arm_store_membase(inst, reg2, ARM_FP, frame_offset);
-		arm_store_membase(inst, reg3, ARM_FP, frame_offset + 4);
-		insn->dest->in_frame = 1;
-		jit_gen_save_inst_ptr(gen, inst);
-	}
-
-JIT_OP_LOAD_RELATIVE_FLOAT32: manual
-	[] -> {
-		/* TODO */
-		TODO();
-	}
-
-JIT_OP_LOAD_RELATIVE_FLOAT64, JIT_OP_LOAD_RELATIVE_NFLOAT: manual
-	[] -> {
-		/* TODO */
-		TODO();
-	}
-
-JIT_OP_LOAD_RELATIVE_STRUCT: manual
-	[] -> {
-		/* TODO */
-		TODO();
-	}
-
-JIT_OP_STORE_RELATIVE_BYTE: manual
-	[] -> {
-		arm_inst_buf inst;
-		int reg = _jit_regs_load_value
-			(gen, insn->dest, 0,
-			 (insn->flags & (JIT_INSN_DEST_NEXT_USE |
-			 				 JIT_INSN_DEST_LIVE)));
-		int reg2 = _jit_regs_load_value
-			(gen, insn->value1, 0,
-			 (insn->flags & (JIT_INSN_VALUE1_NEXT_USE |
-			 				 JIT_INSN_VALUE1_LIVE)));
-		jit_gen_load_inst_ptr(gen, inst);
-		reg  = _jit_reg_info[reg].cpu_reg;
-		reg2 = _jit_reg_info[reg2].cpu_reg;
-		arm_store_membase_byte(inst, reg2, reg, insn->value2->address);
-		jit_gen_save_inst_ptr(gen, inst);
-	}
-
-JIT_OP_STORE_RELATIVE_SHORT: manual
-	[] -> {
-		arm_inst_buf inst;
-		int reg = _jit_regs_load_value
-			(gen, insn->dest, 0,
-			 (insn->flags & (JIT_INSN_DEST_NEXT_USE |
-			 				 JIT_INSN_DEST_LIVE)));
-		int reg2 = _jit_regs_load_value
-			(gen, insn->value1, 1,
-			 (insn->flags & (JIT_INSN_VALUE1_NEXT_USE |
-			 				 JIT_INSN_VALUE1_LIVE)));
-		jit_gen_load_inst_ptr(gen, inst);
-		reg  = _jit_reg_info[reg].cpu_reg;
-		reg2 = _jit_reg_info[reg2].cpu_reg;
-		arm_store_membase_short(inst, reg2, reg, insn->value2->address);
-		jit_gen_save_inst_ptr(gen, inst);
-		_jit_regs_free_reg(gen, reg2, 1);
-	}
-
-JIT_OP_STORE_RELATIVE_INT: manual
-	[] -> {
-		arm_inst_buf inst;
-		int reg = _jit_regs_load_value
-			(gen, insn->dest, 0,
-			 (insn->flags & (JIT_INSN_DEST_NEXT_USE |
-			 				 JIT_INSN_DEST_LIVE)));
-		int reg2 = _jit_regs_load_value
-			(gen, insn->value1, 0,
-			 (insn->flags & (JIT_INSN_VALUE1_NEXT_USE |
-			 				 JIT_INSN_VALUE1_LIVE)));
-		jit_gen_load_inst_ptr(gen, inst);
-		reg  = _jit_reg_info[reg].cpu_reg;
-		reg2 = _jit_reg_info[reg2].cpu_reg;
-		arm_store_membase(inst, reg2, reg, insn->value2->address);
-		jit_gen_save_inst_ptr(gen, inst);
-	}
-
-JIT_OP_STORE_RELATIVE_LONG: manual
-	[] -> {
-		arm_inst_buf inst;
-		int reg = _jit_regs_load_value
-			(gen, insn->dest, 0,
-			 (insn->flags & (JIT_INSN_DEST_NEXT_USE |
-			 				 JIT_INSN_DEST_LIVE)));
-		int reg2, reg3;
-		int frame_offset;
-		_jit_regs_get_reg_pair(gen, reg, -1, -1, &reg2, &reg3);
-		_jit_gen_fix_value(insn->value1);
-		jit_gen_load_inst_ptr(gen, inst);
-		reg  = _jit_reg_info[reg].cpu_reg;
-		reg2 = _jit_reg_info[reg2].cpu_reg;
-		reg3 = _jit_reg_info[reg3].cpu_reg;
-		frame_offset = insn->value1->frame_offset;
-		arm_load_membase(inst, reg2, ARM_FP, frame_offset);
-		arm_load_membase(inst, reg3, ARM_FP, frame_offset + 4);
-		arm_store_membase(inst, reg2, reg, insn->value2->address);
-		arm_store_membase(inst, reg3, reg, insn->value2->address + 4);
-		jit_gen_save_inst_ptr(gen, inst);
-	}
-
-JIT_OP_STORE_RELATIVE_FLOAT32: manual
-	[] -> {
-		/* TODO */
-		TODO();
-	}
-
-JIT_OP_STORE_RELATIVE_FLOAT64, JIT_OP_STORE_RELATIVE_NFLOAT: manual
-	[] -> {
-		/* TODO */
-		TODO();
-	}
-
-JIT_OP_STORE_RELATIVE_STRUCT: manual
-	[] -> {
-		/* TODO */
-		TODO();
-	}
-
-JIT_OP_ADD_RELATIVE: unary
-	[reg] -> {
-		if(insn->value2->address != 0)
-		{
-			arm_alu_reg_imm(inst, ARM_ADD, $1, $1, insn->value2->address);
-		}
-	}
diff -ruN libjit/jit/jit-rules-x86-64.ins libjit-mikyt/jit/jit-rules-x86-64.ins
--- libjit/jit/jit-rules-x86-64.ins	2009-01-01 19:35:41.000000000 +0100
+++ libjit-mikyt/jit/jit-rules-x86-64.ins	2008-12-11 08:52:19.000000000 +0100
@@ -165,9 +165,6 @@
 	}
 
 JIT_OP_NFLOAT_TO_FLOAT32: stack
-	[=local, freg] -> {
-		x86_64_fstp_membase_size(inst, X86_64_RBP, $1, 4);
-	}
 	[=xreg, freg] -> {
 #ifdef HAVE_RED_ZONE
 		/* Avoid modifying the stack pointer by simply using negative */
@@ -183,9 +180,6 @@
 	}
 
 JIT_OP_NFLOAT_TO_FLOAT64: stack
-	[=local, freg] -> {
-		x86_64_fstp_membase_size(inst, X86_64_RBP, $1, 8);
-	}
 	[=xreg, freg] -> {
 #ifdef HAVE_RED_ZONE
 		/* Avoid modifying the stack pointer by simply using negative */
@@ -1782,14 +1776,7 @@
 
 JIT_OP_BR_ILT: branch
 	[reg, imm] -> {
-		if($2 == 0)
-		{
-			x86_64_test_reg_reg_size(inst, $1, $1, 4);
-		}
-		else
-		{
-			x86_64_cmp_reg_imm_size(inst, $1, $2, 4);
-		}
+		x86_64_cmp_reg_imm_size(inst, $1, $2, 4);
 		inst = output_branch(func, inst, 0x7C /* lt */, insn);
 	}
 	[reg, local] -> {
@@ -1817,14 +1804,7 @@
 
 JIT_OP_BR_ILE: branch
 	[reg, imm] -> {
-		if($2 == 0)
-		{
-			x86_64_test_reg_reg_size(inst, $1, $1, 4);
-		}
-		else
-		{
-			x86_64_cmp_reg_imm_size(inst, $1, $2, 4);
-		}
+		x86_64_cmp_reg_imm_size(inst, $1, $2, 4);
 		inst = output_branch(func, inst, 0x7E /* le */, insn);
 	}
 	[reg, local] -> {
@@ -1852,14 +1832,7 @@
 
 JIT_OP_BR_IGT: branch
 	[reg, imm] -> {
-		if($2 == 0)
-		{
-			x86_64_test_reg_reg_size(inst, $1, $1, 4);
-		}
-		else
-		{
-			x86_64_cmp_reg_imm_size(inst, $1, $2, 4);
-		}
+		x86_64_cmp_reg_imm_size(inst, $1, $2, 4);
 		inst = output_branch(func, inst, 0x7F /* gt */, insn);
 	}
 	[reg, local] -> {
@@ -1887,14 +1860,7 @@
 
 JIT_OP_BR_IGE: branch
 	[reg, imm] -> {
-		if($2 == 0)
-		{
-			x86_64_test_reg_reg_size(inst, $1, $1, 4);
-		}
-		else
-		{
-			x86_64_cmp_reg_imm_size(inst, $1, $2, 4);
-		}
+		x86_64_cmp_reg_imm_size(inst, $1, $2, 4);
 		inst = output_branch(func, inst, 0x7D /* ge */, insn);
 	}
 	[reg, local] -> {
@@ -2803,29 +2769,6 @@
 		x86_64_cmov_reg_reg_size(inst, X86_CC_GT, $1, $2, 0, 4);
 	}
 
-JIT_OP_ISIGN:
-	[=reg, imm] -> {
-		if($2 < 0)
-		{
-			x86_64_mov_reg_imm_size(inst, $1, -1, 4);
-		}
-		else if($2 > 0)
-		{
-			x86_64_mov_reg_imm_size(inst, $1, 1, 4);
-		}
-		else
-		{
-			x86_64_clear_reg(inst, $1);
-		}
-	}
-	[=+reg, +reg] -> {
-		x86_64_clear_reg(inst, $1);
-		x86_64_test_reg_reg_size(inst, $2, $2, 4);
-		x86_64_set_reg(inst, X86_CC_NZ, $1, 0);
-		x86_64_sar_reg_imm_size(inst, $2, 31, 4);
-		x86_64_or_reg_reg_size(inst, $1, $2, 4);
-	}
-
 JIT_OP_LMAX: commutative
 	[reg, reg] -> {
 		x86_64_cmp_reg_reg_size(inst, $1, $2, 8);
@@ -2850,29 +2793,6 @@
 		x86_64_cmov_reg_reg_size(inst, X86_CC_GT, $1, $2, 0, 8);
 	}
 
-JIT_OP_LSIGN:
-	[=reg, imm] -> {
-		if($2 < 0)
-		{
-			x86_64_mov_reg_imm_size(inst, $1, -1, 4);
-		}
-		else if($2 > 0)
-		{
-			x86_64_mov_reg_imm_size(inst, $1, 1, 4);
-		}
-		else
-		{
-			x86_64_clear_reg(inst, $1);
-		}
-	}
-	[=+reg, +reg] -> {
-		x86_64_clear_reg(inst, $1);
-		x86_64_test_reg_reg_size(inst, $2, $2, 8);
-		x86_64_set_reg(inst, X86_CC_NZ, $1, 0);
-		x86_64_sar_reg_imm_size(inst, $2, 63, 8);
-		x86_64_or_reg_reg_size(inst, $1, $2, 4);
-	}
-
 JIT_OP_FMAX: commutative
 	[xreg, local] -> {
 		x86_64_maxss_reg_membase(inst, $1, X86_64_RBP, $2);
diff -ruN libjit/jit/jit-rules.c libjit-mikyt/jit/jit-rules.c
--- libjit/jit/jit-rules.c	2008-01-24 21:12:53.000000000 +0100
+++ libjit-mikyt/jit/jit-rules.c	2009-01-19 21:02:44.000000000 +0100
@@ -2,6 +2,7 @@
  * jit-rules.c - Rules that define the characteristics of the back-end.
  *
  * Copyright (C) 2004  Southern Storm Software, Pty Ltd.
+ * Copyright (C) 2008  Michele Tartara <mikyt@users.sourceforge.net>
  *
  * This file is part of the libjit library.
  *
@@ -22,6 +23,7 @@
 
 #include "jit-internal.h"
 #include "jit-rules.h"
+#include <assert.h>
 
 /*
  * The information blocks for all registers in the system.
@@ -48,7 +50,9 @@
 	unsigned int	max_regs;
 	const int	   *word_regs;
 	jit_value_t		word_values[JIT_MAX_WORD_REG_PARAMS];
-
+	#ifdef JIT_BACKEND_ARM
+	char in_word;
+	#endif
 } jit_param_passing_t;
 
 /*
@@ -59,6 +63,29 @@
 #define	STACK_WORDS(size)	\
 		(((size) + (sizeof(void *) - 1)) / sizeof(void *))
 
+#ifdef JIT_BACKEND_ARM
+/**
+ * Returns the byte alignment for a parameter of the given type
+ */
+int get_param_alignment(jit_type_t type)
+{
+	int kind=jit_type_get_kind (type);
+	if(kind==JIT_TYPE_SBYTE || kind==JIT_TYPE_UBYTE || kind==JIT_TYPE_SHORT || kind==JIT_TYPE_USHORT)
+	{
+		/* 
+		 * If the argument is an integral Fundamental Data Type that is
+		 * smaller than a word, then it is zero- or sign-extended to a 
+		 * full word and its size is set to 4 bytes.
+		 */
+		return 4;
+	}
+	else
+	{
+		return jit_type_get_alignment(type);
+	}
+}
+#endif
+
 /*
  * Allocate a word register or incoming frame position to a value.
  */
@@ -129,6 +156,37 @@
 	return 1;
 }
 
+#ifdef JIT_BACKEND_ARM
+int padBetweenWords(jit_function_t func, char *padding, jit_param_passing_t *passing, int param)
+{
+	assert(func);
+	assert(padding);
+	assert(passing);
+	assert(param>=0);
+	
+	/* Add needed padding words at the end of the parameter */
+	int i=padding[param];
+	while(i>0)
+	{
+		if(passing->word_regs[passing->index] != -1)
+		{
+			//Leave an empty register
+			(passing->index)++;
+		}
+		else
+		{
+			//Leave an empty stack position
+			if (!jit_insn_push(func, jit_value_create_nint_constant(func, jit_type_nint, 0)))
+			{
+				return 0;
+			}
+		}
+		i--;
+	}
+	return 1;
+}
+#endif
+
 int _jit_create_entry_insns(jit_function_t func)
 {
 	jit_type_t signature = func->signature;
@@ -141,6 +199,7 @@
 	unsigned int size;
 	jit_param_passing_t passing;
 	jit_nint partial_offset;
+	int has_return_ptr=0;
 
 	/* Reset the local variable frame size for this function */
 	func->builder->frame_size = JIT_INITIAL_FRAME_SIZE;
@@ -187,22 +246,143 @@
 		{
 			return 0;
 		}
+		has_return_ptr=1;
 	}
 
 	/* Determine the maximum number of registers that may be needed
 	   to pass the function's parameters */
 	num_params = jit_type_num_params(signature);
 	passing.max_regs = passing.index;
+	#ifdef JIT_BACKEND_ARM
+	/* Compute correct word alignment */
+	/*
+	 * Init the array containing the number of padding words to be added
+	 * at the end of each parameter
+	 */
+	char padding[num_params];
+	int i;
+	for (i=0; i<num_params; i++)
+	{
+		padding[i]=0;
+	}
+	int byteOffset[num_params+1];
+	for (i=0; i<num_params; i++)
+	{
+		byteOffset[i]=0;
+	}
+	passing.in_word=0;
+	char wordIndex=0;
+	
+	jit_value_t receivedValues[num_params];
+	for (i=0; i<num_params; i++)
+	{
+		receivedValues[i]=0;
+	}
+//	printf("********* Incoming **********\n");
+	int return_ptr_padding=0;
+	#endif
 	for(param = 0; param < num_params; ++param)
 	{
 		value = jit_value_get_param(func, param);
 		if(value)
 		{
+			#ifdef JIT_BACKEND_ARM
+			/* Compute correct reg alignment */
+			type=jit_value_get_type(value);
+			assert(type);
+			
+			int alignment=get_param_alignment(type);
+			assert(alignment > 0);
+			size=jit_type_get_size(type);
+			char word_alignment = (alignment)/sizeof(void *);
+			if (word_alignment==0)
+			{
+				/* Alignment inside a word	*/
+				passing.in_word=1;
+				
+				/* Add needed padding bytes inside the word */
+				while((wordIndex % alignment) != 0)
+				{
+					wordIndex++;
+				}
+				
+				if (wordIndex + size > sizeof(void *))
+				{
+					//Overflow to the next word
+					byteOffset[param]=0;
+					wordIndex = size;
+					(passing.max_regs)++;
+//					printf("Small param of size %d at offset %d in word %d\n", size, byteOffset[param], passing.max_regs);
+					
+				}
+				else
+				{
+					byteOffset[param]=wordIndex;
+					wordIndex += size;
+//					printf("Small param of size %d at offset %d in word %d\n", size, byteOffset[param], passing.max_regs);
+				}
+				//The rest of the function is only for values one or more word long
+				continue;
+			}
+			else
+			{
+				//This value is not smaller than a word
+				byteOffset[param]=-1;
+				
+				if(passing.in_word)
+				{
+					/* The previous param was smaller than a word, so we have to jump to the next word */
+					(passing.max_regs)++;
+					passing.in_word=0;
+					wordIndex=0;
+//					printf("End word with small params\n");
+				}
+				
+				while((passing.max_regs % word_alignment)!=0)
+				{
+					//Add padding reg
+					(passing.max_regs)++;
+					if (!(param==0 && has_return_ptr))
+					{
+						/* There is no problem in using param-1, since the first parameter is always aligned, so we will never arrive here with param=0 */
+						assert(param!=0);
+						(padding[param-1])++;
+					}
+					else
+					{
+						assert(has_return_ptr);
+						assert(param==0);
+						return_ptr_padding++;
+					}
+					
+				}
+			}
+			#endif
 			size = STACK_WORDS(jit_type_get_size(jit_value_get_type(value)));
 			passing.max_regs += size;
 		}
 	}
-
+	#ifdef JIT_BACKEND_ARM
+	/* Padding */
+	if(passing.in_word)
+	{
+		/* The last param was smaller than a word, still we have to count a full word for it */
+		(passing.max_regs)++;
+		passing.in_word=0;
+		wordIndex=0;
+//		printf("End last word with small params\n");
+	}
+	
+	/* Add padding between the return pointer and the first parameter (if needed) */
+	i=return_ptr_padding;
+	while(i>0)
+	{
+		//Leave an empty register
+		(passing.index)++;
+		i--;
+	}
+	#endif
+	
 	/* Allocate the parameter offsets */
 	for(param = 0; param < num_params; ++param)
 	{
@@ -212,13 +392,49 @@
 			continue;
 		}
 		type = jit_type_remove_tags(jit_value_get_type(value));
+		int offset=0;
+		#ifdef JIT_BACKEND_ARM
+		if(byteOffset[param]>=0)
+		{
+			//* We are dealing with a small param
+			if(byteOffset[param]!=0)
+			{
+				/* 
+				 * This is not the first small param of this word,
+				 * so we have already taken its value from the 
+				 * incoming regs or the stack
+				 */
+				assert(param!=0);
+				assert(receivedValues[param-1]);
+				receivedValues[param]=receivedValues[param-1];
+				
+				//Pad if needed
+				if (!padBetweenWords(func, padding, &passing, param))
+				{
+					return 0;
+				}
+				/* 
+				 * Nothing else to be done for this param: it's incoming value
+				 * has already been saved
+				 */
+				continue;
+			}
+			else
+			{
+				/* First small param of a word */
+				receivedValues[param]=jit_value_create(func, jit_type_int);
+				value=receivedValues[param];
+			}
+		}
+		#endif
 		switch(type->kind)
 		{
 			case JIT_TYPE_SBYTE:
 			case JIT_TYPE_UBYTE:
 			{
+//				printf("	receiving byte\n", offset);
 				if(!alloc_incoming_word
-					(func, &passing, value, _jit_nint_lowest_byte()))
+					(func, &passing, value, _jit_nint_lowest_byte(offset)))
 				{
 					return 0;
 				}
@@ -344,7 +560,73 @@
 			}
 			break;
 		}
+		#ifdef JIT_BACKEND_ARM
+		//Pad if needed
+		if (!padBetweenWords(func, padding, &passing, param))
+		{
+			return 0;
+		}
+		#endif
+	}
+	
+	#ifdef JIT_BACKEND_ARM
+	/* Extract small params from the received values */
+	for(param=0; param<num_params; param++)
+	{
+		if(receivedValues[param])
+		{
+			/* We have a param to extract */
+			int offset=byteOffset[param];
+			assert(offset!=-1);
+			
+			jit_value_t destValue = jit_value_get_param(func, param);
+			size=jit_type_get_size(jit_value_get_type(destValue));
+			
+			jit_value_t final_value=0;
+			
+			jit_nint mask;
+			switch(size)
+			{
+				case 1:
+				{
+					mask=0xFF;
+				}
+				break;
+				case 2:
+				{
+					mask=0xFFFF;
+				}
+				break;
+				case 3:
+				{
+					mask=0xFFFFFF;
+				}
+				break;
+				default:
+				{
+					//Problem: should we define some new mask?
+					assert(0);
+				}
+				break;
+			}
+			mask=mask<<(offset*8);
+			jit_value_t mask_value= jit_value_create_nint_constant(func, jit_type_int, (jit_nint) mask);
+			jit_value_t temp= jit_insn_and(func, receivedValues[param], mask_value);
+			
+			if (offset>0)
+			{
+				jit_value_t offset_bits= jit_value_create_nint_constant(func, jit_type_int, (jit_nint) (offset*8));
+				final_value = jit_insn_shr(func, temp, offset_bits);
+			}
+			else
+			{	
+				final_value=temp;
+			}
+			assert(final_value);
+			jit_insn_store(func, destValue, final_value);
+		}
 	}
+	#endif
 	return 1;
 }
 
@@ -413,6 +695,24 @@
 {
 	jit_nint size = (jit_nint)(jit_type_get_size(value->type));
 	passing->offset -= ROUND_STACK(size);
+	#if 0
+	def JIT_BACKEND_ARM
+	// Word alignment
+	while ((passing->offset % type->alignment)!=0)
+	{
+		passing->offset -= sizeof(void *);
+		#ifndef JIT_USE_PARAM_AREA
+		/*
+		 * If we are putting parameters on the stack, then we need to insert
+		 * an empty word to keep the right alignment
+		 */
+		if (!jit_insn_push(func, jit_value_create_nint_constant(func, jit_type_nint, 0)))
+		{
+			return 0;
+		}
+		#endif
+	}
+	#endif
 	if(is_struct_or_union(type) && !is_struct_or_union(value->type))
 	{
 	#ifdef JIT_USE_PARAM_AREA
@@ -469,6 +769,63 @@
 	return 1;
 }
 
+#ifdef JIT_BACKEND_ARM
+/**
+ * Add a parameter with an alignment smaller than a word
+ */
+void addSmallParam(unsigned int param, jit_type_t type, char *smallerThanWord, char *miniParamEndIndex, jit_param_passing_t *passing)
+{
+	assert(type);
+	assert(smallerThanWord);
+	assert(miniParamEndIndex);
+	assert(passing);
+	
+	int size=jit_type_get_size(type);
+	int alignment=get_param_alignment(type);
+	
+	assert(alignment < sizeof(void *));
+	assert(size < sizeof(void *));
+	
+//	printf("addSmallParam: size %d, alignment %d\n", size, alignment);
+	/*Adding a parameter that's aligned to less than a word	*/	
+	smallerThanWord[param]=1;
+	passing->in_word=1;
+	
+	int offset;
+	if (param!=0 && smallerThanWord[param-1])
+	{
+		/* The current word already holds one small param: find out where our space starts */
+		offset=miniParamEndIndex[param-1];
+	}
+	else
+	{
+		offset=0;
+	}
+//	printf("addSmallParam: this param begins at %d\n", offset);
+	/* Calculate the padding for byte alignment	*/
+	while((offset % alignment) != 0)
+	{
+		offset++;
+	}
+//	printf("addSmallParam: after padding, this param begins at %d\n", offset);
+	
+	/* Verify whether there is still space enough for this param in this word */
+	if (offset+size <= sizeof(void *))
+	{ 
+		/*Enough space in the current word to keep this param	*/
+		miniParamEndIndex[param]=offset+size;
+//		printf("addSmallParam: this param ends at %d\n", miniParamEndIndex[param]);
+	}
+	else
+	{
+		/* Not enough space: use next word */
+		need_outgoing_word(passing);
+		miniParamEndIndex[param]=size;
+//		printf("addSmallParam: this param is allocated in the next word and ends at %d\n", miniParamEndIndex[param]);
+	}
+}
+#endif
+
 int _jit_create_call_setup_insns
 	(jit_function_t func, jit_type_t signature,
 	 jit_value_t *args, unsigned int num_args,
@@ -484,7 +841,40 @@
 	jit_value_t return_ptr;
 	jit_value_t partial;
 	unsigned int param;
-
+	#ifdef JIT_BACKEND_ARM
+	//Init the array that will store the count of needed paddings
+	int i;
+	char padding[num_args];
+	//passing.padding= padding;
+	for(i=0; i<num_args; i++)
+	{
+		padding[i]=0;
+	}
+	int lastOnReg=-1; //< The last param in a register
+	//Init the array that will store the count of needed byte paddings internal to a word
+	char smallerThanWord[num_args];
+	for(i=0; i<num_args; i++)
+	{
+		smallerThanWord[i]=0;
+	}
+	char miniParamEndIndex[num_args];
+	for(i=0; i<num_args; i++)
+	{
+		miniParamEndIndex[i]=0;
+	}
+	
+	passing.in_word=0;
+//	printf("------ Outgoing --------\n");
+	jit_value_t words[num_args+1];
+	for(i=0; i<num_args; i++)
+	{
+		words[i]=0;
+	}
+	
+	int return_ptr_padding = 0;
+	#endif
+	
+	
 	/* Initialize the parameter passing information block */
 	passing.offset = 0;
 	passing.index = 0;
@@ -535,6 +925,102 @@
 	{
 		type = jit_type_get_param(signature, param);
 		size = STACK_WORDS(jit_type_get_size(type));
+		#ifdef JIT_BACKEND_ARM
+		/* Count the right word alignment */
+		if(passing.word_regs[passing.index] != -1)
+		{
+			//Align on registers
+			int type_alignment=get_param_alignment(type);
+			assert(type_alignment != 0);
+			
+			int alignment=type_alignment/sizeof(void *);
+			if (alignment == 0)
+			{
+				/* Add a parameter smaller than a word	*/
+				addSmallParam(param, type, smallerThanWord, miniParamEndIndex, &passing);
+				continue;
+			}
+			else
+			{
+				if (passing.in_word)
+				{
+					//The previous word contained small parameters. Get the next one
+					assert(smallerThanWord[param-1]);
+					need_outgoing_word(&passing);
+					passing.in_word=0;
+//					printf("End word with small params (reg)\n");
+				}
+				
+				if(type_alignment!=jit_type_get_alignment(type))
+				{
+					assert(jit_type_get_alignment(type) < 4);
+					/* An integral Fundamental Data Type has to be widened in order to be stored in a full word */
+					int empty_bytes=(type_alignment-jit_type_get_alignment(type));
+					jit_value_t empty_bits= jit_value_create_nint_constant(func, jit_type_int, (jit_nint) (empty_bytes*8));
+					jit_value_t temp= jit_insn_shl(func, args[param], empty_bits);
+					//Shift right: signed or unsigned, depending on the value type
+					args[param]= jit_insn_shr(func, temp, empty_bits);
+				}
+				
+				while((passing.index % (type_alignment/sizeof(void *))) != 0)
+				{
+					//Add a padding word in the next register
+					need_outgoing_word(&passing);
+					if(!(param==0 && return_ptr))
+					{
+						/*Add the padding to the count of the previous parameter, because it's the one that will have to phisically add it. There is no risk of using -1 as an index, since the first parameter is always aligned so we never arrive here with param=0 */
+						assert(param!=0);
+						(padding[param-1])++;
+					}
+					else
+					{
+						/*One word of padding has to be added between the return pointer 
+						 (that is passed in r0) and the first parameter.
+						 Count it!
+						 */
+						assert(return_ptr);
+						assert(param==0);
+						return_ptr_padding++;
+					}
+					//This parameter could be the last in a register
+					lastOnReg=param-1;
+//					printf("Need a padding word (reg)\n");
+				}
+			}
+		}
+		else
+		{
+			//Align on the stack
+			int type_alignment=get_param_alignment(type);
+			assert(type_alignment != 0);
+
+			int alignment=type_alignment/sizeof(void *);
+			if (alignment == 0)
+			{
+				/* Add a parameter smaller than a word	*/
+				addSmallParam(param, type, smallerThanWord, miniParamEndIndex, &passing);
+				continue;
+			}
+			else
+			{
+				if (passing.in_word)
+				{
+					//The previous word contained small parameters. Get the next one
+					assert(smallerThanWord[param-1]);
+					need_outgoing_word(&passing);
+					passing.in_word=0;
+//					printf("End word with small params (stack)\n");
+				}
+				while((passing.offset % (type_alignment/sizeof(void *))) != 0)
+				{
+					//Add a padding word in the next position on the stack
+					need_outgoing_word(&passing);
+					(padding[param-1])++;
+//					printf("Need a padding word (stack)\n");
+				}
+			}
+		}
+		#endif
 		if(size <= 1)
 		{
 			/* Allocate a word register or stack position */
@@ -617,6 +1103,95 @@
 			}
 		}
 	}
+	#ifdef JIT_BACKEND_ARM
+	if (passing.in_word)
+	{
+		//The last word contained small parameters. Get the next one
+		assert(smallerThanWord[param-1]);
+		need_outgoing_word(&passing);
+		passing.in_word=0;
+//		printf("End last word with small params\n");
+	}
+	assert(passing.in_word==0);
+	
+	/* Build the words of small parameters */
+	param=num_args;
+	while(param>0)
+	{
+		param--;
+		if(smallerThanWord[param])
+		{
+			type = jit_type_get_param(signature, param);
+			size=jit_type_get_size(type);
+			int alignment=get_param_alignment(type);
+			
+			assert(size < sizeof(void *));
+			assert(alignment < sizeof(void *));
+			
+			/* Place the param value at the correct offset and put it into the word	*/
+			jit_value_t temp;
+			
+			int offset=miniParamEndIndex[param] - size;
+			assert(offset>=0);
+			
+			if (offset!=0)
+			{
+				jit_value_t offset_bits= jit_value_create_nint_constant(func, jit_type_int, (jit_nint) (offset*8));
+				temp= jit_insn_shl(func, args[param], offset_bits);
+			}
+			else
+			{
+				temp=args[param];
+			}
+			
+			if(passing.in_word)
+			{
+				assert(words[param+1]);
+				
+				words[param]= jit_insn_or(func, words[param+1], temp);
+				words[param+1]=0;
+//				printf("Composing word: new part at offset %d\n", offset);
+			}
+			else
+			{
+				/* First part of the word */
+				words[param]=temp;
+//				printf("Composing word: first part at offset %d\n", offset);
+			}
+			
+			assert(words[param] != 0);
+			
+			if(offset!=0)
+			{
+				//The word is still unfinished.
+				assert(smallerThanWord[param-1]);
+				passing.in_word=1;
+				//Let's go on building it
+				continue;
+			}
+			else
+			{
+				//The word is ready to be written
+				passing.in_word=0;
+				continue;
+			}
+		}
+		else
+		{
+			//The previous word has to be completely built by now
+			assert(passing.in_word==0);
+		}
+	}
+	//The last word has been built
+	assert(passing.in_word==0);
+	/*if (passing.in_word)
+	{
+		//The last word contained smaller-than-word parameters
+		assert(smallerThanWord[0]);
+		passing.in_word=0;
+	}*/
+	#endif
+	
 #ifdef JIT_USE_PARAM_AREA
 	if(passing.offset > func->builder->param_area_size)
 	{
@@ -636,6 +1211,74 @@
 	while(param > 0)
 	{
 		--param;
+		#ifdef JIT_BACKEND_ARM
+		/* Add needed padding words at the end of the parameter */
+		/* Word padding	*/
+		int i=padding[param];
+		while(i>0)
+		{
+			if(passing.word_regs[passing.index] != -1 || param==lastOnReg)
+			{
+//				printf("Add padding register\n");
+				//Leave an empty register
+				(passing.index)--;
+			}
+			else
+			{
+//				printf("Add padding stack position\n");
+				//Leave an empty stack position
+				if (!jit_insn_push(func, jit_value_create_nint_constant(func, jit_type_nint, 0)))
+				{
+					return 0;
+				}
+			}
+			i--;
+		}
+		
+		if(smallerThanWord[param])
+		{
+			if(words[param])
+			{
+				/*
+				 * There is a previously built word that contain one or more parameters
+				 * smaller that a word.
+				 * At least param itself is a parameter smaller than a word
+				 */
+				assert(smallerThanWord[param]);
+				
+				//The word is ready to be written
+				rounded_size=sizeof(void *);
+				if(rounded_size <= passing.offset)
+				{
+					/* This word is on the stack	*/
+					if(!push_param(func, &passing, words[param], jit_type_int))
+					{
+						return 0;
+					}
+//					printf("Write word on stack\n");
+				}
+				else
+				{
+					/* This word is in a register	*/
+					if(!alloc_outgoing_word(func, &passing, words[param]))
+					{
+						return 0;
+					}
+//					printf("Write word in reg\n");
+				}
+				
+				//Nothing more to be done for this param
+				continue;
+			}
+			else
+			{
+				//This param has been merged in a single word with the previous one
+				assert(param!=0);
+				assert(smallerThanWord[param-1]);
+				continue;
+			}
+		}
+		#endif
 		type = jit_type_get_param(signature, param);
 		size = (jit_nint)(jit_type_get_size(type));
 		rounded_size = ROUND_STACK(size);
@@ -679,6 +1322,29 @@
 		{
 			/* This parameter is completely in registers.  If the parameter
 			   occupies multiple registers, then it has already been split */
+			#if 0
+			ifdef JIT_BACKEND_ARM
+			//Word alignment
+			/*while ((passing.index % (type->alignment/sizeof(void *)))!=0)
+			{
+				(passing.index)--;
+			}*/
+			int i=passing.padding[param];
+			while(i>0)
+			{
+					(passing.index)--;
+					i--;
+			}
+			/* 
+			 * The last parameter has always to be in r0, and sometimes
+			 * some padding has to be added for this to happen
+			 */
+			/*if(param==0 && (passing.index - (type->alignment/sizeof(void *)))>0)
+			{
+				//Set the current position so that the last value will be in r0
+				passing.index=(type->alignment/sizeof(void *));
+			}*/
+			#endif
 			while(size > 0)
 			{
 				if(!alloc_outgoing_word(func, &passing, args[param]))
@@ -693,6 +1359,18 @@
 	/* Add the structure return pointer if required */
 	if(return_ptr)
 	{
+		#ifdef JIT_BACKEND_ARM
+		/* Add needed padding words at the end of the parameter */
+		/* Word padding	*/
+		int i=return_ptr_padding;
+		while(i>0)
+		{
+			//Leave an empty register
+			(passing.index)--;
+			i--;
+		}
+		#endif
+		
 		if(passing.index > 0)
 		{
 			if(!alloc_outgoing_word(func, &passing, return_ptr))
@@ -737,8 +1415,9 @@
 
 #endif /* JIT_CDECL_WORD_REG_PARAMS */
 
-int _jit_int_lowest_byte(void)
-{
+int _jit_int_lowest_byte(int offset)
+{	
+	assert(offset<4);
 	union
 	{
 		unsigned char bytes[4];
@@ -747,7 +1426,8 @@
 	int posn;
 	un.value = (jit_int)0x01020304;
 	posn = 0;
-	while(un.bytes[posn] != 0x04)
+	unsigned char look_for=0x04-offset;
+	while(un.bytes[posn] != look_for)
 	{
 		++posn;
 	}
@@ -771,11 +1451,12 @@
 	return posn;
 }
 
-int _jit_nint_lowest_byte(void)
+int _jit_nint_lowest_byte(int offset)
 {
 #ifdef JIT_NATIVE_INT32
-	return _jit_int_lowest_byte();
+	return _jit_int_lowest_byte(offset);
 #else
+	assert(offset < 8);
 	union
 	{
 		unsigned char bytes[8];
@@ -784,7 +1465,8 @@
 	int posn;
 	un.value = (jit_long)0x0102030405060708;
 	posn = 0;
-	while(un.bytes[posn] != 0x08)
+	unsigned char look_for=0x08-offset;
+	while(un.bytes[posn] != look_for)
 	{
 		++posn;
 	}
diff -ruN libjit/jit/jit-rules.h libjit-mikyt/jit/jit-rules.h
--- libjit/jit/jit-rules.h	2008-03-02 18:07:06.000000000 +0100
+++ libjit-mikyt/jit/jit-rules.h	2008-12-17 17:06:34.000000000 +0100
@@ -45,8 +45,11 @@
 #elif defined(__amd64) || defined(__amd64__) || defined(_x86_64) || defined(_x86_64__)
 	#define JIT_BACKEND_X86_64		1
 	#define	JIT_HAVE_BACKEND		1
+#elif defined(__arm) || defined(__arm__)
+	#define	JIT_BACKEND_ARM			1
+	#define	JIT_HAVE_BACKEND		1
 #endif
-/*#define	JIT_BACKEND_ARM		1*/
+
 #if !defined(JIT_HAVE_BACKEND)
 	#define	JIT_BACKEND_INTERP		1
 #endif
@@ -218,7 +221,7 @@
  * Determine the byte number within a "jit_int" where the low
  * order byte can be found.
  */
-int _jit_int_lowest_byte(void);
+int _jit_int_lowest_byte(int offset);
 
 /*
  * Determine the byte number within a "jit_int" where the low
@@ -230,7 +233,7 @@
  * Determine the byte number within a "jit_nint" where the low
  * order byte can be found.
  */
-int _jit_nint_lowest_byte(void);
+int _jit_nint_lowest_byte(int offset);
 
 /*
  * Determine the byte number within a "jit_nint" where the low
diff -ruN libjit/jit/jit-type.c libjit-mikyt/jit/jit-type.c
--- libjit/jit/jit-type.c	2008-01-24 21:12:54.000000000 +0100
+++ libjit-mikyt/jit/jit-type.c	2008-12-17 17:06:34.000000000 +0100
@@ -416,7 +416,12 @@
 	{
 		type->size = maxSize;
 	}
-	type->alignment = maxAlign;
+	#ifdef JIT_BACKEND_ARM
+	if(maxAlign > type->alignment)
+	#endif
+	{
+	  type->alignment = maxAlign;
+	}
 }
 
 /*@
diff -ruN libjit/jitdynamic/.cvsignore libjit-mikyt/jitdynamic/.cvsignore
--- libjit/jitdynamic/.cvsignore	2004-05-11 12:23:14.000000000 +0200
+++ libjit-mikyt/jitdynamic/.cvsignore	1970-01-01 01:00:00.000000000 +0100
@@ -1,6 +0,0 @@
-Makefile
-Makefile.in
-.deps
-.libs
-*.lo
-*.la
diff -ruN libjit/jitplus/.cvsignore libjit-mikyt/jitplus/.cvsignore
--- libjit/jitplus/.cvsignore	2004-05-11 12:23:14.000000000 +0200
+++ libjit-mikyt/jitplus/.cvsignore	1970-01-01 01:00:00.000000000 +0100
@@ -1,6 +0,0 @@
-Makefile
-Makefile.in
-.deps
-.libs
-*.lo
-*.la
diff -ruN libjit/jitruby/README libjit-mikyt/jitruby/README
--- libjit/jitruby/README	2008-12-12 12:30:57.000000000 +0100
+++ libjit-mikyt/jitruby/README	1970-01-01 01:00:00.000000000 +0100
@@ -1,50 +0,0 @@
-Ruby-libjit 0.1.0
-Copyright (C) 2008 Paul Brannan
-
-Ruby-libjit is a wrapper for the libjit library.  It provides basic
-functionality for jit-compiling functions, including integrating those
-functions as callable methods from within Ruby.  Abstractions are also
-provided so that jit code may be written in a ruby-like manner.
-
-Please see the file COPYING for license information.
-
-A simple example:
-
-  :include: sample/simple.rb
-
-Looping structures and other abstractions are provided to make writing
-jit code easier:
-
-  :include: sample/fib.rb
-
-To build ruby-libjit, you will need to install libjit.  If it is not
-available pre-compiled for your platform, you may build the latest
-release like this:
-
-  $ wget ftp://ftp.gnu.org/gnu/dotgnu/pnet/libjit-0.1.0.tar.gz
-  $ tar xvfz libjit-0.1.0.tar.gz
-  $ cd libjit-0.1.0
-  $ ./configure
-  $ make
-  $ sudo make install
-
-Or the latest development version like this:
-
-  $ cvs -z3 -d:pserver:anonymous@cvs.sv.gnu.org:/sources/dotgnu-pnet co libjit
-  $ cd libjit
-  $ ./auto_gen.sh
-  $ ./configure
-  $ make
-  $ sudo make install
-
-To build ruby-libjit, run setup.rb:
-
-  $ ruby setup.rb config
-  $ ruby setup.rb setup
-  $ sudo ruby setup.rb install
-
-For a more complete JIT framework and compiler for Ruby code, please
-take a look at Ludicrous:
-
-  http://rubystuff.org/ludicrous/
-
diff -ruN libjit/jitruby/ext/extconf.rb libjit-mikyt/jitruby/ext/extconf.rb
--- libjit/jitruby/ext/extconf.rb	2008-12-12 12:30:58.000000000 +0100
+++ libjit-mikyt/jitruby/ext/extconf.rb	1970-01-01 01:00:00.000000000 +0100
@@ -1,108 +0,0 @@
-require 'mkmf'
-require 'rbconfig'
-
-if Config::CONFIG['host_os'] =~ /cygwin|win32|windows/ then
-  need_windows_h = [ 'windows.h' ]
-  $defs << ' -DNEED_WINDOWS_H'
-else
-  need_windows_h = [ ]
-end
-
-if not have_library('jit', 'jit_init', need_windows_h + ["jit/jit.h"]) then
-  $stderr.puts "libjit not found"
-  exit 1
-end
-
-if not have_macro("SIZEOF_VALUE", "ruby.h") then
-  check_sizeof("VALUE", "ruby.h")
-end
-
-if not have_macro("SIZEOF_ID", "ruby.h") then
-  check_sizeof("ID", "ruby.h")
-end
-
-if have_macro("_GNU_SOURCE", "ruby.h") then
-  $defs.push("-DRUBY_DEFINES_GNU_SOURCE")
-end
-
-have_func("rb_class_boot", "ruby.h")
-have_func("rb_errinfo", "ruby.h")
-have_func('fmemopen')
-have_func("rb_ensure", "ruby.h")
-
-if have_header('ruby/node.h') then
-  # ruby.h defines HAVE_RUBY_NODE_H, even though it is not there
-  $defs.push("-DREALLY_HAVE_RUBY_NODE_H")
-elsif have_header('node.h') then
-  # okay
-else
-  $defs.push("-DNEED_MINIMAL_NODE")
-end
-
-have_header('env.h')
-
-checking_for("whether VALUE is a pointer") do
-  if not try_link(<<"SRC")
-#include <ruby.h>
-int main()
-{
-  VALUE v;
-  v /= 5;
-}
-SRC
-  then
-    $defs.push("-DVALUE_IS_PTR");
-  end
-end
-
-if defined?(RUBY_ENGINE) and RUBY_ENGINE == 'rbx' then
-  $defs.push("-DHAVE_RUBINIUS")
-end
-
-rb_files = Dir['*.rb']
-rpp_files = Dir['*.rpp']
-generated_files = rpp_files.map { |f| f.sub(/\.rpp$/, '') }
-
-srcs = Dir['*.c']
-generated_files.each do |f|
-  if f =~ /\.c$/ then
-    srcs << f
-  end
-end
-srcs.uniq!
-$objs = srcs.map { |f| f.sub(/\.c$/, ".#{$OBJEXT}") }
-
-if Config::CONFIG['CC'] == 'gcc' then
-  # $CFLAGS << ' -Wall -g -pedantic -Wno-long-long'
-  $CFLAGS << ' -Wall -g'
-end
-
-create_makefile("jit")
-
-append_to_makefile = ''
-
-rpp_files.each do |rpp_file|
-dest_file = rpp_file.sub(/\.rpp$/, '')
-append_to_makefile << <<END
-#{dest_file}: #{rpp_file} #{rb_files.join(' ')}
-	$(RUBY) rubypp.rb #{rpp_file} #{dest_file}
-END
-end
-
-generated_headers = generated_files.select { |x| x =~ /\.h$/ || x =~ /\.inc$/ }
-append_to_makefile << <<END
-$(OBJS): #{generated_headers.join(' ')}
-clean: clean_generated_files
-clean_generated_files:
-	@$(RM) #{generated_files.join(' ')}
-
-install: $(includedir)/rubyjit.h
-
-$(includedir)/rubyjit.h: rubyjit.h
-	$(INSTALL_PROG) rubyjit.h $(includedir)
-END
-
-File.open('Makefile', 'a') do |makefile|
-  makefile.puts(append_to_makefile)
-end
-
diff -ruN libjit/jitruby/ext/insns.inc.rpp libjit-mikyt/jitruby/ext/insns.inc.rpp
--- libjit/jitruby/ext/insns.inc.rpp	2008-12-12 12:31:02.000000000 +0100
+++ libjit-mikyt/jitruby/ext/insns.inc.rpp	1970-01-01 01:00:00.000000000 +0100
@@ -1,203 +0,0 @@
-#ruby <<END
-
-V = :value
-L = :label_ptr
-B = :label
-N = :nint
-T = :type_t
-_ = :void
-
-def incoming_args(arg_types)
-  num_args = arg_types.length
-  return (1..num_args).map { |n| ", VALUE arg#{n}" }.join
-end
-
-def declaration(name, type)
-  case type
-  when V then return "jit_value_t #{name};"
-  when L then return "jit_label_t * #{name};"
-  when B then return "jit_label_t * #{name};"
-  when N then return "jit_nint #{name};"
-  when T then return "jit_type_t #{name};"
-  when :void then nil
-  else raise "Invalid type #{type}"
-  end
-end
-
-def write_declaration(name, type, indent)
-  d = declaration(name, type)
-  if d then
-    puts "#{' '*indent}#{d}"
-  end
-end
-
-def ruby_type(type)
-  case type
-  when V then return "rb_cValue"
-  when L then return "rb_cLabel"
-  when B then return "rb_cLabel"
-  when N then return "rb_cFixnum"
-  when T then return "rb_cType"
-  else raise "Invalid type #{type}"
-  end
-end
-
-def jit_type(type)
-  case type
-  when V then return "struct _jit_value"
-  when L then return "jit_label_t"
-  when B then return "jit_label_t"
-  when T then return "struct _jit_type"
-  else raise "Invalid type #{type}"
-  end
-end
-
-def get_value(type, arg, j_arg)
-  case type
-  when N then
-    return "#{j_arg} = NUM2INT(#{arg})"
-  else
-    return "Data_Get_Struct(#{arg}, #{jit_type(type)}, #{j_arg})"
-  end
-end
-
-def jit_insn_args(arg_types)
-  num_args = arg_types.length
-  arg_list = (1..num_args).map do |n|
-    case arg_types[n-1]
-    when B then ", *j_arg#{n}"
-    else ", j_arg#{n}"
-    end
-  end
-  return arg_list.join
-end
-
-def write_insn(name, retval_type, arg_types)
-  num_args = arg_types.length
-  an = [?a, ?e, ?i, ?o, ?u].include?(name[0])
-  puts "/* Generate a#{an} #{name} instruction (see the libjit documentation for more"
-  puts " * details. */"
-  puts "static VALUE function_insn_#{name}(VALUE self#{incoming_args(arg_types)})"
-  puts "{"
-  puts "  jit_function_t function;"
-  write_declaration('retval', retval_type, 2)
-  arg_types.each_with_index do |type, n|
-    write_declaration("j_arg#{n+1}", type, 2)
-  end
-  puts
-  arg_types.each_with_index do |type, n|
-    puts "  check_type(\"arg#{n+1}\", #{ruby_type(type)}, arg#{n+1});"
-  end
-  puts
-  puts "  Data_Get_Struct(self, struct _jit_function, function);"
-  arg_types.each_with_index do |type, n|
-    puts "  " + get_value(type, "arg#{n+1}", "j_arg#{n+1}") + ";"
-  end
-  puts
-  if retval_type == V then
-    puts "  retval = jit_insn_#{name}(function#{jit_insn_args(arg_types)});"
-    puts "  return Data_Wrap_Struct(rb_cValue, 0, 0, retval);"
-  elsif retval_type == :void then
-    puts "  jit_insn_#{name}(function#{jit_insn_args(arg_types)});"
-    puts "  return Qnil;"
-  else
-    raise "Invalid retval type #{retval_type}"
-  end
-  puts "}"
-end
-
-insns = [
-  [ 'load'                 , V, V       ] ,
-  [ 'store'                , _, V, V    ] ,
-  [ 'dup'                  , V, V       ] ,
-  [ 'add'                  , V, V, V    ] , 
-  [ 'add_ovf'              , V, V, V    ] , 
-  [ 'sub'                  , V, V, V    ] , 
-  [ 'sub_ovf'              , V, V, V    ] , 
-  [ 'mul'                  , V, V, V    ] , 
-  [ 'mul_ovf'              , V, V, V    ] , 
-  [ 'div'                  , V, V, V    ] , 
-  [ 'rem'                  , V, V, V    ] , 
-  [ 'rem_ieee'             , V, V, V    ] , 
-  [ 'neg'                  , V, V       ] , 
-  [ 'and'                  , V, V, V    ] , 
-  [ 'or'                   , V, V, V    ] , 
-  [ 'xor'                  , V, V, V    ] , 
-  [ 'not'                  , V, V       ] , 
-  [ 'shl'                  , V, V, V    ] , 
-  [ 'shr'                  , V, V, V    ] , 
-  [ 'ushr'                 , V, V, V    ] , 
-  [ 'sshr'                 , V, V, V    ] , 
-  [ 'eq'                   , V, V, V    ] , 
-  [ 'ne'                   , V, V, V    ] , 
-  [ 'lt'                   , V, V, V    ] , 
-  [ 'le'                   , V, V, V    ] , 
-  [ 'gt'                   , V, V, V    ] , 
-  [ 'ge'                   , V, V, V    ] , 
-  [ 'cmpl'                 , V, V, V    ] , 
-  [ 'cmpg'                 , V, V, V    ] , 
-  [ 'to_bool'              , V, V       ] , 
-  [ 'to_not_bool'          , V, V       ] , 
-  [ 'acos'                 , V, V       ] , 
-  [ 'asin'                 , V, V       ] , 
-  [ 'atan'                 , V, V       ] , 
-  [ 'atan2'                , V, V, V    ] ,
-  [ 'ceil'                 , V, V       ] , 
-  [ 'cos'                  , V, V       ] , 
-  [ 'cosh'                 , V, V       ] , 
-  [ 'exp'                  , V, V       ] , 
-  [ 'floor'                , V, V       ] , 
-  [ 'log'                  , V, V       ] , 
-  [ 'log10'                , V, V       ] , 
-  [ 'pow'                  , V, V, V    ] ,
-  [ 'rint'                 , V, V       ] , 
-  [ 'round'                , V, V       ] , 
-  [ 'sin'                  , V, V       ] , 
-  [ 'sinh'                 , V, V       ] , 
-  [ 'sqrt'                 , V, V       ] , 
-  [ 'tan'                  , V, V       ] , 
-  [ 'tanh'                 , V, V       ] , 
-  [ 'is_nan'               , V, V       ] , 
-  [ 'is_finite'            , V, V       ] , 
-  [ 'is_inf'               , V, V       ] , 
-  [ 'abs'                  , V, V       ] , 
-  [ 'min'                  , V, V, V    ] , 
-  [ 'max'                  , V, V, V    ] , 
-  [ 'sign'                 , V, V       ] , 
-  [ 'branch'               , _, L       ] ,
-  [ 'branch_if'            , _, V, L    ] ,
-  [ 'branch_if_not'        , _, V, L    ] ,
-  [ 'label'                , _, L       ] ,
-  [ 'address_of'           , V, V       ] ,
-  [ 'address_of_label'     , V, L       ] ,
-  [ 'store_relative'       , _, V, N, V ] ,
-  [ 'load_relative'        , V, V, N, T ] ,
-  [ 'add_relative'         , V ,V, N    ] ,
-  [ 'memcpy'               , _, V, V, V ] ,
-  [ 'memmove'              , _, V, V, V ] ,
-  [ 'memset'               , _, V, V, V ] ,
-  [ 'alloca'               , V, V       ] ,
-  [ 'load_elem'            , V, V, V, T ] ,
-  [ 'store_elem'           , _, V, V, V ] ,
-  [ 'move_blocks_to_end'   , _, B, B    ] ,
-  [ 'move_blocks_to_start' , _, B, B    ] ,
-  [ 'push'                 , _, V       ] ,
-  [ 'push_ptr'             , _, V, T    ] ,
-  [ 'pop_stack'            , _, N       ] ,
-]
-
-insns.each do |name, retval_type, *arg_types|
-  write_insn(name, retval_type, arg_types)
-  puts
-end
-
-puts "static void init_insns()"
-puts "{"
-insns.each do |name, retval_type, *arg_types|
-  num_args = arg_types.length
-  puts "  rb_define_method(rb_cFunction, \"insn_#{name}\", function_insn_#{name}, #{num_args});"
-end
-puts "}"
-
-END
-
diff -ruN libjit/jitruby/ext/jit.c libjit-mikyt/jitruby/ext/jit.c
--- libjit/jitruby/ext/jit.c	2008-12-12 12:31:03.000000000 +0100
+++ libjit-mikyt/jitruby/ext/jit.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,1552 +0,0 @@
-#ifndef RUBY_DEFINES_GNU_SOURCE
-#define _GNU_SOURCE
-#endif
-
-#ifdef NEED_WINDOWS_H
-#include <windows.h>
-#endif
-
-#include <ruby.h>
-
-#include <stdio.h>
-
-#include <jit/jit.h>
-#include <jit/jit-dump.h>
-
-#include "rubyjit.h"
-#include "method_data.h"
-
-#ifdef NEED_MINIMAL_NODE
-#include "minimal_node.h"
-#endif
-
-#ifndef RARRAY_LEN
-#define RARRAY_LEN(a) RARRAY(a)->len
-#endif
-
-#ifndef RARRAY_PTR
-#define RARRAY_PTR(a) RARRAY(a)->ptr
-#endif
-
-static VALUE rb_mJIT;
-static VALUE rb_cContext;
-static VALUE rb_cFunction;
-static VALUE rb_cType;
-static VALUE rb_mABI;
-static VALUE rb_cValue;
-static VALUE rb_cLabel;
-static VALUE rb_mCall;
-static VALUE rb_cClosure;
-
-jit_type_t jit_type_VALUE;
-jit_type_t jit_type_ID;
-jit_type_t jit_type_Function_Ptr;
-
-static jit_type_t ruby_vararg_signature;
-
-typedef void (*Void_Function_Ptr)();
-
-struct Closure
-{
-  VALUE function;
-  Void_Function_Ptr function_ptr;
-};
-
-#ifdef VALUE_IS_PTR
-/* Rubinius */
-typedef jit_ptr jit_VALUE;
-#define jit_underlying_type_VALUE jit_type_void_ptr
-#define SET_CONSTANT_VALUE(c, v) (c.un.ptr_value = v)
-
-#elif SIZEOF_VALUE == 4
-/* 32-bit */
-typedef jit_uint jit_VALUE;
-#define jit_underlying_type_VALUE jit_type_uint
-#define SET_CONSTANT_VALUE(c, v) (c.un.uint_value = v)
-
-#elif SIZEOF_VALUE == 8
-/* 64-bit */
-typedef jit_ulong jit_VALUE;
-#define jit_underlying_type_VALUE jit_type_ulong
-#define SET_CONSTANT_VALUE(c, v) (c.un.ulong_value = v)
-
-#else
-#error "Unsupported size for VALUE"
-#endif
-
-#if SIZEOF_ID == 4
-/* 32-bit */
-typedef jit_uint jit_ID;
-#define jit_underlying_type_ID jit_type_uint
-#define SET_CONSTANT_ID(c, v) (c.un.uint_value = v)
-#elif SIZEOF_ID == 8
-/* 64-bit */
-typedef jit_ulong jit_ID;
-#define jit_underlying_type_ID jit_type_ulong
-#define SET_CONSTANT_ID(c, v) (c.un.ulong_value = v)
-#else
-#error "Unsupported size for ID"
-#endif
-
-typedef jit_ptr jit_Function_Ptr;
-#define jit_underlying_type_void_ptr jit_type_void_ptr
-#define SET_FUNCTION_POINTER_VALUE(c, v) (c.un.ptr_value = v)
-
-#ifdef HAVE_RB_ERRINFO
-#define ruby_errinfo rb_errinfo()
-#endif
-
-/* ---------------------------------------------------------------------------
- * Utility functions
- * ---------------------------------------------------------------------------
- */
-
-static VALUE lookup_const(VALUE module, VALUE symbol)
-{
-  if(SYMBOL_P(symbol))
-  {
-    return rb_const_get(module, SYM2ID(symbol));
-  }
-  else
-  {
-    return symbol;
-  }
-}
-
-static void check_type(char const * param_name, VALUE expected_klass, VALUE val)
-{
-  if(!rb_obj_is_kind_of(val, expected_klass))
-  {
-    rb_raise(
-        rb_eTypeError,
-        "Wrong type for %s; expected %s but got %s",
-        param_name,
-        rb_class2name(expected_klass),
-        rb_class2name(CLASS_OF(val)));
-  }
-}
-
-void raise_memory_error_if_zero(void * v)
-{
-  if(!v)
-  {
-    rb_raise(rb_eNoMemError, "Out of memory");
-  }
-}
-
-/* ---------------------------------------------------------------------------
- * Context
- * ---------------------------------------------------------------------------
- */
-
-static void context_mark(jit_context_t context)
-{
-  VALUE functions = (VALUE)jit_context_get_meta(context, RJT_FUNCTIONS);
-  rb_gc_mark(functions);
-}
-
-/* 
- * call-seq:
- *   context = Context.new
- *
- * Create a new context.
- */
-static VALUE context_s_new(VALUE klass)
-{
-  jit_context_t context = jit_context_create();
-  jit_context_set_meta(context, RJT_FUNCTIONS, (void*)rb_ary_new(), 0);
-  return Data_Wrap_Struct(rb_cContext, context_mark, jit_context_destroy, context);
-}
-
-/* 
- * call-seq:
- *   context.build { ... }
- *
- * Acquire a lock on the context so it can be used to build a function.
- */
-static VALUE context_build(VALUE self)
-{
-  jit_context_t context;
-  Data_Get_Struct(self, struct _jit_context, context);
-  jit_context_build_start(context);
-#ifdef HAVE_RB_ENSURE
-  return rb_ensure(
-      rb_yield,
-      self,
-      RUBY_METHOD_FUNC(jit_context_build_end),
-      (VALUE)context);
-#else
-  /* Rubinius does not yet have rb_ensure */
-  rb_yield(self);
-  jit_context_build_end(context);
-#endif
-}
-
-/*
- * call-seq:
- *   Context.build { |context| ... }
- *
- * Create a context and acquire a lock on it, then yield the context to
- * the block.
- */
-static VALUE context_s_build(VALUE klass)
-{
-  return context_build(context_s_new(klass));
-}
-
-/* ---------------------------------------------------------------------------
- * Closure
- * ---------------------------------------------------------------------------
- */
-
-static void mark_closure(struct Closure * closure)
-{
-  rb_gc_mark(closure->function);
-}
-
-VALUE closure_to_int(VALUE self)
-{
-  struct Closure * closure;
-  Data_Get_Struct(self, struct Closure, closure);
-  VALUE v = ULONG2NUM((unsigned long)closure->function_ptr);
-  return v;
-}
-
-VALUE closure_to_s(VALUE self)
-{
-  struct Closure * closure;
-  VALUE args[4];
-  Data_Get_Struct(self, struct Closure, closure);
-  args[0] = rb_str_new2("#<JIT::Closure:0x%x function=%s function_ptr=0x%x>");
-  args[1] = ULONG2NUM((unsigned long)self);
-  args[2] = rb_any_to_s(closure->function);
-  args[3] = ULONG2NUM((unsigned long)closure->function_ptr);
-  return rb_f_sprintf(sizeof(args)/sizeof(args[0]), args);
-}
-
-VALUE closure_inspect(VALUE self)
-{
-  return closure_to_s(self);
-}
-
-/* ---------------------------------------------------------------------------
- * Function
- * ---------------------------------------------------------------------------
- */
-
-static void mark_function(jit_function_t function)
-{
-  rb_gc_mark((VALUE)jit_function_get_meta(function, RJT_VALUE_OBJECTS));
-  rb_gc_mark((VALUE)jit_function_get_meta(function, RJT_CONTEXT));
-}
-
-static VALUE create_function(int argc, VALUE * argv, VALUE klass)
-{
-  VALUE context_v;
-  VALUE signature_v;
-  VALUE parent_function_v;
-
-  jit_function_t function;
-  jit_function_t parent_function;
-  jit_context_t context;
-  jit_type_t signature;
-  jit_type_t untagged_signature;
-
-  VALUE function_v;
-  VALUE functions;
-
-  int signature_tag;
-
-  rb_scan_args(argc, argv, "21", &context_v, &signature_v, &parent_function_v);
-
-  Data_Get_Struct(context_v, struct _jit_context, context);
-  Data_Get_Struct(signature_v, struct _jit_type, signature);
-
-  signature_tag = jit_type_get_kind(signature);
-
-  /* If this signature was tagged, get the untagged type */
-  if((untagged_signature = jit_type_get_tagged_type(signature)))
-  {
-    signature = untagged_signature;
-  }
-
-  if(RTEST(parent_function_v))
-  {
-    /* If this function has a parent, then it is a nested function */
-    Data_Get_Struct(parent_function_v, struct _jit_function, parent_function);
-    function = jit_function_create_nested(context, signature, parent_function);
-  }
-  else
-  {
-    /* Otherwise, it's a standalone function */
-    function = jit_function_create(context, signature);
-  }
-
-  /* Make sure the function is around as long as the context is */
-  if(!jit_function_set_meta(function, RJT_VALUE_OBJECTS, (void *)rb_ary_new(), 0, 0))
-  {
-    rb_raise(rb_eNoMemError, "Out of memory");
-  }
-
-  /* Remember the signature's tag for later */
-  if(!jit_function_set_meta(function, RJT_TAG_FOR_SIGNATURE, (void *)signature_tag, 0, 0))
-  {
-    rb_raise(rb_eNoMemError, "Out of memory");
-  }
-
-  /* And remember the function's context for later */
-  if(!jit_function_set_meta(function, RJT_CONTEXT, (void *)context_v, 0, 0))
-  {
-    rb_raise(rb_eNoMemError, "Out of memory");
-  }
-
-  function_v = Data_Wrap_Struct(rb_cFunction, mark_function, 0, function);
-
-  /* Add this function to the context's list of functions */
-  functions = (VALUE)jit_context_get_meta(context, RJT_FUNCTIONS);
-  rb_ary_push(functions, function_v);
-
-  return function_v;
-}
-
-/*
- * call-seq:
- *   function.compile()
- *
- * Begin compiling a function.
- */
-static VALUE function_compile(VALUE self)
-{
-  jit_function_t function;
-  Data_Get_Struct(self, struct _jit_function, function);
-  if(!jit_function_compile(function))
-  {
-    rb_raise(rb_eRuntimeError, "Unable to compile function");
-  }
-  return self;
-}
-
-/*
- * call-seq:
- *   function = Function.new(context, signature, [parent])
- *
- * Create a new function.
- */
-static VALUE function_s_new(int argc, VALUE * argv, VALUE klass)
-{
-  if(rb_block_given_p())
-  {
-    rb_raise(rb_eArgError, "Function.new does not take a block");
-  }
-
-  return create_function(argc, argv, klass);
-}
-
-static VALUE function_abandon_if_exception(VALUE function_v)
-{
-  if(ruby_errinfo)
-  {
-    jit_function_t function;
-    Data_Get_Struct(function_v, struct _jit_function, function);
-    jit_function_abandon(function);
-  }
-  return Qnil;
-}
-
-/*
- * call-seq:
- *   function = Function.new(context, signature, [parent]) { |function| ... }
- *
- * Create a new function, begin compiling it, and pass the function to
- * the block.
- */
-static VALUE function_s_compile(int argc, VALUE * argv, VALUE klass)
-{
-  VALUE function = create_function(argc, argv, klass);
-  rb_yield(function);
-  function_compile(function);
-#ifdef HAVE_RB_ENSURE
-  rb_ensure(
-      function_compile,
-      function,
-      function_abandon_if_exception,
-      function);
-#else
-  /* Rubinius does not yet have rb_ensure */
-  function_compile(function);
-  function_abandon_if_exception(function);
-#endif
-  return function;
-}
-
-/*
- * Get the value that corresponds to a specified function parameter.
- *
- * call-seq:
- *   value = function.get_param(index)
- */
-static VALUE function_get_param(VALUE self, VALUE idx)
-{
-  jit_function_t function;
-  jit_value_t value;
-  Data_Get_Struct(self, struct _jit_function, function);
-  value = jit_value_get_param(function, NUM2INT(idx));
-  raise_memory_error_if_zero(value);
-  return Data_Wrap_Struct(rb_cValue, 0, 0, value);
-}
-
-#include "insns.inc"
-
-static VALUE function_value_klass(VALUE self, VALUE type_v, VALUE klass)
-{
-  jit_function_t function;
-  jit_type_t type;
-  jit_value_t value;
-
-  Data_Get_Struct(self, struct _jit_function, function);
-
-  type_v = lookup_const(rb_cType, type_v);
-  check_type("type", rb_cType, type_v);
-  Data_Get_Struct(type_v, struct _jit_type, type);
-
-  /* TODO: When we wrap a value, we should inject a reference to the
-   * function in the object, so the function stays around as long as the
-   * value does */
-  value = jit_value_create(function, type);
-  return Data_Wrap_Struct(klass, 0, 0, value);
-}
-
-static VALUE coerce_to_jit(VALUE function, VALUE type_v, VALUE value_v);
-
-/*
- * call-seq:
- *   value = function.value(type)
- *   value = function.value(type, initial_value)
- *
- * Create a value (placeholder/variable) with the given type.
- */
-static VALUE function_value(int argc, VALUE * argv, VALUE self)
-{
-  VALUE type_v = Qnil;
-  VALUE initial_value_v = Qnil;
-
-  VALUE new_value = Qnil;
-
-  rb_scan_args(argc, argv, "11", &type_v, &initial_value_v);
-
-  new_value = function_value_klass(self, type_v, rb_cValue);
-
-  if(argc > 1)
-  {
-    function_insn_store(
-        self,
-        new_value,
-        coerce_to_jit(self, type_v, initial_value_v));
-  }
-
-  return new_value;
-}
-
-static jit_value_t create_const(jit_function_t function, jit_type_t type, VALUE constant)
-{
-  jit_constant_t c;
-  int kind = jit_type_get_kind(type);
-
-  switch(kind)
-  {
-    case JIT_TYPE_INT:
-    {
-      c.type = type;
-      c.un.int_value = NUM2INT(constant);
-      break;
-    }
-
-    case JIT_TYPE_UINT:
-    {
-      c.type = type;
-      c.un.int_value = NUM2UINT(constant);
-      break;
-    }
-
-    case JIT_TYPE_FLOAT32:
-    {
-      c.type = type;
-      c.un.float32_value = NUM2DBL(constant);
-      break;
-    }
-
-    case JIT_TYPE_FLOAT64:
-    {
-      c.type = type;
-      c.un.float64_value = NUM2DBL(constant);
-      break;
-    }
-
-    case JIT_TYPE_PTR:
-    {
-      c.type = type;
-      c.un.ptr_value = (void *)NUM2ULONG(constant);
-      break;
-    }
-
-    case JIT_TYPE_FIRST_TAGGED + RJT_OBJECT:
-    {
-      VALUE value_objects = (VALUE)jit_function_get_meta(function, RJT_VALUE_OBJECTS);
-
-      c.type = type;
-      SET_CONSTANT_VALUE(c, constant);
-
-      /* Make sure the object gets marked as long as the function is
-       * around */
-      rb_ary_push(value_objects, constant);
-      break;
-    }
-
-    case JIT_TYPE_FIRST_TAGGED + RJT_ID:
-    {
-      c.type = type;
-      SET_CONSTANT_ID(c, SYM2ID(constant));
-      break;
-    }
-
-    case JIT_TYPE_FIRST_TAGGED + RJT_FUNCTION_PTR:
-    {
-      c.type = type;
-      SET_FUNCTION_POINTER_VALUE(
-          c,
-          (Void_Function_Ptr)NUM2ULONG(rb_to_int(constant)));
-      break;
-    }
-
-    default:
-      rb_raise(rb_eTypeError, "Unsupported type");
-  }
-
-  return jit_value_create_constant(function, &c);
-}
-
-/*
- * call-seq:
- *   value = function.const(type, constant_value)
- *
- * Create a constant value with the given type.
- */
-static VALUE function_const(VALUE self, VALUE type_v, VALUE constant)
-{
-  jit_function_t function;
-  jit_type_t type;
-  jit_value_t value;
-
-  Data_Get_Struct(self, struct _jit_function, function);
-
-  type_v = lookup_const(rb_cType, type_v);
-  check_type("type", rb_cType, type_v);
-  Data_Get_Struct(type_v, struct _jit_type, type);
-
-  value = create_const(function, type, constant);
-  return Data_Wrap_Struct(rb_cValue, 0, 0, value);
-}
-
-static VALUE coerce_to_jit(VALUE function, VALUE type_v, VALUE value_v)
-{
-  if(rb_obj_is_kind_of(value_v, rb_cValue))
-  {
-    return value_v;
-  }
-  else
-  {
-    return function_const(function, type_v, value_v);
-  }
-}
-
-static void convert_call_args(jit_function_t function, jit_value_t * args, VALUE args_v, jit_type_t signature)
-{
-  int j;
-
-  for(j = 0; j < RARRAY_LEN(args_v); ++j)
-  {
-    VALUE value = RARRAY_PTR(args_v)[j];
-    jit_value_t arg;
-
-    jit_type_t type = jit_type_get_param(signature, j);
-    if(!type)
-    {
-      rb_raise(rb_eArgError, "Type missing for param %d", j);
-    }
-
-    if(rb_obj_is_kind_of(value, rb_cValue))
-    {
-      Data_Get_Struct(value, struct _jit_value, arg);
-      if(!arg)
-      {
-        rb_raise(rb_eArgError, "Argument %d is invalid", j);
-      }
-      args[j] = arg;
-    }
-    else
-    {
-      args[j] = create_const(function, type, value);
-    }
-  }
-}
-
-/* 
- * call-seq:
- *   value = function.call(name, called_function, flags, [arg1 [, ... ]])
- *
- * Generate an instruction to call the specified function.
- */
-static VALUE function_insn_call(int argc, VALUE * argv, VALUE self)
-{
-  jit_function_t function;
-
-  VALUE name_v;
-  VALUE called_function_v;
-  VALUE args_v;
-  VALUE flags_v = Qnil;
-
-  char const * name;
-  jit_function_t called_function;
-  jit_type_t signature;
-  jit_value_t * args;
-  jit_value_t retval;
-  int flags;
-  size_t num_args;
-
-  rb_scan_args(argc, argv, "3*", &name_v, &called_function_v, &flags_v, &args_v);
-
-  Data_Get_Struct(self, struct _jit_function, function);
-
-  name = STR2CSTR(name_v);
-
-  check_type("called function", rb_cFunction, called_function_v);
-  Data_Get_Struct(called_function_v, struct _jit_function, called_function);
-
-  num_args = RARRAY_LEN(args_v);
-  args = ALLOCA_N(jit_value_t, num_args);
-
-  signature = jit_function_get_signature(function);
-  convert_call_args(function, args, args_v, signature);
-
-  flags = NUM2INT(flags_v);
-
-  retval = jit_insn_call(
-      function, name, called_function, 0, args, num_args, flags);
-  return Data_Wrap_Struct(rb_cValue, 0, 0, retval);
-}
-
-/*
- * call-seq:
- *   value = function.call(name, flags, [arg1 [, ... ]])
- *
- * Generate an instruction to call a native function.
- */
-static VALUE function_insn_call_native(int argc, VALUE * argv, VALUE self)
-{
-  jit_function_t function;
-
-  VALUE name_v;
-  VALUE args_v;
-  VALUE function_ptr_v;
-  VALUE signature_v;
-  VALUE flags_v;
-
-  char const * name;
-  jit_value_t * args;
-  jit_value_t retval;
-  void * function_ptr;
-  jit_type_t signature;
-  int flags;
-  size_t num_args;
-
-  rb_scan_args(argc, argv, "4*", &name_v, &function_ptr_v, &signature_v, &flags_v, &args_v);
-
-  Data_Get_Struct(self, struct _jit_function, function);
-  
-  if(SYMBOL_P(name_v))
-  {
-    name = rb_id2name(SYM2ID(name_v));
-  }
-  else
-  {
-    name = StringValuePtr(name_v);
-  }
-
-  function_ptr = (void *)NUM2ULONG(function_ptr_v);
-
-  Data_Get_Struct(signature_v, struct _jit_type, signature);
-
-  num_args = RARRAY_LEN(args_v);
-  args = ALLOCA_N(jit_value_t, num_args);
-
-  if(num_args != jit_type_num_params(signature))
-  {
-    rb_raise(
-        rb_eArgError,
-        "Wrong number of arguments passed for %s (expecting %d but got %d)", 
-        name,
-        jit_type_num_params(signature),
-        num_args);
-  }
-
-  convert_call_args(function, args, args_v, signature);
-
-  flags = NUM2INT(flags_v);
-
-  retval = jit_insn_call_native(
-      function, name, function_ptr, signature, args, num_args, flags);
-  return Data_Wrap_Struct(rb_cValue, 0, 0, retval);
-}
-
-/*
- * call-seq:
- *   function.insn_return()
- *   function.insn_return(value)
- *
- * Emit an instruction to return from the function.  If value is
- * specified, return the given value, otherwise return void.
- */
-static VALUE function_insn_return(int argc, VALUE * argv, VALUE self)
-{
-  jit_function_t function;
-  jit_value_t value = 0;
-  VALUE value_v = Qnil;
-
-  rb_scan_args(argc, argv, "01", &value_v);
-
-  if(value_v != Qnil)
-  {
-    Data_Get_Struct(value_v, struct _jit_value, value);
-  }
-
-  Data_Get_Struct(self, struct _jit_function, function);
-  jit_insn_return(function, value);
-
-  return Qnil;
-}
-
-/*
- * call-seq:
- *   function.apply(arg1 [, arg2 [, ... ]])
- *
- * Call a compiled function.  Each argument passed in will be converted
- * to the type specified by the function's signature.
- *
- * If the function's signature is Type::RUBY_VARARG_SIGNATURE, then the
- * arguments will be passed in with the first parameter the count of the
- * number of arguments, the second parameter a pointer to an array
- * containing the second through the last argument, and the third
- * parameter the explicit self (that is, the first argument passed to
- * apply).
- */
-static VALUE function_apply(int argc, VALUE * argv, VALUE self)
-{
-  jit_function_t function;
-  jit_type_t signature;
-  int j, n;
-  void * * args;
-  char * arg_data;
-  int signature_tag;
-
-  Data_Get_Struct(self, struct _jit_function, function);
-  signature = jit_function_get_signature(function);
-  n = jit_type_num_params(signature);
-
-  /* void pointers to each of the arguments */
-  args = ALLOCA_N(void *, n);
-
-  /* the actual data */
-  /* TODO: we need to allocate the proper size (but 8 bytes per arg
-   * should be sufficient for now) */
-  arg_data = (char *)ALLOCA_N(char, 8 * n);
-
-  signature_tag = (int)jit_function_get_meta(function, RJT_TAG_FOR_SIGNATURE);
-  if(signature_tag == JIT_TYPE_FIRST_TAGGED + RJT_RUBY_VARARG_SIGNATURE)
-  {
-    jit_VALUE result;
-    int f_argc = argc - 1;
-    VALUE f_self = *(VALUE *)argv;
-    VALUE * f_argv = ((VALUE *)argv) + 1;
-    void * f_args[3];
-    f_args[0] = &f_argc;
-    f_args[1] = &f_argv;
-    f_args[2] = &f_self;
-    jit_function_apply(function, f_args, &result);
-    return result;
-  }
-
-  if(argc != n)
-  {
-    rb_raise(
-        rb_eArgError,
-        "Wrong number of arguments (expected %d but got %d)",
-        n,
-        argc);
-  }
-
-  for(j = 0; j < n; ++j)
-  {
-    jit_type_t arg_type = jit_type_get_param(signature, j);
-    int kind = jit_type_get_kind(arg_type);
-    switch(kind)
-    {
-      case JIT_TYPE_INT:
-      {
-        *(int *)arg_data = NUM2INT(argv[j]);
-        args[j] = (int *)arg_data;
-        arg_data += sizeof(int);
-        break;
-      }
-
-      case JIT_TYPE_UINT:
-      {
-        *(int *)arg_data = NUM2UINT(argv[j]);
-        args[j] = (int *)arg_data;
-        arg_data += sizeof(int);
-        break;
-      }
-
-      case JIT_TYPE_FIRST_TAGGED + RJT_OBJECT:
-      {
-        *(VALUE *)arg_data = argv[j];
-        args[j] = (VALUE *)arg_data;
-        arg_data += sizeof(VALUE);
-        break;
-      }
-
-      case JIT_TYPE_FIRST_TAGGED + RJT_ID:
-      {
-        *(ID *)arg_data = SYM2ID(argv[j]);
-        args[j] = (ID *)arg_data;
-        arg_data += sizeof(ID);
-        break;
-      }
-
-      case JIT_TYPE_FIRST_TAGGED + RJT_FUNCTION_PTR:
-      {
-        *(Void_Function_Ptr *)arg_data =
-          (Void_Function_Ptr)NUM2ULONG(rb_to_int(argv[j]));
-        args[j] = (Void_Function_Ptr *)(arg_data);
-        arg_data += sizeof(Void_Function_Ptr);
-        break;
-      }
-
-      default:
-        rb_raise(rb_eTypeError, "Unsupported type %d", kind);
-    }
-  }
-
-  {
-    jit_type_t return_type = jit_type_get_return(signature);
-    int return_kind = jit_type_get_kind(return_type);
-    switch(return_kind)
-    {
-      case JIT_TYPE_INT:
-      {
-        jit_int result;
-        jit_function_apply(function, args, &result);
-        return INT2NUM(result);
-      }
-
-      case JIT_TYPE_FLOAT32:
-      {
-        jit_float32 result;
-        jit_function_apply(function, args, &result);
-        return rb_float_new(result);
-      }
-
-      case JIT_TYPE_FLOAT64:
-      {
-        jit_float64 result;
-        jit_function_apply(function, args, &result);
-        return rb_float_new(result);
-      }
-
-      case JIT_TYPE_FIRST_TAGGED + RJT_OBJECT:
-      {
-        jit_VALUE result;
-        jit_function_apply(function, args, &result);
-        return result;
-      }
-
-      case JIT_TYPE_FIRST_TAGGED + RJT_ID:
-      {
-        jit_ID result;
-        jit_function_apply(function, args, &result);
-        return ID2SYM(result);
-      }
-
-      default:
-        rb_raise(rb_eTypeError, "Unsupported return type %d", return_kind);
-    }
-  }
-}
-
-/*
- * call-seq:
- *   level = function.optimization_level()
- *
- * Get the optimization level for a function.
- */
-static VALUE function_optimization_level(VALUE self)
-{
-  jit_function_t function;
-  Data_Get_Struct(self, struct _jit_function, function);
-  return INT2NUM(jit_function_get_optimization_level(function));
-}
-
-/*
- * call-seq:
- *   function.optimization_level = level
- *
- * Set the optimization level for a function.
- */
-static VALUE function_set_optimization_level(VALUE self, VALUE level)
-{
-  jit_function_t function;
-  Data_Get_Struct(self, struct _jit_function, function);
-  jit_function_set_optimization_level(function, NUM2INT(level));
-  return level;
-}
-
-/*
- * call-seq:
- *   level = function.max_optimization_level()
- *
- * Get the maximum optimization level (which should be the same for any
- * function).
- */
-static VALUE function_max_optimization_level(VALUE klass)
-{
-  return INT2NUM(jit_function_get_max_optimization_level());
-}
-
-/*
- * call-seq:
- *   str = function.dump()
- *
- * Dump the instructions in a function to a string.
- */
-static VALUE function_dump(VALUE self)
-{
-#ifdef HAVE_FMEMOPEN
-  jit_function_t function;
-  char buf[16*1024]; /* TODO: big enough? */
-  FILE * fp = fmemopen(buf, sizeof(buf), "w");
-  Data_Get_Struct(self, struct _jit_function, function);
-  jit_dump_function(fp, function, 0);
-  fclose(fp);
-  return rb_str_new2(buf);
-#else
-  rb_raise(rb_eNotImpError, "Not implemented: missing fmemopen");
-#endif
-}
-
-/*
- * call-seq:
- *   ptr = function.to_closure()
- *
- * Return a pointer to a closure for a function.  This pointer can be
- * passed into other functions as a function pointer.
- */
-static VALUE function_to_closure(VALUE self)
-{
-  jit_function_t function;
-  struct Closure * closure;
-  VALUE closure_v = Data_Make_Struct(
-      rb_cClosure, struct Closure, mark_closure, free, closure);
-  Data_Get_Struct(self, struct _jit_function, function);
-  closure->function = self;
-  closure->function_ptr =
-    (Void_Function_Ptr)jit_function_to_closure(function);
-  return closure_v;
-}
-
-/*
- * call-seq:
- *   context = function.context()
- *
- * Get a function's context.
- */
-static VALUE function_get_context(VALUE self)
-{
-  jit_function_t function;
-  Data_Get_Struct(self, struct _jit_function, function);
-  return (VALUE)jit_function_get_meta(function, RJT_CONTEXT);
-}
-
-/*
- * call-seq:
- *   is_compiled = function.compiled?
- *
- * Determine whether a function is compiled.
- */
-static VALUE function_is_compiled(VALUE self)
-{
-  jit_function_t function;
-  Data_Get_Struct(self, struct _jit_function, function);
-  return jit_function_is_compiled(function) ? Qtrue : Qfalse;
-}
-
-/* ---------------------------------------------------------------------------
- * Type
- * ---------------------------------------------------------------------------
- */
-
-/* This function does not increment the reference count.  It is assumed
- * that the caller will increment the reference count and that the newly
- * wrapped object will take ownership. */
-static VALUE wrap_type_with_klass(jit_type_t type, VALUE klass)
-{
-  return Data_Wrap_Struct(klass, 0, jit_type_free, type);
-}
-
-static VALUE wrap_type(jit_type_t type)
-{
-  return wrap_type_with_klass(type, rb_cType);
-}
-
-/*
- * call-seq:
- *   type = Type.create_signature(abi, return_type, array_of_param_types)
- *
- * Create a new signature.
- */
-static VALUE type_s_create_signature(
-    VALUE klass, VALUE abi_v, VALUE return_type_v, VALUE params_v)
-{
-  jit_abi_t abi;
-  jit_type_t return_type;
-  jit_type_t * params;
-  jit_type_t signature;
-  int j;
-  int len;
-
-  return_type_v = lookup_const(rb_cType, return_type_v);
-  check_type("return type", rb_cType, return_type_v);
-  Data_Get_Struct(return_type_v, struct _jit_type, return_type);
-
-  Check_Type(params_v, T_ARRAY);
-  len = RARRAY_LEN(params_v);
-  params = ALLOCA_N(jit_type_t, len);
-  for(j = 0; j < len; ++j)
-  {
-    VALUE param = RARRAY_PTR(params_v)[j];
-    param = lookup_const(rb_cType, param);
-    check_type("param", rb_cType, param);
-    Data_Get_Struct(param, struct _jit_type, params[j]);
-  }
-
-  abi_v = lookup_const(rb_mABI, abi_v);
-  abi = NUM2INT(abi_v);
-
-  signature = jit_type_create_signature(abi, return_type, params, len, 1);
-  return wrap_type(signature);
-}
-
-/*
- * call-seq:
- *   type = Type.create_struct(array_of_field_types)
- *
- * Create a new struct type.
- */
-static VALUE type_s_create_struct(
-    VALUE klass, VALUE fields_v)
-{
-  jit_type_t * fields;
-  jit_type_t struct_type;
-  int len;
-  int j;
-
-  Check_Type(fields_v, T_ARRAY);
-  len = RARRAY_LEN(fields_v);
-  fields = ALLOCA_N(jit_type_t, len);
-  for(j = 0; j < len; ++j)
-  {
-    VALUE field = RARRAY_PTR(fields_v)[j];
-    check_type("field", rb_cType, field);
-    Data_Get_Struct(field, struct _jit_type, fields[j]);
-  }
-
-  struct_type = jit_type_create_struct(fields, RARRAY_LEN(fields_v), 1);
-  return wrap_type_with_klass(struct_type, klass);
-}
-
-/*
- * call-seq:
- *   type = Type.create_pointer(pointed_to_type)
- *
- * Create a new pointer type, pointing to the given type.
- */
-static VALUE type_s_create_pointer(
-    VALUE klass, VALUE type_v)
-{
-  jit_type_t type;
-  jit_type_t pointer_type;
-  Data_Get_Struct(type_v, struct _jit_type, type);
-  pointer_type = jit_type_create_pointer(type, 1);
-  return wrap_type_with_klass(pointer_type, klass);
-}
-
-/*
- * call-seq:
- *   offset = struct_type.get_offset(index)
- *
- * Get the offset of the nth field in a struct.
- */
-static VALUE type_get_offset(VALUE self, VALUE field_index_v)
-{
-  int field_index = NUM2INT(field_index_v);
-  jit_type_t type;
-  Data_Get_Struct(self, struct _jit_type, type);
-  return INT2NUM(jit_type_get_offset(type, field_index));
-}
-
-/*
- * call-seq:
- *   offset = struct_type.set_offset(index, offset)
- *
- * Set the offset of the nth field in a struct.
- */
-static VALUE type_set_offset(VALUE self, VALUE field_index_v, VALUE offset_v)
-{
-  int field_index = NUM2INT(field_index_v);
-  int offset = NUM2UINT(offset_v);
-  jit_type_t type;
-  Data_Get_Struct(self, struct _jit_type, type);
-  jit_type_set_offset(type, field_index, offset);
-  return Qnil;
-}
-
-/*
- * call-seq:
- *   offset = struct_type.size
- *
- * Get the size of a struct or union type.
- */
-static VALUE type_size(VALUE self)
-{
-  jit_type_t type;
-  Data_Get_Struct(self, struct _jit_type, type);
-  return INT2NUM(jit_type_get_size(type));
-}
-
-/* ---------------------------------------------------------------------------
- * Value
- * ---------------------------------------------------------------------------
- */
-
-static VALUE value_s_new_value(VALUE klass, VALUE function, VALUE type)
-{
-  return function_value_klass(function, type, klass);
-}
-
-/*
- * call-seq:
- *   str = value.to_s
- *
- * Return a string representation of the value.
- */
-static VALUE value_to_s(VALUE self)
-{
-#ifdef HAVE_FMEMOPEN
-  char buf[1024];
-  FILE * fp = fmemopen(buf, sizeof(buf), "w");
-  jit_value_t value;
-  jit_function_t function;
-  Data_Get_Struct(self, struct _jit_value, value);
-  function = jit_value_get_function(value);
-  jit_dump_value(fp, function, value, 0);
-  fclose(fp);
-  return rb_str_new2(buf);
-#else
-  rb_raise(rb_eNotImpError, "Not implemented: missing fmemopen");
-#endif
-}
-
-/*
- * call-seq:
- *   str = value.inspect
- *
- * Return a string representation of a value with additional
- * information about the value.
- */
-static VALUE value_inspect(VALUE self)
-{
-  jit_value_t value;
-  jit_type_t type;
-  char const * cname = rb_obj_classname(self);
-  VALUE args[6];
-  Data_Get_Struct(self, struct _jit_value, value);
-  type = jit_value_get_type(value);
-  args[0] = rb_str_new2("#<%s:0x%x %s ptr=0x%x type=0x%x>");
-  args[1] = rb_str_new2(cname);
-  args[2] = ULONG2NUM((unsigned long)self);
-  args[3] = value_to_s(self);
-  args[4] = ULONG2NUM((unsigned long)value);
-  args[5] = ULONG2NUM((unsigned long)type);
-  return rb_f_sprintf(sizeof(args)/sizeof(args[0]), args);
-}
-
-/*
- * call-seq:
- *   is_valid = value.valid?
- *
- * Determine if a value is valid (non-zero).
- */
-static VALUE value_is_valid(VALUE self)
-{
-  jit_value_t value;
-  Data_Get_Struct(self, struct _jit_value, value);
-  return (value != 0) ? Qtrue : Qfalse;
-}
-
-/*
- * call-seq:
- *   is_temporary = value.temporary?
- *
- * Determine if a value represents a temporary.
- */
-static VALUE value_is_temporary(VALUE self)
-{
-  jit_value_t value;
-  Data_Get_Struct(self, struct _jit_value, value);
-  return jit_value_is_temporary(value) ? Qtrue : Qfalse;
-}
-
-/*
- * call-seq:
- *   is_local = value.local?
- *
- * Determine if a value represents a local.
- */
-static VALUE value_is_local(VALUE self)
-{
-  jit_value_t value;
-  Data_Get_Struct(self, struct _jit_value, value);
-  return jit_value_is_local(value) ? Qtrue : Qfalse;
-}
-
-/*
- * call-seq:
- *   is_local = value.constant?
- *
- * Determine if a value represents a constant.
- */
-static VALUE value_is_constant(VALUE self)
-{
-  jit_value_t value;
-  Data_Get_Struct(self, struct _jit_value, value);
-  return jit_value_is_constant(value) ? Qtrue : Qfalse;
-}
-
-/*
- * call-seq:
- *   is_volatile = value.volatile?
- *
- * Determine if a value is volatile (that is, the contents must be
- * reloaded from memory each time it is used).
- */
-static VALUE value_is_volatile(VALUE self)
-{
-  jit_value_t value;
-  Data_Get_Struct(self, struct _jit_value, value);
-  return jit_value_is_volatile(value) ? Qtrue : Qfalse;
-}
-
-/*
- * call-seq:
- *   value.volatile = is_volatile
- *
- * Make a value volatile (that is, ensure that its contents are reloaded
- * from memory each time it is used).
- */
-static VALUE value_set_volatile(VALUE self)
-{
-  jit_value_t value;
-  Data_Get_Struct(self, struct _jit_value, value);
-  jit_value_set_volatile(value);
-  return Qnil;
-}
-
-/*
- * call-seq:
- *   is_addressable = value.addressable?
- *
- * Determine if a value is addressable.
- */
-static VALUE value_is_addressable(VALUE self)
-{
-  jit_value_t value;
-  Data_Get_Struct(self, struct _jit_value, value);
-  return jit_value_is_addressable(value) ? Qtrue : Qfalse;
-}
-
-/*
- * call-seq:
- *   value.addressable = is_addressable
- *
- * Make a value addressable.
- */
-static VALUE value_set_addressable(VALUE self)
-{
-  jit_value_t value;
-  Data_Get_Struct(self, struct _jit_value, value);
-  jit_value_set_addressable(value);
-  return Qnil;
-}
-
-/*
- * call-seq:
- *   function = value.function()
- *
- * Get a value's function.
- */
-static VALUE value_function(VALUE self)
-{
-  jit_value_t value;
-  jit_function_t function;
-  Data_Get_Struct(self, struct _jit_value, value);
-  function = jit_value_get_function(value);
-  return Data_Wrap_Struct(rb_cFunction, mark_function, 0, function);
-}
-
-/*
- * call-seq:
- *   function = value.type()
- *
- * Get a value's type.
- */
-static VALUE value_type(VALUE self)
-{
-  jit_value_t value;
-  jit_type_t type;
-  Data_Get_Struct(self, struct _jit_value, value);
-  type = jit_value_get_type(value);
-  type = jit_type_copy(type);
-  return wrap_type(type);
-}
-
-/*
- * call-seq:
- *   value1, value2 = value1.coerce(value2)
- *
- * If the given value is a JIT::Value, return an +[ self, value ]+,
- * otherwise coerce the value to the same type as self and return
- * +[ self, coerced_value ]+.
- */
-static VALUE value_coerce(VALUE self, VALUE value)
-{
-  return rb_assoc_new(
-      self,
-      coerce_to_jit(
-          value_function(self),
-          value_type(self),
-          value));
-}
-
-/* ---------------------------------------------------------------------------
- * Label
- * ---------------------------------------------------------------------------
- */
-
-/*
- * call-seq:
- *   label = Label.new
- *
- * Create a new label.
- */
-static VALUE label_s_new(VALUE klass)
-{
-  jit_label_t * label;
-  VALUE labelval = Data_Make_Struct(rb_cLabel, jit_label_t, 0, xfree, label);
-  *label = jit_label_undefined;
-  return labelval;
-}
-
-/* ---------------------------------------------------------------------------
- * Module
- * ---------------------------------------------------------------------------
- */
-
-/*
- * call-seq:
- *   module.define_jit_method(name, function)
- *
- * Use a Function to define an instance method on a module.  The
- * function should have one of two signatures:
- *
- * * The first parameter to the function should be an OBJECT that
- *   represents the self parameter and the rest of the parameters, or
- *
- * * The function's signature should be Type::RUBY_VARARG_SIGNATURE.
- */
-static VALUE module_define_jit_method(VALUE klass, VALUE name_v, VALUE function_v)
-{
-  char const * name;
-  jit_function_t function;
-  jit_type_t signature;
-  int signature_tag;
-  int arity;
-  VALUE closure_v;
-  struct Closure * closure;
-
-  if(SYMBOL_P(name_v))
-  {
-    name = rb_id2name(SYM2ID(name_v));
-  }
-  else
-  {
-    name = STR2CSTR(name_v);
-  }
-
-  Data_Get_Struct(function_v, struct _jit_function, function);
-
-  signature = jit_function_get_signature(function);
-  signature_tag = (int)jit_function_get_meta(function, RJT_TAG_FOR_SIGNATURE);
-  if(signature_tag == JIT_TYPE_FIRST_TAGGED + RJT_RUBY_VARARG_SIGNATURE)
-  {
-    arity = -1;
-  }
-  else
-  {
-    /* TODO: check the types to make sure they are OBJECT */
-    arity = jit_type_num_params(signature) - 1;
-  }
-
-  closure_v = function_to_closure(function_v);
-  Data_Get_Struct(closure_v, struct Closure, closure);
-  define_method_with_data(
-      klass, rb_intern(name), RUBY_METHOD_FUNC(closure->function_ptr),
-      arity, closure_v);
-  return Qnil;
-}
-
-/* ---------------------------------------------------------------------------
- * Init
- * ---------------------------------------------------------------------------
- */
-
-void Init_jit()
-{
-  jit_init();
-
-  rb_mJIT = rb_define_module("JIT");
-
-  rb_cContext = rb_define_class_under(rb_mJIT, "Context", rb_cObject);
-  rb_define_singleton_method(rb_cContext, "new", context_s_new, 0);
-  rb_define_method(rb_cContext, "build", context_build, 0);
-  rb_define_singleton_method(rb_cContext, "build", context_s_build, 0);
-
-  rb_cClosure = rb_define_class_under(rb_mJIT, "Closure", rb_cObject);
-  rb_define_method(rb_cClosure, "to_int", closure_to_int, 0);
-  rb_define_method(rb_cClosure, "to_s", closure_to_s, 0);
-  rb_define_method(rb_cClosure, "inspect", closure_inspect, 0);
-
-  rb_cFunction = rb_define_class_under(rb_mJIT, "Function", rb_cObject);
-  rb_define_singleton_method(rb_cFunction, "new", function_s_new, -1);
-  rb_define_method(rb_cFunction, "compile", function_compile, 0);
-  rb_define_singleton_method(rb_cFunction, "compile", function_s_compile, -1);
-  rb_define_method(rb_cFunction, "get_param", function_get_param, 1);
-  init_insns();
-  rb_define_method(rb_cFunction, "insn_call", function_insn_call, -1);
-  rb_define_method(rb_cFunction, "insn_call_native", function_insn_call_native, -1);
-  rb_define_method(rb_cFunction, "insn_return", function_insn_return, -1);
-  rb_define_method(rb_cFunction, "apply", function_apply, -1);
-  rb_define_alias(rb_cFunction, "call", "apply");
-  rb_define_method(rb_cFunction, "value", function_value, -1);
-  rb_define_method(rb_cFunction, "const", function_const, 2);
-  rb_define_method(rb_cFunction, "optimization_level", function_optimization_level, 0);
-  rb_define_method(rb_cFunction, "optimization_level=", function_set_optimization_level, 1);
-  rb_define_singleton_method(rb_cFunction, "max_optimization_level", function_max_optimization_level, 0);
-  rb_define_method(rb_cFunction, "dump", function_dump, 0);
-  rb_define_method(rb_cFunction, "to_closure", function_to_closure, 0);
-  rb_define_method(rb_cFunction, "context", function_get_context, 0);
-  rb_define_method(rb_cFunction, "compiled?", function_is_compiled, 0);
-
-  rb_cType = rb_define_class_under(rb_mJIT, "Type", rb_cObject);
-  rb_define_singleton_method(rb_cType, "create_signature", type_s_create_signature, 3);
-  rb_define_singleton_method(rb_cType, "create_struct", type_s_create_struct, 1);
-  rb_define_singleton_method(rb_cType, "create_pointer", type_s_create_pointer, 1);
-  rb_define_method(rb_cType, "get_offset", type_get_offset, 1);
-  rb_define_method(rb_cType, "set_offset", type_set_offset, 2);
-  rb_define_method(rb_cType, "size", type_size, 0);
-  rb_define_const(rb_cType, "VOID", wrap_type(jit_type_void));
-  rb_define_const(rb_cType, "SBYTE", wrap_type(jit_type_sbyte));
-  rb_define_const(rb_cType, "UBYTE", wrap_type(jit_type_ubyte));
-  rb_define_const(rb_cType, "SHORT", wrap_type(jit_type_short));
-  rb_define_const(rb_cType, "USHORT", wrap_type(jit_type_ushort));
-  rb_define_const(rb_cType, "INT", wrap_type(jit_type_int));
-  rb_define_const(rb_cType, "UINT", wrap_type(jit_type_uint));
-  rb_define_const(rb_cType, "NINT", wrap_type(jit_type_nint));
-  rb_define_const(rb_cType, "NUINT", wrap_type(jit_type_nuint));
-  rb_define_const(rb_cType, "LONG", wrap_type(jit_type_long));
-  rb_define_const(rb_cType, "ULONG", wrap_type(jit_type_ulong));
-  rb_define_const(rb_cType, "FLOAT32", wrap_type(jit_type_float32));
-  rb_define_const(rb_cType, "FLOAT64", wrap_type(jit_type_float64));
-  rb_define_const(rb_cType, "NFLOAT", wrap_type(jit_type_nfloat));
-  rb_define_const(rb_cType, "VOID_PTR", wrap_type(jit_type_void_ptr));
-
-  jit_type_VALUE = jit_type_create_tagged(jit_underlying_type_VALUE, RJT_OBJECT, 0, 0, 1);
-  rb_define_const(rb_cType, "OBJECT", wrap_type(jit_type_VALUE));
-
-  jit_type_ID = jit_type_create_tagged(jit_underlying_type_ID, RJT_ID, 0, 0, 1);
-  rb_define_const(rb_cType, "ID", wrap_type(jit_type_ID));
-
-  jit_type_Function_Ptr = jit_type_create_tagged(jit_underlying_type_ID, RJT_FUNCTION_PTR, 0, 0, 1);
-  rb_define_const(rb_cType, "FUNCTION_PTR", wrap_type(jit_type_Function_Ptr));
-
-  {
-    jit_type_t ruby_vararg_param_types[3];
-    jit_type_t ruby_vararg_signature_untagged;
-    ruby_vararg_param_types[0] = jit_type_int;
-    ruby_vararg_param_types[1] = jit_type_void_ptr;
-    ruby_vararg_param_types[2] = jit_type_VALUE;
-    ruby_vararg_signature_untagged = jit_type_create_signature(
-          jit_abi_cdecl,
-          jit_type_VALUE,
-          ruby_vararg_param_types,
-          3,
-          1);
-    ruby_vararg_signature = jit_type_create_tagged(ruby_vararg_signature_untagged, RJT_RUBY_VARARG_SIGNATURE, 0, 0, 1);
-  }
-  rb_define_const(rb_cType, "RUBY_VARARG_SIGNATURE", wrap_type(ruby_vararg_signature));
-
-  rb_mABI = rb_define_module_under(rb_mJIT, "ABI");
-  rb_define_const(rb_mABI, "CDECL", INT2NUM(jit_abi_cdecl));
-  rb_define_const(rb_mABI, "VARARG", INT2NUM(jit_abi_vararg));
-  rb_define_const(rb_mABI, "STDCALL", INT2NUM(jit_abi_stdcall));
-  rb_define_const(rb_mABI, "FASTCALL", INT2NUM(jit_abi_fastcall));
-
-  rb_cValue = rb_define_class_under(rb_mJIT, "Value", rb_cObject);
-  rb_define_singleton_method(rb_cValue, "new_value", value_s_new_value, 2);
-  rb_define_method(rb_cValue, "to_s", value_to_s, 0);
-  rb_define_method(rb_cValue, "inspect", value_inspect, 0);
-  rb_define_method(rb_cValue, "valid?", value_is_valid, 0);
-  rb_define_method(rb_cValue, "temporary?", value_is_temporary, 0);
-  rb_define_method(rb_cValue, "local?", value_is_local, 0);
-  rb_define_method(rb_cValue, "constant?", value_is_constant, 0);
-  rb_define_method(rb_cValue, "volatile?", value_is_volatile, 0);
-  rb_define_method(rb_cValue, "set_volatile", value_set_volatile, 0);
-  rb_define_method(rb_cValue, "addressable?", value_is_addressable, 0);
-  rb_define_method(rb_cValue, "addressable=", value_set_addressable, 0);
-  rb_define_method(rb_cValue, "function", value_function, 0);
-  rb_define_method(rb_cValue, "type", value_type, 0);
-  rb_define_method(rb_cValue, "coerce", value_coerce, 1);
-
-  rb_cLabel = rb_define_class_under(rb_mJIT, "Label", rb_cObject);
-  rb_define_singleton_method(rb_cLabel, "new", label_s_new, 0);
-
-  rb_mCall = rb_define_module_under(rb_mJIT, "Call");
-  rb_define_const(rb_mCall, "NOTHROW", INT2NUM(JIT_CALL_NOTHROW));
-  rb_define_const(rb_mCall, "NORETURN", INT2NUM(JIT_CALL_NORETURN));
-  rb_define_const(rb_mCall, "TAIL", INT2NUM(JIT_CALL_TAIL));
-
-  /* VALUE rb_cModule = rb_define_module(); */
-  rb_define_method(rb_cModule, "define_jit_method", module_define_jit_method, 2);
-
-#ifdef NEED_MINIMAL_NODE
-  Init_minimal_node();
-#endif
-}
-
diff -ruN libjit/jitruby/ext/method_data.c.rpp libjit-mikyt/jitruby/ext/method_data.c.rpp
--- libjit/jitruby/ext/method_data.c.rpp	2008-12-12 12:31:03.000000000 +0100
+++ libjit-mikyt/jitruby/ext/method_data.c.rpp	1970-01-01 01:00:00.000000000 +0100
@@ -1,294 +0,0 @@
-#include "method_data.h"
-
-#include <ruby.h>
-
-#ifndef HAVE_RUBINIUS
-
-#ruby <<END
-MAX_ARGS = 15
-nil
-END
-
-#if defined(HAVE_NODE_H)
-/* pre-YARV */
-#include <node.h>
-#elif defined(REALLY_HAVE_RUBY_NODE_H)
-/* YARV */
-#include <ruby/node.h>
-#elif defined(RUBY_VM)
-/* YARV without node.h */
-#include "minimal_node.h"
-#else
-/* something else */
-#error "Need node.h"
-#endif
-
-#ifdef HAVE_ENV_H
-/* pre-YARV */
-#include <env.h>
-#endif
-
-#ifdef RUBY_VM
-
-/* YARV */
-
-struct rb_thread_struct
-{   
-    VALUE self;
-    void *vm;
-    VALUE *stack;
-    unsigned long stack_size;
-    VALUE *cfp;
-    /* ... */
-};
-
-typedef struct rb_thread_struct rb_thread_t;
-
-#define CFP_DATA_MEMO_NODE_AND_PC cfp[0]
-#define CFP_METHOD_CLASS cfp[11]
-
-/* On YARV, we store the method data on the stack.  We don't have to pop
- * it off the stack, because the stack pointer will be reset to the
- * previous frame's stack pointer when the function returns.
- */
-static void fix_frame()
-{
-  do {
-    extern rb_thread_t * ruby_current_thread;
-    VALUE * cfp = ruby_current_thread->cfp;
-    CFP_DATA_MEMO_NODE_AND_PC = RBASIC(CFP_METHOD_CLASS)->klass;
-
-    if(rb_type(CFP_DATA_MEMO_NODE_AND_PC) != T_NODE)
-    {
-      /* This can happen for module functions that are created after
-       * the stub function */
-      rb_raise(
-          rb_eRuntimeError,
-          "Cannot find method data for module function");
-    }
-    else
-    {
-      CFP_METHOD_CLASS = RCLASS_SUPER(CFP_METHOD_CLASS);
-    }
-  } while(0);
-}
-
-#define FIX_FRAME() \
-  fix_frame()
-
-static NODE * data_memo_node()
-{
-  extern rb_thread_t * ruby_current_thread;
-  VALUE * cfp = ruby_current_thread->cfp;
-  return (NODE *)CFP_DATA_MEMO_NODE_AND_PC;
-}
-
-#else
-
-/* pre-YARV */
-
-/* Okay to not pop this temporary frame, since it will be popped by the
- * caller
- */
-#define FIX_FRAME() \
-  struct FRAME _frame = *ruby_frame; \
-  _frame.last_class = RCLASS(ruby_frame->last_class)->super; \
-  _frame.prev = ruby_frame; \
-  ruby_frame = &_frame; \
-
-static NODE * data_memo_node()
-{
-  return (NODE *)(RBASIC(ruby_frame->prev->last_class)->klass);
-}
-
-#endif
-
-typedef VALUE (*Method_Func)(ANYARGS);
-
-static Method_Func actual_cfunc()
-{
-  return data_memo_node()->nd_cfnc;
-}
-
-static VALUE data_wrapper_m1(int argc, VALUE * argv, VALUE self)
-{
-  VALUE result;
-  FIX_FRAME();
-  result = (*actual_cfunc())(argc, argv, self);
-  return result;
-}
-
-static VALUE data_wrapper_0(VALUE self)
-{
-  VALUE result;
-  FIX_FRAME();
-  result = (*actual_cfunc())(self);
-  return result;
-}
-
-#ruby <<END
-  (1..MAX_ARGS).each do |i|
-    params = (1..i).map { |j| "VALUE arg#{j}" }.join(', ')
-    args = (1..i).map { |j| "arg#{j}" }.join(', ')
-
-    puts <<-END
-static VALUE data_wrapper_#{i}(VALUE self, #{params})
-{
-  VALUE result;
-  FIX_FRAME();
-  result = (*actual_cfunc())(self, #{args});
-  return result;
-}
-    END
-  end
-
-  nil
-END
-
-/* Define a method and attach data to it.
- *
- * The method looks to ruby like a normal aliased CFUNC, with a modified
- * origin class:
- *
- * NODE_FBODY
- *   |- (u1) orig - origin class
- *   |  |- basic
- *   |  |  |- flags - origin class flags + FL_SINGLETON
- *   |  |  +- klass - NODE_MEMO
- *   |  |     |- (u1) cfnc - actual C function to call
- *   |  |     |- (u2) rval - stored data
- *   |  |     +- (u3) 0
- *   |  |- iv_tbl - 0
- *   |  |- m_tbl - 0
- *   |  +- super - actual origin class
- *   |- (u2) mid - name of the method
- *   +- (u3) head - NODE_CFUNC
- *      |- (u1) cfnc - wrapper function to call
- *      +- (u2) argc - function arity
- *
- * Or, on YARV:
- *
- * NODE_FBODY
- *   |- (u1) oid - name of the method
- *   +- (u2) body - NODE_METHOD
- *      |- (u1) clss - origin class
- *      |  |- basic
- *      |  |  |- flags - origin class flags + FL_SINGLETON
- *      |  |  +- klass - NODE_MEMO
- *      |  |     |- (u1) cfnc - actual C function to call
- *      |  |     |- (u2) rval - stored data
- *      |  |     +- (u3) 0
- *      |  |- ptr - rb_classext_t
- *      |  |  |- super - actual origin class
- *      |  |  +- iv_tbl - 0
- *      |  |- m_tbl - 0
- *      |  +- iv_index_tbl - 0?
- *      |- (u2) body - NODE_CFUNC
- *      |  |- (u1) cfnc - wrapper function to call
- *      |  |- (u2) argc - function arity
- *      +- (u3) noex - NOEX_PUBLIC
- *
- * When the wrapper function is called, last_class is set to the origin
- * class found in the FBODY node.  So that the method data will be
- * accessible, and so last_class will point to klass and not to our MEMO
- * node, it is necessary to "fix" the current frame.
- *
- * Pre-YARV, this means we duplicate the current frame and set last_class:
- *
- * ruby_frame
- *   |- last_class - klass
- *   |- prev
- *   |  |- last_class - NODE_MEMO
- *   |  |  |- (u1) cfnc - actual C function to call
- *   |  |  |- (u2) rval - stored data
- *   |  |  +- (u3) 0
- *   |  |- prev - the real previous frame
- *   |  +- ...
- *   +- ...
- *
- * The method data is then accessible via
- * ruby_frame->prev->last_class->rval.
- *
- * On YARV, the current frame is not duplicated; rather, the method data
- * is placed on the stack and is referenced by one of the unused members
- * of the control frame (the program counter):
- *
- * ruby_current_thread->cfp
- *   |- pc - NODE_MEMO
- *   |  |- (u1) cfnc - actual C function to call
- *   |  |- (u2) rval - stored data
- *   |  +- (u3) 0
- *   |- method_class - klass
- *   +- ...
- *
- */
-void define_method_with_data(
-    VALUE klass, ID id, VALUE (*cfunc)(ANYARGS), int arity, VALUE data)
-{
-  /* TODO: origin should have #to_s and #inspect methods defined */
-#ifdef HAVE_RB_CLASS_BOOT
-  VALUE origin = rb_class_boot(klass);
-#else
-  VALUE origin = rb_class_new(klass);
-#endif
-  NODE * node;
-
-  VALUE (*data_wrapper)(ANYARGS);
-  switch(arity)
-  {
-#ruby <<END
-  (0..MAX_ARGS).each do |i|
-    puts <<-END
-    case #{i}: data_wrapper = RUBY_METHOD_FUNC(data_wrapper_#{i}); break;
-    END
-  end
-  nil
-END
-    case -1: data_wrapper = RUBY_METHOD_FUNC(data_wrapper_m1); break;
-    default: rb_raise(rb_eArgError, "unsupported arity %d", arity);
-  }
-
-  FL_SET(origin, FL_SINGLETON);
-  rb_singleton_class_attached(origin, klass);
-  rb_name_class(origin, SYM2ID(rb_class_name(klass)));
-
-  RBASIC(origin)->klass = (VALUE)NEW_NODE(NODE_MEMO, cfunc, data, 0);
-
-#ifdef RUBY_VM
-  /* YARV */
-  node = NEW_FBODY(
-      NEW_METHOD(
-          NEW_CFUNC(data_wrapper, arity),
-          origin,
-          NOEX_PUBLIC),
-      id);
-  st_insert(RCLASS_M_TBL(klass), id, (st_data_t)node);
-#else
-  /* pre-YARV */
-  node = NEW_FBODY(
-      NEW_CFUNC(data_wrapper, arity),
-      id,
-      origin);
-  rb_add_method(klass, id, node, NOEX_PUBLIC);
-#endif
-}
-
-VALUE get_method_data()
-{
-  return data_memo_node()->nd_rval;
-}
-
-#else /* HAVE_RUBINIUS */
-
-void define_method_with_data(
-    VALUE klass, ID id, VALUE (*cfunc)(ANYARGS), int arity, VALUE data)
-{
-  rb_raise(rb_eNotImpError, "Not implemented: define_method_with_data");
-}
-
-VALUE get_method_data()
-{
-  rb_raise(rb_eNotImpError, "Not implemented: get_method_data");
-}
-
-#endif
diff -ruN libjit/jitruby/ext/method_data.h libjit-mikyt/jitruby/ext/method_data.h
--- libjit/jitruby/ext/method_data.h	2008-12-12 12:31:03.000000000 +0100
+++ libjit-mikyt/jitruby/ext/method_data.h	1970-01-01 01:00:00.000000000 +0100
@@ -1,11 +0,0 @@
-#ifndef METHOD_DATA_H
-#define METHOD_DATA_H
-
-#include <ruby.h>
-
-void define_method_with_data(
-    VALUE klass, ID id, VALUE (*cfunc)(ANYARGS), int arity, VALUE data);
-
-VALUE get_method_data();
-
-#endif // METHOD_DATA_H
diff -ruN libjit/jitruby/ext/minimal_node.c libjit-mikyt/jitruby/ext/minimal_node.c
--- libjit/jitruby/ext/minimal_node.c	2008-12-12 12:31:03.000000000 +0100
+++ libjit-mikyt/jitruby/ext/minimal_node.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,35 +0,0 @@
-#ifdef NEED_MINIMAL_NODE
-
-#include "minimal_node.h"
-#include <string.h>
-
-int NODE_MEMO = 0;
-int NODE_METHOD = 0;
-int NODE_FBODY = 0;
-int NODE_CFUNC = 0;
-
-char const * ruby_node_name(int node);
-
-static int node_value(char const * name)
-{
-  /* TODO: any way to end the block? */
-  int j;
-  for(j = 0; ; ++j)
-  {
-    if(!strcmp(name, ruby_node_name(j)))
-    {
-      return j;
-    }
-  }
-}
-
-void Init_minimal_node()
-{
-  NODE_MEMO = node_value("NODE_MEMO");
-  NODE_METHOD = node_value("NODE_METHOD");
-  NODE_FBODY = node_value("NODE_FBODY");
-  NODE_CFUNC = node_value("NODE_CFUNC");
-}
-
-#endif
-
diff -ruN libjit/jitruby/ext/minimal_node.h libjit-mikyt/jitruby/ext/minimal_node.h
--- libjit/jitruby/ext/minimal_node.h	2008-12-12 12:31:03.000000000 +0100
+++ libjit-mikyt/jitruby/ext/minimal_node.h	1970-01-01 01:00:00.000000000 +0100
@@ -1,52 +0,0 @@
-#ifndef minimal_node_h
-#define minimal_node_h
-
-#ifdef NEED_MINIMAL_NODE
-
-#include "ruby.h"
-
-typedef struct RNode {
-  unsigned long flags;
-  void * reserved;
-  union {
-    struct RNode * node;
-    VALUE (*cfunc)(ANYARGS);
-  } u1;
-  union {
-    struct RNode * node;
-    VALUE value;
-  } u2;
-  union {
-    struct RNode * node;
-  } u3;
-} NODE;
-
-#define nd_cfnc u1.cfunc
-#define nd_rval u2.value
-
-#define NEW_NODE(t,a0,a1,a2) rb_node_newnode((t),(VALUE)(a0),(VALUE)(a1),(VALUE)(a2))
-
-/* TODO: No way to know the correct size of node_type */
-enum node_type {
-  NODE_FOO,
-};
-
-void rb_add_method(VALUE, ID, NODE *, int);
-NODE *rb_node_newnode(enum node_type, VALUE, VALUE, VALUE);
-
-extern int NODE_MEMO;
-extern int NODE_METHOD;
-extern int NODE_FBODY;
-extern int NODE_CFUNC;
-
-void Init_minimal_node();
-
-#define NOEX_PUBLIC 0x0
-
-#define NEW_METHOD(n,x,v) NEW_NODE(NODE_METHOD,x,n,v)
-#define NEW_FBODY(n,i) NEW_NODE(NODE_FBODY,i,n,0)
-#define NEW_CFUNC(f,c) NEW_NODE(NODE_CFUNC,f,c,0)
-
-#endif
-
-#endif
diff -ruN libjit/jitruby/ext/rubyjit.h libjit-mikyt/jitruby/ext/rubyjit.h
--- libjit/jitruby/ext/rubyjit.h	2008-12-12 12:31:03.000000000 +0100
+++ libjit-mikyt/jitruby/ext/rubyjit.h	1970-01-01 01:00:00.000000000 +0100
@@ -1,20 +0,0 @@
-#ifndef RUBYJIT_H
-#define RUBYJIT_H
-
-enum Ruby_Libjit_Tag
-{
-  RJT_OBJECT,
-  RJT_ID,
-  RJT_FUNCTION_PTR,
-  RJT_RUBY_VARARG_SIGNATURE,
-  RJT_VALUE_OBJECTS,
-  RJT_FUNCTIONS,
-  RJT_CONTEXT,
-  RJT_TAG_FOR_SIGNATURE
-};
-
-extern jit_type_t jit_type_VALUE;
-extern jit_type_t jit_type_ID;
-extern jit_type_t jit_type_Function_Ptr;
-
-#endif
diff -ruN libjit/jitruby/ext/rubypp.rb libjit-mikyt/jitruby/ext/rubypp.rb
--- libjit/jitruby/ext/rubypp.rb	2008-12-12 12:31:03.000000000 +0100
+++ libjit-mikyt/jitruby/ext/rubypp.rb	1970-01-01 01:00:00.000000000 +0100
@@ -1,97 +0,0 @@
-class Preprocessor
-  def initialize(input, output, filename)
-    @input = input
-    @output = output
-    @filename = filename
-    @linenum = 1
-  end
-
-  def getline
-    line = @input.gets
-    @linenum += 1 if not line.nil?
-    return line
-  end
-
-  def preprocess
-    success = false
-    begin
-      loop do
-        line = getline
-        break if line.nil?
-        case line
-        when /(.*[^\\]|^)\#\{(.*?)\}(.*)/
-          puts "#{$1}#{evaluate($2, @linenum)}#{$3}"
-        when /^\#ruby\s+<<(.*)/
-          marker = $1
-          str = ''
-          evalstart = @linenum
-          loop do
-            line = getline
-            if line.nil? then
-              raise "End of input without #{marker}"
-            end
-            break if line.chomp == marker
-            str << line
-          end
-          result = evaluate(str, evalstart)
-          puts result if not result.nil?
-        when /^\#ruby\s+(.*)/
-          str = line = $1
-          while line[-1] == ?\\
-            str.chop!
-            line = getline
-            break if line.nil?
-            line.chomp!
-            str << line
-          end
-          result = evaluate(str, @linenum)
-          puts result if not result.nil?
-        else
-          puts line
-        end
-      end
-      success = true
-    ensure
-      if not success then
-        $stderr.puts "Error on line #{@linenum}:"
-      end
-    end
-  end
-
-  def evaluate(str, linenum)
-    result = eval(str, TOPLEVEL_BINDING, @filename, linenum)
-    success = true
-    return result
-  end
-
-  def puts(line='')
-    @output.puts(line)
-  end
-end
-
-def puts(line='')
-  $preprocessor.puts(line)
-end
-
-def rubypp(input_file, output_file)
-  input = input_file ? File.open(input_file) : $stdin
-  output = output_file ? File.open(output_file, 'w') : $stdout
-
-  success = false
-  begin
-    $preprocessor = Preprocessor.new(input, output, input_file || "(stdin)")
-    $preprocessor.preprocess()
-    success = true
-  ensure
-    if not success then
-      File.unlink(output_file) rescue Errno::ENOENT
-    end
-  end
-end
-
-if __FILE__ == $0 then
-  input_file = ARGV[0]
-  output_file = ARGV[1]
-  rubypp(input_file, output_file)
-end
-
diff -ruN libjit/jitruby/generate_rdoc.rb libjit-mikyt/jitruby/generate_rdoc.rb
--- libjit/jitruby/generate_rdoc.rb	2008-12-12 12:30:58.000000000 +0100
+++ libjit-mikyt/jitruby/generate_rdoc.rb	1970-01-01 01:00:00.000000000 +0100
@@ -1,33 +0,0 @@
-require 'find'
-
-def list_files(dir, pattern)
-  arr = []
-  Find.find(dir) do |filename|
-    if filename =~ pattern then
-      arr.push(filename)
-    end
-  end
-  return arr
-end
-
-def generate_rdoc(*options)
-  begin
-    require 'rdoc/rdoc'
-  rescue LoadError
-    puts "WARNING: RDoc not installed; skipping generation of docs"
-    return
-  end
-
-  r = RDoc::RDoc.new
-  rdoc_files = []
-  rdoc_files.concat [ 'README' ]
-  rdoc_files.concat list_files('lib', /\.rb$/) if File.exist?('lib')
-  rdoc_files.concat list_files('ext', /\.c$/)  if File.exist?('ext')
-  rdoc_files.reject! { |file| file =~ %r{^ext/cached/} }
-  r.document(options + rdoc_files)
-end
-
-if __FILE__ == $0 then
-  generate_rdoc(*ARGV)
-end
-
diff -ruN libjit/jitruby/lib/jit/array.rb libjit-mikyt/jitruby/lib/jit/array.rb
--- libjit/jitruby/lib/jit/array.rb	2008-12-12 12:31:04.000000000 +0100
+++ libjit-mikyt/jitruby/lib/jit/array.rb	1970-01-01 01:00:00.000000000 +0100
@@ -1,135 +0,0 @@
-require 'jit'
-require 'jit/value'
-
-module JIT
-
-  # An abstraction for a fixed-length array type.
-  #
-  # Example usage:
-  #
-  #   array_type = JIT::Array.new(JIT::Type::INT, 4)
-  #
-  #   JIT::Context.build do |context|
-  #     signature = JIT::Type.create_signature(
-  #         JIT::ABI::CDECL, JIT::Type::INT, [ ])
-  #
-  #     function = JIT::Function.compile(context, signature) do |f|
-  #       array_instance = array_type.create(f)
-  #       array_instance[0] = f.const(JIT::Type::INT, 42)
-  #       f.insn_return(array_instance[0])
-  #     end
-  #
-  #   end
-  #
-  class Array < JIT::Type
-    attr_reader :type
-    attr_reader :length
-
-    # Create a new JIT array type.
-    #
-    # +type+::   The type of the elements in the array.
-    # +length+:: The number of elements in the array.
-    #
-    def self.new(type, length)
-      array = self.create_struct([ type ] * length)
-      array.instance_eval do
-        @type = type
-        @length = length
-      end
-      return array
-    end
-
-    # Wrap an existing array.
-    #
-    # +ptr+:: A pointer to the first element in the array.
-    #
-    def wrap(ptr)
-      return Instance.wrap(self, ptr)
-    end
-
-    # Create a new array.
-    #
-    # +function+:: The JIT::Function this array will be used in.
-    #
-    def create(function)
-      instance = function.value(self)
-      ptr = function.insn_address_of(instance)
-      return wrap(ptr)
-    end
-
-    # Return the offset (in bytes) of the element at the given +index+.
-    #
-    # +index+:: The index of the desired element.
-    #
-    def offset_of(index)
-      return self.get_offset(index)
-    end
-
-    # Return the type of the element at the given +index+.
-    #
-    # +index+:: The index of the desired element.
-    #
-    def type_of(index)
-      return @type
-    end
-
-    # An abstraction for an instance of a fixed-length array.
-    #
-    class Instance < JIT::Value
-      attr_reader :array_type
-      attr_reader :type
-
-      # A pointer to the first element of the array.  Note that this
-      # differs from +address+, which returns the address of a pointer
-      # to the array.
-      attr_reader :ptr
-
-      # TODO: This breaks code below?
-      # attr_reader :function
-
-      # Wrap an existing array.
-      #
-      # +array_type+:: The JIT::Array type to wrap.
-      # +ptr+::        A pointer to the first element in the array.
-      #
-      def self.wrap(array_type, ptr)
-        pointer_type = JIT::Type.create_pointer(array_type)
-        value = self.new_value(ptr.function, pointer_type)
-        value.store(ptr)
-        value.instance_eval do
-          @array_type = array_type
-          @type = array_type.type
-          @function = ptr.function
-          @ptr = ptr
-        end
-        return value
-      end
-
-      # Generate JIT code to retrieve the element at the given +index+.
-      #
-      # +index+:: The index of the desired element.  The value of the
-      #           index must be known at compile-time.
-      #
-      def [](index)
-        @function.insn_load_relative(
-            @ptr,
-            @array_type.offset_of(index),
-            @array_type.type_of(index))
-      end
-
-      # Generate JIT code to assign to the element at the given +index+.
-      #
-      # +index+:: The index of the desired element.  The value of the
-      #           index must be known at compile-time.
-      # +value+:: The JIT::Value to assign to the element.
-      #
-      def []=(index, value)
-        @function.insn_store_relative(
-            @ptr,
-            @array_type.offset_of(index),
-            value)
-      end
-    end
-  end
-end
-
diff -ruN libjit/jitruby/lib/jit/function.rb libjit-mikyt/jitruby/lib/jit/function.rb
--- libjit/jitruby/lib/jit/function.rb	2008-12-12 12:31:04.000000000 +0100
+++ libjit-mikyt/jitruby/lib/jit/function.rb	1970-01-01 01:00:00.000000000 +0100
@@ -1,200 +0,0 @@
-require 'jit'
-
-module JIT
-  class Function
-    # An abstraction for conditionals.
-    #
-    # Example usage:
-    #
-    #   function.if(condition) {
-    #     # condition is true
-    #   } .elsif(condition2) {
-    #     # condition2 is true
-    #   } .else {
-    #     # condition1 and condition2 are false
-    #   } .end
-    #
-    # Caution: if you omit end, then the generated code will have
-    # undefined behavior, but there will be no warning generated.
-    def if(cond, end_label = Label.new, &block)
-      false_label = Label.new
-      insn_branch_if_not(cond, false_label)
-      block.call
-      insn_branch(end_label)
-      insn_label(false_label)
-      return If.new(self, end_label)
-    end
-
-    # An abstraction for an inverted conditional.
-    #
-    # Example usage:
-    #
-    #   function.unless(condition) {
-    #     # condition is false
-    #   } .elsunless(condition2) {
-    #     # condition2 is false
-    #   } .else {
-    #     # condition1 and condition2 are true
-    #   } .end
-    #
-    # Caution: if you omit end, then the generated code will have
-    # undefined behavior, but there will be no warning generated.
-    def unless(cond, end_label = Label.new, &block)
-      true_label = Label.new
-      insn_branch_if(cond, true_label)
-      block.call
-      insn_branch(end_label)
-      insn_label(true_label)
-      return If.new(self, end_label)
-    end
-
-    class If # :nodoc:
-      def initialize(function, end_label)
-        @function = function
-        @end_label = end_label
-      end
-
-      def else(&block)
-        block.call
-        return self
-      end
-
-      def elsif(cond, &block)
-        return @function.if(cond, @end_label, &block)
-      end
-
-      def elsunless(cond, &block)
-        return @function.unless(cond, @end_label, &block)
-      end
-
-      def end
-        @function.insn_label(@end_label)
-      end
-    end
-
-    # An abstraction for a multi-way conditional.
-    #
-    # Example usage:
-    #
-    #   function.case(value1)
-    #   .when(value2) {
-    #     # value1 == value2
-    #   }.when(value3) {
-    #     # value1 == value3
-    #   } .else {
-    #     # all other cases fell through
-    #   } .end
-    #
-    # Caution: if you omit end, then the generated code will have
-    # undefined behavior, but there will be no warning generated.
-    def case(value)
-      return Case.new(self, value)
-    end
-
-    class Case # :nodoc:
-      def initialize(function, value)
-        @function = function
-        @value = value
-        @if = nil
-      end
-
-      def when(value, &block)
-        if not @if then
-          @if = @function.if(value == @value, &block)
-        else
-          @if.elsif(value == @value, &block)
-        end
-        return self
-      end
-
-      def else(&block)
-        @if.else(&block)
-      end
-
-      def end
-        @if.end if @if
-      end
-    end
-
-    # Usage:
-    #
-    #   until { <condition> }.do {
-    #     # loop body
-    #   } .end
-    #
-    def until(&block)
-      start_label = Label.new
-      done_label = Label.new
-      insn_label(start_label)
-      insn_branch_if(block.call, done_label)
-      loop = Loop.new(self, start_label, done_label)
-      return loop
-    end
-
-    # Usage:
-    #
-    #   while { <condition> }.do {
-    #     # loop body
-    #   } .end
-    #
-    def while(&block)
-      start_label = Label.new
-      done_label = Label.new
-      insn_label(start_label)
-      insn_branch_if_not(block.call, done_label)
-      loop = Loop.new(self, start_label, done_label)
-      return loop
-    end
-
-    class Loop # :nodoc:
-      def initialize(function, start_label, done_label)
-        @function = function
-        @start_label = start_label
-        @redo_label = start_label
-        @done_label = done_label
-      end
-
-      def do(&block)
-        block.call(self)
-        return self
-      end
-
-      def end
-        @function.insn_branch(@start_label)
-        @function.insn_label(@done_label)
-      end
-
-      def break
-        @function.insn_branch(@done_label)
-      end
-
-      def redo
-        @function.insn_branch(@redo_label)
-      end
-
-      def redo_from_here
-        @redo_label = JIT::Label.new
-        @function.insn_label(@redo_label)
-      end
-    end
-
-    # An alias for get_param
-    def param(n)
-      self.get_param(n)
-    end
-
-    # An alias for insn_return
-    def return(result)
-      self.insn_return(result)
-    end
-
-    # Create a JIT::Context and compile a new function within that
-    # context.
-    def self.build(*args, &block)
-      JIT::Context.build do |context|
-        JIT::Function.compile(context, *args, &block)
-      end
-    end
-  end
-end
-
diff -ruN libjit/jitruby/lib/jit/pointer.rb libjit-mikyt/jitruby/lib/jit/pointer.rb
--- libjit/jitruby/lib/jit/pointer.rb	2008-12-12 12:31:04.000000000 +0100
+++ libjit-mikyt/jitruby/lib/jit/pointer.rb	1970-01-01 01:00:00.000000000 +0100
@@ -1,98 +0,0 @@
-require 'jit'
-require 'jit/value'
-
-module JIT
-
-  # An abstraction for a pointer to a non-void type.
-  #
-  # Example usage:
-  #
-  # TODO
-  #
-  class Pointer < JIT::Type
-    attr_reader :type
-
-    # Create a new JIT pointer type.
-    #
-    # +type+::   The pointed-to type.
-    #
-    def self.new(type)
-      pointer_type = self.create_pointer(type)
-      pointer_type.instance_eval do
-        @type = type
-      end
-      return pointer_type
-    end
-
-    # Wrap an existing void pointer.
-    #
-    # +ptr+:: The pointer to wrap.
-    #
-    def wrap(ptr)
-      return Instance.wrap(self, ptr)
-    end
-
-    # Return the offset (in bytes) of the element at the given +index+.
-    #
-    # +index+:: The index of the desired element.
-    #
-    def offset_of(index)
-      return index * @type.size
-    end
-
-    # Return the type of the element at the given +index+.
-    #
-    # +index+:: The index of the desired element.
-    #
-    def type_of(index)
-      return @type
-    end
-
-    # An abstraction for a pointer object.
-    #
-    class Instance < JIT::Value
-      # Wrap an existing void pointer.
-      #
-      # +array_type+:: The JIT::Array type to wrap.
-      # +ptr+::        A pointer to the first element in the array.
-      #
-      def self.wrap(pointer_type, ptr)
-        value = self.new_value(ptr.function, pointer_type)
-        value.store(ptr)
-        value.instance_eval do
-          @pointer_type = pointer_type
-          @pointed_type = pointer_type.type
-          @function = ptr.function
-          @ptr = ptr
-        end
-        return value
-      end
-
-      # Generate JIT code to retrieve the element at the given +index+.
-      #
-      # +index+:: The index of the desired element.  The value of the
-      #           index must be known at compile-time.
-      #
-      def [](index)
-        @function.insn_load_relative(
-            @ptr,
-            @pointer_type.offset_of(index),
-            @pointer_type.type_of(index))
-      end
-
-      # Generate JIT code to assign to the element at the given +index+.
-      #
-      # +index+:: The index of the desired element.  The value of the
-      #           index must be known at compile-time.
-      # +value+:: The JIT::Value to assign to the element.
-      #
-      def []=(index, value)
-        @function.insn_store_relative(
-            @ptr,
-            @pointer_type.offset_of(index),
-            value)
-      end
-    end
-  end
-end
-
diff -ruN libjit/jitruby/lib/jit/struct.rb libjit-mikyt/jitruby/lib/jit/struct.rb
--- libjit/jitruby/lib/jit/struct.rb	2008-12-12 12:31:04.000000000 +0100
+++ libjit-mikyt/jitruby/lib/jit/struct.rb	1970-01-01 01:00:00.000000000 +0100
@@ -1,158 +0,0 @@
-require 'jit'
-
-module JIT
-
-  # An abstraction for a record composed of heterogenous fields.
-  #
-  # Example usage:
-  #
-  #   point_type = JIT::Struct.new(
-  #       [ :x, JIT::Type::INT ],
-  #       [ :y, JIT::Type::INT ],
-  #       [ :z, JIT::Type::INT ])
-  #
-  #   JIT::Context.build do |context|
-  #     signature = JIT::Type.create_signature(
-  #         JIT::ABI::CDECL, JIT::Type::INT, [ ])
-  #
-  #     function = JIT::Function.compile(context, signature) do |f|
-  #       point = point_type.create(f)
-  #       point.x = function.const(JIT::Type::INT, 1)
-  #       point.y = function.const(JIT::Type::INT, 2)
-  #       point.z = function.const(JIT::Type::INT, 3)
-  #       f.insn_return(point.x)
-  #     end
-  #
-  #   end
-  #
-  class Struct < JIT::Type
-
-    # Construct a new JIT structure type.
-    #
-    # +members+:: A list of members, where each element in the list is a
-    #             two-element array [ :name, type ]
-    #
-    def self.new(*members)
-      member_names = members.map { |m| m[0].to_s.intern }
-      member_types = members.map { |m| m[1] }
-      type = self.create_struct(member_types)
-      type.instance_eval do
-        @members = members
-        @member_names = member_names
-        @member_types = member_types
-        @index = Hash[*@member_names.zip((0..@member_names.size).to_a).flatten]
-      end
-      return type
-    end
-
-    # Return the names of the members in the structure.
-    def members
-      return @member_names
-    end
-
-    # Wrap an existing structure.
-    #
-    # +ptr+:: A pointer to the first element in the structure.
-    #
-    def wrap(ptr)
-      return Instance.new(self, ptr)
-    end
-
-    # Create a new structure.
-    #
-    # +function+:: The JIT::Function this structure will be used in.
-    #
-    def create(function)
-      instance = function.value(self)
-      ptr = function.insn_address_of(instance)
-      return wrap(ptr)
-    end
-
-    # Return the offset (in bytes) of the element with the given name.
-    #
-    # +name+:: The name of the desired element.
-    #
-    def offset_of(name)
-      name = (Symbol === name) ? name : name.to_s.intern
-      return self.get_offset(@index[name])
-    end
-
-    # Change the offset of the element with the given name.
-    #
-    # +name+::   The name of the desired element.
-    # +offset+:: The new offset.
-    #
-    def set_offset_of(name, offset)
-      name = (Symbol === name) ? name : name.to_s.intern
-      return self.set_offset(@index[name], offset)
-    end
-
-    # Return the type of the element with the given name.
-    #
-    # +name+:: The name of the desired element.
-    #
-    def type_of(name)
-      name = (Symbol === name) ? name : name.to_s.intern
-      return @member_types[@index[name]]
-    end
-
-    # An abstraction for an instance of a JIT::Struct.
-    #
-    class Instance
-      attr_reader :ptr
-
-      # Wrap an existing structure.
-      #
-      # +struct+:: The JIT::Struct type to wrap.
-      # +ptr+      A pointer to the first element of the structure.
-      #
-      def initialize(struct, ptr)
-        @struct = struct
-        @function = ptr.function
-        @ptr = ptr
-
-        mod = Module.new do
-          struct.members.each do |name|
-            define_method("#{name}") do
-              self[name] # return
-            end
-
-            define_method("#{name}=") do |value|
-              self[name] = value # return
-            end
-          end
-        end
-
-        extend(mod)
-      end
-
-      # Generate JIT code to retrieve the element with the given name.
-      #
-      # +name+:: The name of the desired element.
-      #
-      def [](name)
-        @function.insn_load_relative(
-            @ptr,
-            @struct.offset_of(name),
-            @struct.type_of(name))
-      end
-
-      # Generate JIT code to assign to the element with the given name.
-      #
-      # +name+::  The name of the desired element.
-      # +value+:: The JIT::Value to assign to the element.
-      #
-      def []=(name, value)
-        @function.insn_store_relative(
-            @ptr,
-            @struct.offset_of(name),
-            value)
-      end
-
-      def members
-        return @struct.members
-      end
-    end
-  end
-end
-
diff -ruN libjit/jitruby/lib/jit/value.rb libjit-mikyt/jitruby/lib/jit/value.rb
--- libjit/jitruby/lib/jit/value.rb	2008-12-12 12:31:04.000000000 +0100
+++ libjit-mikyt/jitruby/lib/jit/value.rb	1970-01-01 01:00:00.000000000 +0100
@@ -1,199 +0,0 @@
-require 'jit'
-
-module JIT
-  class Value
-    module UNINITIALIZED; end
-
-    # Create a new JIT::Value.  If value is specified, the value will be
-    # variable, otherwise it will be a constant with the given value.
-    #
-    # +function+:: The function to which this value will belong.
-    # +type+::     The type of the new value.
-    # +value+:     The value to use, if this is a constant.
-    #
-    def self.new(function, type, value=UNINITIALIZED)
-      # TODO: Not sure if I like this...
-      if value == UNINITIALIZED then
-        return function.value(type)
-      else
-        return function.const(type, value)
-      end
-    end
-
-    # Assign +value+ to this JIT::Value.
-    #
-    # +value+:: The value to assign.
-    #
-    def store(value)
-      lhs, rhs = coerce(value)
-      self.function.insn_store(lhs, rhs)
-    end
-
-    # Return the address of this value.
-    def address
-      return self.function.insn_address_of(self)
-    end
-
-    # Add this value to another and return the result.
-    #
-    # +rhs+:: The right hand side of the addition operator.
-    #
-    def +(rhs)
-      lhs, rhs = coerce(rhs)
-      return self.function.insn_add(lhs, rhs)
-    end
-
-    # Subtract another value from this one and return the result.
-    #
-    # +rhs+:: The right hand side of the subtraction operator.
-    #
-    def -(rhs)
-      lhs, rhs = coerce(rhs)
-      return self.function.insn_sub(lhs, rhs)
-    end
-
-    # Multiply this value by another and return the result.
-    #
-    # +rhs+:: The right hand side of the multiplication operator.
-    #
-    def *(rhs)
-      lhs, rhs = coerce(rhs)
-      return self.function.insn_mul(lhs, rhs)
-    end
-
-    # Divide this value by another and return the quotient.
-    #
-    # +rhs+:: The right hand side of the division operator.
-    #
-    def /(rhs)
-      lhs, rhs = coerce(rhs)
-      return self.function.insn_div(lhs, rhs)
-    end
-
-    # Return the additive inverse (negation) of this value.
-    def -@()
-      rhs, lhs = coerce(0) # inverted, since we are subtracting from 0
-      return lhs - rhs
-    end
-
-    # Divide this value by another and return the remainder.
-    #
-    # +rhs+:: The right hand side of the modulus operator.
-    #
-    def %(rhs)
-      lhs, rhs = coerce(rhs)
-      return self.function.insn_rem(lhs, rhs)
-    end
-
-    # Perform a bitwise and between this value and another.
-    #
-    # +rhs+:: The right hand side of the operator.
-    #
-    def &(rhs)
-      lhs, rhs = coerce(rhs)
-      return self.function.insn_and(lhs, rhs)
-    end
-
-    # Perform a bitwise or between this value and another.
-    #
-    # +rhs+:: The right hand side of the operator.
-    #
-    def |(rhs)
-      lhs, rhs = coerce(rhs)
-      return self.function.insn_or(lhs, rhs)
-    end
-
-    # Perform a bitwise xor between this value and another.
-    #
-    # +rhs+:: The right hand side of the operator.
-    #
-    def ^(rhs)
-      lhs, rhs = coerce(rhs)
-      return self.function.insn_xor(lhs, rhs)
-    end
-
-    # Compare this value to another, returning 1 if the left hand is
-    # less than the right hand side or 0 otherwise.
-    #
-    # +rhs+:: The right hand side of the comparison.
-    #
-    def <(rhs)
-      lhs, rhs = coerce(rhs)
-      return self.function.insn_lt(lhs, rhs)
-    end
-
-    # Compare this value to another, returning 1 if the left hand is
-    # greater than the right hand side or 0 otherwise.
-    #
-    # +rhs+:: The right hand side of the comparison.
-    #
-    def >(rhs)
-      lhs, rhs = coerce(rhs)
-      return self.function.insn_gt(lhs, rhs)
-    end
-
-    # Compare this value to another, returning 1 if the left hand is
-    # equal to the right hand side or 0 otherwise.
-    #
-    # +rhs+:: The right hand side of the comparison.
-    #
-    def ==(rhs)
-      lhs, rhs = coerce(rhs)
-      return self.function.insn_eq(lhs, rhs)
-    end
-
-    # Compare this value to another, returning 1 if the left hand is
-    # not equal to the right hand side or 0 otherwise.
-    #
-    # +rhs+:: The right hand side of the comparison.
-    #
-    def neq(rhs)
-      lhs, rhs = coerce(rhs)
-      return self.function.insn_ne(lhs, rhs)
-    end
-
-    # Compare this value to another, returning 1 if the left hand is
-    # less than or equal to the right hand side or 0 otherwise.
-    #
-    # +rhs+:: The right hand side of the comparison.
-    #
-    def <=(rhs)
-      lhs, rhs = coerce(rhs)
-      return self.function.insn_le(lhs, rhs)
-    end
-
-    # Compare this value to another, returning 1 if the left hand is
-    # greater than or equal to the right hand side or 0 otherwise.
-    #
-    # +rhs+:: The right hand side of the comparison.
-    #
-    def >=(rhs)
-      lhs, rhs = coerce(rhs)
-      return self.function.insn_ge(lhs, rhs)
-    end
-
-    # Shift this value left by the given number of bits.
-    #
-    # +rhs+:: The number of bits to shift by.
-    #
-    def <<(rhs)
-      lhs, rhs = coerce(rhs)
-      return self.function.insn_shl(lhs, rhs)
-    end
-
-    # Shift this value right by the given number of bits.
-    #
-    # +rhs+:: The number of bits to shift by.
-    #
-    def >>(rhs)
-      lhs, rhs = coerce(rhs)
-      return self.function.insn_shr(lhs, rhs)
-    end
-
-    # Return the logical inverse of this value.
-    def ~()
-      return self.function.insn_not(self)
-    end
-  end
-end
-
diff -ruN libjit/jitruby/lib/jit.rb libjit-mikyt/jitruby/lib/jit.rb
--- libjit/jitruby/lib/jit.rb	2008-12-12 12:31:03.000000000 +0100
+++ libjit-mikyt/jitruby/lib/jit.rb	1970-01-01 01:00:00.000000000 +0100
@@ -1,5 +0,0 @@
-require 'jit.so'
-require 'jit/array'
-require 'jit/function'
-require 'jit/struct'
-require 'jit/value'
diff -ruN libjit/jitruby/metaconfig libjit-mikyt/jitruby/metaconfig
--- libjit/jitruby/metaconfig	2008-12-12 12:30:58.000000000 +0100
+++ libjit-mikyt/jitruby/metaconfig	1970-01-01 01:00:00.000000000 +0100
@@ -1,4 +0,0 @@
-add_bool_config(
-  'without-tests',
-  false,
-  'does not run tests')
diff -ruN libjit/jitruby/post-install.rb libjit-mikyt/jitruby/post-install.rb
--- libjit/jitruby/post-install.rb	2008-12-12 12:30:58.000000000 +0100
+++ libjit-mikyt/jitruby/post-install.rb	1970-01-01 01:00:00.000000000 +0100
@@ -1,4 +0,0 @@
-require 'generate_rdoc'
-
-generate_rdoc('--ri-site')
-
diff -ruN libjit/jitruby/post-setup.rb libjit-mikyt/jitruby/post-setup.rb
--- libjit/jitruby/post-setup.rb	2008-12-12 12:30:58.000000000 +0100
+++ libjit-mikyt/jitruby/post-setup.rb	1970-01-01 01:00:00.000000000 +0100
@@ -1,7 +0,0 @@
-require 'run_tests'
-require 'generate_rdoc'
-
-if config('without-tests') != 'yes' then
-  run_tests()
-end
-
diff -ruN libjit/jitruby/ruby-libjit.gemspec libjit-mikyt/jitruby/ruby-libjit.gemspec
--- libjit/jitruby/ruby-libjit.gemspec	2008-12-12 12:30:58.000000000 +0100
+++ libjit-mikyt/jitruby/ruby-libjit.gemspec	1970-01-01 01:00:00.000000000 +0100
@@ -1,39 +0,0 @@
-require 'enumerator'
-
-spec = Gem::Specification.new do |s|
-  s.name = 'ruby-libjit'
-  s.version = '0.1.0'
-  s.summary = 'A wrapper for the libjit library'
-  s.homepage = 'http://ruby-libjit.rubyforge.org'
-  s.rubyforge_project = 'ruby-libjit'
-  s.author = 'Paul Brannan'
-  s.email = 'curlypaul924@gmail.com'
-
-  s.description = <<-END
-A wrapper for the libjit library
-  END
-
-
-  patterns = [
-    'COPYING',
-    'LGPL',
-    'LICENSE',
-    'README',
-    'lib/*.rb',
-    'lib/jit/*.rb',
-    'ext/*.rb',
-    'ext/*.c',
-    'ext/*.h',
-    'ext/*.rpp',
-    'sample/*.rb',
-  ]
-
-  s.files = patterns.collect { |p| Dir.glob(p) }.flatten
-
-  s.test_files = Dir.glob('test/test_*.rb')
-
-  s.extensions = 'ext/extconf.rb'
-
-  s.has_rdoc = true
-end
-
diff -ruN libjit/jitruby/run_tests.rb libjit-mikyt/jitruby/run_tests.rb
--- libjit/jitruby/run_tests.rb	2008-12-12 12:30:58.000000000 +0100
+++ libjit-mikyt/jitruby/run_tests.rb	1970-01-01 01:00:00.000000000 +0100
@@ -1,81 +0,0 @@
-$mini_unit_exit_code = 0
-
-def disable_mini_unit_auto_run
-  MiniTest::Unit.class_eval do
-    alias :run_ :run
-    def run(*args)
-      return $mini_unit_exit_code
-    end
-  end
-end
-
-def run_tests_with_mini_unit
-  begin
-    test = MiniTest::Unit.new
-    args = ARGV.dup
-    args << '-v'
-    $mini_unit_exit_code = test.run(args)
-    exit($mini_unit_exit_code)
-  ensure
-    disable_mini_unit_auto_run
-  end
-end
-
-def run_tests_with_test_unit
-  tests = []
-  ObjectSpace.each_object(Class) do |o|
-    if o < Test::Unit::TestCase then
-      tests << o
-    end
-  end
-
-  suite = Test::Unit::TestSuite.new("RubyInternal")
-  tests.each do |test|
-    test.suite.tests.each do |testcase|
-      suite << testcase
-    end
-  end
-
-  require 'test/unit/ui/console/testrunner'
-  verbose = nil
-  begin
-    verbose = Test::Unit::UI.const_get(:VERBOSE)
-  rescue NameError
-    verbose = Test::Unit::UI::Console::TestRunner.const_get(:VERBOSE)
-  end
-
-  result = Test::Unit::UI::Console::TestRunner.run(
-      suite,
-      verbose)
-  exit(result.error_count + result.failure_count)
-end
-
-def run_tests
-  begin
-    require 'test/unit'
-  rescue LoadError
-    puts "WARNING: Test::Unit not installed; skipping tests"
-    return
-  end
-
-  $:.unshift(File.join(Dir.pwd, 'ext'))
-  $:.unshift(File.join(Dir.pwd, 'lib'))
-  Dir.chdir('test')
-  tests = Dir['test_*.rb']
-  tests.each do |test|
-    load test
-  end
-
-  if defined?(MiniTest) then
-    run_tests_with_mini_unit
-  else
-    run_tests_with_test_unit
-  end
-end
-
-if __FILE__ == $0 then
-  require 'timeout'
-  result = nil
-  timeout(600) { run_tests() }
-end
-
diff -ruN libjit/jitruby/sample/fib.rb libjit-mikyt/jitruby/sample/fib.rb
--- libjit/jitruby/sample/fib.rb	2008-12-12 12:31:04.000000000 +0100
+++ libjit-mikyt/jitruby/sample/fib.rb	1970-01-01 01:00:00.000000000 +0100
@@ -1,29 +0,0 @@
-require 'jit'
-
-fib = nil
-signature = JIT::Type.create_signature(
-    :CDECL,
-    :INT,
-    [ :INT ])
-fib = JIT::Function.build(signature) do |f|
-  n = f.param(0)
-
-  a = f.value(:INT, 0)
-  b = f.value(:INT, 1)
-  c = f.value(:INT, 1)
-
-  i = f.value(:INT, 0)
-
-  f.while{ i < n }.do {
-    c.store(a + b)
-    a.store(b)
-    b.store(c)
-    i.store(i + 1)
-  }.end
-
-  f.return(c)
-end
-
-values = (0...10).collect { |x| fib.apply(x) }
-p values #=> [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
-
diff -ruN libjit/jitruby/sample/gcd_benchmark.rb libjit-mikyt/jitruby/sample/gcd_benchmark.rb
--- libjit/jitruby/sample/gcd_benchmark.rb	2008-12-12 12:31:04.000000000 +0100
+++ libjit-mikyt/jitruby/sample/gcd_benchmark.rb	1970-01-01 01:00:00.000000000 +0100
@@ -1,117 +0,0 @@
-require 'jit'
-require 'benchmark'
-
-# GCD, JIT-compiled
-
-jit_gcd = nil
-
-JIT::Context.build do |context|
-  signature = JIT::Type.create_signature(
-      JIT::ABI::CDECL,
-      JIT::Type::INT,
-      [ JIT::Type::INT, JIT::Type::INT ])
-  jit_gcd = JIT::Function.compile(context, signature) do |f|
-    x = f.get_param(0)
-    y = f.get_param(1)
-    temp1 = f.insn_eq(x, y)
-    label1 = JIT::Label.new
-    f.insn_branch_if_not(temp1, label1)
-    f.insn_return(x)
-    f.insn_label(label1)
-    temp2 = f.insn_lt(x, y)
-    label2 = JIT::Label.new
-    f.insn_branch_if_not(temp2, label2)
-    s1 = f.insn_sub(y, x)
-    temp3 = f.insn_call("gcd", f, 0, x, s1)
-    f.insn_return(temp3)
-    f.insn_label(label2)
-    s2 = f.insn_sub(x, y)
-    temp4 = f.insn_call("gcd", f, 0, s2, y)
-    f.insn_return(temp4)
-
-    f.optimization_level = 3
-  end
-end
-
-if jit_gcd.apply(28, 21) != 7 then
-  puts "jit_gcd is broken"
-  exit 1
-end
-
-
-# GCD with tail recursion optimization
-
-jit_gcd_tail = nil
-
-JIT::Context.build do |context|
-  signature = JIT::Type.create_signature(
-      JIT::ABI::CDECL,
-      JIT::Type::INT,
-      [ JIT::Type::INT, JIT::Type::INT ])
-  jit_gcd_tail = JIT::Function.compile(context, signature) do |f|
-    x = f.get_param(0)
-    y = f.get_param(1)
-    temp1 = f.insn_eq(x, y)
-    label1 = JIT::Label.new
-    f.insn_branch_if_not(temp1, label1)
-    f.insn_return(x)
-    f.insn_label(label1)
-    temp2 = f.insn_lt(x, y)
-    label2 = JIT::Label.new
-    f.insn_branch_if_not(temp2, label2)
-    s1 = f.insn_sub(y, x)
-    temp3 = f.insn_call("gcd", f, JIT::Call::TAIL, x, s1)
-    # f.insn_return(temp3)
-    f.insn_label(label2)
-    s2 = f.insn_sub(x, y)
-    temp4 = f.insn_call("gcd", f, JIT::Call::TAIL, s2, x)
-    # f.insn_return(temp4)
-
-    f.optimization_level = 3
-  end
-end
-
-if jit_gcd_tail.apply(28, 21) != 7 then
-  puts "jit_gcd_tail is broken"
-  exit 1
-end
-
-
-# GCD in ruby with recursion
-
-def gcd(x, y)
-  if x == y
-    return x
-  elsif x < y
-    return gcd(x, y - x)
-  else
-    return gcd(x - y, y)
-  end
-end
-
-
-# GCD in ruby without recursion
-
-def gcd2(x, y)
-  while x != y do
-    if x < y
-      y -= x
-    else
-      x -= y
-    end
-  end
-  return x
-end
-
-N = 1000
-
-X = 1000
-Y = 1005
-
-Benchmark.bm(16) do |x|
-  x.report("jit")            { N.times { jit_gcd.apply(X, Y) } }
-  x.report("jit tail:")      { N.times { jit_gcd_tail.apply(X, Y) } }
-  x.report("ruby recur:")    { N.times { gcd(X, Y) } }
-  x.report("ruby iter:")     { N.times { gcd2(X, Y) } }
-end
-
diff -ruN libjit/jitruby/sample/simple.rb libjit-mikyt/jitruby/sample/simple.rb
--- libjit/jitruby/sample/simple.rb	2008-12-12 12:31:04.000000000 +0100
+++ libjit-mikyt/jitruby/sample/simple.rb	1970-01-01 01:00:00.000000000 +0100
@@ -1,15 +0,0 @@
-require 'jit'
-
-function = nil
-JIT::Context.build do |context|
-  signature = JIT::Type.create_signature(
-      JIT::ABI::CDECL,
-      JIT::Type::INT,       # returns an integer
-      [ JIT::Type::INT ])   # and tages an integer as a parameter
-  function = JIT::Function.compile(context, signature) do |f|
-    value = f.get_param(0)
-    f.insn_return(value)
-  end
-end
-
-p function.apply(42) #=> 42
diff -ruN libjit/jitruby/setup.rb libjit-mikyt/jitruby/setup.rb
--- libjit/jitruby/setup.rb	2008-12-12 12:30:58.000000000 +0100
+++ libjit-mikyt/jitruby/setup.rb	1970-01-01 01:00:00.000000000 +0100
@@ -1,1599 +0,0 @@
-#
-# setup.rb
-#
-# Copyright (c) 2000-2006 Minero Aoki
-#
-# This program is free software.
-# You can distribute/modify this program under the terms of
-# the GNU LGPL, Lesser General Public License version 2.1.
-#
-
-unless Enumerable.method_defined?(:map)   # Ruby 1.4.6
-  module Enumerable
-    alias map collect
-  end
-end
-
-unless File.respond_to?(:read)   # Ruby 1.6
-  def File.read(fname)
-    open(fname) {|f|
-      return f.read
-    }
-  end
-end
-
-unless Errno.const_defined?(:ENOTEMPTY)   # Windows?
-  module Errno
-    class ENOTEMPTY
-      # We do not raise this exception, implementation is not needed.
-    end
-  end
-end
-
-def File.binread(fname)
-  open(fname, 'rb') {|f|
-    return f.read
-  }
-end
-
-# for corrupted Windows' stat(2)
-def File.dir?(path)
-  File.directory?((path[-1,1] == '/') ? path : path + '/')
-end
-
-
-class ConfigTable
-
-  include Enumerable
-
-  def initialize(rbconfig)
-    @rbconfig = rbconfig
-    @items = []
-    @table = {}
-    # options
-    @install_prefix = nil
-    @config_opt = nil
-    @verbose = true
-    @no_harm = false
-  end
-
-  attr_accessor :install_prefix
-  attr_accessor :config_opt
-
-  attr_writer :verbose
-
-  def verbose?
-    @verbose
-  end
-
-  attr_writer :no_harm
-
-  def no_harm?
-    @no_harm
-  end
-
-  def [](key)
-    lookup(key).resolve(self)
-  end
-
-  def []=(key, val)
-    lookup(key).set val
-  end
-
-  def names
-    @items.map {|i| i.name }
-  end
-
-  def each(&block)
-    @items.each(&block)
-  end
-
-  def key?(name)
-    @table.key?(name)
-  end
-
-  def lookup(name)
-    @table[name] or setup_rb_error "no such config item: #{name}"
-  end
-
-  def add(item)
-    @items.push item
-    @table[item.name] = item
-  end
-
-  def remove(name)
-    item = lookup(name)
-    @items.delete_if {|i| i.name == name }
-    @table.delete_if {|name, i| i.name == name }
-    item
-  end
-
-  def load_script(path, inst = nil)
-    if File.file?(path)
-      MetaConfigEnvironment.new(self, inst).instance_eval File.read(path), path
-    end
-  end
-
-  def savefile
-    '.config'
-  end
-
-  def load_savefile
-    begin
-      File.foreach(savefile()) do |line|
-        k, v = *line.split(/=/, 2)
-        self[k] = v.strip
-      end
-    rescue Errno::ENOENT
-      setup_rb_error $!.message + "\n#{File.basename($0)} config first"
-    end
-  end
-
-  def save
-    @items.each {|i| i.value }
-    File.open(savefile(), 'w') {|f|
-      @items.each do |i|
-        f.printf "%s=%s\n", i.name, i.value if i.value? and i.value
-      end
-    }
-  end
-
-  def load_standard_entries
-    standard_entries(@rbconfig).each do |ent|
-      add ent
-    end
-  end
-
-  def standard_entries(rbconfig)
-    c = rbconfig
-
-    rubypath = File.join(c['bindir'], c['ruby_install_name'] + c['EXEEXT'])
-
-    major = c['MAJOR'].to_i
-    minor = c['MINOR'].to_i
-    teeny = c['TEENY'].to_i
-    version = "#{major}.#{minor}"
-
-    # ruby ver. >= 1.4.4?
-    newpath_p = ((major >= 2) or
-                 ((major == 1) and
-                  ((minor >= 5) or
-                   ((minor == 4) and (teeny >= 4)))))
-
-    if c['rubylibdir']
-      # V > 1.6.3
-      libruby         = "#{c['prefix']}/lib/ruby"
-      librubyver      = c['rubylibdir']
-      librubyverarch  = c['archdir']
-      siteruby        = c['sitedir']
-      siterubyver     = c['sitelibdir']
-      siterubyverarch = c['sitearchdir']
-    elsif newpath_p
-      # 1.4.4 <= V <= 1.6.3
-      libruby         = "#{c['prefix']}/lib/ruby"
-      librubyver      = "#{c['prefix']}/lib/ruby/#{version}"
-      librubyverarch  = "#{c['prefix']}/lib/ruby/#{version}/#{c['arch']}"
-      siteruby        = c['sitedir']
-      siterubyver     = "$siteruby/#{version}"
-      siterubyverarch = "$siterubyver/#{c['arch']}"
-    else
-      # V < 1.4.4
-      libruby         = "#{c['prefix']}/lib/ruby"
-      librubyver      = "#{c['prefix']}/lib/ruby/#{version}"
-      librubyverarch  = "#{c['prefix']}/lib/ruby/#{version}/#{c['arch']}"
-      siteruby        = "#{c['prefix']}/lib/ruby/#{version}/site_ruby"
-      siterubyver     = siteruby
-      siterubyverarch = "$siterubyver/#{c['arch']}"
-    end
-    parameterize = lambda {|path|
-      path.sub(/\A#{Regexp.quote(c['prefix'])}/, '$prefix')
-    }
-
-    if arg = c['configure_args'].split.detect {|arg| /--with-make-prog=/ =~ arg }
-      makeprog = arg.sub(/'/, '').split(/=/, 2)[1]
-    else
-      makeprog = 'make'
-    end
-
-    [
-      ExecItem.new('installdirs', 'std/site/home',
-                   'std: install under libruby; site: install under site_ruby; home: install under $HOME')\
-          {|val, table|
-            case val
-            when 'std'
-              table['rbdir'] = '$librubyver'
-              table['sodir'] = '$librubyverarch'
-            when 'site'
-              table['rbdir'] = '$siterubyver'
-              table['sodir'] = '$siterubyverarch'
-            when 'home'
-              setup_rb_error '$HOME was not set' unless ENV['HOME']
-              table['prefix'] = ENV['HOME']
-              table['rbdir'] = '$libdir/ruby'
-              table['sodir'] = '$libdir/ruby'
-            end
-          },
-      PathItem.new('prefix', 'path', c['prefix'],
-                   'path prefix of target environment'),
-      PathItem.new('bindir', 'path', parameterize.call(c['bindir']),
-                   'the directory for commands'),
-      PathItem.new('libdir', 'path', parameterize.call(c['libdir']),
-                   'the directory for libraries'),
-      PathItem.new('datadir', 'path', parameterize.call(c['datadir']),
-                   'the directory for shared data'),
-      PathItem.new('mandir', 'path', parameterize.call(c['mandir']),
-                   'the directory for man pages'),
-      PathItem.new('sysconfdir', 'path', parameterize.call(c['sysconfdir']),
-                   'the directory for system configuration files'),
-      PathItem.new('localstatedir', 'path', parameterize.call(c['localstatedir']),
-                   'the directory for local state data'),
-      PathItem.new('libruby', 'path', libruby,
-                   'the directory for ruby libraries'),
-      PathItem.new('librubyver', 'path', librubyver,
-                   'the directory for standard ruby libraries'),
-      PathItem.new('librubyverarch', 'path', librubyverarch,
-                   'the directory for standard ruby extensions'),
-      PathItem.new('siteruby', 'path', siteruby,
-          'the directory for version-independent aux ruby libraries'),
-      PathItem.new('siterubyver', 'path', siterubyver,
-                   'the directory for aux ruby libraries'),
-      PathItem.new('siterubyverarch', 'path', siterubyverarch,
-                   'the directory for aux ruby binaries'),
-      PathItem.new('rbdir', 'path', '$siterubyver',
-                   'the directory for ruby scripts'),
-      PathItem.new('sodir', 'path', '$siterubyverarch',
-                   'the directory for ruby extentions'),
-      PathItem.new('rubypath', 'path', rubypath,
-                   'the path to set to #! line'),
-      ProgramItem.new('rubyprog', 'name', rubypath,
-                      'the ruby program using for installation'),
-      ProgramItem.new('makeprog', 'name', makeprog,
-                      'the make program to compile ruby extentions'),
-      SelectItem.new('shebang', 'all/ruby/never', 'ruby',
-                     'shebang line (#!) editing mode'),
-      BoolItem.new('without-ext', 'yes/no', 'no',
-                   'does not compile/install ruby extentions')
-    ]
-  end
-  private :standard_entries
-
-  def load_multipackage_entries
-    multipackage_entries().each do |ent|
-      add ent
-    end
-  end
-
-  def multipackage_entries
-    [
-      PackageSelectionItem.new('with', 'name,name...', '', 'ALL',
-                               'package names that you want to install'),
-      PackageSelectionItem.new('without', 'name,name...', '', 'NONE',
-                               'package names that you do not want to install')
-    ]
-  end
-  private :multipackage_entries
-
-  ALIASES = {
-    'std-ruby'         => 'librubyver',
-    'stdruby'          => 'librubyver',
-    'rubylibdir'       => 'librubyver',
-    'archdir'          => 'librubyverarch',
-    'site-ruby-common' => 'siteruby',     # For backward compatibility
-    'site-ruby'        => 'siterubyver',  # For backward compatibility
-    'bin-dir'          => 'bindir',
-    'bin-dir'          => 'bindir',
-    'rb-dir'           => 'rbdir',
-    'so-dir'           => 'sodir',
-    'data-dir'         => 'datadir',
-    'ruby-path'        => 'rubypath',
-    'ruby-prog'        => 'rubyprog',
-    'ruby'             => 'rubyprog',
-    'make-prog'        => 'makeprog',
-    'make'             => 'makeprog'
-  }
-
-  def fixup
-    ALIASES.each do |ali, name|
-      @table[ali] = @table[name]
-    end
-  end
-
-  def options_re
-    /\A--(#{@table.keys.join('|')})(?:=(.*))?\z/
-  end
-
-  def parse_opt(opt)
-    m = options_re().match(opt) or setup_rb_error "config: unknown option #{opt}"
-    m.to_a[1,2]
-  end
-
-  def dllext
-    @rbconfig['DLEXT']
-  end
-
-  def value_config?(name)
-    lookup(name).value?
-  end
-
-  class Item
-    def initialize(name, template, default, desc)
-      @name = name.freeze
-      @template = template
-      @value = default
-      @default = default
-      @description = desc
-    end
-
-    attr_reader :name
-    attr_reader :description
-
-    attr_accessor :default
-    alias help_default default
-
-    def help_opt
-      "--#{@name}=#{@template}"
-    end
-
-    def value?
-      true
-    end
-
-    def value
-      @value
-    end
-
-    def resolve(table)
-      @value.gsub(%r<\$([^/]+)>) { table[$1] }
-    end
-
-    def set(val)
-      @value = check(val)
-    end
-
-    private
-
-    def check(val)
-      setup_rb_error "config: --#{name} requires argument" unless val
-      val
-    end
-  end
-
-  class BoolItem < Item
-    def config_type
-      'bool'
-    end
-
-    def help_opt
-      "--#{@name}"
-    end
-
-    private
-
-    def check(val)
-      return 'yes' unless val
-      case val
-      when /\Ay(es)?\z/i, /\At(rue)?\z/i then 'yes'
-      when /\An(o)?\z/i, /\Af(alse)\z/i  then 'no'
-      else
-        setup_rb_error "config: --#{@name} accepts only yes/no for argument"
-      end
-    end
-  end
-
-  class PathItem < Item
-    def config_type
-      'path'
-    end
-
-    private
-
-    def check(path)
-      setup_rb_error "config: --#{@name} requires argument"  unless path
-      path[0,1] == '$' ? path : File.expand_path(path)
-    end
-  end
-
-  class ProgramItem < Item
-    def config_type
-      'program'
-    end
-  end
-
-  class SelectItem < Item
-    def initialize(name, selection, default, desc)
-      super
-      @ok = selection.split('/')
-    end
-
-    def config_type
-      'select'
-    end
-
-    private
-
-    def check(val)
-      unless @ok.include?(val.strip)
-        setup_rb_error "config: use --#{@name}=#{@template} (#{val})"
-      end
-      val.strip
-    end
-  end
-
-  class ExecItem < Item
-    def initialize(name, selection, desc, &block)
-      super name, selection, nil, desc
-      @ok = selection.split('/')
-      @action = block
-    end
-
-    def config_type
-      'exec'
-    end
-
-    def value?
-      false
-    end
-
-    def resolve(table)
-      setup_rb_error "$#{name()} wrongly used as option value"
-    end
-
-    undef set
-
-    def evaluate(val, table)
-      v = val.strip.downcase
-      unless @ok.include?(v)
-        setup_rb_error "invalid option --#{@name}=#{val} (use #{@template})"
-      end
-      @action.call v, table
-    end
-  end
-
-  class PackageSelectionItem < Item
-    def initialize(name, template, default, help_default, desc)
-      super name, template, default, desc
-      @help_default = help_default
-    end
-
-    attr_reader :help_default
-
-    def config_type
-      'package'
-    end
-
-    private
-
-    def check(val)
-      unless File.dir?("packages/#{val}")
-        setup_rb_error "config: no such package: #{val}"
-      end
-      val
-    end
-  end
-
-  class MetaConfigEnvironment
-    def initialize(config, installer)
-      @config = config
-      @installer = installer
-    end
-
-    def config_names
-      @config.names
-    end
-
-    def config?(name)
-      @config.key?(name)
-    end
-
-    def bool_config?(name)
-      @config.lookup(name).config_type == 'bool'
-    end
-
-    def path_config?(name)
-      @config.lookup(name).config_type == 'path'
-    end
-
-    def value_config?(name)
-      @config.lookup(name).config_type != 'exec'
-    end
-
-    def add_config(item)
-      @config.add item
-    end
-
-    def add_bool_config(name, default, desc)
-      @config.add BoolItem.new(name, 'yes/no', default ? 'yes' : 'no', desc)
-    end
-
-    def add_path_config(name, default, desc)
-      @config.add PathItem.new(name, 'path', default, desc)
-    end
-
-    def set_config_default(name, default)
-      @config.lookup(name).default = default
-    end
-
-    def remove_config(name)
-      @config.remove(name)
-    end
-
-    # For only multipackage
-    def packages
-      raise '[setup.rb fatal] multi-package metaconfig API packages() called for single-package; contact application package vendor' unless @installer
-      @installer.packages
-    end
-
-    # For only multipackage
-    def declare_packages(list)
-      raise '[setup.rb fatal] multi-package metaconfig API declare_packages() called for single-package; contact application package vendor' unless @installer
-      @installer.packages = list
-    end
-  end
-
-end   # class ConfigTable
-
-
-# This module requires: #verbose?, #no_harm?
-module FileOperations
-
-  def mkdir_p(dirname, prefix = nil)
-    dirname = prefix + File.expand_path(dirname) if prefix
-    $stderr.puts "mkdir -p #{dirname}" if verbose?
-    return if no_harm?
-
-    # Does not check '/', it's too abnormal.
-    dirs = File.expand_path(dirname).split(%r<(?=/)>)
-    if /\A[a-z]:\z/i =~ dirs[0]
-      disk = dirs.shift
-      dirs[0] = disk + dirs[0]
-    end
-    dirs.each_index do |idx|
-      path = dirs[0..idx].join('')
-      Dir.mkdir path unless File.dir?(path)
-    end
-  end
-
-  def rm_f(path)
-    $stderr.puts "rm -f #{path}" if verbose?
-    return if no_harm?
-    force_remove_file path
-  end
-
-  def rm_rf(path)
-    $stderr.puts "rm -rf #{path}" if verbose?
-    return if no_harm?
-    remove_tree path
-  end
-
-  def remove_tree(path)
-    if File.symlink?(path)
-      remove_file path
-    elsif File.dir?(path)
-      remove_tree0 path
-    else
-      force_remove_file path
-    end
-  end
-
-  def remove_tree0(path)
-    Dir.foreach(path) do |ent|
-      next if ent == '.'
-      next if ent == '..'
-      entpath = "#{path}/#{ent}"
-      if File.symlink?(entpath)
-        remove_file entpath
-      elsif File.dir?(entpath)
-        remove_tree0 entpath
-      else
-        force_remove_file entpath
-      end
-    end
-    begin
-      Dir.rmdir path
-    rescue Errno::ENOTEMPTY
-      # directory may not be empty
-    end
-  end
-
-  def move_file(src, dest)
-    force_remove_file dest
-    begin
-      File.rename src, dest
-    rescue
-      File.open(dest, 'wb') {|f|
-        f.write File.binread(src)
-      }
-      File.chmod File.stat(src).mode, dest
-      File.unlink src
-    end
-  end
-
-  def force_remove_file(path)
-    begin
-      remove_file path
-    rescue
-    end
-  end
-
-  def remove_file(path)
-    File.chmod 0777, path
-    File.unlink path
-  end
-
-  def install(from, dest, mode, prefix = nil)
-    $stderr.puts "install #{from} #{dest}" if verbose?
-    return if no_harm?
-
-    realdest = prefix ? prefix + File.expand_path(dest) : dest
-    realdest = File.join(realdest, File.basename(from)) if File.dir?(realdest)
-    str = File.binread(from)
-    if diff?(str, realdest)
-      verbose_off {
-        rm_f realdest if File.exist?(realdest)
-      }
-      File.open(realdest, 'wb') {|f|
-        f.write str
-      }
-      File.chmod mode, realdest
-
-      File.open("#{objdir_root()}/InstalledFiles", 'a') {|f|
-        if prefix
-          f.puts realdest.sub(prefix, '')
-        else
-          f.puts realdest
-        end
-      }
-    end
-  end
-
-  def diff?(new_content, path)
-    return true unless File.exist?(path)
-    new_content != File.binread(path)
-  end
-
-  def command(*args)
-    $stderr.puts args.join(' ') if verbose?
-    system(*args) or raise RuntimeError,
-        "system(#{args.map{|a| a.inspect }.join(' ')}) failed"
-  end
-
-  def ruby(*args)
-    command config('rubyprog'), *args
-  end
-  
-  def make(task = nil)
-    command(*[config('makeprog'), task].compact)
-  end
-
-  def extdir?(dir)
-    File.exist?("#{dir}/MANIFEST") or File.exist?("#{dir}/extconf.rb")
-  end
-
-  def files_of(dir)
-    Dir.open(dir) {|d|
-      return d.select {|ent| File.file?("#{dir}/#{ent}") }
-    }
-  end
-
-  DIR_REJECT = %w( . .. CVS SCCS RCS CVS.adm .svn )
-
-  def directories_of(dir)
-    Dir.open(dir) {|d|
-      return d.select {|ent| File.dir?("#{dir}/#{ent}") } - DIR_REJECT
-    }
-  end
-
-end
-
-
-# This module requires: #srcdir_root, #objdir_root, #relpath
-module HookScriptAPI
-
-  def get_config(key)
-    @config[key]
-  end
-
-  alias config get_config
-
-  # obsolete: use metaconfig to change configuration
-  def set_config(key, val)
-    @config[key] = val
-  end
-
-  #
-  # srcdir/objdir (works only in the package directory)
-  #
-
-  def curr_srcdir
-    "#{srcdir_root()}/#{relpath()}"
-  end
-
-  def curr_objdir
-    "#{objdir_root()}/#{relpath()}"
-  end
-
-  def srcfile(path)
-    "#{curr_srcdir()}/#{path}"
-  end
-
-  def srcexist?(path)
-    File.exist?(srcfile(path))
-  end
-
-  def srcdirectory?(path)
-    File.dir?(srcfile(path))
-  end
-  
-  def srcfile?(path)
-    File.file?(srcfile(path))
-  end
-
-  def srcentries(path = '.')
-    Dir.open("#{curr_srcdir()}/#{path}") {|d|
-      return d.to_a - %w(. ..)
-    }
-  end
-
-  def srcfiles(path = '.')
-    srcentries(path).select {|fname|
-      File.file?(File.join(curr_srcdir(), path, fname))
-    }
-  end
-
-  def srcdirectories(path = '.')
-    srcentries(path).select {|fname|
-      File.dir?(File.join(curr_srcdir(), path, fname))
-    }
-  end
-
-end
-
-
-class ToplevelInstaller
-
-  Version   = '3.4.1'
-  Copyright = 'Copyright (c) 2000-2006 Minero Aoki'
-
-  TASKS = [
-    [ 'all',      'do config, setup, then install' ],
-    [ 'config',   'saves your configurations' ],
-    [ 'show',     'shows current configuration' ],
-    [ 'setup',    'compiles ruby extentions and others' ],
-    [ 'install',  'installs files' ],
-    [ 'test',     'run all tests in test/' ],
-    [ 'clean',    "does `make clean' for each extention" ],
-    [ 'distclean',"does `make distclean' for each extention" ]
-  ]
-
-  def ToplevelInstaller.invoke
-    config = ConfigTable.new(load_rbconfig())
-    config.load_standard_entries
-    config.load_multipackage_entries if multipackage?
-    config.fixup
-    klass = (multipackage?() ? ToplevelInstallerMulti : ToplevelInstaller)
-    klass.new(File.dirname($0), config).invoke
-  end
-
-  def ToplevelInstaller.multipackage?
-    File.dir?(File.dirname($0) + '/packages')
-  end
-
-  def ToplevelInstaller.load_rbconfig
-    if arg = ARGV.detect {|arg| /\A--rbconfig=/ =~ arg }
-      ARGV.delete(arg)
-      load File.expand_path(arg.split(/=/, 2)[1])
-      $".push 'rbconfig.rb'
-    else
-      require 'rbconfig'
-    end
-    ::Config::CONFIG
-  end
-
-  def initialize(ardir_root, config)
-    @ardir = File.expand_path(ardir_root)
-    @config = config
-    # cache
-    @valid_task_re = nil
-  end
-
-  def config(key)
-    @config[key]
-  end
-
-  def inspect
-    "#<#{self.class} #{__id__()}>"
-  end
-
-  def invoke
-    run_metaconfigs
-    case task = parsearg_global()
-    when nil, 'all'
-      parsearg_config
-      init_installers
-      exec_config
-      exec_setup
-      exec_install
-    else
-      case task
-      when 'config', 'test'
-        ;
-      when 'clean', 'distclean'
-        @config.load_savefile if File.exist?(@config.savefile)
-      else
-        @config.load_savefile
-      end
-      __send__ "parsearg_#{task}"
-      init_installers
-      __send__ "exec_#{task}"
-    end
-  end
-  
-  def run_metaconfigs
-    @config.load_script "#{@ardir}/metaconfig"
-  end
-
-  def init_installers
-    @installer = Installer.new(@config, @ardir, File.expand_path('.'))
-  end
-
-  #
-  # Hook Script API bases
-  #
-
-  def srcdir_root
-    @ardir
-  end
-
-  def objdir_root
-    '.'
-  end
-
-  def relpath
-    '.'
-  end
-
-  #
-  # Option Parsing
-  #
-
-  def parsearg_global
-    while arg = ARGV.shift
-      case arg
-      when /\A\w+\z/
-        setup_rb_error "invalid task: #{arg}" unless valid_task?(arg)
-        return arg
-      when '-q', '--quiet'
-        @config.verbose = false
-      when '--verbose'
-        @config.verbose = true
-      when '--help'
-        print_usage $stdout
-        exit 0
-      when '--version'
-        puts "#{File.basename($0)} version #{Version}"
-        exit 0
-      when '--copyright'
-        puts Copyright
-        exit 0
-      else
-        setup_rb_error "unknown global option '#{arg}'"
-      end
-    end
-    nil
-  end
-
-  def valid_task?(t)
-    valid_task_re() =~ t
-  end
-
-  def valid_task_re
-    @valid_task_re ||= /\A(?:#{TASKS.map {|task,desc| task }.join('|')})\z/
-  end
-
-  def parsearg_no_options
-    unless ARGV.empty?
-      task = caller(0).first.slice(%r<`parsearg_(\w+)'>, 1)
-      setup_rb_error "#{task}: unknown options: #{ARGV.join(' ')}"
-    end
-  end
-
-  alias parsearg_show       parsearg_no_options
-  alias parsearg_setup      parsearg_no_options
-  alias parsearg_test       parsearg_no_options
-  alias parsearg_clean      parsearg_no_options
-  alias parsearg_distclean  parsearg_no_options
-
-  def parsearg_config
-    evalopt = []
-    set = []
-    @config.config_opt = []
-    while i = ARGV.shift
-      if /\A--?\z/ =~ i
-        @config.config_opt = ARGV.dup
-        break
-      end
-      name, value = *@config.parse_opt(i)
-      if @config.value_config?(name)
-        @config[name] = value
-      else
-        evalopt.push [name, value]
-      end
-      set.push name
-    end
-    evalopt.each do |name, value|
-      @config.lookup(name).evaluate value, @config
-    end
-    # Check if configuration is valid
-    set.each do |n|
-      @config[n] if @config.value_config?(n)
-    end
-  end
-
-  def parsearg_install
-    @config.no_harm = false
-    @config.install_prefix = ''
-    while a = ARGV.shift
-      case a
-      when '--no-harm'
-        @config.no_harm = true
-      when /\A--prefix=/
-        path = a.split(/=/, 2)[1]
-        path = File.expand_path(path) unless path[0,1] == '/'
-        @config.install_prefix = path
-      else
-        setup_rb_error "install: unknown option #{a}"
-      end
-    end
-  end
-
-  def print_usage(out)
-    out.puts 'Typical Installation Procedure:'
-    out.puts "  $ ruby #{File.basename $0} config"
-    out.puts "  $ ruby #{File.basename $0} setup"
-    out.puts "  # ruby #{File.basename $0} install (may require root privilege)"
-    out.puts
-    out.puts 'Detailed Usage:'
-    out.puts "  ruby #{File.basename $0} <global option>"
-    out.puts "  ruby #{File.basename $0} [<global options>] <task> [<task options>]"
-
-    fmt = "  %-24s %s\n"
-    out.puts
-    out.puts 'Global options:'
-    out.printf fmt, '-q,--quiet',   'suppress message outputs'
-    out.printf fmt, '   --verbose', 'output messages verbosely'
-    out.printf fmt, '   --help',    'print this message'
-    out.printf fmt, '   --version', 'print version and quit'
-    out.printf fmt, '   --copyright',  'print copyright and quit'
-    out.puts
-    out.puts 'Tasks:'
-    TASKS.each do |name, desc|
-      out.printf fmt, name, desc
-    end
-
-    fmt = "  %-24s %s [%s]\n"
-    out.puts
-    out.puts 'Options for CONFIG or ALL:'
-    @config.each do |item|
-      out.printf fmt, item.help_opt, item.description, item.help_default
-    end
-    out.printf fmt, '--rbconfig=path', 'rbconfig.rb to load',"running ruby's"
-    out.puts
-    out.puts 'Options for INSTALL:'
-    out.printf fmt, '--no-harm', 'only display what to do if given', 'off'
-    out.printf fmt, '--prefix=path',  'install path prefix', ''
-    out.puts
-  end
-
-  #
-  # Task Handlers
-  #
-
-  def exec_config
-    @installer.exec_config
-    @config.save   # must be final
-  end
-
-  def exec_setup
-    @installer.exec_setup
-  end
-
-  def exec_install
-    @installer.exec_install
-  end
-
-  def exec_test
-    @installer.exec_test
-  end
-
-  def exec_show
-    @config.each do |i|
-      printf "%-20s %s\n", i.name, i.value if i.value?
-    end
-  end
-
-  def exec_clean
-    @installer.exec_clean
-  end
-
-  def exec_distclean
-    @installer.exec_distclean
-  end
-
-end   # class ToplevelInstaller
-
-
-class ToplevelInstallerMulti < ToplevelInstaller
-
-  include FileOperations
-
-  def initialize(ardir_root, config)
-    super
-    @packages = directories_of("#{@ardir}/packages")
-    raise 'no package exists' if @packages.empty?
-    @root_installer = Installer.new(@config, @ardir, File.expand_path('.'))
-  end
-
-  def run_metaconfigs
-    @config.load_script "#{@ardir}/metaconfig", self
-    @packages.each do |name|
-      @config.load_script "#{@ardir}/packages/#{name}/metaconfig"
-    end
-  end
-
-  attr_reader :packages
-
-  def packages=(list)
-    raise 'package list is empty' if list.empty?
-    list.each do |name|
-      raise "directory packages/#{name} does not exist"\
-              unless File.dir?("#{@ardir}/packages/#{name}")
-    end
-    @packages = list
-  end
-
-  def init_installers
-    @installers = {}
-    @packages.each do |pack|
-      @installers[pack] = Installer.new(@config,
-                                       "#{@ardir}/packages/#{pack}",
-                                       "packages/#{pack}")
-    end
-    with    = extract_selection(config('with'))
-    without = extract_selection(config('without'))
-    @selected = @installers.keys.select {|name|
-                  (with.empty? or with.include?(name)) \
-                      and not without.include?(name)
-                }
-  end
-
-  def extract_selection(list)
-    a = list.split(/,/)
-    a.each do |name|
-      setup_rb_error "no such package: #{name}"  unless @installers.key?(name)
-    end
-    a
-  end
-
-  def print_usage(f)
-    super
-    f.puts 'Inluded packages:'
-    f.puts '  ' + @packages.sort.join(' ')
-    f.puts
-  end
-
-  #
-  # Task Handlers
-  #
-
-  def exec_config
-    run_hook 'pre-config'
-    each_selected_installers {|inst| inst.exec_config }
-    run_hook 'post-config'
-    @config.save   # must be final
-  end
-
-  def exec_setup
-    run_hook 'pre-setup'
-    each_selected_installers {|inst| inst.exec_setup }
-    run_hook 'post-setup'
-  end
-
-  def exec_install
-    run_hook 'pre-install'
-    each_selected_installers {|inst| inst.exec_install }
-    run_hook 'post-install'
-  end
-
-  def exec_test
-    run_hook 'pre-test'
-    each_selected_installers {|inst| inst.exec_test }
-    run_hook 'post-test'
-  end
-
-  def exec_clean
-    rm_f @config.savefile
-    run_hook 'pre-clean'
-    each_selected_installers {|inst| inst.exec_clean }
-    run_hook 'post-clean'
-  end
-
-  def exec_distclean
-    rm_f @config.savefile
-    run_hook 'pre-distclean'
-    each_selected_installers {|inst| inst.exec_distclean }
-    run_hook 'post-distclean'
-  end
-
-  #
-  # lib
-  #
-
-  def each_selected_installers
-    Dir.mkdir 'packages' unless File.dir?('packages')
-    @selected.each do |pack|
-      $stderr.puts "Processing the package `#{pack}' ..." if verbose?
-      Dir.mkdir "packages/#{pack}" unless File.dir?("packages/#{pack}")
-      Dir.chdir "packages/#{pack}"
-      yield @installers[pack]
-      Dir.chdir '../..'
-    end
-  end
-
-  def run_hook(id)
-    @root_installer.run_hook id
-  end
-
-  # module FileOperations requires this
-  def verbose?
-    @config.verbose?
-  end
-
-  # module FileOperations requires this
-  def no_harm?
-    @config.no_harm?
-  end
-
-end   # class ToplevelInstallerMulti
-
-
-class Installer
-
-  FILETYPES = %w( bin lib ext data conf man )
-
-  include FileOperations
-  include HookScriptAPI
-
-  def initialize(config, srcroot, objroot)
-    @config = config
-    @srcdir = File.expand_path(srcroot)
-    @objdir = File.expand_path(objroot)
-    @currdir = '.'
-  end
-
-  def inspect
-    "#<#{self.class} #{File.basename(@srcdir)}>"
-  end
-
-  def noop(rel)
-  end
-
-  #
-  # Hook Script API base methods
-  #
-
-  def srcdir_root
-    @srcdir
-  end
-
-  def objdir_root
-    @objdir
-  end
-
-  def relpath
-    @currdir
-  end
-
-  #
-  # Config Access
-  #
-
-  # module FileOperations requires this
-  def verbose?
-    @config.verbose?
-  end
-
-  # module FileOperations requires this
-  def no_harm?
-    @config.no_harm?
-  end
-
-  def verbose_off
-    begin
-      save, @config.verbose = @config.verbose?, false
-      yield
-    ensure
-      @config.verbose = save
-    end
-  end
-
-  #
-  # TASK config
-  #
-
-  def exec_config
-    exec_task_traverse 'config'
-  end
-
-  alias config_dir_bin noop
-  alias config_dir_lib noop
-
-  def config_dir_ext(rel)
-    extconf if extdir?(curr_srcdir())
-  end
-
-  alias config_dir_data noop
-  alias config_dir_conf noop
-  alias config_dir_man noop
-
-  def extconf
-    ruby "#{curr_srcdir()}/extconf.rb", *@config.config_opt
-  end
-
-  #
-  # TASK setup
-  #
-
-  def exec_setup
-    exec_task_traverse 'setup'
-  end
-
-  def setup_dir_bin(rel)
-    files_of(curr_srcdir()).each do |fname|
-      update_shebang_line "#{curr_srcdir()}/#{fname}"
-    end
-  end
-
-  alias setup_dir_lib noop
-
-  def setup_dir_ext(rel)
-    make if extdir?(curr_srcdir())
-  end
-
-  alias setup_dir_data noop
-  alias setup_dir_conf noop
-  alias setup_dir_man noop
-
-  def update_shebang_line(path)
-    return if no_harm?
-    return if config('shebang') == 'never'
-    old = Shebang.load(path)
-    if old
-      $stderr.puts "warning: #{path}: Shebang line includes too many args.  It is not portable and your program may not work." if old.args.size > 1
-      new = new_shebang(old)
-      return if new.to_s == old.to_s
-    else
-      return unless config('shebang') == 'all'
-      new = Shebang.new(config('rubypath'))
-    end
-    $stderr.puts "updating shebang: #{File.basename(path)}" if verbose?
-    open_atomic_writer(path) {|output|
-      File.open(path, 'rb') {|f|
-        f.gets if old   # discard
-        output.puts new.to_s
-        output.print f.read
-      }
-    }
-  end
-
-  def new_shebang(old)
-    if /\Aruby/ =~ File.basename(old.cmd)
-      Shebang.new(config('rubypath'), old.args)
-    elsif File.basename(old.cmd) == 'env' and old.args.first == 'ruby'
-      Shebang.new(config('rubypath'), old.args[1..-1])
-    else
-      return old unless config('shebang') == 'all'
-      Shebang.new(config('rubypath'))
-    end
-  end
-
-  def open_atomic_writer(path, &block)
-    tmpfile = File.basename(path) + '.tmp'
-    begin
-      File.open(tmpfile, 'wb', &block)
-      File.rename tmpfile, File.basename(path)
-    ensure
-      File.unlink tmpfile if File.exist?(tmpfile)
-    end
-  end
-
-  class Shebang
-    def Shebang.load(path)
-      line = nil
-      File.open(path) {|f|
-        line = f.gets
-      }
-      return nil unless /\A#!/ =~ line
-      parse(line)
-    end
-
-    def Shebang.parse(line)
-      cmd, *args = *line.strip.sub(/\A\#!/, '').split(' ')
-      new(cmd, args)
-    end
-
-    def initialize(cmd, args = [])
-      @cmd = cmd
-      @args = args
-    end
-
-    attr_reader :cmd
-    attr_reader :args
-
-    def to_s
-      "#! #{@cmd}" + (@args.empty? ? '' : " #{@args.join(' ')}")
-    end
-  end
-
-  #
-  # TASK install
-  #
-
-  def exec_install
-    rm_f 'InstalledFiles'
-    exec_task_traverse 'install'
-  end
-
-  def install_dir_bin(rel)
-    install_files targetfiles(), "#{config('bindir')}/#{rel}", 0755, strip_ext?
-  end
-
-  def strip_ext?
-    /mswin|mingw/ !~ RUBY_PLATFORM
-  end
-
-  def install_dir_lib(rel)
-    install_files libfiles(), "#{config('rbdir')}/#{rel}", 0644
-  end
-
-  def install_dir_ext(rel)
-    return unless extdir?(curr_srcdir())
-    install_files rubyextentions('.'),
-                  "#{config('sodir')}/#{File.dirname(rel)}",
-                  0555
-  end
-
-  def install_dir_data(rel)
-    install_files targetfiles(), "#{config('datadir')}/#{rel}", 0644
-  end
-
-  def install_dir_conf(rel)
-    # FIXME: should not remove current config files
-    # (rename previous file to .old/.org)
-    install_files targetfiles(), "#{config('sysconfdir')}/#{rel}", 0644
-  end
-
-  def install_dir_man(rel)
-    install_files targetfiles(), "#{config('mandir')}/#{rel}", 0644
-  end
-
-  def install_files(list, dest, mode, stripext = false)
-    mkdir_p dest, @config.install_prefix
-    list.each do |fname|
-      if stripext
-        install fname, "#{dest}/#{File.basename(fname, '.*')}",
-                mode, @config.install_prefix
-      else
-        install fname, dest, mode, @config.install_prefix
-      end
-    end
-  end
-
-  def libfiles
-    glob_reject(%w(*.y *.output), targetfiles())
-  end
-
-  def rubyextentions(dir)
-    ents = glob_select("*.#{@config.dllext}", targetfiles())
-    if ents.empty?
-      setup_rb_error "no ruby extention exists: 'ruby #{$0} setup' first"
-    end
-    ents
-  end
-
-  def targetfiles
-    mapdir(existfiles() - hookfiles())
-  end
-
-  def mapdir(ents)
-    ents.map {|ent|
-      if File.exist?(ent)
-      then ent                         # objdir
-      else "#{curr_srcdir()}/#{ent}"   # srcdir
-      end
-    }
-  end
-
-  # picked up many entries from cvs-1.11.1/src/ignore.c
-  JUNK_FILES = %w( 
-    core RCSLOG tags TAGS .make.state
-    .nse_depinfo #* .#* cvslog.* ,* .del-* *.olb
-    *~ *.old *.bak *.BAK *.orig *.rej _$* *$
-
-    *.org *.in .*
-  )
-
-  def existfiles
-    glob_reject(JUNK_FILES, (files_of(curr_srcdir()) | files_of('.')))
-  end
-
-  def hookfiles
-    %w( pre-%s post-%s pre-%s.rb post-%s.rb ).map {|fmt|
-      %w( config setup install clean distclean ).map {|t| sprintf(fmt, t) }
-    }.flatten
-  end
-
-  def glob_select(pat, ents)
-    re = globs2re([pat])
-    ents.select {|ent| re =~ ent }
-  end
-
-  def glob_reject(pats, ents)
-    re = globs2re(pats)
-    ents.reject {|ent| re =~ ent }
-  end
-
-  GLOB2REGEX = {
-    '.' => '\.',
-    '$' => '\$',
-    '#' => '\#',
-    '*' => '.*'
-  }
-
-  def globs2re(pats)
-    /\A(?:#{
-      pats.map {|pat| pat.gsub(/[\.\$\#\*]/) {|ch| GLOB2REGEX[ch] } }.join('|')
-    })\z/
-  end
-
-  #
-  # TASK test
-  #
-
-  TESTDIR = 'test'
-
-  def exec_test
-    unless File.directory?('test')
-      $stderr.puts 'no test in this package' if verbose?
-      return
-    end
-    $stderr.puts 'Running tests...' if verbose?
-    begin
-      require 'test/unit'
-    rescue LoadError
-      setup_rb_error 'test/unit cannot loaded.  You need Ruby 1.8 or later to invoke this task.'
-    end
-    runner = Test::Unit::AutoRunner.new(true)
-    runner.to_run << TESTDIR
-    runner.run
-  end
-
-  #
-  # TASK clean
-  #
-
-  def exec_clean
-    exec_task_traverse 'clean'
-    rm_f @config.savefile
-    rm_f 'InstalledFiles'
-  end
-
-  alias clean_dir_bin noop
-  alias clean_dir_lib noop
-  alias clean_dir_data noop
-  alias clean_dir_conf noop
-  alias clean_dir_man noop
-
-  def clean_dir_ext(rel)
-    return unless extdir?(curr_srcdir())
-    make 'clean' if File.file?('Makefile')
-  end
-
-  #
-  # TASK distclean
-  #
-
-  def exec_distclean
-    exec_task_traverse 'distclean'
-    rm_f @config.savefile
-    rm_f 'InstalledFiles'
-  end
-
-  alias distclean_dir_bin noop
-  alias distclean_dir_lib noop
-
-  def distclean_dir_ext(rel)
-    return unless extdir?(curr_srcdir())
-    make 'distclean' if File.file?('Makefile')
-  end
-
-  alias distclean_dir_data noop
-  alias distclean_dir_conf noop
-  alias distclean_dir_man noop
-
-  #
-  # Traversing
-  #
-
-  def exec_task_traverse(task)
-    run_hook "pre-#{task}"
-    FILETYPES.each do |type|
-      if type == 'ext' and config('without-ext') == 'yes'
-        $stderr.puts 'skipping ext/* by user option' if verbose?
-        next
-      end
-      traverse task, type, "#{task}_dir_#{type}"
-    end
-    run_hook "post-#{task}"
-  end
-
-  def traverse(task, rel, mid)
-    dive_into(rel) {
-      run_hook "pre-#{task}"
-      __send__ mid, rel.sub(%r[\A.*?(?:/|\z)], '')
-      directories_of(curr_srcdir()).each do |d|
-        traverse task, "#{rel}/#{d}", mid
-      end
-      run_hook "post-#{task}"
-    }
-  end
-
-  def dive_into(rel)
-    return unless File.dir?("#{@srcdir}/#{rel}")
-
-    dir = File.basename(rel)
-    Dir.mkdir dir unless File.dir?(dir)
-    prevdir = Dir.pwd
-    Dir.chdir dir
-    $stderr.puts '---> ' + rel if verbose?
-    @currdir = rel
-    yield
-    Dir.chdir prevdir
-    $stderr.puts '<--- ' + rel if verbose?
-    @currdir = File.dirname(rel)
-  end
-
-  def run_hook(id)
-    path = [ "#{curr_srcdir()}/#{id}",
-             "#{curr_srcdir()}/#{id}.rb" ].detect {|cand| File.file?(cand) }
-    return unless path
-    $stderr.puts "invoking hook script #{path}" if verbose?
-    begin
-      instance_eval File.read(path), path, 1
-    rescue
-      raise if $DEBUG
-      setup_rb_error "hook #{path} failed:\n" + $!.message
-    end
-  end
-
-end   # class Installer
-
-
-class SetupError < StandardError; end
-
-def setup_rb_error(msg)
-  raise SetupError, msg
-end
-
-# $DEBUG = true
-
-if $0 == __FILE__
-    ToplevelInstaller.invoke
-    # begin
-    #   ToplevelInstaller.invoke
-    # rescue SetupError
-    #   raise if $DEBUG
-    #   $stderr.puts $!.message
-    #   $stderr.puts "Try 'ruby #{$0} --help' for detailed usage."
-    #   exit 1
-    # end
-end
diff -ruN libjit/jitruby/test/assertions.rb libjit-mikyt/jitruby/test/assertions.rb
--- libjit/jitruby/test/assertions.rb	2008-12-12 12:31:05.000000000 +0100
+++ libjit-mikyt/jitruby/test/assertions.rb	1970-01-01 01:00:00.000000000 +0100
@@ -1,34 +0,0 @@
-module JitAssertions
-  def assert_function_result(args, &block)
-    result_type = nil
-    expected_result = nil
-    param_types = []
-    params = []
-
-    args.each do |k, v|
-      case k.to_s
-      when /^arg(\d+)$/
-        n = $1.to_i
-        param_types[n] = v[0]
-        params[n] = v[1]
-      when 'result'
-        result_type = v[0]
-        expected_result = v[1]
-      else
-        raise "Bad arg #{arg}"
-      end
-    end
-
-    function = nil
-    JIT::Context.build do |context|
-      signature = JIT::Type.create_signature(
-          JIT::ABI::CDECL,
-          result_type,
-          param_types)
-      function = JIT::Function.compile(context, signature, &block)
-    end
-
-    assert_equal(expected_result, function.apply(*params))
-  end
-end
-
diff -ruN libjit/jitruby/test/test_jit_array.rb libjit-mikyt/jitruby/test/test_jit_array.rb
--- libjit/jitruby/test/test_jit_array.rb	2008-12-12 12:31:05.000000000 +0100
+++ libjit-mikyt/jitruby/test/test_jit_array.rb	1970-01-01 01:00:00.000000000 +0100
@@ -1,70 +0,0 @@
-require 'jit/array'
-require 'jit/function'
-require 'test/unit'
-require 'assertions'
-
-class TestJitArray < Test::Unit::TestCase
-  include JitAssertions
-
-  def test_new_array
-    a_type = JIT::Array.new(JIT::Type::INT, 12)
-    assert_equal JIT::Type::INT, a_type.type
-    assert_equal 12, a_type.length
-  end
-
-  # TODO: wrap
-
-  def test_create
-    p = proc { |f|
-      a_type = JIT::Array.new(JIT::Type::INT, 4)
-      a = a_type.create(f)
-      f.return f.const(JIT::Type::INT, 0)
-    }
-    assert_function_result(
-        :result => [ JIT::Type::INT, 0 ],
-        &p)
-  end
-
-  def test_offset_of
-    a_type = JIT::Array.new(JIT::Type::INT, 4)
-    assert_equal 0, a_type.offset_of(0)
-    assert_equal 4, a_type.offset_of(1)
-    assert_equal 8, a_type.offset_of(2)
-    assert_equal 12, a_type.offset_of(3)
-    # TODO: check out of bounds
-  end
-
-  def test_type_of
-    a_type = JIT::Array.new(JIT::Type::INT, 4)
-    assert_equal JIT::Type::INT, a_type.type_of(0)
-    assert_equal JIT::Type::INT, a_type.type_of(1)
-    assert_equal JIT::Type::INT, a_type.type_of(2)
-    assert_equal JIT::Type::INT, a_type.type_of(3)
-    # TODO: check out of bounds
-  end
-
-  def test_instance_bracket
-    p = proc { |f|
-      a_type = JIT::Array.new(JIT::Type::INT, 4)
-      a = a_type.create(f)
-      f.insn_store_relative(a.ptr, 4, f.const(JIT::Type::INT, 42))
-      f.return a[1]
-    }
-    assert_function_result(
-        :result => [ JIT::Type::INT, 42 ],
-        &p)
-  end
-
-  def test_instance_bracket_eq
-    p = proc { |f|
-      a_type = JIT::Array.new(JIT::Type::INT, 4)
-      a = a_type.create(f)
-      a[1] = f.const(JIT::Type::INT, 42)
-      f.return a[1]
-    }
-    assert_function_result(
-        :result => [ JIT::Type::INT, 42 ],
-        &p)
-  end
-end
-
diff -ruN libjit/jitruby/test/test_jit_function.rb libjit-mikyt/jitruby/test/test_jit_function.rb
--- libjit/jitruby/test/test_jit_function.rb	2008-12-12 12:31:05.000000000 +0100
+++ libjit-mikyt/jitruby/test/test_jit_function.rb	1970-01-01 01:00:00.000000000 +0100
@@ -1,329 +0,0 @@
-require 'jit/function'
-require 'jit/value'
-require 'test/unit'
-
-class TestJitFunction < Test::Unit::TestCase
-  def test_if_false
-    function = nil
-    JIT::Context.build do |context|
-      signature = JIT::Type.create_signature(
-          JIT::ABI::CDECL,
-          JIT::Type::INT,
-          [ JIT::Type::INT ])
-      function = JIT::Function.compile(context, signature) do |f|
-        result = f.value(JIT::Type::INT)
-        result.store f.const(JIT::Type::INT, 1)
-        f.if(f.get_param(0)) {
-          result.store f.const(JIT::Type::INT, 2)
-        } .end
-        f.insn_return result
-      end
-    end
-
-    assert_equal(1, function.apply(0))
-  end
-
-  def test_if_true
-    function = nil
-    JIT::Context.build do |context|
-      signature = JIT::Type.create_signature(
-          JIT::ABI::CDECL,
-          JIT::Type::INT,
-          [ JIT::Type::INT ])
-      function = JIT::Function.compile(context, signature) do |f|
-        result = f.value(JIT::Type::INT)
-        result.store f.const(JIT::Type::INT, 1)
-        f.if(f.get_param(0)) {
-          result.store f.const(JIT::Type::INT, 2)
-        } .end
-        f.insn_return result
-      end
-    end
-
-    assert_equal(2, function.apply(1))
-  end
-
-  def test_if_false_else
-    function = nil
-    JIT::Context.build do |context|
-      signature = JIT::Type.create_signature(
-          JIT::ABI::CDECL,
-          JIT::Type::INT,
-          [ JIT::Type::INT ])
-      function = JIT::Function.compile(context, signature) do |f|
-        result = f.value(JIT::Type::INT)
-        result.store f.const(JIT::Type::INT, 1)
-        f.if(f.get_param(0)) {
-          result.store f.const(JIT::Type::INT, 2)
-        } .else {
-          result.store f.const(JIT::Type::INT, 3)
-        } .end
-        f.insn_return result
-      end
-    end
-
-    assert_equal(3, function.apply(0))
-  end
-
-  def test_if_true_else
-    function = nil
-    JIT::Context.build do |context|
-      signature = JIT::Type.create_signature(
-          JIT::ABI::CDECL,
-          JIT::Type::INT,
-          [ JIT::Type::INT ])
-      function = JIT::Function.compile(context, signature) do |f|
-        result = f.value(JIT::Type::INT)
-        result.store f.const(JIT::Type::INT, 1)
-        f.if(f.get_param(0)) {
-          result.store f.const(JIT::Type::INT, 2)
-        } .else {
-          result.store f.const(JIT::Type::INT, 3)
-        } .end
-        f.insn_return result
-      end
-    end
-
-    assert_equal(2, function.apply(1))
-  end
-
-  def test_if_false_else_if_true_else
-    function = nil
-    JIT::Context.build do |context|
-      signature = JIT::Type.create_signature(
-          JIT::ABI::CDECL,
-          JIT::Type::INT,
-          [ JIT::Type::INT, JIT::Type::INT ])
-      function = JIT::Function.compile(context, signature) do |f|
-        result = f.value(JIT::Type::INT)
-        result.store f.const(JIT::Type::INT, 1)
-        f.if(f.get_param(0)) {
-          result.store f.const(JIT::Type::INT, 2)
-        } .elsif(f.get_param(1)) {
-          result.store f.const(JIT::Type::INT, 3)
-        } .else {
-          result.store f.const(JIT::Type::INT, 4)
-        } .end
-        f.insn_return result
-      end
-    end
-
-    assert_equal(3, function.apply(0, 1))
-  end
-
-  def test_if_true_else_if_false_else
-    function = nil
-    JIT::Context.build do |context|
-      signature = JIT::Type.create_signature(
-          JIT::ABI::CDECL,
-          JIT::Type::INT,
-          [ JIT::Type::INT, JIT::Type::INT ])
-      function = JIT::Function.compile(context, signature) do |f|
-        result = f.value(JIT::Type::INT)
-        result.store f.const(JIT::Type::INT, 1)
-        f.if(f.get_param(0)) {
-          result.store f.const(JIT::Type::INT, 2)
-        } .elsif(f.get_param(1)) {
-          result.store f.const(JIT::Type::INT, 3)
-        } .else {
-          result.store f.const(JIT::Type::INT, 4)
-        } .end
-        f.insn_return result
-      end
-    end
-
-    assert_equal(2, function.apply(1, 0))
-  end
-
-  def test_if_false_else_if_false_else
-    function = nil
-    JIT::Context.build do |context|
-      signature = JIT::Type.create_signature(
-          JIT::ABI::CDECL,
-          JIT::Type::INT,
-          [ JIT::Type::INT, JIT::Type::INT ])
-      function = JIT::Function.compile(context, signature) do |f|
-        result = f.value(JIT::Type::INT)
-        result.store f.const(JIT::Type::INT, 1)
-        f.if(f.get_param(0)) {
-          result.store f.const(JIT::Type::INT, 2)
-        } .elsif(f.get_param(1)) {
-          result.store f.const(JIT::Type::INT, 3)
-        } .else {
-          result.store f.const(JIT::Type::INT, 4)
-        } .end
-        f.insn_return result
-      end
-    end
-
-    assert_equal(4, function.apply(0, 0))
-  end
-
-  def test_while_true_enters_loop
-    function = nil
-    JIT::Context.build do |context|
-      signature = JIT::Type.create_signature(
-          JIT::ABI::CDECL,
-          JIT::Type::INT,
-          [ ])
-      function = JIT::Function.compile(context, signature) do |f|
-        true_value = f.const(JIT::Type::INT, 1)
-        false_value = f.const(JIT::Type::INT, 0)
-        f.while{ true_value }.do {
-          f.insn_return true_value
-        }.end
-        f.insn_return false_value
-      end
-    end
-
-    assert_equal(1, function.apply)
-  end
-
-  def test_while_true_reenters_loop
-    function = nil
-    JIT::Context.build do |context|
-      signature = JIT::Type.create_signature(
-          JIT::ABI::CDECL,
-          JIT::Type::INT,
-          [ ])
-      function = JIT::Function.compile(context, signature) do |f|
-        value = f.value(JIT::Type::INT)
-        value.store(f.const(JIT::Type::INT, 0))
-        f.while{ value < f.const(JIT::Type::INT, 2) }.do {
-          value.store(value + f.const(JIT::Type::INT, 1))
-        }.end
-        f.insn_return value
-      end
-    end
-
-    assert_equal(2, function.apply)
-  end
-
-  def test_while_false_does_not_enter_loop
-    function = nil
-    JIT::Context.build do |context|
-      signature = JIT::Type.create_signature(
-          JIT::ABI::CDECL,
-          JIT::Type::INT,
-          [ ])
-      function = JIT::Function.compile(context, signature) do |f|
-        true_value = f.const(JIT::Type::INT, 1)
-        false_value = f.const(JIT::Type::INT, 0)
-        f.while{ false_value }.do {
-          f.insn_return true_value
-        }.end
-        f.insn_return false_value
-      end
-    end
-
-    assert_equal(0, function.apply)
-  end
-
-  def test_until_false_enters_loop
-    function = nil
-    JIT::Context.build do |context|
-      signature = JIT::Type.create_signature(
-          JIT::ABI::CDECL,
-          JIT::Type::INT,
-          [ ])
-      function = JIT::Function.compile(context, signature) do |f|
-        true_value = f.const(JIT::Type::INT, 1)
-        false_value = f.const(JIT::Type::INT, 0)
-        f.until{ false_value }.do {
-          f.insn_return true_value
-        }.end
-        f.insn_return false_value
-      end
-    end
-
-    assert_equal(1, function.apply)
-  end
-
-  def test_until_false_reenters_loop
-    function = nil
-    JIT::Context.build do |context|
-      signature = JIT::Type.create_signature(
-          JIT::ABI::CDECL,
-          JIT::Type::INT,
-          [ ])
-      function = JIT::Function.compile(context, signature) do |f|
-        value = f.value(JIT::Type::INT)
-        value.store(f.const(JIT::Type::INT, 0))
-        f.until{ value == f.const(JIT::Type::INT, 2) }.do {
-          value.store(value + f.const(JIT::Type::INT, 1))
-        }.end
-        f.insn_return value
-      end
-    end
-
-    assert_equal(2, function.apply)
-  end
-
-  def test_until_true_does_not_enter_loop
-    function = nil
-    JIT::Context.build do |context|
-      signature = JIT::Type.create_signature(
-          JIT::ABI::CDECL,
-          JIT::Type::INT,
-          [ ])
-      function = JIT::Function.compile(context, signature) do |f|
-        true_value = f.const(JIT::Type::INT, 1)
-        false_value = f.const(JIT::Type::INT, 0)
-        f.until{ true_value }.do {
-          f.insn_return true_value
-        }.end
-        f.insn_return false_value
-      end
-    end
-
-      assert_equal(0, function.apply)
-  end
-
-  # TODO: while/break
-  # TODO: while/redo
-  # TODO: until/break
-  # TODO: until/redo
-  # TODO: unless
-  # TODO: elsunless
-
-  def test_define_jit_method
-    function = nil
-    JIT::Context.build do |context|
-      signature = JIT::Type.create_signature(
-          JIT::ABI::CDECL,
-          JIT::Type::OBJECT,
-          [ JIT::Type::OBJECT ])
-      function = JIT::Function.compile(context, signature) do |f|
-        f.insn_return(f.const(JIT::Type::OBJECT, 42))
-      end
-    end
-
-    c = Class.new
-    c.instance_eval do
-      define_jit_method('foo', function)
-    end
-
-    o = c.new
-    assert_equal 42, o.foo
-  end
-
-  def test_define_jit_method_non_object_param
-    # TODO: should raise an exception
-  end
-
-  # TODO: get_param
-  # TODO: insn_call
-  # TODO: insn_call_native
-  # TODO: insn_return
-  # TODO: apply
-  # TODO: value
-  # TODO: const
-  # TODO: optimization_level
-  # TODO: optimization_level=
-  # TODO: max_optimization_level
-  # TODO: dump
-  # TODO: to_closure
-  # TODO: context
-  # TODO: compiled?
-end
-
diff -ruN libjit/jitruby/test/test_jit_pointer.rb libjit-mikyt/jitruby/test/test_jit_pointer.rb
--- libjit/jitruby/test/test_jit_pointer.rb	2008-12-12 12:31:05.000000000 +0100
+++ libjit-mikyt/jitruby/test/test_jit_pointer.rb	1970-01-01 01:00:00.000000000 +0100
@@ -1,63 +0,0 @@
-require 'jit/pointer'
-require 'jit/array'
-require 'jit/function'
-require 'test/unit'
-require 'assertions'
-
-class TestJitArray < Test::Unit::TestCase
-  include JitAssertions
-
-  def test_new_pointer
-    p_type = JIT::Pointer.new(JIT::Type::INT)
-    assert_equal JIT::Type::INT, p_type.type
-  end
-
-  # TODO: wrap
-
-  def test_offset_of
-    p_type = JIT::Pointer.new(JIT::Type::INT)
-    assert_equal 0, p_type.offset_of(0)
-    assert_equal 4, p_type.offset_of(1)
-    assert_equal 8, p_type.offset_of(2)
-    assert_equal 12, p_type.offset_of(3)
-    # TODO: check out of bounds
-  end
-
-  def test_type_of
-    p_type = JIT::Pointer.new(JIT::Type::INT)
-    assert_equal JIT::Type::INT, p_type.type_of(0)
-    assert_equal JIT::Type::INT, p_type.type_of(1)
-    assert_equal JIT::Type::INT, p_type.type_of(2)
-    assert_equal JIT::Type::INT, p_type.type_of(3)
-    # TODO: check out of bounds
-  end
-
-  def test_instance_bracket
-    p = proc { |f|
-      a_type = JIT::Array.new(JIT::Type::INT, 4)
-      p_type = JIT::Pointer.new(JIT::Type::INT)
-      a = a_type.create(f)
-      ptr = p_type.wrap(a.ptr)
-      f.insn_store_relative(a.ptr, 4, f.const(JIT::Type::INT, 42))
-      f.return ptr[1]
-    }
-    assert_function_result(
-        :result => [ JIT::Type::INT, 42 ],
-        &p)
-  end
-
-  def test_instance_bracket_eq
-    p = proc { |f|
-      a_type = JIT::Array.new(JIT::Type::INT, 4)
-      p_type = JIT::Pointer.new(JIT::Type::INT)
-      a = a_type.create(f)
-      ptr = p_type.wrap(a.ptr)
-      ptr[1] = f.const(JIT::Type::INT, 42)
-      f.return a[1]
-    }
-    assert_function_result(
-        :result => [ JIT::Type::INT, 42 ],
-        &p)
-  end
-end
-
diff -ruN libjit/jitruby/test/test_jit_struct.rb libjit-mikyt/jitruby/test/test_jit_struct.rb
--- libjit/jitruby/test/test_jit_struct.rb	2008-12-12 12:31:05.000000000 +0100
+++ libjit-mikyt/jitruby/test/test_jit_struct.rb	1970-01-01 01:00:00.000000000 +0100
@@ -1,111 +0,0 @@
-require 'jit/array'
-require 'jit/function'
-require 'test/unit'
-require 'assertions'
-
-class TestJitStruct < Test::Unit::TestCase
-  include JitAssertions
-
-  def test_new_struct
-    s_type = JIT::Struct.new(
-        [ :foo, JIT::Type::INT ],
-        [ :bar, JIT::Type::VOID_PTR ],
-        [ :baz, JIT::Type::FLOAT32 ])
-    assert_equal [ :foo, :bar, :baz ], s_type.members
-  end
-
-  def test_create
-    p = proc { |f|
-      s_type = JIT::Struct.new(
-          [ :foo, JIT::Type::INT ],
-          [ :bar, JIT::Type::VOID_PTR ],
-          [ :baz, JIT::Type::FLOAT32 ])
-      s = s_type.create(f)
-      f.return f.const(JIT::Type::INT, 0)
-    }
-    assert_function_result(
-        :result => [ JIT::Type::INT, 0 ],
-        &p)
-  end
-
-  def test_offset_of
-    s_type = JIT::Struct.new(
-        [ :foo, JIT::Type::INT ],
-        [ :bar, JIT::Type::FLOAT64 ],
-        [ :baz, JIT::Type::VOID_PTR ])
-    assert_equal 0, s_type.offset_of(:foo)
-    assert_equal 4, s_type.offset_of(:bar)
-    assert_equal 12, s_type.offset_of(:baz)
-  end
-
-  def test_type_of
-    s_type = JIT::Struct.new(
-        [ :foo, JIT::Type::INT ],
-        [ :bar, JIT::Type::FLOAT64 ],
-        [ :baz, JIT::Type::VOID_PTR ])
-    assert_equal JIT::Type::INT, s_type.type_of(:foo)
-    assert_equal JIT::Type::FLOAT64, s_type.type_of(:bar)
-    assert_equal JIT::Type::VOID_PTR, s_type.type_of(:baz)
-  end
-
-  def test_instance_bracket
-    p = proc { |f|
-      s_type = JIT::Struct.new(
-          [ :foo, JIT::Type::INT ],
-          [ :bar, JIT::Type::FLOAT64 ],
-          [ :baz, JIT::Type::VOID_PTR ])
-      s = s_type.create(f)
-      f.insn_store_relative(s.ptr, 4, f.const(JIT::Type::FLOAT64, 42.0))
-      f.return s[:bar]
-    }
-    assert_function_result(
-        :result => [ JIT::Type::FLOAT64, 42.0 ],
-        &p)
-  end
-
-  def test_instance_attrget
-    p = proc { |f|
-      s_type = JIT::Struct.new(
-          [ :foo, JIT::Type::INT ],
-          [ :bar, JIT::Type::FLOAT64 ],
-          [ :baz, JIT::Type::VOID_PTR ])
-      s = s_type.create(f)
-      f.insn_store_relative(s.ptr, 4, f.const(JIT::Type::FLOAT64, 42.0))
-      f.return s.bar
-    }
-    assert_function_result(
-        :result => [ JIT::Type::FLOAT64, 42.0 ],
-        &p)
-  end
-
-  def test_instance_bracket_eq
-    p = proc { |f|
-      s_type = JIT::Struct.new(
-          [ :foo, JIT::Type::INT ],
-          [ :bar, JIT::Type::FLOAT64 ],
-          [ :baz, JIT::Type::VOID_PTR ])
-      s = s_type.create(f)
-      s[:bar] = f.const(JIT::Type::FLOAT64, 42.0)
-      f.return s[:bar]
-    }
-    assert_function_result(
-        :result => [ JIT::Type::FLOAT64, 42.0 ],
-        &p)
-  end
-
-  def test_instance_attrset
-    p = proc { |f|
-      s_type = JIT::Struct.new(
-          [ :foo, JIT::Type::INT ],
-          [ :bar, JIT::Type::FLOAT64 ],
-          [ :baz, JIT::Type::VOID_PTR ])
-      s = s_type.create(f)
-      s.bar = f.const(JIT::Type::FLOAT64, 42.0)
-      f.return s.bar
-    }
-    assert_function_result(
-        :result => [ JIT::Type::FLOAT64, 42.0 ],
-        &p)
-  end
-end
-
diff -ruN libjit/jitruby/test/test_jit_value.rb libjit-mikyt/jitruby/test/test_jit_value.rb
--- libjit/jitruby/test/test_jit_value.rb	2008-12-12 12:31:05.000000000 +0100
+++ libjit-mikyt/jitruby/test/test_jit_value.rb	1970-01-01 01:00:00.000000000 +0100
@@ -1,258 +0,0 @@
-require 'jit/value'
-require 'jit/function'
-require 'test/unit'
-require 'assertions'
-
-class TestJitValue < Test::Unit::TestCase
-  include JitAssertions
-
-  def test_store
-    p = proc { |f|
-      v = f.value(JIT::Type::INT)
-      v.store(f.const(JIT::Type::INT, 42))
-      f.return v
-    }
-    assert_function_result(
-        :result => [ JIT::Type::INT, 42 ],
-        &p)
-  end
-
-  # TODO: address
-
-  def test_int_plus
-    p = proc { |f|
-      v1 = f.get_param(0)
-      v2 = f.get_param(1)
-      f.return v1 + v2
-    }
-    assert_function_result(
-        :arg0 => [ JIT::Type::INT, 1 ],
-        :arg1 => [ JIT::Type::INT, 2 ],
-        :result => [ JIT::Type::INT, 3 ],
-        &p)
-  end
-
-  def test_int_minus
-    p = proc { |f|
-      v1 = f.get_param(0)
-      v2 = f.get_param(1)
-      f.return v1 - v2
-    }
-    assert_function_result(
-        :arg0 => [ JIT::Type::INT, 3 ],
-        :arg1 => [ JIT::Type::INT, 2 ],
-        :result => [ JIT::Type::INT, 1 ],
-        &p)
-  end
-
-  def test_int_mult
-    p = proc { |f|
-      v1 = f.get_param(0)
-      v2 = f.get_param(1)
-      f.return v1 * v2
-    }
-    assert_function_result(
-        :arg0 => [ JIT::Type::INT, 3 ],
-        :arg1 => [ JIT::Type::INT, 2 ],
-        :result => [ JIT::Type::INT, 6 ],
-        &p)
-  end
-
-  def test_int_div
-    p = proc { |f|
-      v1 = f.get_param(0)
-      v2 = f.get_param(1)
-      f.return v1 / v2
-    }
-    assert_function_result(
-        :arg0 => [ JIT::Type::INT, 6 ],
-        :arg1 => [ JIT::Type::INT, 2 ],
-        :result => [ JIT::Type::INT, 3 ],
-        &p)
-  end
-
-  def test_int_mod
-    p = proc { |f|
-      v1 = f.get_param(0)
-      v2 = f.get_param(1)
-      f.return v1 % v2
-    }
-    assert_function_result(
-        :arg0 => [ JIT::Type::INT, 20 ],
-        :arg1 => [ JIT::Type::INT, 6 ],
-        :result => [ JIT::Type::INT, 2 ],
-        &p)
-  end
-
-  def test_int_and
-    p = proc { |f|
-      v1 = f.get_param(0)
-      v2 = f.get_param(1)
-      f.return v1 & v2
-    }
-    assert_function_result(
-        :arg0 => [ JIT::Type::INT, 11 ],
-        :arg1 => [ JIT::Type::INT, 3 ],
-        :result => [ JIT::Type::INT, 3 ],
-        &p)
-    assert_function_result(
-        :arg0 => [ JIT::Type::INT, 8 ],
-        :arg1 => [ JIT::Type::INT, 3 ],
-        :result => [ JIT::Type::INT, 0 ],
-        &p)
-  end
-
-  def test_int_or
-    p = proc { |f|
-      v1 = f.get_param(0)
-      v2 = f.get_param(1)
-      f.return v1 | v2
-    }
-    assert_function_result(
-        :arg0 => [ JIT::Type::INT, 10 ],
-        :arg1 => [ JIT::Type::INT, 3 ],
-        :result => [ JIT::Type::INT, 11 ],
-        &p)
-  end
-
-  def test_int_xor
-    p = proc { |f|
-      v1 = f.get_param(0)
-      v2 = f.get_param(1)
-      f.return v1 ^ v2
-    }
-    assert_function_result(
-        :arg0 => [ JIT::Type::INT, 10 ],
-        :arg1 => [ JIT::Type::INT, 3 ],
-        :result => [ JIT::Type::INT, 9 ],
-        &p)
-  end
-
-  def test_int_lt
-    p = proc { |f|
-      v1 = f.get_param(0)
-      v2 = f.get_param(1)
-      f.return v1 < v2
-    }
-    assert_function_result(
-        :arg0 => [ JIT::Type::INT, 1 ],
-        :arg1 => [ JIT::Type::INT, 2 ],
-        :result => [ JIT::Type::INT, 1 ],
-        &p)
-    assert_function_result(
-        :arg0 => [ JIT::Type::INT, 2 ],
-        :arg1 => [ JIT::Type::INT, 1 ],
-        :result => [ JIT::Type::INT, 0 ],
-        &p)
-  end
-
-  def test_int_gt
-    p = proc { |f|
-      v1 = f.get_param(0)
-      v2 = f.get_param(1)
-      f.return v1 > v2
-    }
-    assert_function_result(
-        :arg0 => [ JIT::Type::INT, 1 ],
-        :arg1 => [ JIT::Type::INT, 2 ],
-        :result => [ JIT::Type::INT, 0 ],
-        &p)
-    assert_function_result(
-        :arg0 => [ JIT::Type::INT, 2 ],
-        :arg1 => [ JIT::Type::INT, 1 ],
-        :result => [ JIT::Type::INT, 1 ],
-        &p)
-  end
-
-  def test_int_eq
-    p = proc { |f|
-      v1 = f.get_param(0)
-      v2 = f.get_param(1)
-      f.return v1 == v2
-    }
-    assert_function_result(
-        :arg0 => [ JIT::Type::INT, 1 ],
-        :arg1 => [ JIT::Type::INT, 2 ],
-        :result => [ JIT::Type::INT, 0 ],
-        &p)
-    assert_function_result(
-        :arg0 => [ JIT::Type::INT, 1 ],
-        :arg1 => [ JIT::Type::INT, 1 ],
-        :result => [ JIT::Type::INT, 1 ],
-        &p)
-  end
-
-  def test_int_le
-    p = proc { |f|
-      v1 = f.get_param(0)
-      v2 = f.get_param(1)
-      f.return v1 <= v2
-    }
-    assert_function_result(
-        :arg0 => [ JIT::Type::INT, 1 ],
-        :arg1 => [ JIT::Type::INT, 2 ],
-        :result => [ JIT::Type::INT, 1 ],
-        &p)
-    assert_function_result(
-        :arg0 => [ JIT::Type::INT, 2 ],
-        :arg1 => [ JIT::Type::INT, 1 ],
-        :result => [ JIT::Type::INT, 0 ],
-        &p)
-    assert_function_result(
-        :arg0 => [ JIT::Type::INT, 1 ],
-        :arg1 => [ JIT::Type::INT, 1 ],
-        :result => [ JIT::Type::INT, 1 ],
-        &p)
-  end
-
-  def test_int_ge
-    p = proc { |f|
-      v1 = f.get_param(0)
-      v2 = f.get_param(1)
-      f.return v1 >= v2
-    }
-    assert_function_result(
-        :arg0 => [ JIT::Type::INT, 1 ],
-        :arg1 => [ JIT::Type::INT, 2 ],
-        :result => [ JIT::Type::INT, 0 ],
-        &p)
-    assert_function_result(
-        :arg0 => [ JIT::Type::INT, 2 ],
-        :arg1 => [ JIT::Type::INT, 1 ],
-        :result => [ JIT::Type::INT, 1 ],
-        &p)
-    assert_function_result(
-        :arg0 => [ JIT::Type::INT, 1 ],
-        :arg1 => [ JIT::Type::INT, 1 ],
-        :result => [ JIT::Type::INT, 1 ],
-        &p)
-  end
-
-  def test_int_lshift
-    p = proc { |f|
-      v1 = f.get_param(0)
-      v2 = f.get_param(1)
-      f.return v1 << v2
-    }
-    assert_function_result(
-        :arg0 => [ JIT::Type::INT, 31 ],
-        :arg1 => [ JIT::Type::INT, 2 ],
-        :result => [ JIT::Type::INT, 124 ],
-        &p)
-  end
-
-  def test_int_rshift
-    p = proc { |f|
-      v1 = f.get_param(0)
-      v2 = f.get_param(1)
-      f.return v1 >> v2
-    }
-    assert_function_result(
-        :arg0 => [ JIT::Type::INT, 31 ],
-        :arg1 => [ JIT::Type::INT, 2 ],
-        :result => [ JIT::Type::INT, 7 ],
-        &p)
-  end
-end
-
-
diff -ruN libjit/tests/.cvsignore libjit-mikyt/tests/.cvsignore
--- libjit/tests/.cvsignore	2004-05-12 03:11:18.000000000 +0200
+++ libjit-mikyt/tests/.cvsignore	1970-01-01 01:00:00.000000000 +0100
@@ -1,6 +0,0 @@
-Makefile
-Makefile.in
-.deps
-.libs
-*.lo
-*.la
diff -ruN libjit/tools/.cvsignore libjit-mikyt/tools/.cvsignore
--- libjit/tools/.cvsignore	2007-01-04 12:44:30.000000000 +0100
+++ libjit-mikyt/tools/.cvsignore	1970-01-01 01:00:00.000000000 +0100
@@ -1,18 +0,0 @@
-Makefile
-Makefile.in
-.deps
-.libs
-gen-apply
-gen-apply.exe
-gen-sel
-gen-sel.exe
-gen-rules
-gen-rules.exe
-*.lo
-*.la
-gen-sel-parser.c
-gen-sel-parser.h
-gen-sel-scanner.c
-gen-rules-parser.c
-gen-rules-parser.h
-gen-rules-scanner.c
diff -ruN libjit/tools/gen-apply-macosx.h libjit-mikyt/tools/gen-apply-macosx.h
--- libjit/tools/gen-apply-macosx.h	2008-11-23 10:15:25.000000000 +0100
+++ libjit-mikyt/tools/gen-apply-macosx.h	2008-01-25 08:27:19.000000000 +0100
@@ -62,13 +62,6 @@
 #define JIT_APPLY_X86_POP_STRUCT_RETURN 0
 #define JIT_APPLY_PAD_FLOAT_REGS 1
 
-#define JIT_APPLY_NUM_DOUBLE_REGS 0
-#define JIT_APPLY_NUM_NFLOAT_REGS 0
-#define JIT_APPLY_DOUBLES_IN_WORD_REGS 0
-#define JIT_APPLY_NFLOATS_IN_WORD_REGS 0
-#define JIT_APPLY_RETURN_DOUBLES_AFTER 0
-#define JIT_APPLY_RETURN_NFLOATS_AFTER 0
-
 #ifdef	__cplusplus
 };
 #endif
diff -ruN libjit/tools/gen-apply.c libjit-mikyt/tools/gen-apply.c
--- libjit/tools/gen-apply.c	2008-11-23 10:15:25.000000000 +0100
+++ libjit-mikyt/tools/gen-apply.c	2008-12-09 23:11:24.000000000 +0100
@@ -22,13 +22,7 @@
 
 #include <jit/jit-arch.h>
 #include <jit/jit-defs.h>
-
-#if defined(__APPLE__) && defined(__MACH__)
-# define	JIT_MEMCPY	"_mem_copy"
-#else
-# define	JIT_MEMCPY	"mem_copy"
-#endif
-
+#define	JIT_MEMCPY		"mem_copy"
 #include "jit-apply-func.h"
 #include <stdio.h>
 #include <config.h>
@@ -67,6 +61,9 @@
 #if defined(__x86_64__) || defined(__x86_64)
 	#define	PLATFORM_IS_X86_64	1
 #endif
+#if defined(__arm__) || defined(__arm)
+	#define PLATFORM_IS_ARM		1
+#endif
 
 #if PLATFORM_IS_X86
 /*
@@ -2721,6 +2718,9 @@
 	printf("#define JIT_APPLY_PARENT_FRAME_OFFSET %d\n", parent_frame_offset);
 	printf("#define JIT_APPLY_RETURN_ADDRESS_OFFSET %d\n",
 		   return_address_offset);
+//	#ifdef PLATFORM_IS_ARM
+//		broken_frame_builtins=1;
+//	#endif
 	printf("#define JIT_APPLY_BROKEN_FRAME_BUILTINS %d\n",
 		   broken_frame_builtins);
 	printf("#define JIT_APPLY_X86_POP_STRUCT_RETURN %d\n",
diff -ruN libjit/tutorial/.cvsignore libjit-mikyt/tutorial/.cvsignore
--- libjit/tutorial/.cvsignore	2007-01-04 12:44:30.000000000 +0100
+++ libjit-mikyt/tutorial/.cvsignore	1970-01-01 01:00:00.000000000 +0100
@@ -1,12 +0,0 @@
-Makefile
-Makefile.in
-.deps
-.libs
-*.exe
-t1
-t2
-t3
-t4
-t5
-*.lo
-*.la
