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

     1  /*
     2   * jit-rules-x86.c - Rules that define the characteristics of the x86.
     3   *
     4   * Copyright (C) 2004  Southern Storm Software, Pty Ltd.
     5   *
     6   * This file is part of the libjit library.
     7   *
     8   * The libjit library is free software: you can redistribute it and/or
     9   * modify it under the terms of the GNU Lesser General Public License
    10   * as published by the Free Software Foundation, either version 2.1 of
    11   * the License, or (at your option) any later version.
    12   *
    13   * The libjit library is distributed in the hope that it will be useful,
    14   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    15   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    16   * Lesser General Public License for more details.
    17   *
    18   * You should have received a copy of the GNU Lesser General Public
    19   * License along with the libjit library.  If not, see
    20   * <http://www.gnu.org/licenses/>.
    21   */
    22  
    23  #include "jit-internal.h"
    24  #include "jit-rules.h"
    25  #include "jit-apply-rules.h"
    26  
    27  #if defined(JIT_BACKEND_X86)
    28  
    29  #include "jit-gen-x86.h"
    30  #include "jit-reg-alloc.h"
    31  #include "jit-setjmp.h"
    32  #include <stdio.h>
    33  
    34  /*
    35   * Pseudo register numbers for the x86 registers.  These are not the
    36   * same as the CPU instruction register numbers.  The order of these
    37   * values must match the order in "JIT_REG_INFO".
    38   */
    39  #define	X86_REG_EAX			0
    40  #define	X86_REG_ECX			1
    41  #define	X86_REG_EDX			2
    42  #define	X86_REG_EBX			3
    43  #define	X86_REG_ESI			4
    44  #define	X86_REG_EDI			5
    45  #define	X86_REG_EBP			6
    46  #define	X86_REG_ESP			7
    47  #define	X86_REG_ST0			8
    48  #define	X86_REG_ST1			9
    49  #define	X86_REG_ST2			10
    50  #define	X86_REG_ST3			11
    51  #define	X86_REG_ST4			12
    52  #define	X86_REG_ST5			13
    53  #define	X86_REG_ST6			14
    54  #define	X86_REG_ST7			15
    55  
    56  /*
    57   * Determine if a pseudo register number is word-based or float-based.
    58   */
    59  #define	IS_WORD_REG(reg)	((reg) < X86_REG_ST0)
    60  #define	IS_FLOAT_REG(reg)	((reg) >= X86_REG_ST0)
    61  
    62  /*
    63   * Round a size up to a multiple of the stack word size.
    64   */
    65  #define	ROUND_STACK(size)	\
    66  		(((size) + (sizeof(void *) - 1)) & ~(sizeof(void *) - 1))
    67  
    68  static _jit_regclass_t *x86_reg;
    69  static _jit_regclass_t *x86_breg;
    70  static _jit_regclass_t *x86_freg;
    71  static _jit_regclass_t *x86_lreg;
    72  
    73  void _jit_init_backend(void)
    74  {
    75  	x86_reg = _jit_regclass_create(
    76  		"reg", JIT_REG_WORD, 6,
    77  		X86_REG_EAX, X86_REG_ECX,
    78  		X86_REG_EDX, X86_REG_EBX,
    79  		X86_REG_ESI, X86_REG_EDI);
    80  
    81  	x86_breg = _jit_regclass_create(
    82  		"breg", JIT_REG_WORD, 4,
    83  		X86_REG_EAX, X86_REG_ECX,
    84  		X86_REG_EDX, X86_REG_EBX);
    85  
    86  	x86_freg = _jit_regclass_create(
    87  		"freg", JIT_REG_X86_FLOAT | JIT_REG_IN_STACK, 8,
    88  		X86_REG_ST0, X86_REG_ST1,
    89  		X86_REG_ST2, X86_REG_ST3,
    90  		X86_REG_ST4, X86_REG_ST5,
    91  		X86_REG_ST6, X86_REG_ST7);
    92  
    93  	x86_lreg = _jit_regclass_create(
    94  		"lreg", JIT_REG_LONG, 2,
    95  		X86_REG_EAX, X86_REG_ECX);
    96  }
    97  
    98  void _jit_gen_get_elf_info(jit_elf_info_t *info)
    99  {
   100  #ifdef JIT_NATIVE_INT32
   101  	info->machine = 3;	/* EM_386 */
   102  #else
   103  	info->machine = 62;	/* EM_X86_64 */
   104  #endif
   105  #if JIT_APPLY_X86_FASTCALL == 0
   106  	info->abi = 0;		/* ELFOSABI_SYSV */
   107  #else
   108  	info->abi = 186;	/* Private code, indicating STDCALL/FASTCALL support */
   109  #endif
   110  	info->abi_version = 0;
   111  }
   112  
   113  int _jit_setup_indirect_pointer(jit_function_t func, jit_value_t value)
   114  {
   115  	return jit_insn_outgoing_reg(func, value, X86_REG_EAX);
   116  }
   117  
   118  int _jit_create_call_return_insns
   119  	(jit_function_t func, jit_type_t signature,
   120  	 jit_value_t *args, unsigned int num_args,
   121  	 jit_value_t return_value, int is_nested)
   122  {
   123  	jit_nint pop_bytes;
   124  	unsigned int size;
   125  	jit_type_t return_type;
   126  	int ptr_return;
   127  
   128  	/* Calculate the number of bytes that we need to pop */
   129  	return_type = jit_type_normalize(jit_type_get_return(signature));
   130  	ptr_return = jit_type_return_via_pointer(return_type);
   131  #if JIT_APPLY_X86_FASTCALL == 1
   132  	if(jit_type_get_abi(signature) == jit_abi_stdcall ||
   133  	   jit_type_get_abi(signature) == jit_abi_fastcall)
   134  	{
   135  		/* STDCALL and FASTCALL functions pop their own arguments */
   136  		pop_bytes = 0;
   137  	}
   138  	else
   139  #endif
   140  	{
   141  		pop_bytes = 0;
   142  		while(num_args > 0)
   143  		{
   144  			--num_args;
   145  			size = jit_type_get_size(jit_value_get_type(args[num_args]));
   146  			pop_bytes += ROUND_STACK(size);
   147  		}
   148  #if JIT_APPLY_X86_POP_STRUCT_RETURN == 1
   149  		if(ptr_return && is_nested)
   150  		{
   151  			/* Note: we only need this for nested functions, because
   152  			   regular functions will pop the structure return for us */
   153  			pop_bytes += sizeof(void *);
   154  		}
   155  #else
   156  		if(ptr_return)
   157  		{
   158  			pop_bytes += sizeof(void *);
   159  		}
   160  #endif
   161  		if(is_nested)
   162  		{
   163  			pop_bytes += sizeof(void *);
   164  		}
   165  	}
   166  
   167  	/* Pop the bytes from the system stack */
   168  	if(pop_bytes > 0)
   169  	{
   170  		if(!jit_insn_defer_pop_stack(func, pop_bytes))
   171  		{
   172  			return 0;
   173  		}
   174  	}
   175  
   176  	/* Bail out now if we don't need to worry about return values */
   177  	if(!return_value || ptr_return)
   178  	{
   179  		return 1;
   180  	}
   181  
   182  	/* Structure values must be flushed into the frame, and
   183  	   everything else ends up in a register */
   184  	if(jit_type_is_struct(return_type) || jit_type_is_union(return_type))
   185  	{
   186  		if(!jit_insn_flush_struct(func, return_value))
   187  		{
   188  			return 0;
   189  		}
   190  	}
   191  	else if(return_type == jit_type_float32 ||
   192  			return_type == jit_type_float64 ||
   193  			return_type == jit_type_nfloat)
   194  	{
   195  		if(!jit_insn_return_reg(func, return_value, X86_REG_ST0))
   196  		{
   197  			return 0;
   198  		}
   199  	}
   200  	else if(return_type->kind != JIT_TYPE_VOID)
   201  	{
   202  		if(!jit_insn_return_reg(func, return_value, X86_REG_EAX))
   203  		{
   204  			return 0;
   205  		}
   206  	}
   207  
   208  	/* Everything is back where it needs to be */
   209  	return 1;
   210  }
   211  
   212  int _jit_opcode_is_supported(int opcode)
   213  {
   214  	switch(opcode)
   215  	{
   216  	#define JIT_INCLUDE_SUPPORTED
   217  	#include "jit-rules-x86.inc"
   218  	#undef JIT_INCLUDE_SUPPORTED
   219  	}
   220  	return 0;
   221  }
   222  
   223  void *_jit_gen_prolog(jit_gencode_t gen, jit_function_t func, void *buf)
   224  {
   225  	unsigned char prolog[JIT_PROLOG_SIZE];
   226  	unsigned char *inst = prolog;
   227  	int reg;
   228  
   229  	/* Push ebp onto the stack */
   230  	x86_push_reg(inst, X86_EBP);
   231  
   232  	/* Initialize EBP for the current frame */
   233  	x86_mov_reg_reg(inst, X86_EBP, X86_ESP, sizeof(void *));
   234  
   235  	/* Allocate space for the local variable frame */
   236  	if(func->builder->frame_size > 0)
   237  	{
   238  		x86_alu_reg_imm(inst, X86_SUB, X86_ESP,
   239  			 			(int)(func->builder->frame_size));
   240  	}
   241  
   242  	/* Save registers that we need to preserve */
   243  	for(reg = 0; reg <= 7; ++reg)
   244  	{
   245  		if(jit_reg_is_used(gen->touched, reg) &&
   246  		   (_jit_reg_info[reg].flags & JIT_REG_CALL_USED) == 0)
   247  		{
   248  			x86_push_reg(inst, _jit_reg_info[reg].cpu_reg);
   249  		}
   250  	}
   251  
   252  	/* Copy the prolog into place and return the adjusted entry position */
   253  	reg = (int)(inst - prolog);
   254  	jit_memcpy(((unsigned char *)buf) + JIT_PROLOG_SIZE - reg, prolog, reg);
   255  	return (void *)(((unsigned char *)buf) + JIT_PROLOG_SIZE - reg);
   256  }
   257  
   258  void _jit_gen_epilog(jit_gencode_t gen, jit_function_t func)
   259  {
   260  	jit_nint pop_bytes = 0;
   261  	int reg, offset;
   262  	unsigned char *inst;
   263  	int struct_return_offset = 0;
   264  	void **fixup;
   265  	void **next;
   266  
   267  	/* Check if there is sufficient space for the epilog */
   268  	_jit_gen_check_space(gen, 48);
   269  
   270  #if JIT_APPLY_X86_FASTCALL == 1
   271  	/* Determine the number of parameter bytes to pop when we return */
   272  	{
   273  		jit_type_t signature;
   274  		unsigned int num_params;
   275  		unsigned int param;
   276  		signature = func->signature;
   277  		if(jit_type_get_abi(signature) == jit_abi_stdcall ||
   278  		   jit_type_get_abi(signature) == jit_abi_fastcall)
   279  		{
   280  			if(func->nested_parent)
   281  			{
   282  				pop_bytes += sizeof(void *);
   283  			}
   284  			if(jit_type_return_via_pointer(jit_type_get_return(signature)))
   285  			{
   286  				struct_return_offset = 2 * sizeof(void *) + pop_bytes;
   287  				pop_bytes += sizeof(void *);
   288  			}
   289  			num_params = jit_type_num_params(signature);
   290  			for(param = 0; param < num_params; ++param)
   291  			{
   292  				pop_bytes += ROUND_STACK
   293  						(jit_type_get_size
   294  							(jit_type_get_param(signature, param)));
   295  			}
   296  			if(jit_type_get_abi(signature) == jit_abi_fastcall)
   297  			{
   298  				/* The first two words are in fastcall registers */
   299  				if(pop_bytes > (2 * sizeof(void *)))
   300  				{
   301  					pop_bytes -= 2 * sizeof(void *);
   302  				}
   303  				else
   304  				{
   305  					pop_bytes = 0;
   306  				}
   307  				struct_return_offset = 0;
   308  			}
   309  		}
   310  		else if(!(func->nested_parent) &&
   311  				jit_type_return_via_pointer(jit_type_get_return(signature)))
   312  		{
   313  #if JIT_APPLY_X86_POP_STRUCT_RETURN == 1
   314  			pop_bytes += sizeof(void *);
   315  #endif
   316  			struct_return_offset = 2 * sizeof(void *);
   317  		}
   318  	}
   319  #else
   320  	{
   321  		/* We only need to pop structure pointers in non-nested functions */
   322  		jit_type_t signature;
   323  		signature = func->signature;
   324  		if(!(func->nested_parent) &&
   325  		   jit_type_return_via_pointer(jit_type_get_return(signature)))
   326  		{
   327  #if JIT_APPLY_X86_POP_STRUCT_RETURN == 1
   328  			pop_bytes += sizeof(void *);
   329  #endif
   330  			struct_return_offset = 2 * sizeof(void *);
   331  		}
   332  	}
   333  #endif
   334  
   335  	/* Perform fixups on any blocks that jump to the epilog */
   336  	inst = gen->ptr;
   337  	fixup = (void **)(gen->epilog_fixup);
   338  	while(fixup != 0)
   339  	{
   340  		next = (void **)(fixup[0]);
   341  		fixup[0] = (void *)(((jit_nint)inst) - ((jit_nint)fixup) - 4);
   342  		fixup = next;
   343  	}
   344  	gen->epilog_fixup = 0;
   345  
   346  	/* If we are returning a structure via a pointer, then copy
   347  	   the pointer value into EAX when we return */
   348  	if(struct_return_offset != 0)
   349  	{
   350  		x86_mov_reg_membase(inst, X86_EAX, X86_EBP, struct_return_offset, 4);
   351  	}
   352  
   353  	/* Restore the callee save registers that we used */
   354  	if(gen->stack_changed)
   355  	{
   356  		offset = -(func->builder->frame_size);
   357  		for(reg = 0; reg <= 7; ++reg)
   358  		{
   359  			if(jit_reg_is_used(gen->touched, reg) &&
   360  			   (_jit_reg_info[reg].flags & JIT_REG_CALL_USED) == 0)
   361  			{
   362  				offset -= sizeof(void *);
   363  				x86_mov_reg_membase(inst, _jit_reg_info[reg].cpu_reg,
   364  									X86_EBP, offset, sizeof(void *));
   365  			}
   366  		}
   367  	}
   368  	else
   369  	{
   370  		for(reg = 7; reg >= 0; --reg)
   371  		{
   372  			if(jit_reg_is_used(gen->touched, reg) &&
   373  			   (_jit_reg_info[reg].flags & JIT_REG_CALL_USED) == 0)
   374  			{
   375  				x86_pop_reg(inst, _jit_reg_info[reg].cpu_reg);
   376  			}
   377  		}
   378  	}
   379  
   380  	/* Pop the stack frame and restore the saved copy of ebp */
   381  	if(gen->stack_changed || func->builder->frame_size > 0)
   382  	{
   383  		x86_mov_reg_reg(inst, X86_ESP, X86_EBP, sizeof(void *));
   384  	}
   385  	x86_pop_reg(inst, X86_EBP);
   386  
   387  	/* Return from the current function */
   388  	if(pop_bytes > 0)
   389  	{
   390  		x86_ret_imm(inst, pop_bytes);
   391  	}
   392  	else
   393  	{
   394  		x86_ret(inst);
   395  	}
   396  	gen->ptr = inst;
   397  }
   398  
   399  #if 0
   400  /*
   401   * The x86 backend does not need this function because it uses
   402   * _jit_create_indirector() instead.
   403   */
   404  void *_jit_gen_redirector(jit_gencode_t gen, jit_function_t func)
   405  {
   406  	void *ptr, *entry;
   407  	_jit_gen_check_space(gen, 8);
   408  	ptr = (void *)&(func->entry_point);
   409  	entry = gen->ptr;
   410  	x86_jump_mem(gen->ptr, ptr);
   411  	return entry;
   412  }
   413  #endif
   414  
   415  /*
   416   * Setup or teardown the x86 code output process.
   417   */
   418  #define	jit_cache_setup_output(needed)			\
   419  	unsigned char *inst = gen->ptr;		\
   420  	_jit_gen_check_space(gen, (needed))
   421  
   422  #define	jit_cache_end_output()	\
   423  	gen->ptr = inst
   424  
   425  /*
   426   * Get a temporary register that isn't one of the specified registers.
   427   */
   428  static int get_temp_reg(int reg1, int reg2, int reg3)
   429  {
   430  	if(reg1 != X86_EAX && reg2 != X86_EAX && reg3 != X86_EAX)
   431  	{
   432  		return X86_EAX;
   433  	}
   434  	if(reg1 != X86_EDX && reg2 != X86_EDX && reg3 != X86_EDX)
   435  	{
   436  		return X86_EDX;
   437  	}
   438  	if(reg1 != X86_ECX && reg2 != X86_ECX && reg3 != X86_ECX)
   439  	{
   440  		return X86_ECX;
   441  	}
   442  	if(reg1 != X86_EBX && reg2 != X86_EBX && reg3 != X86_EBX)
   443  	{
   444  		return X86_EBX;
   445  	}
   446  	if(reg1 != X86_ESI && reg2 != X86_ESI && reg3 != X86_ESI)
   447  	{
   448  		return X86_ESI;
   449  	}
   450  	return X86_EDI;
   451  }
   452  
   453  /*
   454   * Store a byte value to a membase address.
   455   */
   456  static unsigned char *mov_membase_reg_byte
   457  			(unsigned char *inst, int basereg, int offset, int srcreg)
   458  {
   459  	if(srcreg == X86_EAX || srcreg == X86_EBX ||
   460  	   srcreg == X86_ECX || srcreg == X86_EDX)
   461  	{
   462  		x86_mov_membase_reg(inst, basereg, offset, srcreg, 1);
   463  	}
   464  	else if(basereg != X86_EAX)
   465  	{
   466  		x86_push_reg(inst, X86_EAX);
   467  		x86_mov_reg_reg(inst, X86_EAX, srcreg, 4);
   468  		x86_mov_membase_reg(inst, basereg, offset, X86_EAX, 1);
   469  		x86_pop_reg(inst, X86_EAX);
   470  	}
   471  	else
   472  	{
   473  		x86_push_reg(inst, X86_EDX);
   474  		x86_mov_reg_reg(inst, X86_EDX, srcreg, 4);
   475  		x86_mov_membase_reg(inst, basereg, offset, X86_EDX, 1);
   476  		x86_pop_reg(inst, X86_EDX);
   477  	}
   478  	return inst;
   479  }
   480  
   481  /*
   482   * Store a small structure from registers to a pointer.  The base
   483   * register must not be either "reg" or "other_reg".
   484   */
   485  static unsigned char *store_small_struct
   486  	(unsigned char *inst, int reg, int other_reg,
   487  	 int base_reg, jit_nint offset, jit_nint size, int preserve)
   488  {
   489  	switch(size)
   490  	{
   491  		case 1:
   492  		{
   493  			inst = mov_membase_reg_byte(inst, base_reg, offset, reg);
   494  		}
   495  		break;
   496  
   497  		case 2:
   498  		{
   499  			x86_mov_membase_reg(inst, base_reg, offset, reg, 2);
   500  		}
   501  		break;
   502  
   503  		case 3:
   504  		{
   505  			if(preserve)
   506  			{
   507  				x86_push_reg(inst, reg);
   508  			}
   509  			x86_mov_membase_reg(inst, base_reg, offset, reg, 2);
   510  			x86_shift_reg_imm(inst, reg, X86_SHR, 16);
   511  			inst = mov_membase_reg_byte(inst, base_reg, offset + 2, reg);
   512  			if(preserve)
   513  			{
   514  				x86_pop_reg(inst, reg);
   515  			}
   516  		}
   517  		break;
   518  
   519  		case 4:
   520  		{
   521  			x86_mov_membase_reg(inst, base_reg, offset, reg, 4);
   522  		}
   523  		break;
   524  
   525  		case 5:
   526  		{
   527  			x86_mov_membase_reg(inst, base_reg, offset, reg, 4);
   528  			inst = mov_membase_reg_byte(inst, base_reg, offset + 4, other_reg);
   529  		}
   530  		break;
   531  
   532  		case 6:
   533  		{
   534  			x86_mov_membase_reg(inst, base_reg, offset, reg, 4);
   535  			x86_mov_membase_reg(inst, base_reg, offset + 4, other_reg, 2);
   536  		}
   537  		break;
   538  
   539  		case 7:
   540  		{
   541  			if(preserve)
   542  			{
   543  				x86_push_reg(inst, other_reg);
   544  			}
   545  			x86_mov_membase_reg(inst, base_reg, offset, reg, 4);
   546  			x86_mov_membase_reg(inst, base_reg, offset + 4, other_reg, 2);
   547  			x86_shift_reg_imm(inst, other_reg, X86_SHR, 16);
   548  			inst = mov_membase_reg_byte(inst, base_reg, offset + 6, other_reg);
   549  			if(preserve)
   550  			{
   551  				x86_pop_reg(inst, other_reg);
   552  			}
   553  		}
   554  		break;
   555  
   556  		case 8:
   557  		{
   558  			x86_mov_membase_reg(inst, base_reg, offset, reg, 4);
   559  			x86_mov_membase_reg(inst, base_reg, offset + 4, other_reg, 4);
   560  		}
   561  		break;
   562  	}
   563  	return inst;
   564  }
   565  
   566  void _jit_gen_spill_reg(jit_gencode_t gen, int reg,
   567  						int other_reg, jit_value_t value)
   568  {
   569  	int offset;
   570  
   571  	/* Make sure that we have sufficient space */
   572  	jit_cache_setup_output(16);
   573  
   574  	/* If the value is associated with a global register, then copy to that */
   575  	if(value->has_global_register)
   576  	{
   577  		reg = _jit_reg_info[reg].cpu_reg;
   578  		other_reg = _jit_reg_info[value->global_reg].cpu_reg;
   579  		x86_mov_reg_reg(inst, other_reg, reg, sizeof(void *));
   580  		jit_cache_end_output();
   581  		return;
   582  	}
   583  
   584  	/* Fix the value in place within the local variable frame */
   585  	_jit_gen_fix_value(value);
   586  
   587  	/* Output an appropriate instruction to spill the value */
   588  	offset = (int)(value->frame_offset);
   589  	if(IS_WORD_REG(reg))
   590  	{
   591  		/* Spill a word register.  If the value is smaller than a word,
   592  		   then we write the entire word.  The local stack frame is
   593  		   allocated such that the extra bytes will be simply ignored */
   594  		reg = _jit_reg_info[reg].cpu_reg;
   595  		x86_mov_membase_reg(inst, X86_EBP, offset, reg, 4);
   596  		if(other_reg != -1)
   597  		{
   598  			/* Spill the other word register in a pair */
   599  			reg = _jit_reg_info[other_reg].cpu_reg;
   600  			offset += sizeof(void *);
   601  			x86_mov_membase_reg(inst, X86_EBP, offset, reg, 4);
   602  		}
   603  	}
   604  	else
   605  	{
   606  		/* Spill the top of the floating-point register stack */
   607  		switch(jit_type_normalize(value->type)->kind)
   608  		{
   609  			case JIT_TYPE_FLOAT32:
   610  			{
   611  				x86_fst_membase(inst, X86_EBP, offset, 0, 1);
   612  			}
   613  			break;
   614  
   615  			case JIT_TYPE_FLOAT64:
   616  			{
   617  				x86_fst_membase(inst, X86_EBP, offset, 1, 1);
   618  			}
   619  			break;
   620  
   621  			case JIT_TYPE_NFLOAT:
   622  			{
   623  				x86_fst80_membase(inst, X86_EBP, offset);
   624  			}
   625  			break;
   626  		}
   627  	}
   628  
   629  	/* End the code output process */
   630  	jit_cache_end_output();
   631  }
   632  
   633  void
   634  _jit_gen_free_reg(jit_gencode_t gen, int reg, int other_reg, int value_used)
   635  {
   636  	/* We only need to take explicit action if we are freeing a
   637  	   floating-point register whose value hasn't been used yet */
   638  	if(!value_used && IS_FLOAT_REG(reg))
   639  	{
   640  		_jit_gen_check_space(gen, 2);
   641  		x86_fstp(gen->ptr, reg - X86_REG_ST0);
   642  	}
   643  }
   644  
   645  static int
   646  fp_stack_index(jit_gencode_t gen, int reg)
   647  {
   648  	return gen->reg_stack_top - reg - 1;
   649  }
   650  
   651  void
   652  _jit_gen_exch_top(jit_gencode_t gen, int reg)
   653  {
   654  	if(IS_FLOAT_REG(reg))
   655  	{
   656  		jit_cache_setup_output(2);
   657  		x86_fxch(inst, fp_stack_index(gen, reg));
   658  		jit_cache_end_output();
   659  	}
   660  }
   661  
   662  void
   663  _jit_gen_move_top(jit_gencode_t gen, int reg)
   664  {
   665  	if(IS_FLOAT_REG(reg))
   666  	{
   667  		jit_cache_setup_output(2);
   668  		x86_fstp(inst, fp_stack_index(gen, reg));
   669  		jit_cache_end_output();
   670  	}
   671  }
   672  
   673  void
   674  _jit_gen_spill_top(jit_gencode_t gen, int reg, jit_value_t value, int pop)
   675  {
   676  	int offset;
   677  	if(IS_FLOAT_REG(reg))
   678  	{
   679  		/* Make sure that we have sufficient space */
   680  		jit_cache_setup_output(16);
   681  
   682  		/* Fix the value in place within the local variable frame */
   683  		_jit_gen_fix_value(value);
   684  
   685  		/* Output an appropriate instruction to spill the value */
   686  		offset = (int)(value->frame_offset);
   687  
   688  		/* Spill the top of the floating-point register stack */
   689  		switch(jit_type_normalize(value->type)->kind)
   690  		{
   691  			case JIT_TYPE_FLOAT32:
   692  			{
   693  				x86_fst_membase(inst, X86_EBP, offset, 0, pop);
   694  			}
   695  			break;
   696  
   697  			case JIT_TYPE_FLOAT64:
   698  			{
   699  				x86_fst_membase(inst, X86_EBP, offset, 1, pop);
   700  			}
   701  			break;
   702  
   703  			case JIT_TYPE_NFLOAT:
   704  			{
   705  				x86_fst80_membase(inst, X86_EBP, offset);
   706  				if(!pop)
   707  				{
   708  					x86_fld80_membase(inst, X86_EBP, offset);
   709  				}
   710  			}
   711  			break;
   712  		}
   713  
   714  		/* End the code output process */
   715  		jit_cache_end_output();
   716  	}
   717  }
   718  
   719  void
   720  _jit_gen_load_value(jit_gencode_t gen, int reg, int other_reg, jit_value_t value)
   721  {
   722  	jit_type_t type;
   723  	int src_reg, other_src_reg;
   724  	void *ptr;
   725  	int offset;
   726  
   727  	/* Make sure that we have sufficient space */
   728  	jit_cache_setup_output(16);
   729  
   730  	type = jit_type_normalize(value->type);
   731  
   732  	/* Load zero */
   733  	if(value->is_constant)
   734  	{
   735  		switch(type->kind)
   736  		{
   737  			case JIT_TYPE_SBYTE:
   738  			case JIT_TYPE_UBYTE:
   739  			case JIT_TYPE_SHORT:
   740  			case JIT_TYPE_USHORT:
   741  			case JIT_TYPE_INT:
   742  			case JIT_TYPE_UINT:
   743  			{
   744  				if((jit_nint)(value->address) == 0)
   745  				{
   746  					x86_clear_reg(inst, _jit_reg_info[reg].cpu_reg);
   747  				}
   748  				else
   749  				{
   750  					x86_mov_reg_imm(inst, _jit_reg_info[reg].cpu_reg,
   751  							(jit_nint)(value->address));
   752  				}
   753  			}
   754  			break;
   755  
   756  			case JIT_TYPE_LONG:
   757  			case JIT_TYPE_ULONG:
   758  			{
   759  				jit_long long_value;
   760  				long_value = jit_value_get_long_constant(value);
   761  				if(long_value == 0)
   762  				{
   763  #ifdef JIT_NATIVE_INT64
   764  					x86_clear_reg(inst, _jit_reg_info[reg].cpu_reg);
   765  #else
   766  					x86_clear_reg(inst, _jit_reg_info[reg].cpu_reg);
   767  					x86_clear_reg(inst, _jit_reg_info[other_reg].cpu_reg);
   768  #endif
   769  				}
   770  				else
   771  				{
   772  #ifdef JIT_NATIVE_INT64
   773  					x86_mov_reg_imm(inst, _jit_reg_info[reg].cpu_reg,
   774  							(jit_nint)long_value);
   775  #else
   776  					x86_mov_reg_imm(inst, _jit_reg_info[reg].cpu_reg,
   777  							(jit_int)long_value);
   778  					x86_mov_reg_imm(inst, _jit_reg_info[other_reg].cpu_reg,
   779  							(jit_int)(long_value >> 32));
   780  #endif
   781  				}
   782  			}
   783  			break;
   784  
   785  			case JIT_TYPE_FLOAT32:
   786  			{
   787  				jit_float32 float32_value;
   788  				float32_value = jit_value_get_float32_constant(value);
   789  				if(IS_WORD_REG(reg))
   790  				{
   791  					union
   792  					{
   793  						jit_float32 float32_value;
   794  						jit_int int_value;
   795  					} un;
   796  
   797  					un.float32_value = float32_value;
   798  					x86_mov_reg_imm(inst, _jit_reg_info[reg].cpu_reg, un.int_value);
   799  				}
   800  				else
   801  				{
   802  					if(float32_value == (jit_float32) 0.0)
   803  					{
   804  						x86_fldz(inst);
   805  					}
   806  					else if(float32_value == (jit_float32) 1.0)
   807  					{
   808  						x86_fld1(inst);
   809  					}
   810  					else
   811  					{
   812  						ptr = _jit_gen_alloc(gen, sizeof(jit_float32));
   813  						jit_memcpy(ptr, &float32_value, sizeof(float32_value));
   814  						x86_fld(inst, ptr, 0);
   815  					}
   816  				}
   817  			}
   818  			break;
   819  
   820  			case JIT_TYPE_FLOAT64:
   821  			{
   822  				jit_float64 float64_value;
   823  				float64_value = jit_value_get_float64_constant(value);
   824  				if(IS_WORD_REG(reg))
   825  				{
   826  					union
   827  					{
   828  						jit_float64 float64_value;
   829  						jit_int int_value[2];
   830  					} un;
   831  
   832  					un.float64_value = float64_value;
   833  					x86_mov_reg_imm(inst, _jit_reg_info[reg].cpu_reg,
   834  							un.int_value[0]);
   835  					x86_mov_reg_imm(inst, _jit_reg_info[other_reg].cpu_reg,
   836  							un.int_value[1]);
   837  				}
   838  				else
   839  				{
   840  					if(float64_value == (jit_float64) 0.0)
   841  					{
   842  						x86_fldz(inst);
   843  					}
   844  					else if(float64_value == (jit_float64) 1.0)
   845  					{
   846  						x86_fld1(inst);
   847  					}
   848  					else
   849  					{
   850  						ptr = _jit_gen_alloc(gen, sizeof(jit_float64));
   851  						jit_memcpy(ptr, &float64_value, sizeof(float64_value));
   852  						x86_fld(inst, ptr, 1);
   853  					}
   854  				}
   855  			}
   856  			break;
   857  
   858  			case JIT_TYPE_NFLOAT:
   859  			{
   860  				jit_nfloat nfloat_value;
   861  				nfloat_value = jit_value_get_nfloat_constant(value);
   862  				if(IS_WORD_REG(reg) && sizeof(jit_nfloat) == sizeof(jit_float64))
   863  				{
   864  					union
   865  					{
   866  						jit_nfloat nfloat_value;
   867  						jit_int int_value[2];
   868  					} un;
   869  
   870  					un.nfloat_value = nfloat_value;
   871  					x86_mov_reg_imm(inst, _jit_reg_info[reg].cpu_reg,
   872  							un.int_value[0]);
   873  					x86_mov_reg_imm(inst, _jit_reg_info[other_reg].cpu_reg,
   874  							un.int_value[1]);
   875  				}
   876  				else
   877  				{
   878  					if(nfloat_value == (jit_nfloat) 0.0)
   879  					{
   880  						x86_fldz(inst);
   881  					}
   882  					else if(nfloat_value == (jit_nfloat) 1.0)
   883  					{
   884  						x86_fld1(inst);
   885  					}
   886  					else
   887  					{
   888  						ptr = _jit_gen_alloc(gen, sizeof(jit_nfloat));
   889  						jit_memcpy(ptr, &nfloat_value, sizeof(nfloat_value));
   890  						if(sizeof(jit_nfloat) == sizeof(jit_float64))
   891  						{
   892  							x86_fld(inst, ptr, 1);
   893  						}
   894  						else
   895  						{
   896  							x86_fld80_mem(inst, ptr);
   897  						}
   898  					}
   899  				}
   900  			}
   901  			break;
   902  		}
   903  	}
   904  	else if(value->in_register || value->in_global_register)
   905  	{
   906  		if(value->in_register)
   907  		{
   908  			src_reg = value->reg;
   909  			if(other_reg >= 0)
   910  			{
   911  				other_src_reg = jit_reg_other_reg(src_reg);
   912  			}
   913  			else
   914  			{
   915  				other_src_reg = -1;
   916  			}
   917  		}
   918  		else
   919  		{
   920  			src_reg = value->global_reg;
   921  			other_src_reg = -1;
   922  		}
   923  
   924  		switch(type->kind)
   925  		{
   926  #if 0
   927  			case JIT_TYPE_SBYTE:
   928  			{
   929  				x86_widen_reg(inst, _jit_reg_info[reg].cpu_reg,
   930  					      _jit_reg_info[src_reg].cpu_reg, 1, 0);
   931  			}
   932  			break;
   933  
   934  			case JIT_TYPE_UBYTE:
   935  			{
   936  				x86_widen_reg(inst, _jit_reg_info[reg].cpu_reg,
   937  					      _jit_reg_info[src_reg].cpu_reg, 0, 0);
   938  			}
   939  			break;
   940  
   941  			case JIT_TYPE_SHORT:
   942  			{
   943  				x86_widen_reg(inst, _jit_reg_info[reg].cpu_reg,
   944  					      _jit_reg_info[src_reg].cpu_reg, 1, 1);
   945  			}
   946  			break;
   947  
   948  			case JIT_TYPE_USHORT:
   949  			{
   950  				x86_widen_reg(inst, _jit_reg_info[reg].cpu_reg,
   951  					      _jit_reg_info[src_reg].cpu_reg, 0, 1);
   952  			}
   953  			break;
   954  #else
   955  			case JIT_TYPE_SBYTE:
   956  			case JIT_TYPE_UBYTE:
   957  			case JIT_TYPE_SHORT:
   958  			case JIT_TYPE_USHORT:
   959  #endif
   960  			case JIT_TYPE_INT:
   961  			case JIT_TYPE_UINT:
   962  			{
   963  				x86_mov_reg_reg(inst, _jit_reg_info[reg].cpu_reg,
   964  						_jit_reg_info[src_reg].cpu_reg, 4);
   965  			}
   966  			break;
   967  
   968  			case JIT_TYPE_LONG:
   969  			case JIT_TYPE_ULONG:
   970  			{
   971  #ifdef JIT_NATIVE_INT64
   972  				x86_mov_reg_reg(inst, _jit_reg_info[reg].cpu_reg,
   973  						_jit_reg_info[src_reg].cpu_reg, 8);
   974  #else
   975  				x86_mov_reg_reg(inst, _jit_reg_info[reg].cpu_reg,
   976  						_jit_reg_info[src_reg].cpu_reg, 4);
   977  				x86_mov_reg_reg(inst, _jit_reg_info[other_reg].cpu_reg,
   978  						_jit_reg_info[other_src_reg].cpu_reg, 4);
   979  #endif
   980  			}
   981  			break;
   982  
   983  			case JIT_TYPE_FLOAT32:
   984  			case JIT_TYPE_FLOAT64:
   985  			case JIT_TYPE_NFLOAT:
   986  			{
   987  				if(!IS_WORD_REG(reg))
   988  				{
   989  					x86_fld_reg(inst, fp_stack_index(gen, src_reg));
   990  				}
   991  			}
   992  			break;
   993  		}
   994  	}
   995  	else
   996  	{
   997  		/* Fix the position of the value in the stack frame */
   998  		_jit_gen_fix_value(value);
   999  		offset = (int)(value->frame_offset);
  1000  
  1001  		/* Load the value into the specified register */
  1002  		switch(type->kind)
  1003  		{
  1004  			case JIT_TYPE_SBYTE:
  1005  			{
  1006  				x86_widen_membase(inst, _jit_reg_info[reg].cpu_reg,
  1007  						  X86_EBP, offset, 1, 0);
  1008  			}
  1009  			break;
  1010  
  1011  			case JIT_TYPE_UBYTE:
  1012  			{
  1013  				x86_widen_membase(inst, _jit_reg_info[reg].cpu_reg,
  1014  						  X86_EBP, offset, 0, 0);
  1015  			}
  1016  			break;
  1017  
  1018  			case JIT_TYPE_SHORT:
  1019  			{
  1020  				x86_widen_membase(inst, _jit_reg_info[reg].cpu_reg,
  1021  						  X86_EBP, offset, 1, 1);
  1022  			}
  1023  			break;
  1024  
  1025  			case JIT_TYPE_USHORT:
  1026  			{
  1027  				x86_widen_membase(inst, _jit_reg_info[reg].cpu_reg,
  1028  						  X86_EBP, offset, 0, 1);
  1029  			}
  1030  			break;
  1031  
  1032  			case JIT_TYPE_INT:
  1033  			case JIT_TYPE_UINT:
  1034  			{
  1035  				x86_mov_reg_membase(inst, _jit_reg_info[reg].cpu_reg,
  1036  						    X86_EBP, offset, 4);
  1037  			}
  1038  			break;
  1039  
  1040  			case JIT_TYPE_LONG:
  1041  			case JIT_TYPE_ULONG:
  1042  			{
  1043  #ifdef JIT_NATIVE_INT64
  1044  				x86_mov_reg_membase(inst, _jit_reg_info[reg].cpu_reg,
  1045  						    X86_EBP, offset, 8);
  1046  #else
  1047  				x86_mov_reg_membase(inst, _jit_reg_info[reg].cpu_reg,
  1048  						    X86_EBP, offset, 4);
  1049  				x86_mov_reg_membase(inst, _jit_reg_info[other_reg].cpu_reg,
  1050  						    X86_EBP, offset + 4, 4);
  1051  #endif
  1052  			}
  1053  			break;
  1054  
  1055  			case JIT_TYPE_FLOAT32:
  1056  			{
  1057  				if(IS_WORD_REG(reg))
  1058  				{
  1059  					x86_mov_reg_membase(inst, _jit_reg_info[reg].cpu_reg,
  1060  							    X86_EBP, offset, 4);
  1061  				}
  1062  				else
  1063  				{
  1064  					x86_fld_membase(inst, X86_EBP, offset, 0);
  1065  				}
  1066  			}
  1067  			break;
  1068  
  1069  			case JIT_TYPE_FLOAT64:
  1070  			{
  1071  				if(IS_WORD_REG(reg))
  1072  				{
  1073  					x86_mov_reg_membase(inst, _jit_reg_info[reg].cpu_reg,
  1074  							    X86_EBP, offset, 4);
  1075  					x86_mov_reg_membase(inst, _jit_reg_info[other_reg].cpu_reg,
  1076  							    X86_EBP, offset + 4, 4);
  1077  				}
  1078  				else
  1079  				{
  1080  					x86_fld_membase(inst, X86_EBP, offset, 1);
  1081  				}
  1082  			}
  1083  			break;
  1084  
  1085  			case JIT_TYPE_NFLOAT:
  1086  			{
  1087  				if(IS_WORD_REG(reg) && sizeof(jit_nfloat) == sizeof(jit_float64))
  1088  				{
  1089  					x86_mov_reg_membase(inst, _jit_reg_info[reg].cpu_reg,
  1090  							    X86_EBP, offset, 4);
  1091  					x86_mov_reg_membase(inst, _jit_reg_info[other_reg].cpu_reg,
  1092  							    X86_EBP, offset + 4, 4);
  1093  				}
  1094  				else if(sizeof(jit_nfloat) == sizeof(jit_float64))
  1095  				{
  1096  					x86_fld_membase(inst, X86_EBP, offset, 1);
  1097  				}
  1098  				else
  1099  				{
  1100  					x86_fld80_membase(inst, X86_EBP, offset);
  1101  				}
  1102  			}
  1103  			break;
  1104  		}
  1105  	}
  1106  
  1107  	/* End the code output process */
  1108  	jit_cache_end_output();
  1109  }
  1110  
  1111  void _jit_gen_spill_global(jit_gencode_t gen, int reg, jit_value_t value)
  1112  {
  1113  	jit_cache_setup_output(16);
  1114  	if(value)
  1115  	{
  1116  		_jit_gen_fix_value(value);
  1117  		x86_mov_membase_reg(inst,
  1118  			 X86_EBP, value->frame_offset,
  1119  			_jit_reg_info[value->global_reg].cpu_reg, sizeof(void *));
  1120  	}
  1121  	else
  1122  	{
  1123  		x86_push_reg(inst, _jit_reg_info[reg].cpu_reg);
  1124  	}
  1125  	jit_cache_end_output();
  1126  }
  1127  
  1128  void _jit_gen_load_global(jit_gencode_t gen, int reg, jit_value_t value)
  1129  {
  1130  	jit_cache_setup_output(16);
  1131  	if(value)
  1132  	{
  1133  		x86_mov_reg_membase(inst,
  1134  			_jit_reg_info[value->global_reg].cpu_reg,
  1135  			X86_EBP, value->frame_offset, sizeof(void *));
  1136  	}
  1137  	else
  1138  	{
  1139  		x86_pop_reg(inst, _jit_reg_info[reg].cpu_reg);
  1140  	}
  1141  	jit_cache_end_output();
  1142  }
  1143  
  1144  void _jit_gen_fix_value(jit_value_t value)
  1145  {
  1146  	if(!(value->has_frame_offset) && !(value->is_constant))
  1147  	{
  1148  		jit_nint size = (jit_nint)(ROUND_STACK(jit_type_get_size(value->type)));
  1149  		value->block->func->builder->frame_size += size;
  1150  		value->frame_offset = -(value->block->func->builder->frame_size);
  1151  		value->has_frame_offset = 1;
  1152  	}
  1153  }
  1154  
  1155  /*
  1156   * Set a register value based on a condition code.
  1157   */
  1158  static unsigned char *setcc_reg
  1159  	(unsigned char *inst, int reg, int cond, int is_signed)
  1160  {
  1161  	if(reg == X86_EAX || reg == X86_EBX || reg == X86_ECX || reg == X86_EDX)
  1162  	{
  1163  		/* Use a SETcc instruction if we have a basic register */
  1164  		x86_set_reg(inst, cond, reg, is_signed);
  1165  		x86_widen_reg(inst, reg, reg, 0, 0);
  1166  	}
  1167  	else
  1168  	{
  1169  		/* The register is not useable as an 8-bit destination */
  1170  		unsigned char *patch1, *patch2;
  1171  		patch1 = inst;
  1172  		x86_branch8(inst, cond, 0, is_signed);
  1173  		x86_clear_reg(inst, reg);
  1174  		patch2 = inst;
  1175  		x86_jump8(inst, 0);
  1176  		x86_patch(patch1, inst);
  1177  		x86_mov_reg_imm(inst, reg, 1);
  1178  		x86_patch(patch2, inst);
  1179  	}
  1180  	return inst;
  1181  }
  1182  
  1183  /*
  1184   * Get the long form of a branch opcode.
  1185   */
  1186  static int long_form_branch(int opcode)
  1187  {
  1188  	if(opcode == 0xEB)
  1189  	{
  1190  		return 0xE9;
  1191  	}
  1192  	else
  1193  	{
  1194  		return opcode + 0x0F10;
  1195  	}
  1196  }
  1197  
  1198  /*
  1199   * Output a branch instruction.
  1200   */
  1201  static unsigned char *output_branch
  1202  	(jit_function_t func, unsigned char *inst, int opcode, jit_insn_t insn)
  1203  {
  1204  	jit_block_t block;
  1205  	int offset;
  1206  	if((insn->flags & JIT_INSN_VALUE1_IS_LABEL) != 0)
  1207  	{
  1208  		/* "address_of_label" instruction */
  1209  		block = jit_block_from_label(func, (jit_label_t)(insn->value1));
  1210  	}
  1211  	else
  1212  	{
  1213  		block = jit_block_from_label(func, (jit_label_t)(insn->dest));
  1214  	}
  1215  	if(!block)
  1216  	{
  1217  		return inst;
  1218  	}
  1219  	if(block->address)
  1220  	{
  1221  		/* We already know the address of the block */
  1222  		offset = ((unsigned char *)(block->address)) - (inst + 2);
  1223  		if(x86_is_imm8(offset))
  1224  		{
  1225  			/* We can output a short-form backwards branch */
  1226  			*inst++ = (unsigned char)opcode;
  1227  			*inst++ = (unsigned char)offset;
  1228  		}
  1229  		else
  1230  		{
  1231  			/* We need to output a long-form backwards branch */
  1232  			offset -= 3;
  1233  			opcode = long_form_branch(opcode);
  1234  			if(opcode < 256)
  1235  			{
  1236  				*inst++ = (unsigned char)opcode;
  1237  			}
  1238  			else
  1239  			{
  1240  				*inst++ = (unsigned char)(opcode >> 8);
  1241  				*inst++ = (unsigned char)opcode;
  1242  				--offset;
  1243  			}
  1244  			x86_imm_emit32(inst, offset);
  1245  		}
  1246  	}
  1247  	else
  1248  	{
  1249  		/* Output a placeholder and record on the block's fixup list */
  1250  		opcode = long_form_branch(opcode);
  1251  		if(opcode < 256)
  1252  		{
  1253  			*inst++ = (unsigned char)opcode;
  1254  		}
  1255  		else
  1256  		{
  1257  			*inst++ = (unsigned char)(opcode >> 8);
  1258  			*inst++ = (unsigned char)opcode;
  1259  		}
  1260  		x86_imm_emit32(inst, (int)(block->fixup_list));
  1261  		block->fixup_list = (void *)(inst - 4);
  1262  	}
  1263  	return inst;
  1264  }
  1265  
  1266  /*
  1267   * Jump to the current function's epilog.
  1268   */
  1269  static unsigned char *
  1270  jump_to_epilog(jit_gencode_t gen, unsigned char *inst, jit_block_t block)
  1271  {
  1272  	/* If the epilog is the next thing that we will output,
  1273  	   then fall through to the epilog directly */
  1274  	if(_jit_block_is_final(block))
  1275  	{
  1276  		return inst;
  1277  	}
  1278  
  1279  	/* Output a placeholder for the jump and add it to the fixup list */
  1280  	*inst++ = (unsigned char)0xE9;
  1281  	x86_imm_emit32(inst, (int)(gen->epilog_fixup));
  1282  	gen->epilog_fixup = (void *)(inst - 4);
  1283  	return inst;
  1284  }
  1285  
  1286  /*
  1287   * Throw a builtin exception.
  1288   */
  1289  static unsigned char *
  1290  throw_builtin(unsigned char *inst, jit_function_t func, int type)
  1291  {
  1292  	/* We need to update "catch_pc" if we have a "try" block */
  1293  	if(func->builder->setjmp_value != 0)
  1294  	{
  1295  		_jit_gen_fix_value(func->builder->setjmp_value);
  1296  		if(func->builder->position_independent)
  1297  		{
  1298  			x86_call_imm(inst, 0);
  1299  			x86_pop_membase(inst, X86_EBP,
  1300  					func->builder->setjmp_value->frame_offset
  1301  					+ jit_jmp_catch_pc_offset);
  1302  		}
  1303  		else
  1304  		{
  1305  			int pc = (int) inst;
  1306  			x86_mov_membase_imm(inst, X86_EBP,
  1307  					    func->builder->setjmp_value->frame_offset
  1308  					    + jit_jmp_catch_pc_offset, pc, 4);
  1309  		}
  1310  	}
  1311  
  1312  	/* Push the exception type onto the stack */
  1313  	x86_push_imm(inst, type);
  1314  
  1315  	/* Call the "jit_exception_builtin" function, which will never return */
  1316  	x86_call_code(inst, jit_exception_builtin);
  1317  	return inst;
  1318  }
  1319  
  1320  /*
  1321   * Copy a block of memory that has a specific size.  Other than
  1322   * the parameter pointers, all registers must be unused at this point.
  1323   */
  1324  static unsigned char *memory_copy
  1325  	(jit_gencode_t gen, unsigned char *inst, int dreg, jit_nint doffset,
  1326  	 int sreg, jit_nint soffset, jit_nuint size)
  1327  {
  1328  	int temp_reg = get_temp_reg(dreg, sreg, -1);
  1329  	if(size <= 4 * sizeof(void *))
  1330  	{
  1331  		/* Use direct copies to copy the memory */
  1332  		int offset = 0;
  1333  		while(size >= sizeof(void *))
  1334  		{
  1335  			x86_mov_reg_membase(inst, temp_reg, sreg,
  1336  								soffset + offset, sizeof(void *));
  1337  			x86_mov_membase_reg(inst, dreg, doffset + offset,
  1338  							    temp_reg, sizeof(void *));
  1339  			size -= sizeof(void *);
  1340  			offset += sizeof(void *);
  1341  		}
  1342  	#ifdef JIT_NATIVE_INT64
  1343  		if(size >= 4)
  1344  		{
  1345  			x86_mov_reg_membase(inst, temp_reg, sreg, soffset + offset, 4);
  1346  			x86_mov_membase_reg(inst, dreg, doffset + offset, temp_reg, 4);
  1347  			size -= 4;
  1348  			offset += 4;
  1349  		}
  1350  	#endif
  1351  		if(size >= 2)
  1352  		{
  1353  			x86_mov_reg_membase(inst, temp_reg, sreg, soffset + offset, 2);
  1354  			x86_mov_membase_reg(inst, dreg, doffset + offset, temp_reg, 2);
  1355  			size -= 2;
  1356  			offset += 2;
  1357  		}
  1358  		if(size >= 1)
  1359  		{
  1360  			/* We assume that temp_reg is EAX, ECX, or EDX, which it
  1361  			   should be after calling "get_temp_reg" */
  1362  			x86_mov_reg_membase(inst, temp_reg, sreg, soffset + offset, 1);
  1363  			x86_mov_membase_reg(inst, dreg, doffset + offset, temp_reg, 1);
  1364  		}
  1365  	}
  1366  	else
  1367  	{
  1368  		/* Call out to "jit_memcpy" to effect the copy */
  1369  		x86_push_imm(inst, size);
  1370  		if(soffset == 0)
  1371  		{
  1372  			x86_push_reg(inst, sreg);
  1373  		}
  1374  		else
  1375  		{
  1376  			x86_lea_membase(inst, temp_reg, sreg, soffset);
  1377  			x86_push_reg(inst, temp_reg);
  1378  		}
  1379  		if(dreg != X86_ESP)
  1380  		{
  1381  			if(doffset == 0)
  1382  			{
  1383  				x86_push_reg(inst, dreg);
  1384  			}
  1385  			else
  1386  			{
  1387  				x86_lea_membase(inst, temp_reg, dreg, doffset);
  1388  				x86_push_reg(inst, temp_reg);
  1389  			}
  1390  		}
  1391  		else
  1392  		{
  1393  			/* Copying a structure value onto the stack */
  1394  			x86_lea_membase(inst, temp_reg, X86_ESP,
  1395  							doffset + 2 * sizeof(void *));
  1396  			x86_push_reg(inst, temp_reg);
  1397  		}
  1398  		x86_call_code(inst, jit_memcpy);
  1399  		x86_alu_reg_imm(inst, X86_ADD, X86_ESP, 3 * sizeof(void *));
  1400  	}
  1401  	return inst;
  1402  }
  1403  
  1404  #define	TODO()		\
  1405  	do { \
  1406  		fprintf(stderr, "TODO at %s, %d\n", __FILE__, (int)__LINE__); \
  1407  	} while (0)
  1408  
  1409  void _jit_gen_insn(jit_gencode_t gen, jit_function_t func,
  1410  				   jit_block_t block, jit_insn_t insn)
  1411  {
  1412  	switch(insn->opcode)
  1413  	{
  1414  	#define JIT_INCLUDE_RULES
  1415  	#include "jit-rules-x86.inc"
  1416  	#undef JIT_INCLUDE_RULES
  1417  
  1418  	default:
  1419  		{
  1420  			fprintf(stderr, "TODO(%x) at %s, %d\n",
  1421  				(int)(insn->opcode), __FILE__, (int)__LINE__);
  1422  		}
  1423  		break;
  1424  	}
  1425  }
  1426  
  1427  void _jit_gen_start_block(jit_gencode_t gen, jit_block_t block)
  1428  {
  1429  	void **fixup;
  1430  	void **next;
  1431  
  1432  	/* Set the address of this block */
  1433  	block->address = (void *)(gen->ptr);
  1434  
  1435  	/* If this block has pending fixups, then apply them now */
  1436  	fixup = (void **)(block->fixup_list);
  1437  	while(fixup != 0)
  1438  	{
  1439  		next = (void **)(fixup[0]);
  1440  		fixup[0] = (void *)
  1441  			(((jit_nint)(block->address)) - ((jit_nint)fixup) - 4);
  1442  		fixup = next;
  1443  	}
  1444  	block->fixup_list = 0;
  1445  
  1446  	fixup = (void**)(block->fixup_absolute_list);
  1447  	while(fixup != 0)
  1448  	{
  1449  		next = (void **)(fixup[0]);
  1450  		fixup[0] = (void *)((jit_nint)(block->address));
  1451  		fixup = next;
  1452  	}
  1453  	block->fixup_absolute_list = 0;
  1454  }
  1455  
  1456  void _jit_gen_end_block(jit_gencode_t gen, jit_block_t block)
  1457  {
  1458  	/* Nothing to do here for x86 */
  1459  }
  1460  
  1461  int _jit_gen_is_global_candidate(jit_type_t type)
  1462  {
  1463  	switch(jit_type_remove_tags(type)->kind)
  1464  	{
  1465  		case JIT_TYPE_INT:
  1466  		case JIT_TYPE_UINT:
  1467  		case JIT_TYPE_NINT:
  1468  		case JIT_TYPE_NUINT:
  1469  		case JIT_TYPE_PTR:
  1470  		case JIT_TYPE_SIGNATURE:	return 1;
  1471  	}
  1472  	return 0;
  1473  }
  1474  
  1475  int
  1476  _jit_reg_get_pair(jit_type_t type, int reg)
  1477  {
  1478  	type = jit_type_normalize(type);
  1479  	if(type)
  1480  	{
  1481  		if(type->kind == JIT_TYPE_LONG || type->kind == JIT_TYPE_ULONG)
  1482  		{
  1483  			return jit_reg_other_reg(reg);
  1484  		}
  1485  	}
  1486  	return -1;
  1487  }
  1488  
  1489  #endif /* JIT_BACKEND_X86 */