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

     1  /*
     2   * jit-rules-arm.ins - Instruction selector for 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  %inst_type arm_inst_buf
    25  
    26  /*
    27   * Register classes
    28   */
    29  %regclass reg arm_reg
    30  %regclass freg arm_freg
    31  %regclass freg32 arm_freg32
    32  %regclass freg64 arm_freg64
    33  %lregclass lreg arm_lreg
    34  
    35  /*
    36   * Conversion opcodes.
    37   */
    38  
    39  JIT_OP_TRUNC_SBYTE: 
    40  	[reg] -> {
    41  		arm_shift_reg_imm8(inst, ARM_SHL, $1, $1, 24);
    42  		arm_shift_reg_imm8(inst, ARM_SAR, $1, $1, 24);
    43  	}
    44  
    45  JIT_OP_TRUNC_UBYTE: 
    46  	[reg] -> {
    47  		arm_alu_reg_imm8(inst, ARM_AND, $1, $1, 0xFF);
    48  	}
    49  
    50  JIT_OP_TRUNC_SHORT: 
    51  	[reg] -> {
    52  		arm_shift_reg_imm8(inst, ARM_SHL, $1, $1, 16);
    53  		arm_shift_reg_imm8(inst, ARM_SAR, $1, $1, 16);
    54  	}
    55  
    56  JIT_OP_TRUNC_USHORT: 
    57  	[reg] -> {
    58  		arm_shift_reg_imm8(inst, ARM_SHL, $1, $1, 16);
    59  		arm_shift_reg_imm8(inst, ARM_SHR, $1, $1, 16);
    60  	}
    61  
    62  JIT_OP_INT_TO_NFLOAT:
    63  	[=freg64, local, scratch freg32] -> {
    64  		//Load int from a local variable stored in memory
    65  		arm_load_membase_float(inst, $3, ARM_FP, $2, 0);
    66  		arm_convert_float_signed_integer_double(inst, $1, $3);
    67  	}
    68  	[=freg64, reg, scratch freg32] -> {
    69  		//The int value is in a register
    70  		arm_mov_float_reg(inst, $3, $2);
    71  		arm_convert_float_signed_integer_double(inst, $1, $3)
    72  	}
    73  
    74  JIT_OP_NFLOAT_TO_FLOAT32:
    75  	[=freg32, freg64] -> {
    76  		arm_convert_float_single_double(inst, $1, $2);
    77  	}
    78  
    79  JIT_OP_NFLOAT_TO_FLOAT64, JIT_OP_FLOAT64_TO_NFLOAT: copy
    80  	[freg64] -> {
    81  		/* Nothing to do: float64 and nfloat are the same thing on ARM linux. Just copy the value */
    82  	}
    83  
    84  JIT_OP_FLOAT32_TO_NFLOAT:
    85  	[=freg64, freg32] -> {
    86  		arm_convert_float_double_single(inst, $1, $2);
    87  	}
    88  
    89  /*
    90   * Arithmetic opcodes.
    91   */
    92  
    93  JIT_OP_IADD: 
    94  	[reg, immu8] -> {
    95  		arm_alu_reg_imm8(inst, ARM_ADD, $1, $1, $2);
    96  	}
    97  	[reg, reg] -> {
    98  		arm_alu_reg_reg(inst, ARM_ADD, $1, $1, $2);
    99  	}
   100  
   101  JIT_OP_ISUB: 
   102  	[reg, immu8] -> {
   103  		arm_alu_reg_imm8(inst, ARM_SUB, $1, $1, $2);
   104  	}
   105  	[reg, reg] -> {
   106  		arm_alu_reg_reg(inst, ARM_SUB, $1, $1, $2);
   107  	}
   108  
   109  JIT_OP_IMUL: 
   110  	[reg, immu8] -> {
   111  		/* Handle special cases of immediate multiplies */
   112  		switch($2)
   113  		{
   114  			case 0:
   115  			{
   116  				arm_mov_reg_imm8(inst, $1, 0);
   117  			}
   118  			break;
   119  
   120  			case 1: break;
   121  
   122  			case 2:
   123  			{
   124  				arm_shift_reg_imm8(inst, ARM_SHL, $1, $1, 1);
   125  			}
   126  			break;
   127  
   128  			case 4:
   129  			{
   130  				arm_shift_reg_imm8(inst, ARM_SHL, $1, $1, 2);
   131  			}
   132  			break;
   133  
   134  			case 8:
   135  			{
   136  				arm_shift_reg_imm8(inst, ARM_SHL, $1, $1, 3);
   137  			}
   138  			break;
   139  
   140  			case 16:
   141  			{
   142  				arm_shift_reg_imm8(inst, ARM_SHL, $1, $1, 4);
   143  			}
   144  			break;
   145  
   146  			case 32:
   147  			{
   148  				arm_shift_reg_imm8(inst, ARM_SHL, $1, $1, 5);
   149  			}
   150  			break;
   151  
   152  			case 64:
   153  			{
   154  				arm_shift_reg_imm8(inst, ARM_SHL, $1, $1, 6);
   155  			}
   156  			break;
   157  
   158  			case 128:
   159  			{
   160  				arm_shift_reg_imm8(inst, ARM_SHL, $1, $1, 7);
   161  			}
   162  			break;
   163  
   164  			default:
   165  			{
   166  				arm_mov_reg_imm8(inst, ARM_WORK, $2);
   167  				arm_mul_reg_reg(inst, $1, $1, ARM_WORK);
   168  			}
   169  			break;
   170  		}
   171  	}
   172  	[reg, reg] -> {
   173  		if($1 != $2)
   174  		{
   175  			arm_mul_reg_reg(inst, $1, $1, $2);
   176  		}
   177  		else
   178  		{
   179  			/* Cannot use the same register for both arguments */
   180  			arm_mov_reg_reg(inst, ARM_WORK, $2);
   181  			arm_mul_reg_reg(inst, $1, $1, ARM_WORK);
   182  		}
   183  	}
   184  
   185  JIT_OP_IDIV:
   186  	[any, immzero] -> {
   187  		throw_builtin(&inst, func, ARM_CC_AL, JIT_RESULT_DIVISION_BY_ZERO);
   188  	}
   189  	[reg, immu8, if("$2 == 1")] -> {
   190  		/* Division by 1. Return the value itself */
   191  	}
   192  	[reg, immu8, if("($2 > 0) && (((jit_nuint)$2) & (((jit_nuint)$2) - 1)) == 0")] -> {
   193  		/* Handle special cases of small immediate divides: divisions by positive powers of two */
   194  		/* NB: (n & (n-1)) == 0 if and only if n is a power of 2 */
   195  		
   196  		/* Move the dividend in the work register, setting the codes (in order to know if it's positive or negative) */
   197  		arm_alu_cc_reg(inst, ARM_MOV, ARM_WORK, $1);
   198  
   199  		/* If the dividend is negative, make it positive (0-x = -x)*/
   200  		arm_alu_reg_imm8_cond(inst, ARM_RSB, $1, ARM_WORK, 0, ARM_CC_MI);
   201  
   202  		switch($2)
   203  		{
   204  			//Integer divide by shifting
   205  			case 2:
   206  			{
   207  				arm_shift_reg_imm8(inst, ARM_SAR, $1, $1, 1);
   208  			}
   209  			break;
   210  
   211  			case 4:
   212  			{
   213  				arm_shift_reg_imm8(inst, ARM_SAR, $1, $1, 2);
   214  			}
   215  			break;
   216  
   217  			case 8:
   218  			{
   219  				arm_shift_reg_imm8(inst, ARM_SAR, $1, $1, 3);
   220  			}
   221  			break;
   222  
   223  			case 16:
   224  			{
   225  				arm_shift_reg_imm8(inst, ARM_SAR, $1, $1, 4);
   226  			}
   227  			break;
   228  
   229  			case 32:
   230  			{
   231  				arm_shift_reg_imm8(inst, ARM_SAR, $1, $1, 5);
   232  			}
   233  			break;
   234  
   235  			case 64:
   236  			{
   237  				arm_shift_reg_imm8(inst, ARM_SAR, $1, $1, 6);
   238  			}
   239  			break;
   240  
   241  			case 128:
   242  			{
   243  				arm_shift_reg_imm8(inst, ARM_SAR, $1, $1, 7);
   244  			}
   245  			break;
   246  		}
   247  		
   248  		/* If the dividend was negative, make it negative again (0-x = -x)*/
   249  		arm_alu_reg_imm8_cond(inst, ARM_RSB, $1, $1, 0, ARM_CC_MI);
   250  		
   251  	}
   252  	[reg, imm, if("$2 == -1")] -> {
   253  		/* Dividing by -1 simply negates */
   254  		/*TODO: if the value to be divided by -1 is jit_min_int, 
   255  		  an exception (JIT_RESULT_ARITHMETIC) should probably be thrown */
   256  		arm_alu_reg(inst, ARM_MVN, $1, $1);
   257  	}
   258  	[reg, imm, clobber("r0", "r1")] -> {
   259  		/* Every other immediate division:
   260  		   ARM does not have an integer division operation. It's emulated via software. */
   261  		
   262  		//Put the dividend in the right position
   263  		if ($1 != ARM_R0)
   264  			arm_mov_reg_reg(inst, ARM_R0, $1);
   265  		
   266  		//Put the divisor in the right position
   267  		mov_reg_imm(gen, &inst, ARM_R1, $2);
   268  		
   269  		//Perform the division by calling a function from the runtime ABI
   270  		extern int __aeabi_idiv(int numerator, int denominator);
   271  		arm_call(inst, __aeabi_idiv);
   272  		
   273  		if($1 != ARM_R0)
   274  		{
   275  			//Move the result back where it is expected to be
   276  			arm_mov_reg_reg(inst, $1, ARM_R0);
   277  		}
   278  		
   279  	}
   280  	[reg, reg, scratch reg, clobber("r0", "r1")] -> {
   281  		/* Every division taking data from two registers:
   282  		   ARM does not have an integer division operation. It's emulated via software. */
   283  		
   284  		int dividend = $1;
   285  		int divisor = $2;
   286  		int scratch = $3;
   287  		
   288  		//Put the dividend in the right position
   289  		if (dividend != ARM_R0)
   290  		{
   291  			if (divisor==ARM_R0)
   292  			{
   293  				//Prevent the divisor from being overwritten
   294  				if(dividend != ARM_R1)
   295  				{
   296  					//The place where the divisor should be is free. Move it there
   297  					arm_mov_reg_reg(inst, ARM_R1, divisor);
   298  					divisor=1;
   299  				}
   300  				else
   301  				{
   302  					/* The dividend is where the divisor should be.
   303  					   We must use a scratch register to swap them */
   304  					arm_mov_reg_reg(inst, scratch, divisor);
   305  					divisor=scratch;
   306  				}
   307  				
   308  			}
   309  			
   310  			arm_mov_reg_reg(inst, ARM_R0, dividend);
   311  		}
   312  		
   313  		if (divisor != ARM_R1)
   314  		{
   315  			//Put the divisor in the right position
   316  			arm_mov_reg_reg(inst, ARM_R1, divisor);
   317  		}
   318  		
   319  		//Perform the division by calling a function from the runtime ABI
   320  		extern int __aeabi_idiv(int numerator, int denominator);
   321  		arm_call(inst, __aeabi_idiv);
   322  		
   323  		//Move the result back where it is expected to be
   324  		if($1 != ARM_R0)
   325  		{
   326  			arm_mov_reg_reg(inst, $1, ARM_R0);
   327  		}
   328  	}
   329  
   330  JIT_OP_INEG: 
   331  	[reg] -> {
   332  		/* -x is the same as (0 - x) */
   333  		arm_alu_reg_imm8(inst, ARM_RSB, $1, $1, 0);
   334  	}
   335  
   336  JIT_OP_LADD: 
   337  	[lreg, lreg] -> {
   338  		arm_alu_cc_reg_reg(inst, ARM_ADD, $1, $1, $2);
   339  		arm_alu_reg_reg(inst, ARM_ADC, %1, %1, %2);
   340  	}
   341  
   342  JIT_OP_LSUB: 
   343  	[lreg, lreg] -> {
   344  		arm_alu_cc_reg_reg(inst, ARM_SUB, $1, $1, $2);
   345  		arm_alu_reg_reg(inst, ARM_SBC, %1, %1, %2);
   346  	}
   347  
   348  JIT_OP_LNEG: 
   349  	[lreg] -> {
   350  		arm_alu_reg(inst, ARM_MVN, $1, $1);
   351  		arm_alu_reg(inst, ARM_MVN, %1, %1);
   352  		arm_alu_cc_reg_imm8(inst, ARM_ADD, $1, $1, 1);
   353  		arm_alu_reg_imm8(inst, ARM_ADC, %1, %1, 0);
   354  	}
   355  
   356  JIT_OP_FADD (JIT_ARM_HAS_VFP): 
   357  	[freg32, freg32] -> {
   358  		arm_alu_freg_freg_32(inst, ARM_FADD, $1, $1, $2);
   359  	}
   360  	
   361  JIT_OP_FADD (JIT_ARM_HAS_FPA): /*binary*/
   362  	[freg, freg] -> {
   363  		arm_alu_freg_freg_32(inst, ARM_ADF, $1, $1, $2);
   364  	}
   365  
   366  JIT_OP_FSUB (JIT_ARM_HAS_VFP): 
   367  	[freg32, freg32] -> {
   368  		arm_alu_freg_freg_32(inst, ARM_FSUB, $1, $1, $2);
   369  	}
   370  
   371  JIT_OP_FSUB (JIT_ARM_HAS_FPA): /*binary*/
   372  	[freg, freg] -> {
   373  		arm_alu_freg_freg_32(inst, ARM_SUF, $1, $1, $2);
   374  	}
   375  
   376  JIT_OP_FMUL (JIT_ARM_HAS_VFP): 
   377  	[freg32, freg32] -> {
   378  		arm_alu_freg_freg_32(inst, ARM_FMUL, $1, $1, $2);
   379  	}
   380  
   381  JIT_OP_FMUL (JIT_ARM_HAS_FPA): /*binary*/
   382  	[freg, freg] -> {
   383  		arm_alu_freg_freg_32(inst, ARM_MUF, $1, $1, $2);
   384  	}
   385  
   386  JIT_OP_FDIV (JIT_ARM_HAS_VFP): 
   387  	[freg32, freg32] -> {
   388  		arm_alu_freg_freg_32(inst, ARM_FDIV, $1, $1, $2);
   389  	}
   390  
   391  JIT_OP_FDIV (JIT_ARM_HAS_FPA): /*binary*/
   392  	[freg, freg] -> {
   393  		arm_alu_freg_freg_32(inst, ARM_DVF, $1, $1, $2);
   394  	}
   395  
   396  JIT_OP_FNEG (JIT_ARM_HAS_VFP): 
   397  	[freg32] -> {
   398  		arm_alu_freg_32(inst, ARM_MNF, $1, $1);
   399  	}
   400  
   401  JIT_OP_FNEG (JIT_ARM_HAS_FPA): /*unary*/
   402  	[freg] -> {
   403  		arm_alu_freg_32(inst, ARM_MNF, $1, $1);
   404  	}
   405  
   406  JIT_OP_DADD, JIT_OP_NFADD (JIT_ARM_HAS_VFP): 
   407  	[freg64, freg64] -> {
   408  		arm_alu_freg_freg(inst, ARM_FADD, $1, $1, $2);
   409  	}
   410  
   411  JIT_OP_DADD, JIT_OP_NFADD (JIT_ARM_HAS_FPA): /*binary*/
   412  	[freg, freg] -> {
   413  		arm_alu_freg_freg(inst, ARM_ADF, $1, $1, $2);
   414  	}
   415  
   416  JIT_OP_DSUB, JIT_OP_NFSUB (JIT_ARM_HAS_VFP): 
   417  	[freg64, freg64] -> {
   418  		arm_alu_freg_freg(inst, ARM_FSUB, $1, $1, $2);
   419  	}
   420  
   421  JIT_OP_DSUB, JIT_OP_NFSUB (JIT_ARM_HAS_FPA): /*binary*/
   422  	[freg, freg] -> {
   423  		arm_alu_freg_freg(inst, ARM_SUF, $1, $1, $2);
   424  	}
   425  
   426  JIT_OP_DMUL, JIT_OP_NFMUL (JIT_ARM_HAS_VFP): 
   427  	[freg64, freg64] -> {
   428  		arm_alu_freg_freg(inst, ARM_FMUL, $1, $1, $2);
   429  	}
   430  	
   431  JIT_OP_DMUL, JIT_OP_NFMUL (JIT_ARM_HAS_FPA): /*binary*/
   432  	[freg, freg] -> {
   433  		arm_alu_freg_freg(inst, ARM_MUF, $1, $1, $2);
   434  	}
   435  
   436  JIT_OP_DDIV, JIT_OP_NFDIV (JIT_ARM_HAS_VFP): 
   437  	[freg64, freg64] -> {
   438  		arm_alu_freg_freg(inst, ARM_FDIV, $1, $1, $2);
   439  	}
   440  
   441  JIT_OP_DDIV, JIT_OP_NFDIV (JIT_ARM_HAS_FPA): /*binary*/
   442  	[freg, freg] -> {
   443  		arm_alu_freg_freg(inst, ARM_DVF, $1, $1, $2);
   444  	}
   445  
   446  JIT_OP_DNEG, JIT_OP_NFNEG (JIT_ARM_HAS_VFP): 
   447  	[freg64] -> {
   448  		arm_alu_freg(inst, ARM_MNF, $1, $1);
   449  	}
   450  
   451  JIT_OP_DNEG, JIT_OP_NFNEG (JIT_ARM_HAS_FPA): /*unary*/
   452  	[freg] -> {
   453  		arm_alu_freg(inst, ARM_MNF, $1, $1);
   454  	}
   455  
   456  /*
   457   * Bitwise opcodes.
   458   */
   459  
   460  JIT_OP_IAND: 
   461  	[reg, immu8] -> {
   462  		arm_alu_reg_imm8(inst, ARM_AND, $1, $1, $2);
   463  	}
   464  	[reg, reg] -> {
   465  		arm_alu_reg_reg(inst, ARM_AND, $1, $1, $2);
   466  	}
   467  
   468  JIT_OP_IOR: 
   469  	[reg, immu8] -> {
   470  		arm_alu_reg_imm8(inst, ARM_ORR, $1, $1, $2);
   471  	}
   472  	[reg, reg] -> {
   473  		arm_alu_reg_reg(inst, ARM_ORR, $1, $1, $2);
   474  	}
   475  
   476  JIT_OP_IXOR: 
   477  	[reg, immu8] -> {
   478  		arm_alu_reg_imm8(inst, ARM_EOR, $1, $1, $2);
   479  	}
   480  	[reg, reg] -> {
   481  		arm_alu_reg_reg(inst, ARM_EOR, $1, $1, $2);
   482  	}
   483  
   484  JIT_OP_INOT: 
   485  	[reg] -> {
   486  		/* MVN == "move not" */
   487  		arm_alu_reg(inst, ARM_MVN, $1, $1);
   488  	}
   489  
   490  JIT_OP_ISHL: 
   491  	[reg, imm] -> {
   492  		arm_shift_reg_imm8(inst, ARM_SHL, $1, $1, ($2 & 0x1F));
   493  	}
   494  	[reg, reg] -> {
   495  		arm_alu_reg_imm8(inst, ARM_AND, ARM_WORK, $2, 0x1F);
   496  		arm_shift_reg_reg(inst, ARM_SHL, $1, $1, ARM_WORK);
   497  	}
   498  
   499  JIT_OP_ISHR: 
   500  	[reg, imm] -> {
   501  		arm_shift_reg_imm8(inst, ARM_SAR, $1, $1, ($2 & 0x1F));
   502  	}
   503  	[reg, reg] -> {
   504  		arm_alu_reg_imm8(inst, ARM_AND, ARM_WORK, $2, 0x1F);
   505  		arm_shift_reg_reg(inst, ARM_SAR, $1, $1, ARM_WORK);
   506  	}
   507  
   508  JIT_OP_ISHR_UN: 
   509  	[reg, imm] -> {
   510  		arm_shift_reg_imm8(inst, ARM_SHR, $1, $1, ($2 & 0x1F));
   511  	}
   512  	[reg, reg] -> {
   513  		arm_alu_reg_imm8(inst, ARM_AND, ARM_WORK, $2, 0x1F);
   514  		arm_shift_reg_reg(inst, ARM_SHR, $1, $1, ARM_WORK);
   515  	}
   516  
   517  JIT_OP_LAND: 
   518  	[lreg, lreg] -> {
   519  		arm_alu_reg_reg(inst, ARM_AND, $1, $1, $2);
   520  		arm_alu_reg_reg(inst, ARM_AND, %1, %1, %2);
   521  	}
   522  
   523  JIT_OP_LOR: 
   524  	[lreg, lreg] -> {
   525  		arm_alu_reg_reg(inst, ARM_ORR, $1, $1, $2);
   526  		arm_alu_reg_reg(inst, ARM_ORR, %1, %1, %2);
   527  	}
   528  
   529  JIT_OP_LXOR: 
   530  	[lreg, lreg] -> {
   531  		arm_alu_reg_reg(inst, ARM_EOR, $1, $1, $2);
   532  		arm_alu_reg_reg(inst, ARM_EOR, %1, %1, %2);
   533  	}
   534  
   535  JIT_OP_LNOT: 
   536  	[lreg] -> {
   537  		arm_alu_reg(inst, ARM_MVN, $1, $1);
   538  		arm_alu_reg(inst, ARM_MVN, %1, %1);
   539  	}
   540  
   541  /*
   542   * Branch opcodes.
   543   */
   544  
   545  JIT_OP_BR: branch /*spill_before*/
   546  	[] -> {
   547  		/* ARM_CC_AL == "always branch" */
   548  		output_branch(func, &inst, ARM_CC_AL, insn);
   549  
   550  		/* Flush the constant pool now, to minimize the probability that
   551  		   it is accidentally flushed in the middle of a loop body */
   552  		jit_gen_save_inst_ptr(gen, inst);
   553  		flush_constants(gen, 1);
   554  		jit_gen_load_inst_ptr(gen, inst);
   555  	}
   556  
   557  JIT_OP_BR_IFALSE: branch 
   558  	[reg] -> {
   559  		arm_test_reg_imm8(inst, ARM_CMP, $1, 0);
   560  		output_branch(func, &inst, ARM_CC_EQ, insn);
   561  	}
   562  
   563  JIT_OP_BR_ITRUE: branch 
   564  	[reg] -> {
   565  		arm_test_reg_imm8(inst, ARM_CMP, $1, 0);
   566  		output_branch(func, &inst, ARM_CC_NE, insn);
   567  	}
   568  
   569  JIT_OP_BR_IEQ: branch 
   570  	[reg, immu8] -> {
   571  		arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
   572  		output_branch(func, &inst, ARM_CC_EQ, insn);
   573  	}
   574  	[reg, reg] -> {
   575  		arm_test_reg_reg(inst, ARM_CMP, $1, $2);
   576  		output_branch(func, &inst, ARM_CC_EQ, insn);
   577  	}
   578  
   579  JIT_OP_BR_INE: branch 
   580  	[reg, immu8] -> {
   581  		arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
   582  		output_branch(func, &inst, ARM_CC_NE, insn);
   583  	}
   584  	[reg, reg] -> {
   585  		arm_test_reg_reg(inst, ARM_CMP, $1, $2);
   586  		output_branch(func, &inst, ARM_CC_NE, insn);
   587  	}
   588  
   589  JIT_OP_BR_ILT: branch 
   590  	[reg, immu8] -> {
   591  		arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
   592  		output_branch(func, &inst, ARM_CC_LT, insn);
   593  	}
   594  	[reg, reg] -> {
   595  		arm_test_reg_reg(inst, ARM_CMP, $1, $2);
   596  		output_branch(func, &inst, ARM_CC_LT, insn);
   597  	}
   598  
   599  JIT_OP_BR_ILT_UN: branch 
   600  	[reg, immu8] -> {
   601  		arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
   602  		output_branch(func, &inst, ARM_CC_LT_UN, insn);
   603  	}
   604  	[reg, reg] -> {
   605  		arm_test_reg_reg(inst, ARM_CMP, $1, $2);
   606  		output_branch(func, &inst, ARM_CC_LT_UN, insn);
   607  	}
   608  
   609  JIT_OP_BR_ILE: branch 
   610  	[reg, immu8] -> {
   611  		arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
   612  		output_branch(func, &inst, ARM_CC_LE, insn);
   613  	}
   614  	[reg, reg] -> {
   615  		arm_test_reg_reg(inst, ARM_CMP, $1, $2);
   616  		output_branch(func, &inst, ARM_CC_LE, insn);
   617  	}
   618  
   619  JIT_OP_BR_ILE_UN: branch 
   620  	[reg, immu8] -> {
   621  		arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
   622  		output_branch(func, &inst, ARM_CC_LE_UN, insn);
   623  	}
   624  	[reg, reg] -> {
   625  		arm_test_reg_reg(inst, ARM_CMP, $1, $2);
   626  		output_branch(func, &inst, ARM_CC_LE_UN, insn);
   627  	}
   628  
   629  JIT_OP_BR_IGT: branch 
   630  	[reg, immu8] -> {
   631  		arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
   632  		output_branch(func, &inst, ARM_CC_GT, insn);
   633  	}
   634  	[reg, reg] -> {
   635  		arm_test_reg_reg(inst, ARM_CMP, $1, $2);
   636  		output_branch(func, &inst, ARM_CC_GT, insn);
   637  	}
   638  
   639  JIT_OP_BR_IGT_UN: branch 
   640  	[reg, immu8] -> {
   641  		arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
   642  		output_branch(func, &inst, ARM_CC_GT_UN, insn);
   643  	}
   644  	[reg, reg] -> {
   645  		arm_test_reg_reg(inst, ARM_CMP, $1, $2);
   646  		output_branch(func, &inst, ARM_CC_GT_UN, insn);
   647  	}
   648  
   649  JIT_OP_BR_IGE: branch 
   650  	[reg, immu8] -> {
   651  		arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
   652  		output_branch(func, &inst, ARM_CC_GE, insn);
   653  	}
   654  	[reg, reg] -> {
   655  		arm_test_reg_reg(inst, ARM_CMP, $1, $2);
   656  		output_branch(func, &inst, ARM_CC_GE, insn);
   657  	}
   658  
   659  JIT_OP_BR_IGE_UN: branch 
   660  	[reg, immu8] -> {
   661  		arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
   662  		output_branch(func, &inst, ARM_CC_GE_UN, insn);
   663  	}
   664  	[reg, reg] -> {
   665  		arm_test_reg_reg(inst, ARM_CMP, $1, $2);
   666  		output_branch(func, &inst, ARM_CC_GE_UN, insn);
   667  	}
   668  
   669  /*
   670   * Comparison opcodes.
   671   */
   672  
   673  JIT_OP_ICMP: 
   674  	[reg, immu8] -> {
   675  		arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
   676  		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GT);
   677  		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LE);
   678  		arm_alu_reg_cond(inst, ARM_MVN, $1, $1, ARM_CC_LT);
   679  	}
   680  	[reg, reg] -> {
   681  		arm_test_reg_reg(inst, ARM_CMP, $1, $2);
   682  		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GT);
   683  		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LE);
   684  		arm_alu_reg_cond(inst, ARM_MVN, $1, $1, ARM_CC_LT);
   685  	}
   686  
   687  JIT_OP_ICMP_UN: 
   688  	[reg, immu8] -> {
   689  		arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
   690  		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GT_UN);
   691  		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LE_UN);
   692  		arm_alu_reg_cond(inst, ARM_MVN, $1, $1, ARM_CC_LT_UN);
   693  	}
   694  	[reg, reg] -> {
   695  		arm_test_reg_reg(inst, ARM_CMP, $1, $2);
   696  		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GT_UN);
   697  		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LE_UN);
   698  		arm_alu_reg_cond(inst, ARM_MVN, $1, $1, ARM_CC_LT_UN);
   699  	}
   700  
   701  JIT_OP_IEQ: 
   702  	[reg, immu8] -> {
   703  		arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
   704  		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_EQ);
   705  		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_NE);
   706  	}
   707  	[reg, reg] -> {
   708  		arm_test_reg_reg(inst, ARM_CMP, $1, $2);
   709  		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_EQ);
   710  		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_NE);
   711  	}
   712  
   713  JIT_OP_INE: 
   714  	[reg, immu8] -> {
   715  		arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
   716  		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_NE);
   717  		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_EQ);
   718  	}
   719  	[reg, reg] -> {
   720  		arm_test_reg_reg(inst, ARM_CMP, $1, $2);
   721  		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_NE);
   722  		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_EQ);
   723  	}
   724  
   725  JIT_OP_ILT: 
   726  	[reg, immu8] -> {
   727  		arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
   728  		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_LT);
   729  		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_GE);
   730  	}
   731  	[reg, reg] -> {
   732  		arm_test_reg_reg(inst, ARM_CMP, $1, $2);
   733  		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_LT);
   734  		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_GE);
   735  	}
   736  
   737  JIT_OP_ILT_UN: 
   738  	[reg, immu8] -> {
   739  		arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
   740  		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_LT_UN);
   741  		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_GE_UN);
   742  	}
   743  	[reg, reg] -> {
   744  		arm_test_reg_reg(inst, ARM_CMP, $1, $2);
   745  		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_LT_UN);
   746  		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_GE_UN);
   747  	}
   748  
   749  JIT_OP_ILE: 
   750  	[reg, immu8] -> {
   751  		arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
   752  		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_LE);
   753  		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_GT);
   754  	}
   755  	[reg, reg] -> {
   756  		arm_test_reg_reg(inst, ARM_CMP, $1, $2);
   757  		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_LE);
   758  		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_GT);
   759  	}
   760  
   761  JIT_OP_ILE_UN: 
   762  	[reg, immu8] -> {
   763  		arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
   764  		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_LE_UN);
   765  		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_GT_UN);
   766  	}
   767  	[reg, reg] -> {
   768  		arm_test_reg_reg(inst, ARM_CMP, $1, $2);
   769  		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_LE_UN);
   770  		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_GT_UN);
   771  	}
   772  
   773  JIT_OP_IGT: 
   774  	[reg, immu8] -> {
   775  		arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
   776  		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GT);
   777  		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LE);
   778  	}
   779  	[reg, reg] -> {
   780  		arm_test_reg_reg(inst, ARM_CMP, $1, $2);
   781  		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GT);
   782  		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LE);
   783  	}
   784  
   785  JIT_OP_IGT_UN: 
   786  	[reg, immu8] -> {
   787  		arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
   788  		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GT_UN);
   789  		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LE_UN);
   790  	}
   791  	[reg, reg] -> {
   792  		arm_test_reg_reg(inst, ARM_CMP, $1, $2);
   793  		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GT_UN);
   794  		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LE_UN);
   795  	}
   796  
   797  JIT_OP_IGE: 
   798  	[reg, immu8] -> {
   799  		arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
   800  		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GE);
   801  		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LT);
   802  	}
   803  	[reg, reg] -> {
   804  		arm_test_reg_reg(inst, ARM_CMP, $1, $2);
   805  		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GE);
   806  		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LT);
   807  	}
   808  
   809  JIT_OP_IGE_UN: 
   810  	[reg, immu8] -> {
   811  		arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
   812  		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GE_UN);
   813  		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LT_UN);
   814  	}
   815  	[reg, reg] -> {
   816  		arm_test_reg_reg(inst, ARM_CMP, $1, $2);
   817  		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GE_UN);
   818  		arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LT_UN);
   819  	}
   820  
   821  /*
   822   * Pointer check opcodes.
   823   */
   824  
   825  JIT_OP_CHECK_NULL: note
   826  	[reg] -> {
   827  		arm_test_reg_imm8(inst, ARM_CMP, $1, 0);
   828  		throw_builtin(&inst, func, ARM_CC_EQ, JIT_RESULT_NULL_REFERENCE);
   829  	}
   830  
   831  /*
   832   * Function calls.
   833   */
   834  
   835  JIT_OP_CALL:
   836  	[] -> {
   837  		jit_function_t func = (jit_function_t)(insn->dest);
   838  		arm_call(inst, jit_function_to_closure(func));
   839  	}
   840  
   841  JIT_OP_CALL_TAIL:
   842  	[] -> {
   843  		jit_function_t func = (jit_function_t)(insn->dest);
   844  		arm_pop_frame_tail(inst, 0);
   845  		arm_jump(inst, jit_function_to_closure(func));
   846  	}
   847  
   848  JIT_OP_CALL_INDIRECT:
   849  	[] -> {
   850  		arm_mov_reg_reg((inst), ARM_LINK, ARM_PC);
   851  		arm_mov_reg_reg((inst), ARM_PC, ARM_WORK);
   852  	}
   853  
   854  JIT_OP_CALL_VTABLE_PTR:
   855  	[] -> {
   856  		arm_mov_reg_reg((inst), ARM_LINK, ARM_PC);
   857  		arm_mov_reg_reg((inst), ARM_PC, ARM_WORK);
   858  	}
   859  
   860  JIT_OP_CALL_EXTERNAL:
   861  	[] -> {
   862  		arm_call(inst, (void *)(insn->dest));
   863  	}
   864  
   865  JIT_OP_RETURN:
   866  	[] -> {
   867  		jump_to_epilog(gen, &inst, block);
   868  	}
   869  
   870  JIT_OP_RETURN_INT: /*unary_branch*/
   871  	[reg] -> {
   872  		int cpu_reg = $1;
   873  		if(cpu_reg != ARM_R0)
   874  		{
   875  			arm_mov_reg_reg(inst, ARM_R0, cpu_reg);
   876  		}
   877  		jump_to_epilog(gen, &inst, block);
   878  	}
   879  
   880  JIT_OP_RETURN_LONG: /*unary_branch*/
   881  	[imm] -> {
   882  		mov_reg_imm(gen, &inst, ARM_R0, ((jit_int *)($1))[0]);
   883  		mov_reg_imm(gen, &inst, ARM_R1, ((jit_int *)($1))[1]);
   884  		jump_to_epilog(gen, &inst, block);
   885  	}
   886  	[local] -> {
   887  		arm_load_membase(inst, ARM_R0, ARM_FP, $1);
   888  		arm_load_membase(inst, ARM_R1, ARM_FP, $1 + 4);
   889  		jump_to_epilog(gen, &inst, block);
   890  	}
   891  	[lreg] -> {
   892  		if($1 != 0)
   893  		{
   894  			arm_mov_reg_reg(inst, ARM_R0, $1);
   895  			arm_mov_reg_reg(inst, ARM_R1, %1);
   896  		}
   897  		jump_to_epilog(gen, &inst, block);
   898  	}
   899  
   900  JIT_OP_RETURN_FLOAT32 (JIT_ARM_HAS_VFP): branch 
   901  	[freg32, clobber("r0")] -> {
   902  		arm_mov_reg_float(inst, ARM_R0, $1);
   903  		jump_to_epilog(gen, &inst, block);
   904  	}
   905  	
   906  JIT_OP_RETURN_FLOAT32 (JIT_ARM_HAS_FPA): branch
   907  	[freg] -> {
   908  		if($1 != 0)
   909  		{
   910  			arm_alu_freg_32(inst, ARM_MVF, ARM_F0, $1);
   911  		}
   912  		jump_to_epilog(gen, &inst, block);
   913  	}
   914  
   915  
   916  JIT_OP_RETURN_FLOAT32 (!JIT_ARM_HAS_FLOAT_REGS): manual
   917  	[] -> {
   918  		arm_inst_buf inst;
   919  		_jit_regs_spill_all(gen);
   920  		_jit_gen_fix_value(insn->value1);
   921  		jit_gen_load_inst_ptr(gen, inst);
   922  		if(insn->value1->is_constant)
   923  		{
   924  			mov_reg_imm
   925  				(gen, &inst, ARM_R0, ((int *)(insn->value1->address))[0]);
   926  		}
   927  		else
   928  		{
   929  			arm_load_membase(inst, ARM_R0, ARM_FP, insn->value1->frame_offset);
   930  		}
   931  		jump_to_epilog(gen, &inst, block);
   932  		jit_gen_save_inst_ptr(gen, inst);
   933  	}
   934  
   935  JIT_OP_RETURN_FLOAT64, JIT_OP_RETURN_NFLOAT
   936  		(JIT_ARM_HAS_VFP): branch 
   937  	[freg64, clobber("r0", "r1")] -> {
   938  		arm_mov_reg_reg_double(inst,ARM_R0,ARM_R1, $1);
   939  		jump_to_epilog(gen, &inst, block);
   940  	}
   941  
   942  JIT_OP_RETURN_FLOAT64, JIT_OP_RETURN_NFLOAT (JIT_ARM_HAS_FPA): branch
   943  	[freg] -> {
   944  		if($1 != 0)
   945  		{
   946  			arm_alu_freg(inst, ARM_MVF, ARM_F0, $1);
   947  		}
   948  		jump_to_epilog(gen, &inst, block);
   949  	}
   950  
   951  JIT_OP_RETURN_FLOAT64, JIT_OP_RETURN_NFLOAT (!JIT_ARM_HAS_FLOAT_REGS): manual
   952  	[] -> {
   953  		arm_inst_buf inst;
   954  		_jit_regs_spill_all(gen);
   955  		_jit_gen_fix_value(insn->value1);
   956  		jit_gen_load_inst_ptr(gen, inst);
   957  		if(insn->value1->is_constant)
   958  		{
   959  			mov_reg_imm
   960  				(gen, &inst, ARM_R0, ((int *)(insn->value1->address))[0]);
   961  			mov_reg_imm
   962  				(gen, &inst, ARM_R1, ((int *)(insn->value1->address))[1]);
   963  		}
   964  		else
   965  		{
   966  			arm_load_membase(inst, ARM_R0, ARM_FP, insn->value1->frame_offset);
   967  			arm_load_membase(inst, ARM_R1, ARM_FP,
   968  							 insn->value1->frame_offset + 4);
   969  		}
   970  		jump_to_epilog(gen, &inst, block);
   971  		jit_gen_save_inst_ptr(gen, inst);
   972  	}
   973  
   974  JIT_OP_RETURN_SMALL_STRUCT: note
   975  	[reg, imm, clobber("r0", "r1")] -> {
   976  		//$1: address of the struct to be returned
   977  		//$2: size of the struct to be returned
   978  		
   979  		//Prevent the accidental overwriting of the address
   980  		int temp_reg = $1;
   981  		if(temp_reg < 3)
   982  		{
   983  			arm_mov_reg_reg(inst, ARM_WORK, temp_reg);
   984  			temp_reg = ARM_WORK;
   985  		}
   986  		
   987  		//Copy the struct to the return register in a way that's appropriate to its size
   988  		switch($2)
   989  		{
   990  		case 1:
   991  			arm_load_membase_byte(inst, ARM_R0, temp_reg, 0);
   992  			break;
   993  
   994  		case 2:
   995  			arm_load_membase_ushort(inst, ARM_R0, temp_reg, 0);
   996  			break;
   997  
   998  		case 3:
   999  			arm_load_membase_ushort(inst, ARM_R0, temp_reg, 0);
  1000  			arm_load_membase_byte(inst, ARM_R1, temp_reg, 2);
  1001  			arm_shift_reg_imm8(inst, ARM_SHL, ARM_R1, ARM_R1, 16);
  1002  			arm_alu_reg_reg(inst, ARM_ORR, ARM_R0, ARM_R0, ARM_R1);
  1003  			break;
  1004  
  1005  		case 4:
  1006  			arm_load_membase(inst, ARM_R0, temp_reg, 0);
  1007  			break;
  1008  
  1009  		/*TODO: is this the right way to return a struct > 4 bytes?
  1010  		* Or should it be returned by address? Look at the Procedure Call Standard!
  1011  		*/
  1012  		
  1013  		case 5:
  1014  			arm_load_membase(inst, ARM_R0, temp_reg, 0);
  1015  			arm_load_membase_byte(inst, ARM_R1, temp_reg, 4);
  1016  			break;
  1017  
  1018  		case 6:
  1019  			arm_load_membase(inst, ARM_R0, temp_reg, 0);
  1020  			arm_load_membase_ushort(inst, ARM_R1, temp_reg, 4);
  1021  			break;
  1022  
  1023  		case 7:
  1024  			arm_load_membase(inst, ARM_R0, temp_reg, 0);
  1025  			arm_load_membase_ushort(inst, ARM_R1, temp_reg, 4);
  1026  			arm_load_membase_byte(inst, ARM_R2, temp_reg, 6);
  1027  			arm_shift_reg_imm8(inst, ARM_SHL, ARM_R2, ARM_R2, 16);
  1028  			arm_alu_reg_reg(inst, ARM_ORR, ARM_R1, ARM_R1, ARM_R2);
  1029  			break;
  1030  
  1031  		case 8:
  1032  			arm_load_membase(inst, ARM_R0, temp_reg, 0);
  1033  			arm_load_membase(inst, ARM_R1, temp_reg, 4);
  1034  			break;
  1035  		}
  1036  
  1037  		jump_to_epilog(gen, &inst, block);
  1038  	}
  1039  
  1040  /*
  1041   * Exception handling
  1042   */
  1043  JIT_OP_THROW: branch
  1044  	[reg] -> {
  1045  
  1046  		arm_push_reg(inst, $1);
  1047  		if(func->builder->setjmp_value != 0)
  1048  		{
  1049  			/* We have a "setjmp" block in the current function,
  1050  			   so we must record the location of the throw first */
  1051  			jit_nint pc_offset;
  1052  		
  1053  			_jit_gen_fix_value(func->builder->setjmp_value);
  1054  			
  1055  			pc_offset = func->builder->setjmp_value->frame_offset +
  1056  							jit_jmp_catch_pc_offset;
  1057  							
  1058  			if(func->builder->position_independent)
  1059  			{
  1060  				arm_call_imm(inst, 0);
  1061  				arm_pop_membase(inst, ARM_FP, pc_offset);
  1062  			}
  1063  			else
  1064  			{
  1065  				int pc = (int) (unsigned char *) arm_inst_get_posn(inst);
  1066  				arm_mov_membase_imm(inst, ARM_FP, pc_offset, pc, 4, ARM_WORK);
  1067  			}
  1068  		}
  1069  		arm_call(inst, (void *)jit_exception_throw);
  1070  	}
  1071  
  1072  JIT_OP_LOAD_PC:
  1073  [=reg] -> {
  1074  	if(func->builder->position_independent)
  1075  	{
  1076  		arm_call_imm(inst, 0);
  1077  		arm_pop_reg(inst, $1);
  1078  	}
  1079  	else
  1080  	{
  1081  		int pc = inst.current;
  1082  		mov_reg_imm(gen, &inst, $1, pc);
  1083  	}
  1084  }
  1085  
  1086  JIT_OP_ENTER_FINALLY:
  1087  [] -> { /* 
  1088  	 * The return address is in the link register
  1089  	 * We must save it on the stack in case it will be overwritten by the content
  1090  	 * of the "finally" block.
  1091  	 * In order to respect the ABI of the ARM architecture, that prescribes an 8-byte
  1092  	 * alignment for the stack at a public interface, we save the value twice, 
  1093  	 * in order to move the current SP by 8 bytes 
  1094  	 * (we could have just saved the value once and then moved the SP by 4 bytes)
  1095  	 */
  1096  	arm_push_reg(inst, ARM_LINK);
  1097  	arm_push_reg(inst, ARM_LINK);
  1098  }
  1099  
  1100  JIT_OP_LEAVE_FINALLY: branch
  1101  [] -> {
  1102  	/* The "finally" return address is on the stack (twice, just for padding)*/
  1103  		arm_pop_reg(inst, ARM_LINK);
  1104  		arm_pop_reg(inst, ARM_LINK);
  1105  		arm_return(inst);
  1106  }
  1107  
  1108  JIT_OP_CALL_FINALLY: branch
  1109  [] -> {
  1110  	jit_block_t block;
  1111  	int offset;
  1112  	block = jit_block_from_label(func, (jit_label_t)(insn->dest));
  1113  	if(!block)
  1114  	{
  1115  		return;
  1116  	}
  1117  	if(arm_inst_get_posn(inst) >= arm_inst_get_limit(inst))
  1118  	{
  1119  		/* The buffer has overflowed, so don't worry about fixups */
  1120  		return;
  1121  	}
  1122  	if(block->address)
  1123  	{
  1124  		/* We already know the address of the block */
  1125  		arm_call(inst, block->address);
  1126  	}
  1127  	else
  1128  	{
  1129  		/* Output a placeholder and record on the block's fixup list */
  1130  		if(block->fixup_list)
  1131  		{
  1132  			offset = (int)(((unsigned char *)arm_inst_get_posn(inst)) -
  1133  			((unsigned char *)(block->fixup_list)));
  1134  		}
  1135  		else
  1136  		{
  1137  			offset = 0;
  1138  		}
  1139  		arm_call_imm(inst, offset);
  1140  		block->fixup_list = (void *)(arm_inst_get_posn(inst) - 1);
  1141  	}
  1142  }
  1143  
  1144  JIT_OP_ADDRESS_OF_LABEL:
  1145  [=reg] -> {
  1146  	block = jit_block_from_label(func, (jit_label_t)(insn->value1));
  1147  	if(func->builder->position_independent)
  1148  	{
  1149  		/* TODO */
  1150  			TODO();
  1151  	}
  1152  	else
  1153  	{
  1154  		if(block->address)
  1155  		{
  1156  			mov_reg_imm(gen, &inst, $1, block->address);
  1157  		}
  1158  		else
  1159  		{
  1160  			/* Output a placeholder and record on the block's fixup list */
  1161  				mov_reg_imm(gen, &inst, $1, (int)(block->fixup_absolute_list));
  1162  				block->fixup_absolute_list = (void *)(inst.current - 1);
  1163  		}
  1164  	}
  1165  }
  1166  
  1167  /*
  1168   * Data manipulation.
  1169   */
  1170  
  1171  JIT_OP_COPY_LOAD_SBYTE: 
  1172  	[reg] -> {}
  1173  
  1174  JIT_OP_COPY_LOAD_UBYTE: 
  1175  	[reg] -> {}
  1176  
  1177  JIT_OP_COPY_LOAD_SHORT: 
  1178  	[reg] -> {}
  1179  
  1180  JIT_OP_COPY_LOAD_USHORT: 
  1181  	[reg] -> {}
  1182  
  1183  JIT_OP_COPY_INT: copy 
  1184  	[=local, imm, scratch reg] -> {
  1185  		arm_mov_membase_imm(inst, ARM_FP, $1, $2, 4, $3);
  1186  	}
  1187  	[reg] -> {}
  1188  	
  1189  
  1190  JIT_OP_COPY_LONG: copy 
  1191  	[lreg] -> {}
  1192  
  1193  JIT_OP_COPY_FLOAT32 (JIT_ARM_HAS_FLOAT_REGS): copy
  1194  	[freg32] -> {}
  1195  
  1196  JIT_OP_COPY_FLOAT32 (!JIT_ARM_HAS_FLOAT_REGS): manual
  1197  	[] -> {
  1198  		arm_inst_buf inst;
  1199  		_jit_regs_force_out(gen, insn->value1, 0);
  1200  		_jit_regs_force_out(gen, insn->dest, 1);
  1201  		_jit_gen_fix_value(insn->value1);
  1202  		_jit_gen_fix_value(insn->dest);
  1203  		jit_gen_load_inst_ptr(gen, inst);
  1204  		if(insn->value1->is_constant)
  1205  		{
  1206  			mov_reg_imm
  1207  				(gen, &inst, ARM_WORK, ((int *)(insn->value1->address))[0]);
  1208  		}
  1209  		else
  1210  		{
  1211  			arm_load_membase(inst, ARM_WORK, ARM_FP,
  1212  							 insn->value1->frame_offset);
  1213  		}
  1214  		arm_store_membase(inst, ARM_WORK, ARM_FP, insn->dest->frame_offset);
  1215  		jit_gen_save_inst_ptr(gen, inst);
  1216  	}
  1217  
  1218  JIT_OP_COPY_FLOAT64, JIT_OP_COPY_NFLOAT (JIT_ARM_HAS_FLOAT_REGS): copy
  1219  	[freg64] -> {}
  1220  
  1221  JIT_OP_COPY_FLOAT64, JIT_OP_COPY_NFLOAT (!JIT_ARM_HAS_FLOAT_REGS): manual
  1222  	[] -> {
  1223  		arm_inst_buf inst;
  1224  		_jit_regs_force_out(gen, insn->value1, 0);
  1225  		_jit_regs_force_out(gen, insn->dest, 1);
  1226  		_jit_gen_fix_value(insn->value1);
  1227  		_jit_gen_fix_value(insn->dest);
  1228  		jit_gen_load_inst_ptr(gen, inst);
  1229  		if(insn->value1->is_constant)
  1230  		{
  1231  			mov_reg_imm
  1232  				(gen, &inst, ARM_WORK, ((int *)(insn->value1->address))[0]);
  1233  			arm_store_membase(inst, ARM_WORK, ARM_FP,
  1234  							  insn->dest->frame_offset);
  1235  			mov_reg_imm
  1236  				(gen, &inst, ARM_WORK, ((int *)(insn->value1->address))[1]);
  1237  			arm_store_membase(inst, ARM_WORK, ARM_FP,
  1238  							  insn->dest->frame_offset + 4);
  1239  		}
  1240  		else
  1241  		{
  1242  			arm_load_membase(inst, ARM_WORK, ARM_FP,
  1243  							 insn->value1->frame_offset);
  1244  			arm_store_membase(inst, ARM_WORK, ARM_FP,
  1245  							  insn->dest->frame_offset);
  1246  			arm_load_membase(inst, ARM_WORK, ARM_FP,
  1247  							 insn->value1->frame_offset + 4);
  1248  			arm_store_membase(inst, ARM_WORK, ARM_FP,
  1249  							  insn->dest->frame_offset + 4);
  1250  		}
  1251  		jit_gen_save_inst_ptr(gen, inst);
  1252  	}
  1253  
  1254  JIT_OP_COPY_STRUCT:
  1255  	[=frame, frame, scratch reg] -> {
  1256  		inst = memory_copy(gen, inst, ARM_FP, $1, ARM_FP, $2,
  1257  				jit_type_get_size(jit_value_get_type(insn->dest)), $3);
  1258  	}
  1259  
  1260  JIT_OP_COPY_STORE_BYTE: manual
  1261  	[] -> {
  1262  		arm_inst_buf inst;
  1263  		int reg;
  1264  		_jit_regs_force_out(gen, insn->dest, 1);
  1265  		_jit_gen_fix_value(insn->dest);
  1266  		reg = _jit_regs_load_value
  1267  			(gen, insn->value1, 0,
  1268  			 (insn->flags & (JIT_INSN_VALUE1_NEXT_USE |
  1269  			 				 JIT_INSN_VALUE1_LIVE)));
  1270  		jit_gen_load_inst_ptr(gen, inst);
  1271  		arm_store_membase_byte(inst, _jit_reg_info[reg].cpu_reg,
  1272  							   ARM_FP, insn->dest->frame_offset);
  1273  		jit_gen_save_inst_ptr(gen, inst);
  1274  	}
  1275  
  1276  JIT_OP_COPY_STORE_SHORT: manual
  1277  	[] -> {
  1278  		arm_inst_buf inst;
  1279  		int reg;
  1280  		_jit_regs_force_out(gen, insn->dest, 1);
  1281  		_jit_gen_fix_value(insn->dest);
  1282  		reg = _jit_regs_load_value
  1283  			(gen, insn->value1, 1,
  1284  			 (insn->flags & (JIT_INSN_VALUE1_NEXT_USE |
  1285  			 				 JIT_INSN_VALUE1_LIVE)));
  1286  		jit_gen_load_inst_ptr(gen, inst);
  1287  		arm_store_membase_short(inst, _jit_reg_info[reg].cpu_reg,
  1288  							    ARM_FP, insn->dest->frame_offset);
  1289  		jit_gen_save_inst_ptr(gen, inst);
  1290  		//_jit_regs_free_reg(gen, reg, 1); //TODO: check if it's needed
  1291  	}
  1292  
  1293  JIT_OP_ADDRESS_OF:
  1294  	[=reg, frame] -> {
  1295  		if($2 > 0)
  1296  		{
  1297  			arm_alu_reg_imm(inst, ARM_ADD, $1, ARM_FP, $2);
  1298  		}
  1299  		else if($2 < 0)
  1300  		{
  1301  			arm_alu_reg_imm(inst, ARM_SUB, $1, ARM_FP, -$2);
  1302  		}
  1303  		else
  1304  		{
  1305  			arm_mov_reg_reg(inst, $1, ARM_FP);
  1306  		}
  1307  
  1308  	}
  1309  
  1310  /*
  1311   * Stack pushes and pops.
  1312   */
  1313  
  1314  JIT_OP_INCOMING_REG, JIT_OP_RETURN_REG: note
  1315          [reg] -> {
  1316  		/*
  1317  		 * This rule does nothing itself. Also at this point
  1318  		 * the value is supposed to be already in the register
  1319  		 * so the "reg" pattern does not load it either. But
  1320  		 * it allows the allocator to check the liveness flags
  1321  		 * and free the register if the value is dead.
  1322  		 */
  1323  	}
  1324  
  1325  JIT_OP_RETRIEVE_FRAME_POINTER: note
  1326  	[=reg] -> {
  1327  		arm_mov_reg_reg(inst, $1, ARM_FP);
  1328  	}
  1329  	
  1330  JIT_OP_PUSH_INT: note
  1331  	[reg] -> {
  1332  		arm_push_reg(inst, $1);
  1333  	}
  1334  
  1335  JIT_OP_PUSH_LONG: note
  1336  	[lreg] -> {
  1337  		arm_push_reg(inst, %1);
  1338  		arm_push_reg(inst, $1);
  1339  		gen->stack_changed=1;
  1340  	}
  1341  
  1342  JIT_OP_PUSH_FLOAT32 (JIT_ARM_HAS_FLOAT_REGS): note
  1343  	[freg32] -> {
  1344  		arm_push_reg_float32(inst, $1);
  1345  	}
  1346  
  1347  JIT_OP_PUSH_FLOAT32 (!JIT_ARM_HAS_FLOAT_REGS): manual
  1348  	[] -> {
  1349  		arm_inst_buf inst;
  1350  		_jit_regs_force_out(gen, insn->value1, 0);
  1351  		_jit_gen_fix_value(insn->value1);
  1352  		jit_gen_load_inst_ptr(gen, inst);
  1353  		if(insn->value1->is_constant)
  1354  		{
  1355  			mov_reg_imm
  1356  				(gen, &inst, ARM_WORK, ((int *)(insn->value1->address))[0]);
  1357  		}
  1358  		else
  1359  		{
  1360  			arm_load_membase(inst, ARM_WORK, ARM_FP,
  1361  							 insn->value1->frame_offset);
  1362  		}
  1363  		arm_push_reg(inst, ARM_WORK);
  1364  		jit_gen_save_inst_ptr(gen, inst);
  1365  	}
  1366  
  1367  JIT_OP_PUSH_FLOAT64, JIT_OP_PUSH_NFLOAT (JIT_ARM_HAS_FLOAT_REGS): note
  1368  	[freg64] -> {
  1369  		arm_push_reg_float64(inst, $1);
  1370  	}
  1371  
  1372  JIT_OP_PUSH_FLOAT64, JIT_OP_PUSH_NFLOAT (!JIT_ARM_HAS_FLOAT_REGS): manual
  1373  	[] -> {
  1374  		arm_inst_buf inst;
  1375  		_jit_regs_force_out(gen, insn->value1, 0);
  1376  		_jit_gen_fix_value(insn->value1);
  1377  		jit_gen_load_inst_ptr(gen, inst);
  1378  		if(insn->value1->is_constant)
  1379  		{
  1380  			mov_reg_imm
  1381  				(gen, &inst, ARM_WORK, ((int *)(insn->value1->address))[1]);
  1382  			arm_push_reg(inst, ARM_WORK);
  1383  			mov_reg_imm
  1384  				(gen, &inst, ARM_WORK, ((int *)(insn->value1->address))[0]);
  1385  			arm_push_reg(inst, ARM_WORK);
  1386  		}
  1387  		else
  1388  		{
  1389  			arm_load_membase(inst, ARM_WORK, ARM_FP,
  1390  							 insn->value1->frame_offset + 4);
  1391  			arm_push_reg(inst, ARM_WORK);
  1392  			arm_load_membase(inst, ARM_WORK, ARM_FP,
  1393  							 insn->value1->frame_offset);
  1394  			arm_push_reg(inst, ARM_WORK);
  1395  		}
  1396  		jit_gen_save_inst_ptr(gen, inst);
  1397  	}
  1398  
  1399  JIT_OP_PUSH_STRUCT: /*unary_note*/
  1400  	[reg] -> {
  1401  		/* TODO */
  1402  		TODO();
  1403  	}
  1404  
  1405  JIT_OP_POP_STACK:
  1406  	[] -> {
  1407  		arm_alu_reg_imm(inst, ARM_ADD, ARM_SP, ARM_SP, insn->value1->address);
  1408  	}
  1409  
  1410  JIT_OP_FLUSH_SMALL_STRUCT:
  1411  	[] -> {
  1412  		jit_nuint size;
  1413  		jit_nint offset;
  1414  		_jit_gen_fix_value(insn->value1);
  1415  		size = jit_type_get_size(jit_value_get_type(insn->value1));
  1416  		offset = insn->value1->frame_offset;
  1417  		switch(size)
  1418  		{
  1419  			case 1:
  1420  			{
  1421  				arm_store_membase_byte(inst, ARM_R0, ARM_FP, offset);
  1422  			}
  1423  			break;
  1424  
  1425  			case 2:
  1426  			{
  1427  				arm_store_membase_short(inst, ARM_R0, ARM_FP, offset);
  1428  			}
  1429  			break;
  1430  
  1431  			case 3:
  1432  			{
  1433  				arm_mov_reg_reg(inst, ARM_R1, ARM_R0);
  1434  				arm_store_membase_short(inst, ARM_R0, ARM_FP, offset);
  1435  				arm_shift_reg_imm8(inst, ARM_SHR, ARM_R0, ARM_R1, 16);
  1436  				arm_store_membase_byte(inst, ARM_R0, ARM_FP, offset + 2);
  1437  			}
  1438  			break;
  1439  
  1440  			case 4:
  1441  			{
  1442  				arm_store_membase(inst, ARM_R0, ARM_FP, offset);
  1443  			}
  1444  			break;
  1445  
  1446  			case 5:
  1447  			{
  1448  				arm_store_membase(inst, ARM_R0, ARM_FP, offset);
  1449  				arm_store_membase_byte(inst, ARM_R1, ARM_FP, offset + 4);
  1450  			}
  1451  			break;
  1452  
  1453  			case 6:
  1454  			{
  1455  				arm_store_membase(inst, ARM_R0, ARM_FP, offset);
  1456  				arm_store_membase_short(inst, ARM_R1, ARM_FP, offset + 4);
  1457  			}
  1458  			break;
  1459  
  1460  			case 7:
  1461  			{
  1462  				arm_store_membase(inst, ARM_R0, ARM_FP, offset);
  1463  				arm_mov_reg_reg(inst, ARM_R2, ARM_R1);
  1464  				arm_store_membase_short(inst, ARM_R1, ARM_FP, offset + 4);
  1465  				arm_shift_reg_imm8(inst, ARM_SHR, ARM_R1, ARM_R2, 16);
  1466  				arm_store_membase_byte(inst, ARM_R1, ARM_FP, offset + 6);
  1467  			}
  1468  			break;
  1469  
  1470  			case 8:
  1471  			{
  1472  				arm_store_membase(inst, ARM_R0, ARM_FP, offset);
  1473  				arm_store_membase(inst, ARM_R1, ARM_FP, offset + 4);
  1474  			}
  1475  			break;
  1476  		}
  1477  	}
  1478  
  1479  JIT_OP_SET_PARAM_INT: note
  1480  	[imm, imm] -> {
  1481  		arm_mov_membase_imm(inst, ARM_SP, $2, $1, 4, ARM_WORK);
  1482  	}
  1483  	[reg, imm] -> {
  1484  		arm_mov_membase_reg(inst, ARM_SP, $2, $1, 4);
  1485  	}
  1486  
  1487  JIT_OP_SET_PARAM_LONG: /*unary_note*/
  1488  	[lreg] -> {
  1489  		arm_store_membase(inst, $1, ARM_SP, insn->value2->address);
  1490  		arm_store_membase(inst, %1, ARM_SP, insn->value2->address + 4);
  1491  	}
  1492  
  1493  JIT_OP_SET_PARAM_FLOAT32 (JIT_ARM_HAS_FLOAT_REGS): /*unary_note*/
  1494  	[freg32] -> {
  1495  		arm_store_membase_float32(inst, $1, ARM_SP, insn->value2->address);
  1496  	}
  1497  
  1498  JIT_OP_SET_PARAM_FLOAT32 (!JIT_ARM_HAS_FLOAT_REGS): manual
  1499  	[] -> {
  1500  		arm_inst_buf inst;
  1501  		_jit_regs_force_out(gen, insn->value1, 0);
  1502  		_jit_gen_fix_value(insn->value1);
  1503  		jit_gen_load_inst_ptr(gen, inst);
  1504  		if(insn->value1->is_constant)
  1505  		{
  1506  			mov_reg_imm
  1507  				(gen, &inst, ARM_WORK, ((int *)(insn->value1->address))[0]);
  1508  			arm_store_membase
  1509  				(inst, ARM_WORK, ARM_SP, insn->value2->address);
  1510  		}
  1511  		else
  1512  		{
  1513  			arm_load_membase(inst, ARM_WORK, ARM_FP,
  1514  							 insn->value1->frame_offset);
  1515  			arm_store_membase
  1516  				(inst, ARM_WORK, ARM_SP, insn->value2->address);
  1517  		}
  1518  		jit_gen_save_inst_ptr(gen, inst);
  1519  	}
  1520  
  1521  JIT_OP_SET_PARAM_FLOAT64, JIT_OP_SET_PARAM_NFLOAT
  1522  		(JIT_ARM_HAS_FLOAT_REGS): /*unary_note*/
  1523  	[freg64] -> {
  1524  		arm_store_membase_float64(inst, $1, ARM_SP, insn->value2->address);
  1525  	}
  1526  
  1527  JIT_OP_SET_PARAM_FLOAT64, JIT_OP_SET_PARAM_NFLOAT
  1528  		(!JIT_ARM_HAS_FLOAT_REGS): manual
  1529  	[] -> {
  1530  		arm_inst_buf inst;
  1531  		_jit_regs_force_out(gen, insn->value1, 0);
  1532  		_jit_gen_fix_value(insn->value1);
  1533  		jit_gen_load_inst_ptr(gen, inst);
  1534  		if(insn->value1->is_constant)
  1535  		{
  1536  			mov_reg_imm
  1537  				(gen, &inst, ARM_WORK, ((int *)(insn->value1->address))[0]);
  1538  			arm_store_membase
  1539  				(inst, ARM_WORK, ARM_SP, insn->value2->address);
  1540  			mov_reg_imm
  1541  				(gen, &inst, ARM_WORK, ((int *)(insn->value1->address))[1]);
  1542  			arm_store_membase
  1543  				(inst, ARM_WORK, ARM_SP, insn->value2->address + 4);
  1544  		}
  1545  		else
  1546  		{
  1547  			arm_load_membase(inst, ARM_WORK, ARM_FP,
  1548  							 insn->value1->frame_offset);
  1549  			arm_store_membase
  1550  				(inst, ARM_WORK, ARM_SP, insn->value2->address);
  1551  			arm_load_membase(inst, ARM_WORK, ARM_FP,
  1552  							 insn->value1->frame_offset + 4);
  1553  			arm_store_membase
  1554  				(inst, ARM_WORK, ARM_SP, insn->value2->address + 4);
  1555  		}
  1556  		jit_gen_save_inst_ptr(gen, inst);
  1557  	}
  1558  
  1559  JIT_OP_SET_PARAM_STRUCT: note
  1560  [reg, imm, scratch reg] -> {
  1561  	/* Handle arbitrary-sized structures */
  1562  	jit_nint offset = jit_value_get_nint_constant(insn->dest);
  1563  	inst = memory_copy(gen, inst, ARM_SP, offset, $1, 0, $2, $3);
  1564  }
  1565  		
  1566  /*
  1567   * Pointer-relative loads and stores.
  1568   */
  1569  JIT_OP_LOAD_RELATIVE_SBYTE: 
  1570  	[reg] -> {
  1571  		arm_load_membase_sbyte(inst, $1, $1, insn->value2->address);
  1572  	}
  1573  
  1574  JIT_OP_LOAD_RELATIVE_UBYTE: 
  1575  	[reg] -> {
  1576  		arm_load_membase_byte(inst, $1, $1, insn->value2->address);
  1577  	}
  1578  
  1579  JIT_OP_LOAD_RELATIVE_SHORT: 
  1580  	[reg] -> {
  1581  		arm_load_membase_short(inst, $1, $1, insn->value2->address);
  1582  	}
  1583  
  1584  JIT_OP_LOAD_RELATIVE_USHORT: 
  1585  	[reg] -> {
  1586  		arm_load_membase_ushort(inst, $1, $1, insn->value2->address);
  1587  	}
  1588  
  1589  JIT_OP_LOAD_RELATIVE_INT: 
  1590  	[reg] -> {
  1591  		arm_load_membase(inst, $1, $1, insn->value2->address);
  1592  	}
  1593  
  1594  JIT_OP_LOAD_RELATIVE_LONG:
  1595  	[=lreg, reg, imm] -> {
  1596  		if($1 == $2)
  1597  		{
  1598  			arm_mov_reg_membase(inst, %1, $2, $3 + 4, 4);
  1599  			arm_mov_reg_membase(inst, $1, $2, $3, 4);
  1600  		}
  1601  		else
  1602  		{
  1603  			arm_mov_reg_membase(inst, $1, $2, $3, 4);
  1604  			arm_mov_reg_membase(inst, %1, $2, $3 + 4, 4);
  1605  		}
  1606  	}
  1607  
  1608  JIT_OP_LOAD_RELATIVE_FLOAT32 (JIT_ARM_HAS_VFP):
  1609  [=freg32, reg, imm] -> {
  1610  	arm_fld_membase(inst, $1, $2, $3, 0);
  1611  }
  1612  
  1613  JIT_OP_LOAD_RELATIVE_FLOAT64 (JIT_ARM_HAS_VFP):
  1614  [=freg64, reg, imm] -> {
  1615  	arm_fld_membase(inst, $1, $2, $3, 1);
  1616  }
  1617  
  1618  JIT_OP_LOAD_RELATIVE_NFLOAT: manual
  1619  	[] -> {
  1620  		/* TODO */
  1621  		TODO();
  1622  		abort();
  1623  	}
  1624  
  1625  JIT_OP_LOAD_RELATIVE_STRUCT: more_space
  1626  [=frame, reg, imm, scratch reg] -> {
  1627  	inst = memory_copy(gen, inst, ARM_FP, $1, $2, $3, jit_type_get_size(jit_value_get_type(insn->dest)), $4);
  1628  }
  1629  
  1630  JIT_OP_STORE_RELATIVE_BYTE: ternary
  1631  [imm, imm, imm, scratch reg] -> {
  1632  	arm_mov_mem_imm(inst, $1 + $3, $2, 1, $4);
  1633  }
  1634  [imm, reg, imm] -> {
  1635  	arm_mov_mem_reg(inst, $1 + $3, $2, 1);
  1636  }
  1637  [reg, imm, imm] -> {
  1638  	arm_mov_membase_imm(inst, $1, $3, $2, 1, ARM_WORK);
  1639  }
  1640  [reg, reg, imm] -> {
  1641  	arm_mov_membase_reg(inst, $1, $3, $2, 1);
  1642  }
  1643  
  1644  JIT_OP_STORE_RELATIVE_SHORT: ternary
  1645  [imm, imm, imm, scratch reg] -> {
  1646  	arm_mov_mem_imm(inst, $1 + $3, $2, 2, $4);
  1647  }
  1648  [imm, reg, imm] -> {
  1649  	arm_mov_mem_reg(inst, $1 + $3, $2, 2);
  1650  }
  1651  [reg, imm, imm] -> {
  1652  	arm_mov_membase_imm(inst, $1, $3, $2, 2, ARM_WORK);
  1653  }
  1654  [reg, reg, imm] -> {
  1655  	arm_mov_membase_reg(inst, $1, $3, $2, 2);
  1656  }
  1657  
  1658  JIT_OP_STORE_RELATIVE_INT: ternary
  1659  	[imm, imm, imm, scratch reg] -> {
  1660  		arm_mov_mem_imm(inst, $1 + $3, $2, 4, $4);
  1661  	}
  1662  	[imm, reg, imm] -> {
  1663  		arm_mov_mem_reg(inst, $1 + $3, $2, 4);
  1664  	}
  1665  	[reg, imm, imm] -> {
  1666  		arm_mov_membase_imm(inst, $1, $3, $2, 4, ARM_WORK);
  1667  	}
  1668  	[reg, reg, imm] -> {
  1669  		arm_mov_membase_reg(inst, $1, $3, $2, 4);
  1670  	}
  1671  
  1672  JIT_OP_STORE_RELATIVE_LONG: ternary
  1673  	[reg, imm, imm] -> {
  1674  		arm_mov_membase_imm(inst, $1, $3, *(int *)($2), 4, ARM_WORK);
  1675  		arm_mov_membase_imm(inst, $1, $3 + 4, *(int *)($2 + 4), 4, ARM_WORK);
  1676  	}
  1677  	[reg, local, imm, scratch reg] -> {
  1678  		arm_mov_reg_membase(inst, $4, ARM_FP, $2, 4);
  1679  		arm_mov_membase_reg(inst, $1, $3, $4, 4);
  1680  		arm_mov_reg_membase(inst, $4, ARM_FP, $2 + 4, 4);
  1681  		arm_mov_membase_reg(inst, $1, $3 + 4, $4, 4);
  1682  	}
  1683  	[reg, lreg, imm] -> {
  1684  		arm_mov_membase_reg(inst, $1, $3, $2, 4);
  1685  		arm_mov_membase_reg(inst, $1, $3 + 4, %2, 4);
  1686  	}
  1687  	
  1688  JIT_OP_STORE_RELATIVE_FLOAT32 (JIT_ARM_HAS_VFP): ternary
  1689  	[reg, imm, imm] -> {
  1690  		arm_mov_membase_imm(inst, $1, $3, ((int *)($2))[0], 4, ARM_WORK);
  1691  	}
  1692  	[reg, freg32, imm] -> {
  1693  		arm_store_membase_float32(inst, $2, $1, $3);
  1694  	}
  1695  
  1696  JIT_OP_STORE_RELATIVE_FLOAT64 (JIT_ARM_HAS_VFP): ternary
  1697  	[reg, imm, imm, scratch reg] -> {
  1698  		arm_mov_membase_imm(inst, $1, $3, ((int *)($2))[0], 4, $4);
  1699  		arm_mov_membase_imm(inst, $1, $3 + 4, ((int *)($2))[1], 4, $4);
  1700  	}
  1701  	[reg, freg64, imm] -> {
  1702  		arm_store_membase_float64(inst, $2, $1, $3);
  1703  	}
  1704  
  1705  JIT_OP_STORE_RELATIVE_NFLOAT: manual
  1706  	[] -> {
  1707  		/* TODO */
  1708  		TODO();
  1709  		abort();
  1710  	}
  1711  
  1712  JIT_OP_STORE_RELATIVE_STRUCT: manual
  1713  [] -> {
  1714  	arm_inst_buf inst;
  1715  	int reg = _jit_regs_load_value(gen, insn->dest, 0,
  1716  	  (insn->flags & (JIT_INSN_DEST_NEXT_USE |
  1717  	  JIT_INSN_DEST_LIVE)));
  1718  	_jit_regs_spill_all(gen);
  1719  	_jit_gen_fix_value(insn->value1);
  1720  	jit_gen_load_inst_ptr(gen, inst);
  1721  	_jit_gen_check_space(gen, 128);
  1722  	reg = _jit_reg_info[reg].cpu_reg;
  1723  	inst = memory_copy(gen, inst, reg, (int)(insn->value2->address),
  1724  			ARM_FP, insn->value1->frame_offset,
  1725  			jit_type_get_size(jit_value_get_type(insn->value1)), -1);
  1726  	jit_gen_save_inst_ptr(gen, inst);
  1727  }
  1728  
  1729  JIT_OP_ADD_RELATIVE: 
  1730  	[reg] -> {
  1731  		if(insn->value2->address != 0)
  1732  		{
  1733  			arm_alu_reg_imm(inst, ARM_ADD, $1, $1, insn->value2->address);
  1734  		}
  1735  	}
  1736  
  1737  /*
  1738  * Array element loads and stores.
  1739  */
  1740  JIT_OP_LOAD_ELEMENT_UBYTE:
  1741  [=reg, reg, reg] -> {
  1742  	arm_widen_memindex(inst, $1, $2, 0, $3, 0, 0, 0);
  1743  }
  1744  
  1745  JIT_OP_LOAD_ELEMENT_USHORT:
  1746  [=reg, reg, reg] -> {
  1747  	arm_widen_memindex(inst, $1, $2, 0, $3, 1, 0, 1);
  1748  }
  1749  
  1750  JIT_OP_LOAD_ELEMENT_INT:
  1751  [=reg, reg, reg] -> {
  1752  	/* The last parameter is unimportant: it's not used, 
  1753  	since the displacement (4th param) is 0 */
  1754  	arm_mov_reg_memindex(inst, $1, $2, 0, $3, 2, 4, 0);
  1755  }
  1756  
  1757  JIT_OP_LOAD_ELEMENT_LONG:
  1758  [=lreg, reg, reg, scratch reg, scratch reg] -> {
  1759  	//$1=destination long register (1-st word, LSB)
  1760  	//%1=destination long register (2-nd word, MSB)
  1761  	//$2=base register
  1762  	//$3=index register
  1763  	//$4=scratch register for arm_mov_reg_memindex
  1764  	//$5=scratch register for overwriting prevention
  1765  	
  1766  	assert($2 != $3);
  1767  	
  1768  	int basereg=$2;
  1769  	int indexreg=$3;
  1770  	
  1771  	//Write the 1-st word
  1772  	if($1 == basereg)
  1773  	{
  1774  		//Prevent base reg from being overwritten
  1775  		arm_mov_reg_reg(inst, $5, basereg);
  1776  		basereg=$5;
  1777  	}
  1778  	else if ($1 == indexreg)
  1779  	{	
  1780  		//Prevent index reg from being overwritten
  1781  		arm_mov_reg_reg(inst, $5, indexreg);
  1782  		indexreg=$5;
  1783  	}
  1784  	arm_mov_reg_memindex(inst, $1, basereg, 0, indexreg, 3, 4, $4);
  1785  	
  1786  	//Write the 2-nd word
  1787  	arm_mov_reg_memindex(inst, %1, basereg, 4, indexreg, 3, 4, $4);
  1788  }
  1789  
  1790  JIT_OP_LOAD_ELEMENT_FLOAT64:
  1791  [=freg64, reg, reg, scratch reg] -> {
  1792  	arm_fld_memindex(inst, $1, $2, 0, $3, 3, 1, $4);
  1793  }
  1794  
  1795  JIT_OP_STORE_ELEMENT_BYTE: ternary
  1796  [reg, reg, reg, scratch reg] -> {
  1797  	arm_mov_memindex_reg(inst, $1, 0, $2, 0, $3, 1, $4);
  1798  }
  1799  
  1800  JIT_OP_STORE_ELEMENT_SHORT: ternary
  1801  [reg, reg, reg, scratch reg] -> {
  1802  	arm_mov_memindex_reg(inst, $1, 0, $2, 1, $3, 2, $4);
  1803  }
  1804  
  1805  JIT_OP_STORE_ELEMENT_INT: ternary
  1806  [reg, reg, reg, scratch reg] -> {
  1807  	arm_mov_memindex_reg(inst, $1, 0, $2, 2, $3, 4, $4);
  1808  }
  1809  
  1810  JIT_OP_STORE_ELEMENT_LONG: ternary
  1811  	[reg, reg, imm] -> {
  1812  		TODO();
  1813  		abort();
  1814  		//x86_mov_memindex_imm(inst, $1, 0, $2, 3, *(int *)($3), 4);
  1815  		//x86_mov_memindex_imm(inst, $1, 4, $2, 3, *(int *)($3 + 4), 4);
  1816  	}
  1817  	[reg, reg, local, scratch reg, scratch reg] -> {
  1818  		arm_mov_reg_membase(inst, $4, ARM_FP, $3, 4);
  1819  		arm_mov_memindex_reg(inst, $1, 0, $2, 3, $4, 4, $5);
  1820  		arm_mov_reg_membase(inst, $4, ARM_FP, $3 + 4, 4);
  1821  		arm_mov_memindex_reg(inst, $1, 4, $2, 3, $4, 4, $5);
  1822  	}
  1823  	[reg, reg, lreg, scratch reg] -> {
  1824  		arm_mov_memindex_reg(inst, $1, 0, $2, 3, $3, 4, $4);
  1825  		arm_mov_memindex_reg(inst, $1, 4, $2, 3, %3, 4, $4);
  1826  	}
  1827  
  1828  JIT_OP_STORE_ELEMENT_FLOAT64: ternary
  1829  [reg, reg, freg64, scratch reg] -> {
  1830  	arm_fst_memindex(inst, $3, $1, 0, $2, 3, 1, $4);
  1831  }
  1832  
  1833  /*
  1834  * Allocate memory from the stack.
  1835  */
  1836  JIT_OP_ALLOCA:
  1837  [reg] -> {
  1838  	arm_alu_reg_reg(inst, ARM_SUB, ARM_SP, ARM_SP, $1);
  1839  	arm_mov_reg_reg(inst, $1, ARM_SP);
  1840  	gen->stack_changed = 1;
  1841  }
  1842  
  1843  /*
  1844   * Block operations
  1845   */
  1846  JIT_OP_MEMCPY: ternary
  1847  	[any, any, imm, if("$3 <= 0")] -> { }
  1848  	[reg, reg, imm, scratch reg, clobber("r0", "r1", "r2")] ->
  1849  	{
  1850  		/* 
  1851  		 * Call jit_memcpy(dest,src,size).
  1852  		 * $1=dest, $2=src, $3=size
  1853  		 */
  1854  		int dest=$1;
  1855  		int src=$2;
  1856  		
  1857  		if (dest != ARM_R0) {
  1858  			if(src==ARM_R0)
  1859  			{
  1860  				//Prevent overwriting useful data
  1861  				arm_mov_reg_reg(inst, $4, src);
  1862  				src=$4;
  1863  			}
  1864  			arm_mov_reg_reg((inst), ARM_R0, dest);
  1865  		}
  1866  		if (src != ARM_R1) {
  1867  			//Move the "src" from wherever it is to where it should be
  1868  			arm_mov_reg_reg(inst, ARM_R1, src);
  1869  		}
  1870  		mov_reg_imm(gen, &(inst), ARM_R2, $3);
  1871  	    
  1872  		//Call the function
  1873  		arm_call(inst, jit_memcpy);
  1874  	}
  1875  	[reg, reg, reg, scratch reg, clobber("r0", "r1", "r2")] -> {
  1876  		/* 
  1877  		* Call jit_memcpy(dest,src,size).
  1878  		* $1=dest, $2=src, $3=size
  1879  		*/
  1880  		if ($1 != ARM_R0) {
  1881  			if($2==ARM_R0)
  1882  			{
  1883  				//Prevent overwriting useful data
  1884  				arm_mov_reg_reg(inst, $4, $2);
  1885  			}
  1886  			arm_mov_reg_reg((inst), ARM_R0, $1);
  1887  		}
  1888  		if ($2 != ARM_R1) {
  1889  			if ($2==ARM_R0)
  1890  			{
  1891  				//Recover previously saved data
  1892  				arm_mov_reg_reg(inst, ARM_R1, $4);
  1893  			}
  1894  			else
  1895  			{
  1896  				arm_mov_reg_reg((inst), ARM_R1, $2);
  1897  			}
  1898  		}
  1899  		if ($3 != ARM_R2) {
  1900  			arm_mov_reg_reg((inst), ARM_R2, $3);
  1901  		}
  1902  	    
  1903  		//Call the function
  1904  		arm_call(inst, jit_memcpy);
  1905  
  1906  	}
  1907  
  1908  JIT_OP_MEMSET: ternary
  1909  [any, any, imm, if("$3 <= 0")] -> { }
  1910  [reg, imm, imm, if("$3 <= 32"), space("32 + $3 * 4")] -> {
  1911  	// $1 = pointer to the initial memory location
  1912  	// $2 = value to be written in memory
  1913  	// $3 = length in bytes
  1914  	int disp;
  1915  	disp = 0;
  1916  	while($3 >= (disp + 4))
  1917  	{
  1918  		//NB: if 0<A<255, then A*0x01010101 = a 32-bit value where each of its four bytes is A.
  1919  		arm_mov_membase_imm(inst, $1, disp, $2 * 0x01010101, 4, ARM_WORK);
  1920  		disp += 4;
  1921  	}
  1922  	if($3 >= (disp + 2))
  1923  	{
  1924  		arm_mov_membase_imm(inst, $1, disp, $2 * 0x0101, 2, ARM_WORK);
  1925  		disp += 2;
  1926  	}
  1927  	if(insn->value2->address > disp)
  1928  	{
  1929  		arm_mov_membase_imm(inst, $1, disp, $2, 1, ARM_WORK);
  1930  	}
  1931  }
  1932  [reg, reg, imm, if("$3 < 4")] -> {
  1933  	TODO();
  1934  	abort();
  1935  }
  1936  [reg, +reg, imm, scratch reg, if("$3 <= 32 && ($3 % 2) == 0"), space("32 + $3 * 4")] -> {
  1937  	// $1 = pointer to the initial memory location
  1938  	// $2 = value to be written in memory
  1939  	// $3 = length in bytes
  1940  	// $4 = scratch register
  1941  	int disp;
  1942  	arm_mov_reg_reg(inst, $4, $2);
  1943  	arm_shift_reg_imm8(inst, ARM_SHL, $2, $2, 8);
  1944  	arm_alu_reg_reg(inst, ARM_ORR, $2, $2, $4);
  1945  	arm_mov_reg_reg(inst, $4, $2);
  1946  	arm_shift_reg_imm8(inst, ARM_SHL, $2, $2, 16);
  1947  	arm_alu_reg_reg(inst, ARM_ORR, $2, $2, $4);
  1948  	disp = 0;
  1949  	while($3 >= (disp + 4))
  1950  	{
  1951  		arm_mov_membase_reg(inst, $1, disp, $2, 4);
  1952  		disp += 4;
  1953  	}
  1954  	if($3 > disp)
  1955  	{
  1956  		arm_mov_membase_reg(inst, $1, disp, $2, 2);
  1957  	}
  1958  }
  1959  [reg, +reg, imm, scratch reg,
  1960  if("$3 <= 32 && ($3 % 2) != 0"), space("32 + $3 * 4")] -> {
  1961  	TODO();
  1962  	abort();
  1963  }
  1964  [reg, reg, reg, clobber("r0", "r1", "r2"), scratch reg] -> {
  1965  	// $1 = pointer to the initial memory location
  1966  	// $2 = value to be written in memory
  1967  	// $3 = length in bytes
  1968  	// $4 = scratch register
  1969  	
  1970  	int pointer=$1;
  1971  	int value=$2;
  1972  	int length=$3;
  1973  	int scratch=$4;
  1974  	
  1975  
  1976  	/* Move the outgoing parameters in the right registers (if they are not already where they should be */
  1977  	if (pointer != ARM_R0) {
  1978  		if(value == ARM_R0)
  1979  		{
  1980  			//Prevent the value from being overwritten
  1981  			arm_mov_reg_reg((inst), scratch, ARM_R0);
  1982  			value=scratch;
  1983  		}
  1984  		else if(length==ARM_R0)
  1985  		{
  1986  			//Prevent the length from being overwritten
  1987  			arm_mov_reg_reg((inst), scratch, ARM_R0);
  1988  			length=scratch;
  1989  		}
  1990  		
  1991  		arm_mov_reg_reg((inst), ARM_R0, pointer);
  1992  		
  1993  		//The register that contained the pointer is now free
  1994  		scratch=pointer;
  1995  	}
  1996  	
  1997  	if (value != ARM_R1)
  1998  	{
  1999  		if (length == ARM_R1)
  2000  		{
  2001  			//The length is stored in R1. Prevent it from being overwritten
  2002  			arm_mov_reg_reg(inst, scratch, length);
  2003  			length=scratch;
  2004  		}
  2005  		
  2006  		//Set param 2
  2007  		arm_mov_reg_reg((inst), ARM_R1, value);
  2008  		
  2009  		//The register that contained the value is now free
  2010  		scratch=value;
  2011  	}
  2012  	
  2013  	if(length != ARM_R1)
  2014  	{
  2015  		//Param 3 still isn't in place: move it!
  2016  		arm_mov_reg_reg(inst, ARM_R2, length);
  2017  	}
  2018  	
  2019  	arm_call(inst, jit_memset);
  2020  }