github.com/goccy/go-jit@v0.0.0-20200514131505-ff78d45cf6af/internal/ccall/jit-rules-arm.c (about)

     1  /*
     2   * jit-rules-arm.c - Rules that define the characteristics of the ARM.
     3   *
     4   * Copyright (C) 2004  Southern Storm Software, Pty Ltd.
     5   * Copyright (C) 2008  Michele Tartara <mikyt@users.sourceforge.net>
     6   *
     7   * This file is part of the libjit library.
     8   *
     9   * The libjit library is free software: you can redistribute it and/or
    10   * modify it under the terms of the GNU Lesser General Public License
    11   * as published by the Free Software Foundation, either version 2.1 of
    12   * the License, or (at your option) any later version.
    13   *
    14   * The libjit library is distributed in the hope that it will be useful,
    15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    17   * Lesser General Public License for more details.
    18   *
    19   * You should have received a copy of the GNU Lesser General Public
    20   * License along with the libjit library.  If not, see
    21   * <http://www.gnu.org/licenses/>.
    22   */
    23  
    24  #include "jit-internal.h"
    25  #include "jit-rules.h"
    26  #include "jit-apply-rules.h"
    27  
    28  #if defined(JIT_BACKEND_ARM)
    29  
    30  #include "jit-gen-arm.h"
    31  #include "jit-reg-alloc.h"
    32  #include "jit-setjmp.h"
    33  #include <stdio.h>
    34  #include <stdlib.h>
    35  
    36  /*
    37   * Pseudo register numbers for the ARM registers.  These are not the
    38   * same as the CPU instruction register numbers.  The order of these
    39   * values must match the order in "JIT_REG_INFO".
    40   */
    41  #define ARM_REG_R0		0
    42  #define ARM_REG_R1		1
    43  #define ARM_REG_R2		2
    44  #define ARM_REG_R3		3
    45  #define ARM_REG_R4		4
    46  #define ARM_REG_R5		5
    47  #define ARM_REG_R6		6
    48  #define ARM_REG_R7		7
    49  #define ARM_REG_R8		8
    50  #define ARM_REG_R9		9
    51  #define ARM_REG_R10		10
    52  #define ARM_REG_FP		11
    53  #define ARM_REG_R12		12
    54  #define ARM_REG_SP		13
    55  #define ARM_REG_LR		14
    56  #define ARM_REG_PC		15
    57  
    58  #ifdef JIT_ARM_HAS_FPA
    59  #define ARM_F0			16
    60  #define ARM_F1			17
    61  #define ARM_F2			18
    62  #define ARM_F3			19
    63  #define ARM_F4			20
    64  #define ARM_F5			21
    65  #define ARM_F6			22
    66  #define ARM_F7			23
    67  #endif
    68  
    69  #ifdef JIT_ARM_HAS_VFP
    70  #define ARM_REG_S0		16
    71  #define ARM_REG_S1		17
    72  #define ARM_REG_S2		18
    73  #define ARM_REG_S3		19
    74  #define ARM_REG_S4		20
    75  #define ARM_REG_S5		21
    76  #define ARM_REG_S6		22
    77  #define ARM_REG_S7		23
    78  #define ARM_REG_S8		24
    79  #define ARM_REG_S9		25
    80  #define ARM_REG_S10		26
    81  #define ARM_REG_S11		27
    82  #define ARM_REG_S12		28
    83  #define ARM_REG_S13		29
    84  #define ARM_REG_S14		30
    85  #define ARM_REG_S15		31
    86  #define ARM_REG_D8		32
    87  #define ARM_REG_D9		33
    88  #define ARM_REG_D10		34
    89  #define ARM_REG_D11		35
    90  #define ARM_REG_D12		36
    91  #define ARM_REG_D13		37
    92  #define ARM_REG_D14		38
    93  #define ARM_REG_D15		39
    94  #endif
    95  
    96  /*
    97   * Determine if a pseudo register number is word-based or float-based.
    98   */
    99  #define	IS_WORD_REG(reg)	((reg) <= ARM_REG_PC)
   100  #define	IS_FLOAT_REG(reg)	((reg) > ARM_REG_PC)
   101  
   102  /*
   103   * Round a size up to a multiple of the stack word size.
   104   */
   105  #define	ROUND_STACK(size) \
   106  	(((size) + (sizeof(void *) - 1)) & ~(sizeof(void *) - 1))
   107  
   108  /*
   109   * Given the first register of a long pair get the other register,
   110   * only if the two are currently forming a pair
   111   */
   112  #define jit_reg_current_other_reg(gen,reg) \
   113  	(gen->contents[reg].is_long_start ? jit_reg_other_reg(reg) : -1)
   114  
   115  /* 
   116   * Define the classes of registers
   117   */
   118  static _jit_regclass_t *arm_reg;
   119  static _jit_regclass_t *arm_freg;
   120  static _jit_regclass_t *arm_freg32;
   121  static _jit_regclass_t *arm_freg64;
   122  static _jit_regclass_t *arm_lreg;
   123  
   124  /*
   125   * -------------------- Helper functions --------------------------
   126   */
   127  
   128  /*
   129   * Load the instruction pointer from the generation context.
   130   */
   131  #define	jit_gen_load_inst_ptr(gen,inst)	\
   132  	do { \
   133  		arm_inst_buf_init((inst), (gen)->ptr, (gen)->limit); \
   134  	} while (0)
   135  
   136  /*
   137   * Save the instruction pointer back to the generation context.
   138   */
   139  #define	jit_gen_save_inst_ptr(gen,inst)	\
   140  	do { \
   141  		(gen)->ptr = (unsigned char *)arm_inst_get_posn(inst); \
   142  	} while (0)
   143  
   144  /*
   145   * Get a temporary register that isn't one of the specified registers.
   146   * When this function is used EVERY REGISTER COULD BE DESTROYED!!!
   147   * TODO: this function is only used by JIT_OP_STORE_RELATIVE_STRUCT, through memory_copy: remove
   148   * the need of using it by substituting it with register allocation with [scratch reg]
   149   */
   150  static int get_temp_reg(int reg1, int reg2, int reg3)
   151  {
   152  	/* 
   153  	 * R0-R3 are not used because they could be needed for parameter passing.
   154  	 * R4 is not used because it's used by jit_apply to store the base of the frame where
   155  	 * it saves all the data it needs in order to restart execution after calling a compiled function.
   156  	 * R9 is not used because it's the platform register and could have special
   157  	 * uses on some ARM platform
   158  	 * R11, R13-R15 are not used because they have special meaning on the ARM platform.
   159  	 * The other registers are candidates for 
   160  	 */
   161  	if(reg1 != ARM_R5 && reg2 != ARM_R5 && reg3 != ARM_R5)
   162  	{
   163  		return ARM_R5;
   164  	}
   165  	if(reg1 != ARM_R6 && reg2 != ARM_R6 && reg3 != ARM_R6)
   166  	{
   167  		return ARM_R6;
   168  	}
   169  	if(reg1 != ARM_R7 && reg2 != ARM_R7 && reg3 != ARM_R7)
   170  	{
   171  		return ARM_R7;
   172  	}
   173  	if(reg1 != ARM_R8 && reg2 != ARM_R8 && reg3 != ARM_R8)
   174  	{
   175  		return ARM_R8;
   176  	}
   177  	if(reg1 != ARM_R10 && reg2 != ARM_R10 && reg3 != ARM_R10)
   178  	{
   179  		return ARM_R10;
   180  	}
   181  	return ARM_R12;
   182  }
   183  
   184  static void mov_reg_imm (jit_gencode_t gen, arm_inst_buf *inst, int reg, int value);
   185  
   186  /*
   187   * Copy a block of memory that has a specific size.  Other than
   188   * the parameter pointers, all registers must be unused at this point.
   189   */
   190  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)
   191  {
   192  	//int temp_reg = get_temp_reg(dreg, sreg, -1);
   193  	if(temp_reg == -1)
   194  	{
   195  		temp_reg = get_temp_reg(dreg, sreg, -1);
   196  	}
   197  	if(size <= 4 * sizeof(void *))
   198  	{
   199  		/* Use direct copies to copy the memory */
   200  		int offset = 0;
   201  		while(size >= sizeof(void *))
   202  		{
   203  			arm_mov_reg_membase(inst, temp_reg, sreg, soffset + offset, sizeof(void *));
   204  			arm_mov_membase_reg(inst, dreg, doffset + offset, temp_reg, sizeof(void *));
   205  			size -= sizeof(void *);
   206  			offset += sizeof(void *);
   207  		}
   208  		if(size >= 2)
   209  		{
   210  			arm_mov_reg_membase(inst, temp_reg, sreg, soffset + offset, 2);
   211  			arm_mov_membase_reg(inst, dreg, doffset + offset, temp_reg, 2);
   212  			size -= 2;
   213  			offset += 2;
   214  		}
   215  		if(size >= 1)
   216  		{
   217  			arm_mov_reg_membase(inst, temp_reg, sreg, soffset + offset, 1);
   218  			arm_mov_membase_reg(inst, dreg, doffset + offset, temp_reg, 1);
   219  		}
   220  	}
   221  	else
   222  	{
   223  		/* Call out to "jit_memcpy" to effect the copy */
   224  		//Load the parameters in the right registers
   225  		//R2 <- size
   226  		mov_reg_imm(gen, &inst, ARM_R2, size);
   227  		//R1 <- source pointer
   228  		if(soffset == 0)
   229  		{
   230  			arm_mov_reg_reg(inst, ARM_R1, sreg);
   231  		}
   232  		else
   233  		{
   234  			arm_alu_reg_imm(inst, ARM_ADD, temp_reg, sreg, soffset);
   235  			arm_mov_reg_reg(inst, ARM_R1, temp_reg);
   236  		}
   237  		//R0 <- destination pointer
   238  		/* On ARM, the stack doesn't need special treatment, since parameters
   239  		   are passed using registers, not using the stack as it's done on x86 */
   240  		if(doffset == 0)
   241  		{
   242  			arm_mov_reg_reg(inst, ARM_R0, dreg);
   243  		}
   244  		else
   245  		{
   246  			arm_alu_reg_imm(inst, ARM_ADD, temp_reg, dreg, doffset);
   247  			arm_mov_reg_reg(inst, ARM_R0, temp_reg);
   248  		}
   249  		
   250  		arm_call(inst, jit_memcpy);
   251  	}
   252  	return inst;
   253  }
   254  
   255  /*
   256   * Flush the contents of the constant pool.
   257   */
   258  static void flush_constants(jit_gencode_t gen, int after_epilog)
   259  {
   260  	arm_inst_buf inst;
   261  	arm_inst_word *patch;
   262  	arm_inst_word *current;
   263  	arm_inst_word *fixup;
   264  	int index, value, offset;
   265  
   266  	/* Bail out if there are no constants to flush */
   267  	if(!(gen->num_constants))
   268  	{
   269  		return;
   270  	}
   271  
   272  	/* Initialize the cache output pointer */
   273  	jit_gen_load_inst_ptr(gen, inst);
   274  
   275  	/* Jump over the constant pool if it is being output inline */
   276  	if(!after_epilog)
   277  	{
   278  		patch = arm_inst_get_posn(inst);
   279  		arm_jump_imm(inst, 0);
   280  	}
   281  	else
   282  	{
   283  		patch = 0;
   284  	}
   285  
   286  	/* Align the constant pool, if requested */
   287  	if(gen->align_constants && (((int)arm_inst_get_posn(inst)) & 7) != 0)
   288  	{
   289  		arm_inst_add(inst, 0);
   290  	}
   291  
   292  	/* Output the constant values and apply the necessary fixups */
   293  	for(index = 0; index < gen->num_constants; ++index)
   294  	{
   295  		current = arm_inst_get_posn(inst);
   296  		arm_inst_add(inst, gen->constants[index]);
   297  		fixup = gen->fixup_constants[index];
   298  		while(fixup != 0)
   299  		{
   300  			if((*fixup & 0x0F000000) == 0x05000000)
   301  			{
   302  				/* Word constant fixup */
   303  				value = *fixup & 0x0FFF;
   304  				offset = ((arm_inst_get_posn(inst) - 1 - fixup) * 4) - 8;
   305  				*fixup = ((*fixup & ~0x0FFF) | offset);
   306  			}
   307  			else
   308  			{
   309  				/* Floating-point constant fixup */
   310  				value = (*fixup & 0x00FF) * 4;
   311  				offset = ((arm_inst_get_posn(inst) - 1 - fixup) * 4) - 8;
   312  				*fixup = ((*fixup & ~0x00FF) | (offset / 4));
   313  			}
   314  			if(value)
   315  			{
   316  				fixup -= value / sizeof(void *);
   317  			}
   318  			else
   319  			{
   320  				fixup = 0;
   321  			}
   322  		}
   323  	}
   324  
   325  	/* Backpatch the jump if necessary */
   326  	if(!after_epilog)
   327  	{
   328  		arm_patch(inst, patch, arm_inst_get_posn(inst));
   329  	}
   330  
   331  	/* Flush the pool state and restart */
   332  	gen->num_constants = 0;
   333  	gen->align_constants = 0;
   334  	gen->first_constant_use = 0;
   335  	jit_gen_save_inst_ptr(gen, inst);
   336  }
   337  
   338  /*
   339   * Perform a constant pool flush if we are too far from the starting point.
   340   */
   341  static int flush_if_too_far(jit_gencode_t gen)
   342  {
   343  	if(gen->first_constant_use &&
   344  		  (((arm_inst_word *)(gen->ptr)) -
   345  		  ((arm_inst_word *)(gen->first_constant_use))) >= 100)
   346  	{
   347  		flush_constants(gen, 0);
   348  		return 1;
   349  	}
   350  	else
   351  	{
   352  		return 0;
   353  	}
   354  }
   355  
   356  /*
   357   * Add a fixup for a particular constant pool entry.
   358   */
   359  static void add_constant_fixup
   360  		(jit_gencode_t gen, int index, arm_inst_word *fixup)
   361  {
   362  	arm_inst_word *prev;
   363  	int value;
   364  	if(((unsigned char *)fixup) >= gen->limit)
   365  	{
   366  		/* The instruction buffer is full, so don't record this fixup */
   367  		return;
   368  	}
   369  	prev = gen->fixup_constants[index];
   370  	if(prev)
   371  	{
   372  		value = (fixup - prev) * sizeof(void *);
   373  	}
   374  	else
   375  	{
   376  		value = 0;
   377  	}
   378  	if((*fixup & 0x0F000000) == 0x05000000)
   379  	{
   380  		//Word fixup
   381  		*fixup = ((*fixup & ~0x0FFF) | value);
   382  	}
   383  	else
   384  	{
   385  		//Float fixup
   386  		*fixup = ((*fixup & ~0x00FF) | (value / 4));
   387  	}
   388  	gen->fixup_constants[index] = fixup;
   389  	if(!(gen->first_constant_use))
   390  	{
   391  		gen->first_constant_use = fixup;
   392  	}
   393  }
   394  
   395  /*
   396   * Add an immediate value to the constant pool.  The constant
   397   * is loaded from the instruction at "fixup".
   398   */
   399  static void add_constant(jit_gencode_t gen, int value, arm_inst_word *fixup)
   400  {
   401  	int index;
   402  
   403  	/* Search the constant pool for an existing copy of the value */
   404  	for(index = 0; index < gen->num_constants; ++index)
   405  	{
   406  		if(gen->constants[index] == value)
   407  		{
   408  			add_constant_fixup(gen, index, fixup);
   409  			return;
   410  		}
   411  	}
   412  
   413  	/* Flush the constant pool if there is insufficient space */
   414  	if(gen->num_constants >= JIT_ARM_MAX_CONSTANTS)
   415  	{
   416  		flush_constants(gen, 0);
   417  	}
   418  
   419  	/* Add the constant value to the pool */
   420  	gen->constants[gen->num_constants] = value;
   421  	gen->fixup_constants[gen->num_constants] = 0;
   422  	++(gen->num_constants);
   423  	add_constant_fixup(gen, gen->num_constants - 1, fixup);
   424  }
   425  
   426  /*
   427   * Add a double-word immediate value to the constant pool.
   428   */
   429  static void add_constant_dword
   430  		(jit_gencode_t gen, int value1, int value2, arm_inst_word *fixup, int align)
   431  {
   432  	int index;
   433  
   434  	/* Make sure that the constant pool is properly aligned when output */
   435  	if(align)
   436  	{
   437  		gen->align_constants = 1;
   438  	}
   439  
   440  	/* Search the constant pool for an existing copy of the value */
   441  	for(index = 0; index < (gen->num_constants - 1); ++index)
   442  	{
   443  		if(gen->constants[index] == value1 &&
   444  				 gen->constants[index + 1] == value2)
   445  		{
   446  			if(!align || (index % 2) == 0)
   447  			{
   448  				add_constant_fixup(gen, index, fixup);
   449  				return;
   450  			}
   451  		}
   452  	}
   453  
   454  	/* Flush the constant pool if there is insufficient space */
   455  	if(gen->num_constants >= (JIT_ARM_MAX_CONSTANTS - 1))
   456  	{
   457  		flush_constants(gen, 0);
   458  	}
   459  
   460  	/* Align the constant pool on a 64-bit boundary if necessary */
   461  	if(align && (gen->num_constants % 2) != 0)
   462  	{
   463  		gen->constants[gen->num_constants] = 0;
   464  		gen->fixup_constants[gen->num_constants] = 0;
   465  		++(gen->num_constants);
   466  	}
   467  
   468  	/* Add the double word constant value to the pool */
   469  	gen->constants[gen->num_constants] = value1;
   470  	gen->fixup_constants[gen->num_constants] = 0;
   471  	gen->constants[gen->num_constants+1] = value2;
   472  	gen->fixup_constants[gen->num_constants+1] = 0;
   473  	gen->num_constants += 2;
   474  	add_constant_fixup(gen, gen->num_constants - 2, fixup);
   475  }
   476  
   477  /*
   478   * Load an immediate value into a word register.  If the value is
   479   * complicated, then add an entry to the constant pool.
   480   */
   481  static void mov_reg_imm
   482  		(jit_gencode_t gen, arm_inst_buf *inst, int reg, int value)
   483  {
   484  	arm_inst_word *fixup;
   485  
   486  	/* Bail out if the value is not complex enough to need a pool entry */
   487  	if(!arm_is_complex_imm(value))
   488  	{
   489  		arm_mov_reg_imm(*inst, reg, value);
   490  		return;
   491  	}
   492  
   493  	/* Output a placeholder to load the value later */
   494  	fixup = arm_inst_get_posn(*inst);
   495  	arm_load_membase(*inst, reg, ARM_PC, 0);
   496  
   497  	/* Add the constant to the pool, which may cause a flush */
   498  	jit_gen_save_inst_ptr(gen, *inst);
   499  	add_constant(gen, value, fixup);
   500  	jit_gen_load_inst_ptr(gen, *inst);
   501  }
   502  
   503  /*
   504   * Load a float32 immediate value into a float register.  If the value is
   505   * complicated, then add an entry to the constant pool.
   506   */
   507  static void mov_freg_imm_32
   508  		(jit_gencode_t gen, arm_inst_buf *inst, int reg, int value)
   509  {
   510  	arm_inst_word *fixup;
   511  
   512  	/* Output a placeholder to load the value later */
   513  	fixup = arm_inst_get_posn(*inst);
   514  	arm_load_membase_float32(*inst, reg, ARM_PC, 0);
   515  
   516  	/* Add the constant to the pool, which may cause a flush */
   517  	jit_gen_save_inst_ptr(gen, *inst);
   518  	add_constant(gen, value, fixup);
   519  	jit_gen_load_inst_ptr(gen, *inst);
   520  }
   521  
   522  /*
   523   * Load a float64 immediate value into a float register.  If the value is
   524   * complicated, then add an entry to the constant pool.
   525   */
   526  static void mov_freg_imm_64
   527  		(jit_gencode_t gen, arm_inst_buf *inst, int reg, int value1, int value2)
   528  {
   529  	arm_inst_word *fixup;
   530  
   531  	/* Output a placeholder to load the value later */
   532  	fixup = arm_inst_get_posn(*inst);
   533  	arm_load_membase_float64(*inst, reg, ARM_PC, 0);
   534  
   535  	/* Add the constant to the pool, which may cause a flush */
   536  	jit_gen_save_inst_ptr(gen, *inst);
   537  	add_constant_dword(gen, value1, value2, fixup, 1);
   538  	jit_gen_load_inst_ptr(gen, *inst);
   539  }
   540  
   541  /*
   542   * Output a branch instruction.
   543   */
   544  static void output_branch
   545  		(jit_function_t func, arm_inst_buf *inst, int cond, jit_insn_t insn)
   546  {
   547  	jit_block_t block;
   548  	int offset;
   549  	//block = jit_block_from_label(func, (jit_label_t)(insn->dest));
   550  	if((insn->flags & JIT_INSN_VALUE1_IS_LABEL) != 0)
   551  	{
   552  		/* "address_of_label" instruction */
   553  		block = jit_block_from_label(func, (jit_label_t)(insn->value1));
   554  	}
   555  	else
   556  	{
   557  		block = jit_block_from_label(func, (jit_label_t)(insn->dest));
   558  	}
   559  	if(!block)
   560  	{
   561  		return;
   562  	}
   563  	if(arm_inst_get_posn(*inst) >= arm_inst_get_limit(*inst))
   564  	{
   565  		/* The buffer has overflowed, so don't worry about fixups */
   566  		return;
   567  	}
   568  	if(block->address)
   569  	{
   570  		/* We already know the address of the block */
   571  		arm_branch(*inst, cond, block->address);
   572  	}
   573  	else
   574  	{
   575  		/* Output a placeholder and record on the block's fixup list */
   576  		if(block->fixup_list)
   577  		{
   578  			offset = (int)(((unsigned char *)arm_inst_get_posn(*inst)) -
   579  					((unsigned char *)(block->fixup_list)));
   580  		}
   581  		else
   582  		{
   583  			offset = 0;
   584  		}
   585  		arm_branch_imm(*inst, cond, offset);
   586  		block->fixup_list = (void *)(arm_inst_get_posn(*inst) - 1);
   587  	}
   588  }
   589  
   590  /*
   591   * Throw a builtin exception.
   592   */
   593  static void throw_builtin
   594  		(arm_inst_buf *inst, jit_function_t func, int cond, int type)
   595  {
   596  	arm_inst_word *patch;
   597  
   598  	/* Branch past the following code if "cond" is not true */
   599  	patch = arm_inst_get_posn(*inst);
   600  	arm_branch_imm(*inst, cond ^ 0x01, 0);
   601  
   602  	/* We need to update "catch_pc" if we have a "try" block */
   603  	if(func->builder->setjmp_value != 0)
   604  	{
   605  		_jit_gen_fix_value(func->builder->setjmp_value);
   606  		arm_mov_reg_reg(*inst, ARM_WORK, ARM_PC);
   607  		arm_store_membase(*inst, ARM_WORK, ARM_FP,
   608  				   func->builder->setjmp_value->frame_offset +
   609  						   jit_jmp_catch_pc_offset);
   610  	}
   611  
   612  	/* Push the exception type onto the stack */
   613  	arm_mov_reg_imm(*inst, ARM_WORK, type);
   614  	arm_push_reg(*inst, ARM_WORK);
   615  
   616  	/* Call the "jit_exception_builtin" function, which will never return */
   617  	arm_call(*inst, jit_exception_builtin);
   618  
   619  	/* Back-patch the previous branch instruction */
   620  	arm_patch(*inst, patch, arm_inst_get_posn(*inst));
   621  }
   622  
   623  /*
   624   * Jump to the current function's epilog.
   625   */
   626  static void jump_to_epilog
   627  		(jit_gencode_t gen, arm_inst_buf *inst, jit_block_t block)
   628  {
   629  	int offset;
   630  
   631  	/* If the epilog is the next thing that we will output,
   632  	   then fall through to the epilog directly */
   633  	if(_jit_block_is_final(block))
   634  	{
   635  		return;
   636  	}
   637  
   638  	/* Bail out if the instruction buffer has overflowed */
   639  	if(arm_inst_get_posn(*inst) >= arm_inst_get_limit(*inst))
   640  	{
   641  		return;
   642  	}
   643  
   644  	/* Output a placeholder for the jump and add it to the fixup list */
   645  	if(gen->epilog_fixup)
   646  	{
   647  		offset = (int)(((unsigned char *)arm_inst_get_posn(*inst)) -
   648  				((unsigned char *)(gen->epilog_fixup)));
   649  	}
   650  	else
   651  	{
   652  		offset = 0;
   653  	}
   654  	arm_branch_imm(*inst, ARM_CC_AL, offset);
   655  	gen->epilog_fixup = (void *)(arm_inst_get_posn(*inst) - 1);
   656  }
   657  
   658  #define	TODO()		\
   659  	do { \
   660  		fprintf(stderr, "TODO at %s, %d\n", __FILE__, (int)__LINE__); \
   661  } while (0)
   662  
   663  /*
   664   * -------------------- End of helper functions ------------------------
   665   */
   666  
   667  
   668  /*
   669   * Initialize the backend.
   670   */
   671  void _jit_init_backend(void)
   672  {
   673  	/*
   674  	 * Init the various classes of registers
   675  	 */
   676  
   677  	/* WORD registers */
   678  	arm_reg = _jit_regclass_create(
   679  		"reg", JIT_REG_WORD, 9,
   680  		ARM_REG_R0, ARM_REG_R1,
   681  		ARM_REG_R2, ARM_REG_R3,
   682  		ARM_REG_R4, ARM_REG_R5,
   683  		ARM_REG_R6, ARM_REG_R7,
   684  		ARM_REG_R8);
   685  
   686  #ifdef JIT_ARM_HAS_FPA
   687  	/* float registers */
   688  	arm_freg = _jit_regclass_create(
   689  		"freg64", JIT_REG_ARM_FLOAT, 4,
   690  		ARM_REG_F0, ARM_REG_F1,
   691  		ARM_REG_F2, ARM_REG_F3,
   692  		/*ARM_REG_F4, ARM_REG_F5,
   693  		  ARM_REG_F6, ARM_REG_F7*/);
   694  #endif
   695  
   696  #ifdef JIT_ARM_HAS_VFP
   697  	/* 32-bits float registers */
   698  	arm_freg32 = _jit_regclass_create(
   699  		"freg32", JIT_REG_ARM_FLOAT32, 16,
   700  		ARM_REG_S0, ARM_REG_S1,
   701  		ARM_REG_S2, ARM_REG_S3,
   702  		ARM_REG_S4, ARM_REG_S5,
   703  		ARM_REG_S6, ARM_REG_S7,
   704  		ARM_REG_S8, ARM_REG_S9,
   705  		ARM_REG_S10, ARM_REG_S11,
   706  		ARM_REG_S12, ARM_REG_S13,
   707  		ARM_REG_S14, ARM_REG_S15);
   708  
   709  	/* 64-bits float registers */
   710  	arm_freg64 = _jit_regclass_create(
   711  		"freg64", JIT_REG_ARM_FLOAT64, 8,
   712  		ARM_REG_D8, ARM_REG_D9,
   713  		ARM_REG_D10, ARM_REG_D11,
   714  		ARM_REG_D12, ARM_REG_D13,
   715  		ARM_REG_D14, ARM_REG_D15);
   716  #endif
   717  
   718  	/* Long registers */
   719  	arm_lreg = _jit_regclass_create(
   720  		"lreg", JIT_REG_LONG, 2,
   721  		ARM_REG_R0, ARM_REG_R2);
   722  }
   723  
   724  void _jit_gen_get_elf_info(jit_elf_info_t *info)
   725  {
   726  	info->machine = 40;		/* EM_ARM */
   727  	info->abi = 0;			/* ELFOSABI_SYSV */
   728  	info->abi_version = 0;
   729  }
   730  
   731  int _jit_setup_indirect_pointer(jit_function_t func, jit_value_t value)
   732  {
   733  	return jit_insn_outgoing_reg(func, value, ARM_WORK);
   734  }
   735  
   736  int _jit_create_call_return_insns
   737  	(jit_function_t func, jit_type_t signature,
   738  	 jit_value_t *args, unsigned int num_args,
   739  	 jit_value_t return_value, int is_nested)
   740  {
   741  	jit_type_t return_type;
   742  	int ptr_return;
   743  
   744  	/* Bail out now if we don't need to worry about return values */
   745  	return_type = jit_type_normalize(jit_type_get_return(signature));
   746  	ptr_return = jit_type_return_via_pointer(return_type);
   747  	if(!return_value || ptr_return)
   748  	{
   749  		return 1;
   750  	}
   751  
   752  	/* Structure values must be flushed into the frame, and
   753  	   everything else ends up in a register */
   754  	if(jit_type_is_struct(return_type) || jit_type_is_union(return_type))
   755  	{
   756  		if(!jit_insn_flush_struct(func, return_value))
   757  		{
   758  			return 0;
   759  		}
   760  	}
   761  	else if(return_type->kind != JIT_TYPE_VOID)
   762  	{
   763  		if(!jit_insn_return_reg(func, return_value, ARM_REG_R0))
   764  		{
   765  			return 0;
   766  		}
   767  	}
   768  
   769  	/* Everything is back where it needs to be */
   770  	return 1;
   771  }
   772  
   773  int _jit_opcode_is_supported(int opcode)
   774  {
   775  	switch(opcode)
   776  	{
   777  		#define JIT_INCLUDE_SUPPORTED
   778  		#include "jit-rules-arm.inc"
   779  		#undef JIT_INCLUDE_SUPPORTED
   780  	}
   781  	return 0;
   782  }
   783  
   784  void *_jit_gen_prolog(jit_gencode_t gen, jit_function_t func, void *buf)
   785  {
   786  	unsigned int prolog[JIT_PROLOG_SIZE / sizeof(int)];
   787  	arm_inst_buf inst;
   788  	int reg, regset;
   789  	unsigned int saved;
   790  	unsigned int frame_size;
   791  	unsigned int stack_growth;
   792  	
   793  	/* Initialize the instruction buffer */
   794  	arm_inst_buf_init(inst, prolog, prolog + JIT_PROLOG_SIZE / sizeof(int));
   795  
   796  	/* Determine which registers need to be preserved */
   797  	regset = 0;
   798  	saved = 0;
   799  	for(reg = 0; reg <= 15; ++reg)
   800  	{
   801  		if(jit_reg_is_used(gen->touched, reg) &&
   802  		   (_jit_reg_info[reg].flags & JIT_REG_CALL_USED) == 0)
   803  		{
   804  			regset |= (1 << reg);
   805  			saved += sizeof(void *);
   806  		}
   807  	}
   808  
   809  	/* Setup the frame, pushing all the callee-save registers */
   810  	arm_setup_frame(inst, regset);
   811  
   812  	/* Allocate space for the local variable frame.  Subtract off
   813  	   the space for the registers that we just saved.  The pc, lr,
   814  	   and fp registers are always saved, so account for them too */
   815  	stack_growth=(saved + 4 * sizeof(void *));
   816  	frame_size = func->builder->frame_size - stack_growth;
   817  	frame_size = func->builder->frame_size - (saved + 3 * sizeof(void *));
   818  	frame_size += (unsigned int)(func->builder->param_area_size);
   819  	while(frame_size % JIT_SP_ALIGN_PUBLIC != 0)
   820  	{
   821  		//Pad to reach the required stacl pointer alignment
   822  		frame_size++;
   823  	}
   824  	
   825  	/* If the registers that get saved on the stack make it grow of a odd number
   826  	 * of words, the preceding while isn't able anymore to compute the correct
   827  	 * allignment. The following adds a correction when needed.
   828  	 */
   829  	if (stack_growth % JIT_SP_ALIGN_PUBLIC != 0)
   830  	{
   831  		//Pad to reach the required stack pointer alignment
   832  		frame_size += (stack_growth % JIT_SP_ALIGN_PUBLIC);
   833  	}
   834  	
   835  	if(frame_size > 0)
   836  	{
   837  		arm_alu_reg_imm(inst, ARM_SUB, ARM_SP, ARM_SP, frame_size);
   838  	}
   839  
   840  	/* Copy the prolog into place and return the adjusted entry position */
   841  	reg = (int)((arm_inst_get_posn(inst) - prolog) * sizeof(unsigned int));
   842  	jit_memcpy(((unsigned char *)buf) + JIT_PROLOG_SIZE - reg, prolog, reg);
   843  	return (void *)(((unsigned char *)buf) + JIT_PROLOG_SIZE - reg);
   844  }
   845  
   846  void _jit_gen_epilog(jit_gencode_t gen, jit_function_t func)
   847  {
   848  	int reg, regset;
   849  	arm_inst_buf inst;
   850  	void **fixup;
   851  	void **next;
   852  	jit_nint offset;
   853  
   854  	/* Initialize the instruction buffer */
   855  	jit_gen_load_inst_ptr(gen, inst);
   856  
   857  	/* Determine which registers need to be restored when we return */
   858  	regset = 0;
   859  	for(reg = 0; reg <= 15; ++reg)
   860  	{
   861  		if(jit_reg_is_used(gen->touched, reg) &&
   862  		   (_jit_reg_info[reg].flags & JIT_REG_CALL_USED) == 0)
   863  		{
   864  			regset |= (1 << reg);
   865  		}
   866  	}
   867  
   868  	/* Apply fixups for blocks that jump to the epilog */
   869  	fixup = (void **)(gen->epilog_fixup);
   870  	while(fixup != 0)
   871  	{
   872  		offset = (((jit_nint)(fixup[0])) & 0x00FFFFFF) << 2;
   873  		if(!offset)
   874  		{
   875  			next = 0;
   876  		}
   877  		else
   878  		{
   879  			next = (void **)(((unsigned char *)fixup) - offset);
   880  		}
   881  		arm_patch(inst, fixup, arm_inst_get_posn(inst));
   882  		fixup = next;
   883  	}
   884  	gen->epilog_fixup = 0;
   885  
   886  	/* Pop the local stack frame and return */
   887  	arm_pop_frame(inst, regset);
   888  	jit_gen_save_inst_ptr(gen, inst);
   889  
   890  	/* Flush the remainder of the constant pool */
   891  	flush_constants(gen, 1);
   892  }
   893  
   894  #if 0
   895  /*
   896   * The ARM backend does not need this function because it uses
   897   * _jit_create_indirector() instead.
   898   */
   899  void *_jit_gen_redirector(jit_gencode_t gen, jit_function_t func)
   900  {
   901  	void *ptr, *entry;
   902  	arm_inst_buf inst;
   903  	jit_gen_load_inst_ptr(gen, inst);
   904  	ptr = (void *)&(func->entry_point);
   905  	entry = gen->ptr;
   906  	arm_load_membase(inst, ARM_WORK, ARM_PC, 0);
   907  	arm_load_membase(inst, ARM_PC, ARM_WORK, 0);
   908  	arm_inst_add(inst, (unsigned int)ptr);
   909  	jit_gen_save_inst_ptr(gen, inst);
   910  	return entry;
   911  }
   912  #endif 
   913  /*
   914   * Setup or teardown the ARM code output process.
   915   */
   916  #define	jit_cache_setup_output(needed)	\
   917  	arm_inst_buf inst; \
   918  	jit_gen_load_inst_ptr(gen, inst)
   919  #define	jit_cache_end_output()	\
   920  	jit_gen_save_inst_ptr(gen, inst)
   921  
   922  /** 
   923   * Spill the content of register "reg" (and "other_reg", if it's different from -1) 
   924   * into the global register or the memory area associated with "value"
   925   * NB: it doesn't set value->in_global_register or value->in_frame. The caller has to
   926   * take care of that.
   927   */
   928  void _jit_gen_spill_reg(jit_gencode_t gen, int reg,
   929  						int other_reg, jit_value_t value)
   930  {
   931  	int offset;
   932  
   933  	/* Make sure that we have sufficient space */
   934  	jit_cache_setup_output(32);
   935  	if(flush_if_too_far(gen))
   936  	{
   937  		jit_gen_load_inst_ptr(gen, inst);
   938  	}
   939  
   940  	/* Output an appropriate instruction to spill the value */
   941  	if(value->has_global_register)
   942  	{
   943  		if (IS_FLOAT_REG(reg))
   944  		{
   945  			printf("TODO:Copy from float reg to global reg is not handled properly in %s\n", __FILE__);
   946  			abort();
   947  		}
   948  		else
   949  		{
   950  			arm_mov_reg_reg(inst, _jit_reg_info[value->global_reg].cpu_reg, _jit_reg_info[reg].cpu_reg);
   951  		}
   952  	}
   953  	else
   954  	{
   955  		_jit_gen_fix_value(value);
   956  		offset = (int)(value->frame_offset);
   957  		if(IS_WORD_REG(reg))
   958  		{
   959  			arm_store_membase(inst, reg, ARM_FP, offset);
   960  			if(other_reg != -1)
   961  			{
   962  				/* Spill the other word register in a pair */
   963  				offset += sizeof(void *);
   964  				arm_store_membase(inst, other_reg, ARM_FP, offset);
   965  			}
   966  		}
   967  		else if(jit_type_normalize(value->type)->kind == JIT_TYPE_FLOAT32)
   968  		{
   969  			arm_store_membase_float32(inst, _jit_reg_info[value->reg].cpu_reg, ARM_FP, offset);
   970  		}
   971  		else
   972  		{
   973  			arm_store_membase_float64(inst, _jit_reg_info[value->reg].cpu_reg, ARM_FP, offset);
   974  		}
   975  	}
   976  
   977  	/* End the code output process */
   978  	jit_cache_end_output();
   979  }
   980  
   981  void _jit_gen_free_reg(jit_gencode_t gen, int reg,
   982  					   int other_reg, int value_used)
   983  {
   984  	/* We don't have to do anything to free ARM registers */
   985  }
   986  
   987  /*
   988   * Loads the content of the value @var{value} into register @var{reg} and (if needed) @var{other_reg}
   989   */
   990  void _jit_gen_load_value
   991  	(jit_gencode_t gen, int reg, int other_reg, jit_value_t value)
   992  {
   993  	int offset;
   994  
   995  	/* Make sure that we have sufficient space */
   996  	jit_cache_setup_output(32);
   997  	if(flush_if_too_far(gen))
   998  	{
   999  		jit_gen_load_inst_ptr(gen, inst);
  1000  	}
  1001  
  1002  	if(value->is_constant)
  1003  	{
  1004  		/* Determine the type of constant to be loaded */
  1005  		switch(jit_type_normalize(value->type)->kind)
  1006  		{
  1007  			case JIT_TYPE_SBYTE:
  1008  			case JIT_TYPE_UBYTE:
  1009  			case JIT_TYPE_SHORT:
  1010  			case JIT_TYPE_USHORT:
  1011  			case JIT_TYPE_INT:
  1012  			case JIT_TYPE_UINT:
  1013  			{
  1014  				mov_reg_imm(gen, &inst, _jit_reg_info[reg].cpu_reg,
  1015  							(jit_nint)(value->address));
  1016  			}
  1017  			break;
  1018  
  1019  			case JIT_TYPE_LONG:
  1020  			case JIT_TYPE_ULONG:
  1021  			{
  1022  				jit_long long_value;
  1023  				long_value = jit_value_get_long_constant(value);
  1024  				mov_reg_imm(gen, &inst, _jit_reg_info[reg].cpu_reg,
  1025  						    (jit_int)long_value);
  1026  				mov_reg_imm(gen, &inst, _jit_reg_info[reg].cpu_reg + 1,
  1027  						    (jit_int)(long_value >> 32));
  1028  			}
  1029  			break;
  1030  
  1031  			case JIT_TYPE_FLOAT32:
  1032  			{
  1033  				jit_float32 float32_value;
  1034  				float32_value = jit_value_get_float32_constant(value);
  1035  				if(IS_WORD_REG(reg))
  1036  				{
  1037  					mov_reg_imm(gen, &inst, _jit_reg_info[reg].cpu_reg,
  1038  							    *((int *)&float32_value));
  1039  				}
  1040  				else
  1041  				{
  1042  					mov_freg_imm_32
  1043  						(gen, &inst, _jit_reg_info[reg].cpu_reg,
  1044  					     *((int *)&float32_value));
  1045  				}
  1046  			}
  1047  			break;
  1048  
  1049  			case JIT_TYPE_FLOAT64:
  1050  			case JIT_TYPE_NFLOAT:
  1051  			{
  1052  				jit_float64 float64_value;
  1053  				float64_value = jit_value_get_float64_constant(value);
  1054  				if(IS_WORD_REG(reg))
  1055  				{
  1056  					mov_reg_imm
  1057  						(gen, &inst, _jit_reg_info[reg].cpu_reg,
  1058  						 ((int *)&float64_value)[0]);
  1059  					mov_reg_imm
  1060  						(gen, &inst, _jit_reg_info[reg].cpu_reg + 1,
  1061  						 ((int *)&float64_value)[1]);
  1062  				}
  1063  				else
  1064  				{
  1065  					mov_freg_imm_64
  1066  						(gen, &inst, _jit_reg_info[reg].cpu_reg,
  1067  					     ((int *)&float64_value)[0],
  1068  					     ((int *)&float64_value)[1]);
  1069  				}
  1070  			}
  1071  			break;
  1072  		}
  1073  	}
  1074  	else if(value->in_global_register)
  1075  	{
  1076  		/* Load the value out of a global register */
  1077  		if(IS_FLOAT_REG(reg))
  1078  		{
  1079  			/* Load into a floating point register */
  1080  #ifdef JIT_ARM_HAS_VFP
  1081  			/* Vector Floating Point instructions */
  1082  			if(jit_type_normalize(value->type)->kind == JIT_TYPE_FLOAT32)
  1083  			{
  1084  				arm_mov_float_reg(inst,
  1085  						  _jit_reg_info[reg].cpu_reg,
  1086  						  _jit_reg_info[value->global_reg].cpu_reg);
  1087  			}
  1088  			else
  1089  			{
  1090  				//JIT_TYPE_FLOAT64 or JIT_TYPE_NFLOAT
  1091  				arm_mov_double_reg_reg(inst,
  1092  						       _jit_reg_info[reg].cpu_reg,
  1093  						       _jit_reg_info[value->global_reg].cpu_reg,
  1094  						       _jit_reg_info[value->global_reg].cpu_reg + 1);
  1095  			}
  1096  #endif
  1097  #ifdef JIT_ARM_HAS_FPA
  1098  			/* Floating Point Architecture instructions */
  1099  			TODO();
  1100  			abort();
  1101  #endif
  1102  		}
  1103  		else
  1104  		{
  1105  			/* Load into a general-purpose register */
  1106  			arm_mov_reg_reg(inst,
  1107  					_jit_reg_info[reg].cpu_reg,
  1108  					_jit_reg_info[value->global_reg].cpu_reg);
  1109  		}
  1110  	}
  1111  	else if(value->in_register)
  1112  	{
  1113  		/* The value is already in another register. Move it */
  1114  		switch(jit_type_normalize(value->type)->kind)
  1115  		{
  1116  			case JIT_TYPE_SBYTE:
  1117  			case JIT_TYPE_UBYTE:
  1118  			case JIT_TYPE_SHORT:
  1119  			case JIT_TYPE_USHORT:
  1120  			case JIT_TYPE_INT:
  1121  			case JIT_TYPE_UINT:
  1122  			{
  1123  				arm_mov_reg_reg(inst, jit_reg_code(reg), jit_reg_code(value->reg));
  1124  			}
  1125  			break;
  1126  
  1127  			case JIT_TYPE_LONG:
  1128  			case JIT_TYPE_ULONG:
  1129  			{
  1130  				assert(jit_reg_code(other_reg) !=-1);
  1131  				assert(jit_reg_other_reg(value->reg) != -1);
  1132  				
  1133  				arm_mov_reg_reg(inst, jit_reg_code(reg), jit_reg_code(value->reg));
  1134  				arm_mov_reg_reg(inst, jit_reg_code(other_reg), jit_reg_other_reg(value->reg));
  1135  			}
  1136  			break;
  1137  
  1138  			case JIT_TYPE_FLOAT32:
  1139  			{
  1140  #ifdef JIT_ARM_HAS_VFP
  1141  				/* Vector Floating Point instructions */
  1142  				if(IS_FLOAT_REG(reg))
  1143  				{
  1144  					if(IS_WORD_REG(value->reg))
  1145  					{
  1146  						arm_mov_float_reg(inst,
  1147  								   jit_reg_code(reg),
  1148  								   jit_reg_code(value->reg));
  1149  					}
  1150  					else
  1151  					{
  1152  						arm_alu_freg_32(inst, ARM_MVF, 
  1153  								 jit_reg_code(reg),
  1154  								 jit_reg_code(value->reg));
  1155  					}
  1156  				}
  1157  				else
  1158  				{
  1159  					if(IS_WORD_REG(value->reg))
  1160  					{
  1161  						arm_mov_reg_reg(inst,
  1162  								 jit_reg_code(reg),
  1163  								 jit_reg_code(value->reg));
  1164  					}
  1165  					else
  1166  					{
  1167  						arm_mov_reg_float(inst,
  1168  								   jit_reg_code(reg),
  1169  								   jit_reg_code(value->reg));
  1170  					}
  1171  				}
  1172  #endif
  1173  #ifdef JIT_ARM_HAS_FPA
  1174  				/* Floating Point Architecture instructions */
  1175  				TODO();
  1176  				abort();
  1177  #endif
  1178  			}
  1179  			break;
  1180  			
  1181  			case JIT_TYPE_FLOAT64:
  1182  			case JIT_TYPE_NFLOAT:
  1183  			{
  1184  #ifdef JIT_ARM_HAS_VFP
  1185  				/* Vector Floating Point instruction */
  1186  				if(IS_FLOAT_REG(reg))
  1187  				{
  1188  					if(IS_WORD_REG(value->reg))
  1189  					{
  1190  						assert(jit_reg_other_reg(value->reg) != -1);
  1191  						
  1192  						arm_mov_double_reg_reg(inst,
  1193  									jit_reg_code(reg),
  1194  									jit_reg_code(value->reg),
  1195  									jit_reg_other_reg(value->reg));
  1196  					}
  1197  					else
  1198  					{
  1199  						arm_alu_freg(inst, ARM_MVF,
  1200  							      jit_reg_code(reg),
  1201  							      jit_reg_code(value->reg));
  1202  					}
  1203  				}
  1204  				else
  1205  				{
  1206  					if(IS_WORD_REG(value->reg))
  1207  					{
  1208  						arm_mov_reg_reg(inst,
  1209  								 jit_reg_code(reg),
  1210  								 jit_reg_code(value->reg));
  1211  					}
  1212  					else
  1213  					{
  1214  						assert(jit_reg_other_reg(reg));
  1215  						arm_mov_reg_reg_double(inst,
  1216  									jit_reg_code(reg),
  1217  									jit_reg_other_reg(reg),
  1218  									jit_reg_code(value->reg));
  1219  					}
  1220  				}
  1221  #endif
  1222  #ifdef JIT_ARM_HAS_FPA
  1223  				/* Floating Point Architecture instructions */
  1224  				TODO();
  1225  				abort();
  1226  #endif
  1227  			}
  1228  			break;
  1229  		}
  1230  	}
  1231  	else
  1232  	{
  1233  		/* Load from the stack */
  1234  		assert(!value->in_global_register && !value->is_constant && !value->in_register);
  1235  		
  1236  		/* Fix the position of the value in the stack frame */
  1237  		_jit_gen_fix_value(value);
  1238  		offset = (int)(value->frame_offset);
  1239  
  1240  		switch(jit_type_normalize(value->type)->kind)
  1241  		{
  1242  			case JIT_TYPE_SBYTE:
  1243  			{
  1244  				arm_load_membase_sbyte(inst, _jit_reg_info[reg].cpu_reg,
  1245  								ARM_FP, offset);
  1246  			}
  1247  			break;
  1248  
  1249  			case JIT_TYPE_UBYTE:
  1250  			{
  1251  				arm_load_membase_byte(inst, _jit_reg_info[reg].cpu_reg,
  1252  								ARM_FP, offset);
  1253  			}
  1254  			break;
  1255  
  1256  			case JIT_TYPE_SHORT:
  1257  			{
  1258  				arm_load_membase_short(inst, _jit_reg_info[reg].cpu_reg,
  1259  								ARM_FP, offset);
  1260  			}
  1261  			break;
  1262  
  1263  			case JIT_TYPE_USHORT:
  1264  			{
  1265  				arm_load_membase_ushort(inst, _jit_reg_info[reg].cpu_reg,
  1266  									ARM_FP, offset);
  1267  			}
  1268  			break;
  1269  
  1270  			case JIT_TYPE_INT:
  1271  			case JIT_TYPE_UINT:
  1272  			{
  1273  				arm_load_membase(inst, _jit_reg_info[reg].cpu_reg,
  1274  								ARM_FP, offset);
  1275  			}
  1276  			break;
  1277  
  1278  			case JIT_TYPE_LONG:
  1279  			case JIT_TYPE_ULONG:
  1280  			{
  1281  				arm_load_membase(inst, _jit_reg_info[reg].cpu_reg,
  1282  								ARM_FP, offset);
  1283  				arm_load_membase(inst, _jit_reg_info[reg].cpu_reg + 1,
  1284  								ARM_FP, offset + 4);
  1285  			}
  1286  			break;
  1287  
  1288  			case JIT_TYPE_FLOAT32:
  1289  			{
  1290  				if(IS_WORD_REG(reg))
  1291  				{
  1292  					arm_load_membase(inst, _jit_reg_info[reg].cpu_reg,
  1293  									ARM_FP, offset);
  1294  				}
  1295  				else
  1296  				{
  1297  					arm_load_membase_float32
  1298  						(inst, _jit_reg_info[reg].cpu_reg, ARM_FP, offset);
  1299  				}
  1300  			}
  1301  			break;
  1302  
  1303  			case JIT_TYPE_FLOAT64:
  1304  			case JIT_TYPE_NFLOAT:
  1305  			{
  1306  				if(IS_WORD_REG(reg))
  1307  				{
  1308  					arm_load_membase(inst, _jit_reg_info[reg].cpu_reg,
  1309  									ARM_FP, offset);
  1310  					arm_load_membase(inst, _jit_reg_info[reg].cpu_reg + 1,
  1311  									ARM_FP, offset + 4);
  1312  				}
  1313  				else
  1314  				{
  1315  					arm_load_membase_float64
  1316  						(inst, _jit_reg_info[reg].cpu_reg, ARM_FP, offset);
  1317  				}
  1318  			}
  1319  			break;
  1320  		}
  1321  	}
  1322  
  1323  	/* End the code output process */
  1324  	jit_cache_end_output();
  1325  }
  1326  
  1327  /**
  1328   * Loads a struct indicated by "value" into the given register reg
  1329   */
  1330  void _jit_gen_load_value_struct (jit_gencode_t gen, int reg, jit_value_t value)
  1331  {
  1332  	int offset;
  1333  
  1334  	/* Make sure that we have sufficient space */
  1335  	jit_cache_setup_output(32);
  1336  	if(flush_if_too_far(gen))
  1337  	{
  1338  		jit_gen_load_inst_ptr(gen, inst);
  1339  	}
  1340  
  1341  	if(value->is_constant)
  1342  	{
  1343  		TODO();
  1344  		abort();
  1345  	}
  1346  	else if(value->has_global_register)
  1347  	{
  1348  		/*
  1349  		 * This value has been assinged a global register. This means
  1350  		 * that it can use that register, but not necessarily that it's
  1351  		 * already in it!!
  1352  		 */
  1353  		
  1354  		/* Ensure that the value is already in the global_register */
  1355  		if (!value->in_global_register)
  1356  		{	
  1357  			/* Find the other register in a long pair */
  1358  			int reg = value->reg;
  1359  			int other_reg = jit_reg_current_other_reg(gen,reg);
  1360  			
  1361  			//Spill to the global register
  1362  			_jit_gen_spill_reg(gen, reg, other_reg, value);
  1363  			value->in_global_register=1;
  1364  
  1365  			/* A new instruction has probably been generated by _jit_gen_spill_reg: reload the inst pointer */
  1366  			jit_gen_load_inst_ptr(gen, inst);
  1367  		}
  1368  		/* Load the value out of a global register */
  1369  		arm_mov_reg_reg(inst, _jit_reg_info[reg].cpu_reg,
  1370  						_jit_reg_info[value->global_reg].cpu_reg);
  1371  	}
  1372  	else
  1373  	{
  1374  		/* Fix the position of the value in the stack frame */
  1375  		_jit_gen_fix_value(value);
  1376  		offset = (int)(value->frame_offset);
  1377  
  1378  		/* Ensure that the value is already in the stack frame */
  1379  		if(value->in_register)
  1380  		{
  1381  			/* Find the other register in a long pair */
  1382  			int reg = value->reg;
  1383  			int other_reg = jit_reg_current_other_reg(gen,reg);
  1384  			
  1385  			_jit_gen_spill_reg(gen, reg, other_reg, value);
  1386  			value->in_frame=1;
  1387  
  1388  			/* A new instruction has probably been generated by _jit_gen_spill_reg: reload the inst pointer */
  1389  			jit_gen_load_inst_ptr(gen, inst);
  1390  		}
  1391  		
  1392  		assert(jit_type_normalize(value->type)->kind==JIT_TYPE_STRUCT);
  1393  		
  1394  		arm_load_membase(inst, _jit_reg_info[reg].cpu_reg, ARM_FP, offset);
  1395  		if (jit_type_get_size(jit_value_get_type(value)) > 4)
  1396  		{
  1397  			TODO();
  1398  			abort();
  1399  		}
  1400  		
  1401  	}
  1402  
  1403  	/* End the code output process */
  1404  	jit_cache_end_output();
  1405  }
  1406  
  1407  void _jit_gen_spill_global(jit_gencode_t gen, int reg, jit_value_t value)
  1408  {
  1409  	/* TODO: Implement if ARM needs it. */
  1410  }
  1411  
  1412  void _jit_gen_load_global(jit_gencode_t gen, int reg, jit_value_t value)
  1413  {
  1414  	jit_cache_setup_output(32);
  1415  	arm_load_membase(inst, _jit_reg_info[value->global_reg].cpu_reg,
  1416  					 ARM_FP, value->frame_offset);
  1417  	jit_cache_end_output();
  1418  }
  1419  
  1420  void _jit_gen_fix_value(jit_value_t value)
  1421  {
  1422  	if(!(value->has_frame_offset) && !(value->is_constant))
  1423  	{
  1424  		jit_nint size = (jit_nint)(ROUND_STACK(jit_type_get_size(value->type)));
  1425  		value->block->func->builder->frame_size += size;
  1426  		value->frame_offset = -(value->block->func->builder->frame_size);
  1427  		value->has_frame_offset = 1;
  1428  	}
  1429  }
  1430  
  1431  void _jit_gen_insn(jit_gencode_t gen, jit_function_t func,
  1432  				   jit_block_t block, jit_insn_t insn)
  1433  {
  1434  	flush_if_too_far(gen);
  1435  	switch(insn->opcode)
  1436  	{
  1437  		#define JIT_INCLUDE_RULES
  1438  		#include "jit-rules-arm.inc"
  1439  		#undef JIT_INCLUDE_RULES
  1440  
  1441  		default:
  1442  		{
  1443  			fprintf(stderr, "TODO(%x) at %s, %d\n",
  1444  					(int)(insn->opcode), __FILE__, (int)__LINE__);
  1445  		}
  1446  		break;
  1447  	}
  1448  }
  1449  
  1450  void _jit_gen_start_block(jit_gencode_t gen, jit_block_t block)
  1451  {
  1452  	void **fixup;
  1453  	void **next;
  1454  	jit_nint offset;
  1455  	arm_inst_buf inst;
  1456  
  1457  	/* Set the address of this block */
  1458  	block->address = (void *)(gen->ptr);
  1459  
  1460  	/* If this block has pending fixups, then apply them now */
  1461  	fixup = (void **)(block->fixup_list);
  1462  	while(fixup != 0)
  1463  	{
  1464  		offset = (((jit_nint)(fixup[0])) & 0x00FFFFFF) << 2;
  1465  		if(!offset)
  1466  		{
  1467  			next = 0;
  1468  		}
  1469  		else
  1470  		{
  1471  			next = (void **)(((unsigned char *)fixup) - offset);
  1472  		}
  1473  		jit_gen_load_inst_ptr(gen, inst);
  1474  		arm_patch(inst, fixup, block->address);
  1475  		fixup = next;
  1476  	}
  1477  	block->fixup_list = 0;
  1478  }
  1479  
  1480  void _jit_gen_end_block(jit_gencode_t gen, jit_block_t block)
  1481  {
  1482  	/* Nothing to do here for ARM */
  1483  }
  1484  
  1485  int _jit_gen_is_global_candidate(jit_type_t type)
  1486  {
  1487  	switch(jit_type_remove_tags(type)->kind)
  1488  	{
  1489  		case JIT_TYPE_INT:
  1490  		case JIT_TYPE_UINT:
  1491  		case JIT_TYPE_NINT:
  1492  		case JIT_TYPE_NUINT:
  1493  		case JIT_TYPE_PTR:
  1494  		case JIT_TYPE_SIGNATURE:	return 1;
  1495  	}
  1496  	return 0;
  1497  }
  1498  
  1499  int
  1500  _jit_reg_get_pair(jit_type_t type, int reg)
  1501  {
  1502  	type = jit_type_normalize(type);
  1503  	if(type)
  1504  	{
  1505  		if(type->kind == JIT_TYPE_LONG || type->kind == JIT_TYPE_ULONG)
  1506  		{
  1507  			return jit_reg_other_reg(reg);
  1508  		}
  1509  		else if(type->kind == JIT_TYPE_FLOAT64 || type->kind == JIT_TYPE_NFLOAT)
  1510  		{
  1511  			if(reg == ARM_REG_R0)
  1512  			{
  1513  				return jit_reg_other_reg(reg);
  1514  			}
  1515  		}
  1516  	}
  1517  	return -1;
  1518  }
  1519  
  1520  #endif /* JIT_BACKEND_ARM */