dotgnu-pnet-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[dotgnu-pnet-commits] libjit ChangeLog jit/jit-apply-x86-64.c jit/jit...


From: Klaus Treichel
Subject: [dotgnu-pnet-commits] libjit ChangeLog jit/jit-apply-x86-64.c jit/jit...
Date: Mon, 24 Mar 2008 12:42:51 +0000

CVSROOT:        /cvsroot/dotgnu-pnet
Module name:    libjit
Changes by:     Klaus Treichel <ktreichel>      08/03/24 12:42:51

Modified files:
        .              : ChangeLog 
        jit            : jit-apply-x86-64.c jit-apply-x86-64.h 
                         jit-gen-x86-64.h jit-rules-x86-64.c 
                         jit-rules-x86-64.ins 

Log message:
        Add more X86_64 support.

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/libjit/ChangeLog?cvsroot=dotgnu-pnet&r1=1.352&r2=1.353
http://cvs.savannah.gnu.org/viewcvs/libjit/jit/jit-apply-x86-64.c?cvsroot=dotgnu-pnet&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/libjit/jit/jit-apply-x86-64.h?cvsroot=dotgnu-pnet&r1=1.7&r2=1.8
http://cvs.savannah.gnu.org/viewcvs/libjit/jit/jit-gen-x86-64.h?cvsroot=dotgnu-pnet&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/libjit/jit/jit-rules-x86-64.c?cvsroot=dotgnu-pnet&r1=1.1&r2=1.2
http://cvs.savannah.gnu.org/viewcvs/libjit/jit/jit-rules-x86-64.ins?cvsroot=dotgnu-pnet&r1=1.1&r2=1.2

Patches:
Index: ChangeLog
===================================================================
RCS file: /cvsroot/dotgnu-pnet/libjit/ChangeLog,v
retrieving revision 1.352
retrieving revision 1.353
diff -u -b -r1.352 -r1.353
--- ChangeLog   24 Mar 2008 11:43:59 -0000      1.352
+++ ChangeLog   24 Mar 2008 12:42:50 -0000      1.353
@@ -2,6 +2,22 @@
 
        * jit/jit-function.c (cleanup_on_restart): Reset the epilog_fixup.
 
+       * jit/jit-apply-x86-64.c: Move parameter passing handling from
+       jit-rules-x86-64.c to this file because they are needed by apply too.
+
+       * jit/jit-apply-x86-64.h: Add declarations needed for parameter passing.
+
+       * jit/jit-gen-x86-64.h: Add macros for shift opcodes, register exchanges
+       and moves from general purpose register to xmm register and vice versa.
+
+       * jit/jit-rules-x86-64.c: Move parameter handling to jit-apply.x86-64.c.
+       Add handling of structs in _jit_gen_load_value and _spill_reg. Fix more
+       parameter passing issues.
+
+       * jit/jit-rules-x86-64.ins: Do some cleanup. Add casts to jit_nint when
+       checking for valid ranges. Add integer and long shift opcodes. Add
+       memset opcode.
+
 2008-03-04  Klaus Treichel  <address@hidden>
 
        * jit/Makefile.am: Add jit-rules-x86-64.inc to CLEANFILES to fix

Index: jit/jit-apply-x86-64.c
===================================================================
RCS file: /cvsroot/dotgnu-pnet/libjit/jit/jit-apply-x86-64.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- jit/jit-apply-x86-64.c      2 Mar 2008 17:07:06 -0000       1.2
+++ jit/jit-apply-x86-64.c      24 Mar 2008 12:42:51 -0000      1.3
@@ -28,6 +28,21 @@
 
 #include "jit-gen-x86-64.h"
 
+/*
+ * X86_64 argument types as specified in the X86_64 SysV ABI.
+ */
+#define X86_64_ARG_NO_CLASS            0x00
+#define X86_64_ARG_INTEGER             0x01
+#define X86_64_ARG_MEMORY              0x02
+#define X86_64_ARG_SSE                 0x11
+#define X86_64_ARG_SSEUP               0x12
+#define X86_64_ARG_X87                 0x21
+#define X86_64_ARG_X87UP               0x22
+
+#define X86_64_ARG_IS_SSE(arg) (((arg) & 0x10) != 0)
+#define X86_64_ARG_IS_X87(arg) (((arg) & 0x20) != 0)
+
+
 void _jit_create_closure(unsigned char *buf, void *func,
                          void *closure, void *_type)
 {
@@ -97,7 +112,7 @@
        /* Save all registers used for argument passing */
        /* At this point RSP is not aligned on a 16 byte boundary because */
        /* the return address is pushed on the stack. */
-       /* We need (7 * 8) + (8 * 8) bytes for the registers */
+       /* We need (7 * 8) + (8 * 16) bytes for the registers */
        x86_64_sub_reg_imm_size(buf, X86_64_RSP, 0xB8, 8);
 
        x86_64_mov_membase_reg_size(buf, X86_64_RSP, 0xB0, X86_64_RAX, 8);
@@ -181,7 +196,7 @@
        }
        else
        {
-               jit_nint offset = (jit_nint)entry - ((jit_nint)buf + 7);
+               jit_nint offset = (jit_nint)entry - ((jit_nint)buf + 6);
 
                if((offset >= jit_min_int) && (offset <= jit_max_int))
                {
@@ -230,4 +245,827 @@
        }
 }
 
+/*
+ * Allcate the slot for a parameter passed on the stack.
+ */
+static void
+_jit_alloc_param_slot(jit_param_passing_t *passing, _jit_param_t *param,
+                                         jit_type_t type)
+{
+       jit_int size = jit_type_get_size(type);
+       jit_int alignment = jit_type_get_alignment(type);
+
+       /* Expand the size to a multiple of the stack slot size */
+       size = ROUND_STACK(size);
+
+       /* Expand the alignment to a multiple of the stack slot size */
+       /* We expect the alignment to be a power of two after this step */
+       alignment = ROUND_STACK(alignment);
+
+       /* Make sure the current offset is aligned propperly for the type */
+       if((passing->stack_size & (alignment -1)) != 0)
+       {
+               /* We need padding on the stack to fix the alignment constraint 
*/
+               jit_int padding = passing->stack_size & (alignment -1);
+
+               /* Add the padding to the stack region */
+               passing->stack_size += padding;
+
+               /* record the number of pad words needed after pushing this arg 
*/
+               param->stack_pad = STACK_SLOTS_USED(padding);
+       }
+       /* Record the offset of the parameter in the arg region. */
+       param->un.offset = passing->stack_size;
+
+       /* And increase the argument region used. */
+       passing->stack_size += size;
+}
+
+/*
+ * Determine if a type corresponds to a structure or union.
+ */
+static int
+is_struct_or_union(jit_type_t type)
+{
+       type = jit_type_normalize(type);
+       if(type)
+       {
+               if(type->kind == JIT_TYPE_STRUCT || type->kind == 
JIT_TYPE_UNION)
+               {
+                       return 1;
+               }
+       }
+       return 0;
+}
+
+/*
+ * Classify the argument type.
+ * The type has to be in it's normalized form.
+ */
+static int
+_jit_classify_arg(jit_type_t arg_type, int is_return)
+{
+       switch(arg_type->kind)
+       {
+               case JIT_TYPE_SBYTE:
+               case JIT_TYPE_UBYTE:
+               case JIT_TYPE_SHORT:
+               case JIT_TYPE_USHORT:
+               case JIT_TYPE_INT:
+               case JIT_TYPE_UINT:
+               case JIT_TYPE_NINT:
+               case JIT_TYPE_NUINT:
+               case JIT_TYPE_LONG:
+               case JIT_TYPE_ULONG:
+               case JIT_TYPE_SIGNATURE:
+               case JIT_TYPE_PTR:
+               {
+                       return X86_64_ARG_INTEGER;
+               }
+               break;
+
+               case JIT_TYPE_FLOAT32:
+               case JIT_TYPE_FLOAT64:
+               {
+                       return X86_64_ARG_SSE;
+               }
+               break;
+
+               case JIT_TYPE_NFLOAT:
+               {
+                       /* we assume the nfloat type to be long double (80bit) 
*/
+                       if(is_return)
+                       {
+                               return X86_64_ARG_X87;
+                       }
+                       else
+                       {
+                               return X86_64_ARG_MEMORY;
+                       }
+               }
+               break;
+
+               case JIT_TYPE_STRUCT:
+               case JIT_TYPE_UNION:
+               {
+                       int size = jit_type_get_size(arg_type);
+
+                       if(size > 16)
+                       {
+                               return X86_64_ARG_MEMORY;
+                       }
+                       else if(size <= 8)
+                       {
+                               return X86_64_ARG_INTEGER;
+                       }
+                       /* For structs and unions with sizes between 8 ant 16 
bytes */
+                       /* we have to look at the elements. */
+                       /* TODO */
+               }
+       }
+       return X86_64_ARG_NO_CLASS;
+}
+
+/*
+ * On X86_64 the alignment of native types matches their size.
+ * This leads to the result that all types except nfloats and aggregates
+ * (structs and unions) must start and end in an eightbyte (or the part
+ * we are looking at).
+ */
+static int
+_jit_classify_structpart(jit_type_t struct_type, unsigned int start,
+                                                unsigned int start_offset, 
unsigned int end_offset)
+{
+       int arg_class = X86_64_ARG_NO_CLASS;
+       unsigned int num_fields = jit_type_num_fields(struct_type);
+       unsigned int current_field;
+       
+       for(current_field = 0; current_field < num_fields; ++current_field)
+       {
+               jit_nuint field_offset = jit_type_get_offset(struct_type,
+                                                                               
                         current_field);
+
+               if(field_offset <= end_offset)
+               {
+                       /* The field starts at a place that's inerresting for 
us */
+                       jit_type_t field_type = jit_type_get_field(struct_type,
+                                                                               
                           current_field);
+                       jit_nuint field_size = jit_type_get_size(field_type); 
+
+                       if(field_offset + field_size > start_offset)
+                       {
+                               /* The field is at least partially in the part 
we are */
+                               /* looking at */
+                               int arg_class2 = X86_64_ARG_NO_CLASS;
+
+                               if(is_struct_or_union(field_type))
+                               {
+                                       /* We have to check this struct 
recursively */
+                                       unsigned int current_start;
+                                       unsigned int nested_struct_start;
+                                       unsigned int nested_struct_end;
+
+                                       current_start = start + start_offset;
+                                       if(field_offset < current_start)
+                                       {
+                                               nested_struct_start = 
current_start - field_offset;
+                                       }
+                                       else
+                                       {
+                                               nested_struct_start = 0;
+                                       }
+                                       if(field_offset + field_size - 1 > 
end_offset)
+                                       {
+                                               /* The struct ends beyond the 
part we are looking at */
+                                               nested_struct_end = 
field_offset + field_size -
+                                                                               
                (nested_struct_start + 1);
+                                       }
+                                       else
+                                       {
+                                               nested_struct_end = field_size 
- 1;
+                                       }
+                                       arg_class2 = 
_jit_classify_structpart(field_type,
+                                                                               
                                  start + field_offset,
+                                                                               
                                  nested_struct_start,
+                                                                               
                                  nested_struct_end);
+                               }
+                               else
+                               {
+                                       if((start + start_offset) & (field_size 
- 1))
+                                       {
+                                               /* The field is misaligned */
+                                               return X86_64_ARG_MEMORY;
+                                       }
+                                       arg_class2 = 
_jit_classify_arg(field_type, 0);
+                               }
+                               if(arg_class == X86_64_ARG_NO_CLASS)
+                               {
+                                       arg_class = arg_class2;
+                               }
+                               else if(arg_class != arg_class2)
+                               {
+                                       if(arg_class == X86_64_ARG_MEMORY ||
+                                          arg_class2 == X86_64_ARG_MEMORY)
+                                       {
+                                               arg_class = X86_64_ARG_MEMORY;
+                                       }
+                                       else if(arg_class == X86_64_ARG_INTEGER 
||
+                                          arg_class2 == X86_64_ARG_INTEGER)
+                                       {
+                                               arg_class = X86_64_ARG_INTEGER;
+                                       }
+                                       else if(arg_class == X86_64_ARG_X87 ||
+                                          arg_class2 == X86_64_ARG_X87)
+                                       {
+                                               arg_class = X86_64_ARG_MEMORY;
+                                       }
+                                       else
+                                       {
+                                               arg_class = X86_64_ARG_SSE;
+                                       }
+                               }
+                       }
+               }
+       }
+       return arg_class;
+}
+
+int
+_jit_classify_struct(jit_param_passing_t *passing,
+                                       _jit_param_t *param, jit_type_t 
param_type)
+{
+       jit_nuint size = (jit_nuint)jit_type_get_size(param_type);
+
+       if(size <= 8)
+       {
+               int arg_class;
+       
+               arg_class = _jit_classify_structpart(param_type, 0, 0, size - 
1);
+               if(arg_class == X86_64_ARG_NO_CLASS)
+               {
+                       arg_class = X86_64_ARG_SSE;
+               }
+               if(arg_class == X86_64_ARG_INTEGER)
+               {
+                       if(passing->word_index < passing->max_word_regs)
+                       {
+                               /* Set the arg class to the number of registers 
used */
+                               param->arg_class = 1;
+
+                               /* Set the first register to the register used 
*/
+                               param->un.reg_info[0].reg = 
passing->word_regs[passing->word_index];
+                               param->un.reg_info[0].value = param->value;
+                               ++(passing->word_index);
+                       }
+                       else
+                       {
+                               /* Set the arg class to stack */
+                               param->arg_class = JIT_ARG_CLASS_STACK;
+
+                               /* Allocate the slot in the arg passing frame */
+                               _jit_alloc_param_slot(passing, param, 
param_type);
+                       }                       
+               }
+               else if(arg_class == X86_64_ARG_SSE)
+               {
+                       if(passing->float_index < passing->max_float_regs)
+                       {
+                               /* Set the arg class to the number of registers 
used */
+                               param->arg_class = 1;
+
+                               /* Set the first register to the register used 
*/
+                               param->un.reg_info[0].reg =     
passing->float_regs[passing->float_index];
+                               param->un.reg_info[0].value = param->value;
+                               ++(passing->float_index);
+                       }
+                       else
+                       {
+                               /* Set the arg class to stack */
+                               param->arg_class = JIT_ARG_CLASS_STACK;
+
+                               /* Allocate the slot in the arg passing frame */
+                               _jit_alloc_param_slot(passing, param, 
param_type);
+                       }
+               }
+               else
+               {
+                       /* Set the arg class to stack */
+                       param->arg_class = JIT_ARG_CLASS_STACK;
+
+                       /* Allocate the slot in the arg passing frame */
+                       _jit_alloc_param_slot(passing, param, param_type);
+               }
+       }
+       else if(size <= 16)
+       {
+               int arg_class1;
+               int arg_class2;
+
+               arg_class1 = _jit_classify_structpart(param_type, 0, 0, 7);
+               arg_class2 = _jit_classify_structpart(param_type, 0, 8, size - 
1);
+               if(arg_class1 == X86_64_ARG_NO_CLASS)
+               {
+                       arg_class1 = X86_64_ARG_SSE;
+               }
+               if(arg_class2 == X86_64_ARG_NO_CLASS)
+               {
+                       arg_class2 = X86_64_ARG_SSE;
+               }
+               if(arg_class1 == X86_64_ARG_SSE && arg_class2 == X86_64_ARG_SSE)
+               {
+                       /* We use only one sse register in this case */
+                       if(passing->float_index < passing->max_float_regs)
+                       {
+                               /* Set the arg class to the number of registers 
used */
+                               param->arg_class = 1;
+
+                               /* Set the first register to the register used 
*/
+                               param->un.reg_info[0].reg =     
passing->float_regs[passing->float_index];
+                               param->un.reg_info[0].value = param->value;
+                               ++(passing->float_index);
+                       }
+                       else
+                       {
+                               /* Set the arg class to stack */
+                               param->arg_class = JIT_ARG_CLASS_STACK;
+
+                               /* Allocate the slot in the arg passing frame */
+                               _jit_alloc_param_slot(passing, param, 
param_type);
+                       }
+               }
+               else if(arg_class1 == X86_64_ARG_MEMORY ||
+                               arg_class2 == X86_64_ARG_MEMORY)
+               {
+                       /* Set the arg class to stack */
+                       param->arg_class = JIT_ARG_CLASS_STACK;
+
+                       /* Allocate the slot in the arg passing frame */
+                       _jit_alloc_param_slot(passing, param, param_type);
+               }
+               else if(arg_class1 == X86_64_ARG_INTEGER &&
+                               arg_class2 == X86_64_ARG_INTEGER)
+               {
+                       /* We need two general purpose registers in this case */
+                       if((passing->word_index + 1) < passing->max_word_regs)
+                       {
+                               /* Set the arg class to the number of registers 
used */
+                               param->arg_class = 2;
+
+                               /* Assign the registers */
+                               param->un.reg_info[0].reg = 
passing->word_regs[passing->word_index];
+                               ++(passing->word_index);
+                               param->un.reg_info[1].reg = 
passing->word_regs[passing->word_index];
+                               ++(passing->word_index);
+                       }
+                       else
+                       {
+                               /* Set the arg class to stack */
+                               param->arg_class = JIT_ARG_CLASS_STACK;
+
+                               /* Allocate the slot in the arg passing frame */
+                               _jit_alloc_param_slot(passing, param, 
param_type);
+                       }                       
+               }
+               else
+               {
+                       /* We need one xmm and one general purpose register */
+                       if((passing->word_index < passing->max_word_regs) &&
+                          (passing->float_index < passing->max_float_regs))
+                       {
+                               /* Set the arg class to the number of registers 
used */
+                               param->arg_class = 2;
+
+                               if(arg_class1 == X86_64_ARG_INTEGER)
+                               {
+                                       param->un.reg_info[0].reg = 
passing->word_regs[passing->word_index];
+                                       ++(passing->word_index);
+                                       param->un.reg_info[1].reg =     
passing->float_regs[passing->float_index];
+                                       ++(passing->float_index);
+                               }
+                               else
+                               {
+                                       param->un.reg_info[0].reg =     
passing->float_regs[passing->float_index];
+                                       ++(passing->float_index);
+                                       param->un.reg_info[1].reg = 
passing->word_regs[passing->word_index];
+                                       ++(passing->word_index);
+                               }
+                       }
+                       else
+                       {
+                               /* Set the arg class to stack */
+                               param->arg_class = JIT_ARG_CLASS_STACK;
+
+                               /* Allocate the slot in the arg passing frame */
+                               _jit_alloc_param_slot(passing, param, 
param_type);
+                       }
+               }
+       }
+       else
+       {
+               /* Set the arg class to stack */
+               param->arg_class = JIT_ARG_CLASS_STACK;
+
+               /* Allocate the slot in the arg passing frame */
+               _jit_alloc_param_slot(passing, param, param_type);
+       }
+       return 1;
+}
+
+int
+_jit_classify_param(jit_param_passing_t *passing,
+                                       _jit_param_t *param, jit_type_t 
param_type)
+{
+       if(is_struct_or_union(param_type))
+       {
+               return _jit_classify_struct(passing, param, param_type);
+       }
+       else
+       {
+               int arg_class;
+
+               arg_class = _jit_classify_arg(param_type, 0);
+
+               switch(arg_class)
+               {
+                       case X86_64_ARG_INTEGER:
+                       {
+                               if(passing->word_index < passing->max_word_regs)
+                               {
+                                       /* Set the arg class to the number of 
registers used */
+                                       param->arg_class = 1;
+
+                                       /* Set the first register to the 
register used */
+                                       param->un.reg_info[0].reg = 
passing->word_regs[passing->word_index];
+                                       param->un.reg_info[0].value = 
param->value;
+                                       ++(passing->word_index);
+                               }
+                               else
+                               {
+                                       /* Set the arg class to stack */
+                                       param->arg_class = JIT_ARG_CLASS_STACK;
+
+                                       /* Allocate the slot in the arg passing 
frame */
+                                       _jit_alloc_param_slot(passing, param, 
param_type);
+                               }
+                       }
+                       break;
+
+                       case X86_64_ARG_SSE:
+                       {
+                               if(passing->float_index < 
passing->max_float_regs)
+                               {
+                                       /* Set the arg class to the number of 
registers used */
+                                       param->arg_class = 1;
+
+                                       /* Set the first register to the 
register used */
+                                       param->un.reg_info[0].reg =     
passing->float_regs[passing->float_index];
+                                       param->un.reg_info[0].value = 
param->value;
+                                       ++(passing->float_index);
+                               }
+                               else
+                               {
+                                       /* Set the arg class to stack */
+                                       param->arg_class = JIT_ARG_CLASS_STACK;
+
+                                       /* Allocate the slot in the arg passing 
frame */
+                                       _jit_alloc_param_slot(passing, param, 
param_type);
+                               }
+                       }
+                       break;
+
+                       case X86_64_ARG_MEMORY:
+                       {
+                               /* Set the arg class to stack */
+                               param->arg_class = JIT_ARG_CLASS_STACK;
+
+                               /* Allocate the slot in the arg passing frame */
+                               _jit_alloc_param_slot(passing, param, 
param_type);
+                       }
+                       break;
+               }
+       }
+       return 1;
+}
+
+void
+_jit_builtin_apply_add_struct(jit_apply_builder *builder,
+                                                         void *value,
+                                                         jit_type_t 
struct_type)
+{
+       unsigned int size = jit_type_get_size(struct_type);
+
+       if(size <= 16)
+       {
+               if(size <= 8)
+               {
+                       int arg_class;
+       
+                       arg_class = _jit_classify_structpart(struct_type, 0, 0, 
size - 1);
+                       if(arg_class == X86_64_ARG_NO_CLASS)
+                       {
+                               arg_class = X86_64_ARG_SSE;
+                       }
+                       if((arg_class == X86_64_ARG_INTEGER) &&
+                          (builder->word_used < JIT_APPLY_NUM_WORD_REGS))
+                       {
+                               /* The struct is passed in a general purpose 
register */
+                               
jit_memcpy(&(builder->apply_args->word_regs[builder->word_used]),
+                                                                               
                value, size);
+                               ++(builder->word_used);
+                       }
+                       else if((arg_class == X86_64_ARG_SSE) &&
+                                       (builder->float_used < 
JIT_APPLY_NUM_FLOAT_REGS))
+                       {
+                               /* The struct is passed in one sse register */
+                               
jit_memcpy(&(builder->apply_args->float_regs[builder->float_used]),
+                                                                               
                value, size);
+                               ++(builder->float_used);
+                       }
+                       else
+                       {
+                               unsigned int align = 
jit_type_get_alignment(struct_type);
+
+                               jit_apply_builder_add_struct(builder, value, 
size, align);
+                       }
+               }
+               else
+               {
+                       int arg_class1;
+                       int arg_class2;
+
+                       arg_class1 = _jit_classify_structpart(struct_type, 0, 
0, 7);
+                       arg_class2 = _jit_classify_structpart(struct_type, 0, 
8, size - 1);
+                       if(arg_class1 == X86_64_ARG_NO_CLASS)
+                       {
+                               arg_class1 = X86_64_ARG_SSE;
+                       }
+                       if(arg_class2 == X86_64_ARG_NO_CLASS)
+                       {
+                               arg_class2 = X86_64_ARG_SSE;
+                       }
+                       if(arg_class1 == X86_64_ARG_SSE && arg_class2 == 
X86_64_ARG_SSE &&
+                          (builder->float_used < JIT_APPLY_NUM_FLOAT_REGS))
+                       {
+                               /* The struct is passed in one sse register */
+                               
jit_memcpy(&(builder->apply_args->float_regs[builder->float_used]),
+                                                                               
        value, size);
+                               ++(builder->float_used);
+                       }
+                       else if(arg_class1 == X86_64_ARG_INTEGER &&
+                                       arg_class2 == X86_64_ARG_INTEGER &&
+                                       (builder->word_used < 
(JIT_APPLY_NUM_WORD_REGS + 1)))
+                       {
+                               /* The struct is passed in two general purpose 
registers */
+                               
jit_memcpy(&(builder->apply_args->word_regs[builder->word_used]),
+                                                                               
        value, size);
+                               (builder->word_used) += 2;
+                       }
+                       else if(arg_class1 == X86_64_ARG_INTEGER &&
+                                       arg_class2 == X86_64_ARG_SSE &&
+                                       (builder->float_used < 
JIT_APPLY_NUM_FLOAT_REGS) &&
+                                       (builder->word_used < 
JIT_APPLY_NUM_WORD_REGS))
+                       {
+                               /* The first eightbyte is passed in a general 
purpose */
+                               /* register and the second eightbyte in a sse 
register */
+                               
builder->apply_args->word_regs[builder->word_used] =
+                                                                               
        ((jit_nint *)value)[0];
+                               ++(builder->word_used);
+                               
jit_memcpy(&(builder->apply_args->float_regs[builder->float_used]),
+                                                                               
        ((char *)value) + 8, size - 8);
+                               ++(builder->float_used);
+                       }
+                       else if(arg_class1 == X86_64_ARG_SSE &&
+                                       arg_class2 == X86_64_ARG_INTEGER &&
+                                       (builder->float_used < 
JIT_APPLY_NUM_FLOAT_REGS) &&
+                                       (builder->word_used < 
JIT_APPLY_NUM_WORD_REGS))
+                       {
+                               /* The first eightbyte is passed in a sse 
register and */
+                               /* the second eightbyte in a general purpose  
register */
+                               
jit_memcpy(&(builder->apply_args->float_regs[builder->float_used]),
+                                                                               
        value, 8);
+                               ++(builder->float_used);
+                               
jit_memcpy(&(builder->apply_args->word_regs[builder->word_used]),
+                                                                               
        ((char *)value) + 8, size - 8);
+                               ++(builder->word_used);
+                       }
+                       else
+                       {
+                               unsigned int align = 
jit_type_get_alignment(struct_type);
+
+                               jit_apply_builder_add_struct(builder, value, 
size, align);
+                       }
+               }
+       }
+       else
+       {
+               unsigned int align = jit_type_get_alignment(struct_type);
+
+               jit_apply_builder_add_struct(builder, value, size, align);
+       }
+}
+
+void
+_jit_builtin_apply_get_struct(jit_apply_builder *builder,
+                                                         void *value,
+                                                         jit_type_t 
struct_type)
+{
+       unsigned int size = jit_type_get_size(struct_type);
+
+       if(size <= 16)
+       {
+               if(size <= 8)
+               {
+                       int arg_class;
+       
+                       arg_class = _jit_classify_structpart(struct_type, 0, 0, 
size - 1);
+                       if(arg_class == X86_64_ARG_NO_CLASS)
+                       {
+                               arg_class = X86_64_ARG_SSE;
+                       }
+                       if((arg_class == X86_64_ARG_INTEGER) &&
+                          (builder->word_used < JIT_APPLY_NUM_WORD_REGS))
+                       {
+                               /* The struct is passed in a general purpose 
register */
+                               jit_memcpy(value,
+                                                  
&(builder->apply_args->word_regs[builder->word_used]),
+                                                  size);
+                               ++(builder->word_used);
+                       }
+                       else if((arg_class == X86_64_ARG_SSE) &&
+                                       (builder->float_used < 
JIT_APPLY_NUM_FLOAT_REGS))
+                       {
+                               /* The struct is passed in one sse register */
+                               jit_memcpy(value,
+                                                  
&(builder->apply_args->float_regs[builder->float_used]),
+                                                  size);
+                               ++(builder->float_used);
+                       }
+                       else
+                       {
+                               /* TODO: always load the value from stack */
+                               unsigned int align = 
jit_type_get_alignment(struct_type);
+
+                               jit_apply_parser_get_struct(builder, size, 
align, value);
+                       }
+               }
+               else
+               {
+                       int arg_class1;
+                       int arg_class2;
+
+                       arg_class1 = _jit_classify_structpart(struct_type, 0, 
0, 7);
+                       arg_class2 = _jit_classify_structpart(struct_type, 0, 
8, size - 1);
+                       if(arg_class1 == X86_64_ARG_NO_CLASS)
+                       {
+                               arg_class1 = X86_64_ARG_SSE;
+                       }
+                       if(arg_class2 == X86_64_ARG_NO_CLASS)
+                       {
+                               arg_class2 = X86_64_ARG_SSE;
+                       }
+                       if(arg_class1 == X86_64_ARG_SSE && arg_class2 == 
X86_64_ARG_SSE &&
+                          (builder->float_used < JIT_APPLY_NUM_FLOAT_REGS))
+                       {
+                               /* The struct is passed in one sse register */
+                               jit_memcpy(value,
+                                                  
&(builder->apply_args->float_regs[builder->float_used]),
+                                                  size);
+                               ++(builder->float_used);
+                       }
+                       else if(arg_class1 == X86_64_ARG_INTEGER &&
+                                       arg_class2 == X86_64_ARG_INTEGER &&
+                                       (builder->word_used < 
(JIT_APPLY_NUM_WORD_REGS + 1)))
+                       {
+                               /* The struct is passed in two general purpose 
registers */
+                               jit_memcpy(value,
+                                                  
&(builder->apply_args->word_regs[builder->word_used]),
+                                                  size);
+                               (builder->word_used) += 2;
+                       }
+                       else if(arg_class1 == X86_64_ARG_INTEGER &&
+                                       arg_class2 == X86_64_ARG_SSE &&
+                                       (builder->float_used < 
JIT_APPLY_NUM_FLOAT_REGS) &&
+                                       (builder->word_used < 
JIT_APPLY_NUM_WORD_REGS))
+                       {
+                               /* The first eightbyte is passed in a general 
purpose */
+                               /* register and the second eightbyte in a sse 
register */
+                               ((jit_nint *)value)[0] =
+                                       
builder->apply_args->word_regs[builder->word_used];
+                               ++(builder->word_used);
+
+                               jit_memcpy(((char *)value) + 8,
+                                                  
&(builder->apply_args->float_regs[builder->float_used]),
+                                                  size - 8);
+                               ++(builder->float_used);
+                       }
+                       else if(arg_class1 == X86_64_ARG_SSE &&
+                                       arg_class2 == X86_64_ARG_INTEGER &&
+                                       (builder->float_used < 
JIT_APPLY_NUM_FLOAT_REGS) &&
+                                       (builder->word_used < 
JIT_APPLY_NUM_WORD_REGS))
+                       {
+                               /* The first eightbyte is passed in a sse 
register and */
+                               /* the second eightbyte in a general purpose  
register */
+                               jit_memcpy(value,
+                                                  
&(builder->apply_args->float_regs[builder->float_used]),
+                                                  8);
+                               ++(builder->float_used);
+
+                               jit_memcpy(((char *)value) + 8,
+                                                  
&(builder->apply_args->word_regs[builder->word_used]),
+                                                  size - 8);
+                               ++(builder->word_used);
+                       }
+                       else
+                       {
+                               /* TODO: always load the value from stack */
+                               unsigned int align = 
jit_type_get_alignment(struct_type);
+
+                               jit_apply_parser_get_struct(builder, size, 
align, value);
+                       }
+               }
+       }
+       else
+       {
+               /* TODO: always load the value from stack */
+               unsigned int align = jit_type_get_alignment(struct_type);
+
+               jit_apply_parser_get_struct(builder, size, align, value);
+       }
+}
+
+void
+_jit_builtin_apply_get_struct_return(jit_apply_builder *builder,
+                                                                        void 
*return_value,
+                                                                        
jit_apply_return *apply_return,
+                                                                        
jit_type_t struct_type)
+{
+       unsigned int size = jit_type_get_size(struct_type);
+
+       if(size <= 16)
+       {
+               if(size <= 8)
+               {
+                       int arg_class;
+       
+                       arg_class = _jit_classify_structpart(struct_type, 0, 0, 
size - 1);
+                       if(arg_class == X86_64_ARG_NO_CLASS)
+                       {
+                               arg_class = X86_64_ARG_SSE;
+                       }
+                       if(arg_class == X86_64_ARG_INTEGER)
+                       {
+                               /* The struct is returned in %rax */
+                               jit_memcpy(return_value, (void *)apply_return, 
size);
+                               return;
+                       }
+                       else if(arg_class == X86_64_ARG_SSE)
+                       {
+                               /* The struct is returned in %xmm0 */
+                               jit_memcpy(return_value,
+                                                  &(((jit_ubyte 
*)apply_return)[16]), size);
+                               return;
+                       }
+               }
+               else
+               {
+                       int arg_class1;
+                       int arg_class2;
+
+                       arg_class1 = _jit_classify_structpart(struct_type, 0, 
0, 7);
+                       arg_class2 = _jit_classify_structpart(struct_type, 0, 
8, size - 1);
+                       if(arg_class1 == X86_64_ARG_NO_CLASS)
+                       {
+                               arg_class1 = X86_64_ARG_SSE;
+                       }
+                       if(arg_class2 == X86_64_ARG_NO_CLASS)
+                       {
+                               arg_class2 = X86_64_ARG_SSE;
+                       }
+                       if(arg_class1 == X86_64_ARG_SSE && arg_class2 == 
X86_64_ARG_SSE)
+                       {
+                               /* The struct is returned in %xmm0 */
+                               jit_memcpy(return_value,
+                                                  &(((jit_ubyte 
*)apply_return)[16]), size);
+                               return;
+                       }
+                       else if(arg_class1 == X86_64_ARG_INTEGER &&
+                                       arg_class2 == X86_64_ARG_INTEGER)
+                       {
+                               /* The struct is returned in %rax and %rdx */
+                               jit_memcpy(return_value, (void *)apply_return, 
size);
+                               return;
+                       }
+                       else if(arg_class1 == X86_64_ARG_INTEGER &&
+                                       arg_class2 == X86_64_ARG_SSE)
+                       {
+                               /* The first eightbyte is returned in %rax and 
the second */
+                               /* eightbyte in %xmm0 */
+                               ((jit_nint *)return_value)[0] =
+                                       *(jit_nint *)apply_return;
+
+                               jit_memcpy(((char *)return_value) + 8,
+                                                  &(((jit_ubyte 
*)apply_return)[16]), size - 8);
+                               return;
+                       }
+                       else if(arg_class1 == X86_64_ARG_SSE &&
+                                       arg_class2 == X86_64_ARG_INTEGER)
+                       {
+                               /* The first eightbyte is returned in %xmm0 and 
the second */
+                               /* eightbyte in %rax */
+                               jit_memcpy(return_value,
+                                                  &(((jit_ubyte 
*)apply_return)[16]), 8);
+
+                               jit_memcpy(((char *)return_value) + 8,
+                                                  (void *)apply_return, size - 
8);
+                               return;
+                       }
+               }
+       }
+       /* All other cases are returned via return_ptr */
+       if(builder->struct_return != return_value)
+       {
+               jit_memcpy(return_value, (builder)->struct_return, size);
+       }
+}
+
 #endif /* x86-64 */

Index: jit/jit-apply-x86-64.h
===================================================================
RCS file: /cvsroot/dotgnu-pnet/libjit/jit/jit-apply-x86-64.h,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -b -r1.7 -r1.8
--- jit/jit-apply-x86-64.h      2 Mar 2008 17:07:06 -0000       1.7
+++ jit/jit-apply-x86-64.h      24 Mar 2008 12:42:51 -0000      1.8
@@ -23,6 +23,97 @@
 #ifndef        _JIT_APPLY_X86_64_H
 #define        _JIT_APPLY_X86_64_H
 
+#include "jit-internal.h"
+
+/*
+ * Flag that a parameter is passed on the stack.
+ */
+#define JIT_ARG_CLASS_STACK    0xFFFF
+
+/*
+ * Define the way the parameter is passed to a specific function
+ */
+typedef struct
+{
+       int reg;
+       jit_value_t value;
+} _jit_structpassing_t;
+
+typedef struct
+{
+       jit_value_t value;
+       jit_ushort arg_class;
+       jit_ushort stack_pad;           /* Number of stack words needed for 
padding */
+       union
+       {
+               _jit_structpassing_t reg_info[4];
+               jit_int offset;
+       } un;
+} _jit_param_t;
+
+/*
+ * Structure that is used to help with parameter passing.
+ */
+typedef struct
+{
+       int                             stack_size;                     /* 
Number of bytes needed on the */
+                                                                               
/* stack for parameter passing */
+       int                             stack_pad;                      /* 
Number of stack words we have */
+                                                                               
/* to push before pushing the */
+                                                                               
/* parameters for keeping the stack */
+                                                                               
/* aligned */
+       unsigned int    word_index;                     /* Number of word 
registers */
+                                                                               
/* allocated */
+       unsigned int    max_word_regs;          /* Number of word registers */
+                                                                               
/* available for parameter passing */
+       const int          *word_regs;
+       unsigned int    float_index;
+       unsigned int    max_float_regs;
+       const int          *float_regs;
+       _jit_param_t   *params;
+
+} jit_param_passing_t;
+
+/*
+ * Determine how a parameter is passed.
+ */
+int
+_jit_classify_param(jit_param_passing_t *passing,
+                                       _jit_param_t *param, jit_type_t 
param_type);
+
+/*
+ * Determine how a struct type is passed.
+ */
+int
+_jit_classify_struct(jit_param_passing_t *passing,
+                                       _jit_param_t *param, jit_type_t 
param_type);
+
+/*
+ * We handle struct passing ourself
+ */
+#define HAVE_JIT_BUILTIN_APPLY_STRUCT 1
+
+/*
+ * We handle struct returning ourself
+ */
+#define HAVE_JIT_BUILTIN_APPLY_STRUCT_RETURN 1
+
+/*
+ * The granularity of the stack
+ */
+#define STACK_SLOT_SIZE        sizeof(void *)
+
+/*
+ * Get he number of complete stack slots used
+ */
+#define STACK_SLOTS_USED(size) ((size) >> 3)
+
+/*
+ * Round a size up to a multiple of the stack word size.
+ */
+#define        ROUND_STACK(size)       \
+               (((size) + (STACK_SLOT_SIZE - 1)) & ~(STACK_SLOT_SIZE - 1))
+
 /*
  * The "__builtin_apply" functionality in gcc orders the registers
  * in a strange way, which makes it difficult to use.  Our replacement
@@ -59,7 +150,7 @@
                do { \
                        void *__func = (void *)(func); \
                        void *__args = (void *)(args); \
-                       long __size = (long)(size); \
+                       long __size = (((long)(size) + (long)0xf) & 
~(long)0xf); \
                        void *__return_buf = alloca(64); \
                        (return_buf) = __return_buf; \
                        __asm__ ( \
@@ -165,6 +256,10 @@
                        return; \
                } while (0)
 
+#define jit_builtin_return_struct(return_buf, type) \
+               do { \
+               } while (0)
+
 #endif /* GNUC */
 
 /*

Index: jit/jit-gen-x86-64.h
===================================================================
RCS file: /cvsroot/dotgnu-pnet/libjit/jit/jit-gen-x86-64.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- jit/jit-gen-x86-64.h        2 Mar 2008 17:07:06 -0000       1.2
+++ jit/jit-gen-x86-64.h        24 Mar 2008 12:42:51 -0000      1.3
@@ -1890,6 +1890,351 @@
        x86_64_xor_reg_reg_size((inst), (reg), (reg), 4)
 
 /*
+ * shift instructions
+ */
+#define x86_64_shift_reg_imm_size(inst, opc, dreg, imm, size) \
+       do { \
+               if((imm) == 1) \
+               { \
+                       if((size) == 2) \
+                       { \
+                               *(inst)++ = (unsigned char)0x66; \
+                       } \
+                       x86_64_rex_emit((inst), (size), 0, 0, (dreg)); \
+                       x86_64_opcode1_emit((inst), 0xd0, (size)); \
+                       x86_64_reg_emit((inst), (opc), (dreg)); \
+               } \
+               else \
+               { \
+                       if((size) == 2) \
+                       { \
+                               *(inst)++ = (unsigned char)0x66; \
+                       } \
+                       x86_64_rex_emit((inst), (size), 0, 0, (dreg)); \
+                       x86_64_opcode1_emit((inst), 0xc0, (size)); \
+                       x86_64_reg_emit((inst), (opc), (dreg)); \
+                       x86_imm_emit8((inst), (imm)); \
+               } \
+       } while(0)
+
+#define x86_64_shift_mem_imm_size(inst, opc, mem, imm, size) \
+       do { \
+               if((imm) == 1) \
+               { \
+                       if((size) == 2) \
+                       { \
+                               *(inst)++ = (unsigned char)0x66; \
+                       } \
+                       x86_64_rex_emit((inst), (size), 0, 0, 0); \
+                       x86_64_opcode1_emit((inst), 0xd0, (size)); \
+                       x86_64_mem_emit((inst), (opc), (mem)); \
+               } \
+               else \
+               { \
+                       if((size) == 2) \
+                       { \
+                               *(inst)++ = (unsigned char)0x66; \
+                       } \
+                       x86_64_rex_emit((inst), (size), 0, 0, 0); \
+                       x86_64_opcode1_emit((inst), 0xc0, (size)); \
+                       x86_64_mem_emit((inst), (opc), (mem)); \
+                       x86_imm_emit8((inst), (imm)); \
+               } \
+       } while(0)
+
+#define x86_64_shift_regp_imm_size(inst, opc, dregp, imm, size) \
+       do { \
+               if((imm) == 1) \
+               { \
+                       if((size) == 2) \
+                       { \
+                               *(inst)++ = (unsigned char)0x66; \
+                       } \
+                       x86_64_rex_emit((inst), (size), 0, 0, (dregp)); \
+                       x86_64_opcode1_emit((inst), 0xd0, (size)); \
+                       x86_64_regp_emit((inst), (opc), (dregp)); \
+               } \
+               else \
+               { \
+                       if((size) == 2) \
+                       { \
+                               *(inst)++ = (unsigned char)0x66; \
+                       } \
+                       x86_64_rex_emit((inst), (size), 0, 0, (dregp)); \
+                       x86_64_opcode1_emit((inst), 0xc0, (size)); \
+                       x86_64_regp_emit((inst), (opc), (dregp)); \
+                       x86_imm_emit8((inst), (imm)); \
+               } \
+       } while(0)
+
+#define x86_64_shift_membase_imm_size(inst, opc, basereg, disp, imm, size) \
+       do { \
+               if((imm) == 1) \
+               { \
+                       if((size) == 2) \
+                       { \
+                               *(inst)++ = (unsigned char)0x66; \
+                       } \
+                       x86_64_rex_emit((inst), (size), 0, 0, (basereg)); \
+                       x86_64_opcode1_emit((inst), 0xd0, (size)); \
+                       x86_64_membase_emit((inst), (opc), (basereg), (disp)); \
+               } \
+               else \
+               { \
+                       if((size) == 2) \
+                       { \
+                               *(inst)++ = (unsigned char)0x66; \
+                       } \
+                       x86_64_rex_emit((inst), (size), 0, 0, (basereg)); \
+                       x86_64_opcode1_emit((inst), 0xc0, (size)); \
+                       x86_64_membase_emit((inst), (opc), (basereg), (disp)); \
+                       x86_imm_emit8((inst), (imm)); \
+               } \
+       } while(0)
+
+#define x86_64_shift_memindex_imm_size(inst, opc, basereg, disp, indexreg, 
shift, imm, size) \
+       do { \
+               if((imm) == 1) \
+               { \
+                       if((size) == 2) \
+                       { \
+                               *(inst)++ = (unsigned char)0x66; \
+                       } \
+                       x86_64_rex_emit((inst), (size), 0, (indexreg), 
(basereg)); \
+                       x86_64_opcode1_emit((inst), 0xd0, (size)); \
+                       x86_64_memindex_emit((inst), (opc), (basereg), (disp), 
(indexreg), (shift)); \
+               } \
+               else \
+               { \
+                       if((size) == 2) \
+                       { \
+                               *(inst)++ = (unsigned char)0x66; \
+                       } \
+                       x86_64_rex_emit((inst), (size), 0, (indexreg), 
(basereg)); \
+                       x86_64_opcode1_emit((inst), 0xc0, (size)); \
+                       x86_64_memindex_emit((inst), (opc), (basereg), (disp), 
(indexreg), (shift)); \
+                       x86_imm_emit8((inst), (imm)); \
+               } \
+       } while(0)
+
+/*
+ * shift by the number of bits in %cl
+ */
+#define x86_64_shift_reg_size(inst, opc, dreg, size) \
+       do { \
+               if((size) == 2) \
+               { \
+                       *(inst)++ = (unsigned char)0x66; \
+               } \
+               x86_64_rex_emit((inst), (size), 0, 0, (dreg)); \
+               x86_64_opcode1_emit((inst), 0xd2, (size)); \
+               x86_64_reg_emit((inst), (opc), (dreg)); \
+       } while(0)
+
+#define x86_64_shift_mem_size(inst, opc, mem, size) \
+       do { \
+               if((size) == 2) \
+               { \
+                       *(inst)++ = (unsigned char)0x66; \
+               } \
+               x86_64_rex_emit((inst), (size), 0, 0, 0); \
+               x86_64_opcode1_emit((inst), 0xd2, (size)); \
+               x86_64_mem_emit((inst), (opc), (mem)); \
+       } while(0)
+
+#define x86_64_shift_regp_size(inst, opc, dregp, size) \
+       do { \
+               if((size) == 2) \
+               { \
+                       *(inst)++ = (unsigned char)0x66; \
+               } \
+               x86_64_rex_emit((inst), (size), 0, 0, (dregp)); \
+               x86_64_opcode1_emit((inst), 0xd2, (size)); \
+               x86_64_regp_emit((inst), (opc), (dregp)); \
+       } while(0)
+
+#define x86_64_shift_membase_size(inst, opc, basereg, disp, size) \
+       do { \
+               if((size) == 2) \
+               { \
+                       *(inst)++ = (unsigned char)0x66; \
+               } \
+               x86_64_rex_emit((inst), (size), 0, 0, (basereg)); \
+               x86_64_opcode1_emit((inst), 0xd2, (size)); \
+               x86_64_membase_emit((inst), (opc), (basereg), (disp)); \
+       } while(0)
+
+#define x86_64_shift_memindex_size(inst, opc, basereg, disp, indexreg, shift, 
size) \
+       do { \
+               if((size) == 2) \
+               { \
+                       *(inst)++ = (unsigned char)0x66; \
+               } \
+               x86_64_rex_emit((inst), (size), 0, (indexreg), (basereg)); \
+               x86_64_opcode1_emit((inst), 0xd2, (size)); \
+               x86_64_memindex_emit((inst), (opc), (basereg), (disp), 
(indexreg), (shift)); \
+       } while(0)
+
+/*
+ * shl: Shit left (clear the least significant bit)
+ */
+#define x86_64_shl_reg_imm_size(inst, dreg, imm, size) \
+       do { \
+               x86_64_shift_reg_imm_size((inst), 4, (dreg), (imm), (size)); \
+       } while(0)
+
+#define x86_64_shl_mem_imm_size(inst, mem, imm, size) \
+       do { \
+               x86_64_shift_mem_imm_size((inst), 4, (mem), (imm), (size)); \
+       } while(0)
+
+#define x86_64_shl_regp_imm_size(inst, dregp, imm, size) \
+       do { \
+               x86_64_shift_regp_imm_size((inst), 4, (dregp), (imm), (size)); \
+       } while(0)
+
+#define x86_64_shl_membase_imm_size(inst, basereg, disp, imm, size) \
+       do { \
+               x86_64_shift_membase_imm_size((inst), 4, (basereg), (disp), 
(imm), (size)); \
+       } while(0)
+
+#define x86_64_shl_memindex_imm_size(inst, basereg, disp, indexreg, shift, 
imm, size) \
+       do { \
+               x86_64_shift_memindex_imm_size((inst), 4, (basereg), (disp), 
(indexreg), (shift), (imm), (size)); \
+       } while(0)
+
+#define x86_64_shl_reg_size(inst, dreg, size) \
+       do { \
+               x86_64_shift_reg_size((inst), 4, (dreg), (size)); \
+       } while(0)
+
+#define x86_64_shl_mem_size(inst, mem, size) \
+       do { \
+               x86_64_shift_mem_size((inst), 4, (mem), (size)); \
+       } while(0)
+
+#define x86_64_shl_regp_size(inst, dregp, size) \
+       do { \
+               x86_64_shift_regp_size((inst), 4, (dregp), (size)); \
+       } while(0)
+
+#define x86_64_shl_membase_size(inst, basereg, disp, size) \
+       do { \
+               x86_64_shift_membase_size((inst), 4, (basereg), (disp), 
(size)); \
+       } while(0)
+
+#define x86_64_shl_memindex_size(inst, basereg, disp, indexreg, shift, size) \
+       do { \
+               x86_64_shift_memindex_size((inst), 4, (basereg), (disp), 
(indexreg), (shift), (size)); \
+       } while(0)
+
+/*
+ * shr: Unsigned shit right (clear the most significant bit)
+ */
+#define x86_64_shr_reg_imm_size(inst, dreg, imm, size) \
+       do { \
+               x86_64_shift_reg_imm_size((inst), 5, (dreg), (imm), (size)); \
+       } while(0)
+
+#define x86_64_shr_mem_imm_size(inst, mem, imm, size) \
+       do { \
+               x86_64_shift_mem_imm_size((inst), 5, (mem), (imm), (size)); \
+       } while(0)
+
+#define x86_64_shr_regp_imm_size(inst, dregp, imm, size) \
+       do { \
+               x86_64_shift_regp_imm_size((inst), 5, (dregp), (imm), (size)); \
+       } while(0)
+
+#define x86_64_shr_membase_imm_size(inst, basereg, disp, imm, size) \
+       do { \
+               x86_64_shift_membase_imm_size((inst), 5, (basereg), (disp), 
(imm), (size)); \
+       } while(0)
+
+#define x86_64_shr_memindex_imm_size(inst, basereg, disp, indexreg, shift, 
imm, size) \
+       do { \
+               x86_64_shift_memindex_imm_size((inst), 5, (basereg), (disp), 
(indexreg), (shift), (imm), (size)); \
+       } while(0)
+
+#define x86_64_shr_reg_size(inst, dreg, size) \
+       do { \
+               x86_64_shift_reg_size((inst), 5, (dreg), (size)); \
+       } while(0)
+
+#define x86_64_shr_mem_size(inst, mem, size) \
+       do { \
+               x86_64_shift_mem_size((inst), 5, (mem), (size)); \
+       } while(0)
+
+#define x86_64_shr_regp_size(inst, dregp, size) \
+       do { \
+               x86_64_shift_regp_size((inst), 5, (dregp), (size)); \
+       } while(0)
+
+#define x86_64_shr_membase_size(inst, basereg, disp, size) \
+       do { \
+               x86_64_shift_membase_size((inst), 5, (basereg), (disp), 
(size)); \
+       } while(0)
+
+#define x86_64_shr_memindex_size(inst, basereg, disp, indexreg, shift, size) \
+       do { \
+               x86_64_shift_memindex_size((inst), 5, (basereg), (disp), 
(indexreg), (shift), (size)); \
+       } while(0)
+
+/*
+ * sar: Signed shit right (keep the most significant bit)
+ */
+#define x86_64_sar_reg_imm_size(inst, dreg, imm, size) \
+       do { \
+               x86_64_shift_reg_imm_size((inst), 7, (dreg), (imm), (size)); \
+       } while(0)
+
+#define x86_64_sar_mem_imm_size(inst, mem, imm, size) \
+       do { \
+               x86_64_shift_mem_imm_size((inst), 7, (mem), (imm), (size)); \
+       } while(0)
+
+#define x86_64_sar_regp_imm_size(inst, dregp, imm, size) \
+       do { \
+               x86_64_shift_regp_imm_size((inst), 7, (dregp), (imm), (size)); \
+       } while(0)
+
+#define x86_64_sar_membase_imm_size(inst, basereg, disp, imm, size) \
+       do { \
+               x86_64_shift_membase_imm_size((inst), 7, (basereg), (disp), 
(imm), (size)); \
+       } while(0)
+
+#define x86_64_sar_memindex_imm_size(inst, basereg, disp, indexreg, shift, 
imm, size) \
+       do { \
+               x86_64_shift_memindex_imm_size((inst), 7, (basereg), (disp), 
(indexreg), (shift), (imm), (size)); \
+       } while(0)
+
+#define x86_64_sar_reg_size(inst, dreg, size) \
+       do { \
+               x86_64_shift_reg_size((inst), 7, (dreg), (size)); \
+       } while(0)
+
+#define x86_64_sar_mem_size(inst, mem, size) \
+       do { \
+               x86_64_shift_mem_size((inst), 7, (mem), (size)); \
+       } while(0)
+
+#define x86_64_sar_regp_size(inst, dregp, size) \
+       do { \
+               x86_64_shift_regp_size((inst), 7, (dregp), (size)); \
+       } while(0)
+
+#define x86_64_sar_membase_size(inst, basereg, disp, size) \
+       do { \
+               x86_64_shift_membase_size((inst), 7, (basereg), (disp), 
(size)); \
+       } while(0)
+
+#define x86_64_sar_memindex_size(inst, basereg, disp, indexreg, shift, size) \
+       do { \
+               x86_64_shift_memindex_size((inst), 7, (basereg), (disp), 
(indexreg), (shift), (size)); \
+       } while(0)
+
+/*
  * Lea instructions
  */
 #define x86_64_lea_mem_size(inst, dreg, mem, size) \
@@ -2026,7 +2371,7 @@
                        case 8: \
                        { \
                                jit_nint __x86_64_imm = (imm); \
-                               if(__x86_64_imm >= jit_min_int && __x86_64_imm 
<= jit_max_int) \
+                               if(__x86_64_imm >= (jit_nint)jit_min_int && 
__x86_64_imm <= (jit_nint)jit_max_int) \
                                { \
                                        *(inst)++ = (unsigned char)0xc7; \
                                        x86_64_reg_emit((inst), 0, (dreg)); \
@@ -2610,6 +2955,41 @@
        } while(0)
 
 /*
+ * xchg: Exchange values
+ */
+#define x86_64_xchg_reg_reg_size(inst, dreg, sreg, size) \
+       do { \
+               if(((size) > 1) && ((dreg) == X86_64_RAX || (sreg) == 
X86_64_RAX)) \
+               { \
+                       if((size) == 2) \
+                       { \
+                               *(inst)++ = (unsigned char)0x66; \
+                       } \
+                       if((dreg) == X86_64_RAX) \
+                       { \
+                               x86_64_rex_emit((inst), (size), 0, 0, (sreg)); \
+                               *(inst)++ = (unsigned char)(0x90 + (unsigned 
char)(sreg & 0x7)); \
+                       } \
+                       else \
+                       { \
+                               x86_64_rex_emit((inst), (size), 0, 0, (dreg)); \
+                               *(inst)++ = (unsigned char)(0x90 + (unsigned 
char)(dreg & 0x7)); \
+                       } \
+               } \
+               else \
+               { \
+                       if((size) == 1) \
+                       { \
+                               x86_64_alu1_reg_reg_size((inst), 0x86, (dreg), 
(sreg), (size)); \
+                       } \
+                       else \
+                       { \
+                               x86_64_alu1_reg_reg_size((inst), 0x87, (dreg), 
(sreg), (size)); \
+                       } \
+               } \
+       } while(0)
+
+/*
  * XMM instructions
  */
 
@@ -2737,6 +3117,112 @@
  */
 
 /*
+ * movd: Move doubleword from/to xmm register
+ */
+#define x86_64_movd_xreg_reg(inst, dreg, sreg) \
+       do { \
+               x86_64_p1_xmm2_reg_reg_size((inst), 0x66, 0x0f, 0x6e, (dreg), 
(sreg), 4); \
+       } while(0)
+
+#define x86_64_movd_xreg_mem(inst, dreg, mem) \
+       do { \
+               x86_64_p1_xmm2_reg_mem_size((inst), 0x66, 0x0f, 0x6e, (dreg), 
(mem), 4); \
+       } while(0)
+
+#define x86_64_movd_xreg_regp(inst, dreg, sregp) \
+       do { \
+               x86_64_p1_xmm2_reg_regp_size((inst), 0x66, 0x0f, 0x6e, (dreg), 
(sregp), 4); \
+       } while(0)
+
+#define x86_64_movd_xreg_membase(inst, dreg, basereg, disp) \
+       do { \
+               x86_64_p1_xmm2_reg_membase_size((inst), 0x66, 0x0f, 0x6e, 
(dreg), (basereg), (disp), 4); \
+       } while(0)
+
+#define x86_64_movd_xreg_memindex(inst, dreg, basereg, disp, indexreg, shift) \
+       do { \
+               x86_64_p1_xmm2_reg_memindex_size((inst), 0x66, 0x0f, 0x6e, 
(dreg), (basereg), (disp), (indexreg), (shift), 4); \
+       } while(0)
+
+#define x86_64_movd_reg_xreg(inst, dreg, sreg) \
+       do { \
+               x86_64_p1_xmm2_reg_reg_size((inst), 0x66, 0x0f, 0x7e, (sreg), 
(dreg), 4); \
+       } while(0)
+
+#define x86_64_movd_mem_xreg(inst, mem, sreg) \
+       do { \
+               x86_64_p1_xmm2_reg_mem_size((inst), 0x66, 0x0f, 0x7e, (sreg), 
(mem), 4); \
+       } while(0)
+
+#define x86_64_movd_regp_xreg(inst, dregp, sreg) \
+       do { \
+               x86_64_p1_xmm2_reg_regp_size((inst), 0x66, 0x0f, 0x7e, (sreg), 
(dregp), 4); \
+       } while(0)
+
+#define x86_64_movd_membase_xreg(inst, basereg, disp, sreg) \
+       do { \
+               x86_64_p1_xmm2_reg_membase_size((inst), 0x66, 0x0f, 0x7e, 
(sreg), (basereg), (disp), 4); \
+       } while(0)
+
+#define x86_64_movd_memindex_xreg(inst, basereg, disp, indexreg, shift, sreg) \
+       do { \
+               x86_64_p1_xmm2_reg_memindex_size((inst), 0x66, 0x0f, 0x7e, 
(sreg), (basereg), (disp), (indexreg), (shift), 4); \
+       } while(0)
+
+/*
+ * movq: Move quadword from/to xmm register
+ */
+#define x86_64_movq_xreg_reg(inst, dreg, sreg) \
+       do { \
+               x86_64_p1_xmm2_reg_reg_size((inst), 0x66, 0x0f, 0x6e, (dreg), 
(sreg), 8); \
+       } while(0)
+
+#define x86_64_movq_xreg_mem(inst, dreg, mem) \
+       do { \
+               x86_64_p1_xmm2_reg_mem_size((inst), 0x66, 0x0f, 0x6e, (dreg), 
(mem), 8); \
+       } while(0)
+
+#define x86_64_movq_xreg_regp(inst, dreg, sregp) \
+       do { \
+               x86_64_p1_xmm2_reg_regp_size((inst), 0x66, 0x0f, 0x6e, (dreg), 
(sregp), 8); \
+       } while(0)
+
+#define x86_64_movq_xreg_membase(inst, dreg, basereg, disp) \
+       do { \
+               x86_64_p1_xmm2_reg_membase_size((inst), 0x66, 0x0f, 0x6e, 
(dreg), (basereg), (disp), 8); \
+       } while(0)
+
+#define x86_64_movq_xreg_memindex(inst, dreg, basereg, disp, indexreg, shift) \
+       do { \
+               x86_64_p1_xmm2_reg_memindex_size((inst), 0x66, 0x0f, 0x6e, 
(dreg), (basereg), (disp), (indexreg), (shift), 8); \
+       } while(0)
+
+#define x86_64_movq_reg_xreg(inst, dreg, sreg) \
+       do { \
+               x86_64_p1_xmm2_reg_reg_size((inst), 0x66, 0x0f, 0x7e, (sreg), 
(dreg), 8); \
+       } while(0)
+
+#define x86_64_movq_mem_xreg(inst, mem, sreg) \
+       do { \
+               x86_64_p1_xmm2_reg_mem_size((inst), 0x66, 0x0f, 0x7e, (sreg), 
(mem), 8); \
+       } while(0)
+
+#define x86_64_movq_regp_xreg(inst, dregp, sreg) \
+       do { \
+               x86_64_p1_xmm2_reg_regp_size((inst), 0x66, 0x0f, 0x7e, (sreg), 
(dregp), 8); \
+       } while(0)
+
+#define x86_64_movq_membase_xreg(inst, basereg, disp, sreg) \
+       do { \
+               x86_64_p1_xmm2_reg_membase_size((inst), 0x66, 0x0f, 0x7e, 
(sreg), (basereg), (disp), 8); \
+       } while(0)
+
+#define x86_64_movq_memindex_xreg(inst, basereg, disp, indexreg, shift, sreg) \
+       do { \
+               x86_64_p1_xmm2_reg_memindex_size((inst), 0x66, 0x0f, 0x7e, 
(sreg), (basereg), (disp), (indexreg), (shift), 8); \
+       } while(0)
+
+/*
  * movaps: Move aligned quadword (16 bytes)
  */
 #define x86_64_movaps_reg_reg(inst, dreg, sreg) \

Index: jit/jit-rules-x86-64.c
===================================================================
RCS file: /cvsroot/dotgnu-pnet/libjit/jit/jit-rules-x86-64.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- jit/jit-rules-x86-64.c      2 Mar 2008 17:07:06 -0000       1.1
+++ jit/jit-rules-x86-64.c      24 Mar 2008 12:42:51 -0000      1.2
@@ -104,36 +104,6 @@
 #define HAVE_RED_ZONE 1
 
 /*
- * X86_64 argument types as specified in the X86_64 SysV ABI.
- */
-#define X86_64_ARG_NO_CLASS            0x00
-#define X86_64_ARG_INTEGER             0x01
-#define X86_64_ARG_MEMORY              0x02
-#define X86_64_ARG_SSE                 0x11
-#define X86_64_ARG_SSEUP               0x12
-#define X86_64_ARG_X87                 0x21
-#define X86_64_ARG_X87UP               0x22
-
-#define X86_64_ARG_IS_SSE(arg) (((arg) & 0x10) != 0)
-#define X86_64_ARG_IS_X87(arg) (((arg) & 0x20) != 0)
-
-/*
- * The granularity of the stack
- */
-#define STACK_SLOT_SIZE        sizeof(void *)
-
-/*
- * Get he number of complete stack slots used
- */
-#define STACK_SLOTS_USED(size) ((size) >> 3)
-
-/*
- * Round a size up to a multiple of the stack word size.
- */
-#define        ROUND_STACK(size)       \
-               (((size) + (STACK_SLOT_SIZE - 1)) & ~(STACK_SLOT_SIZE - 1))
-
-/*
  * Setup or teardown the x86 code output process.
  */
 #define        jit_cache_setup_output(needed)  \
@@ -197,6 +167,10 @@
                                                                                
/* purpose registers */
 static _jit_regclass_t *x86_64_rreg;   /* general purpose registers not used*/
                                                                                
/* for returning values */
+static _jit_regclass_t *x86_64_sreg;   /* general purpose registers that can*/
+                                                                               
/* be used for the value to be */
+                                                                               
/* shifted (all but %rcx)*/
+                                                                               
/* for returning values */
 static _jit_regclass_t *x86_64_freg;   /* X86_64 fpu registers */
 static _jit_regclass_t *x86_64_xreg;   /* X86_64 xmm registers */
 
@@ -232,6 +206,17 @@
                X86_64_REG_R12, X86_64_REG_R13,
                X86_64_REG_R14, X86_64_REG_R15);
 
+       /* register class with all registers that can be used for shifted 
values */
+       x86_64_sreg = _jit_regclass_create(
+               "sreg", JIT_REG_WORD | JIT_REG_LONG, 13,
+               X86_64_REG_RAX, X86_64_REG_RDX,
+               X86_64_REG_RBX, X86_64_REG_RSI,
+               X86_64_REG_RDI, X86_64_REG_R8,
+               X86_64_REG_R9, X86_64_REG_R10,
+               X86_64_REG_R11, X86_64_REG_R12,
+               X86_64_REG_R13, X86_64_REG_R14,
+               X86_64_REG_R15);
+
        x86_64_freg = _jit_regclass_create(
                "freg", JIT_REG_X86_64_FLOAT | JIT_REG_IN_STACK, 8,
                X86_64_REG_ST0, X86_64_REG_ST1,
@@ -716,11 +701,10 @@
  *
  * We have only 4 bytes for the jump offsets.
  * Therefore we have do something tricky here.
- * We need some fixed value that is known to be fix throughout the
- * building of the function and that will be near the emitted code.
- * The posn limit looks like the perfect value to use.
+ * The fixup pointer in the block/gen points to the last fixup.
+ * The fixup itself contains the offset to the previous fixup or
+ * null if it's the last fixup in the list.
  */
-#define _JIT_GET_FIXVALUE(gen) ((gen)->posn.limit)
 
 /*
  * Calculate the fixup value
@@ -1028,10 +1012,19 @@
                                }
                                else
                                {
+                                       if((jit_nint)(value->address) > 0 && 
(jit_nint)(value->address) <= (jit_nint)jit_max_uint)
+                                       {
+                                               x86_64_mov_reg_imm_size(inst, 
_jit_reg_info[reg].cpu_reg,
+                                                               
(jit_nint)(value->address), 4);
+
+                                       }
+                                       else
+                                       {
                                        x86_64_mov_reg_imm_size(inst, 
_jit_reg_info[reg].cpu_reg,
                                                        
(jit_nint)(value->address), 8);
                                }
                        }
+                       }
                        break;
 
                        case JIT_TYPE_FLOAT32:
@@ -1416,6 +1409,49 @@
                                }
                        }
                        break;
+
+                       case JIT_TYPE_STRUCT:
+                       case JIT_TYPE_UNION:
+                       {
+                               if(IS_GENERAL_REG(reg))
+                               {
+                                       if(IS_GENERAL_REG(src_reg))
+                                       {
+                                               x86_64_mov_reg_reg_size(inst, 
_jit_reg_info[reg].cpu_reg,
+                                                                               
                _jit_reg_info[src_reg].cpu_reg, 8);
+                                       }
+                                       else if(IS_XMM_REG(src_reg))
+                                       {
+                                               x86_64_movq_reg_xreg(inst, 
_jit_reg_info[reg].cpu_reg,
+                                                                               
         _jit_reg_info[src_reg].cpu_reg);
+                                       }
+                                       else
+                                       {
+                                               fputs("Unsupported struct/union 
reg - reg move\n", stderr);
+                                       }
+                               }
+                               else if(IS_XMM_REG(reg))
+                               {
+                                       if(IS_GENERAL_REG(src_reg))
+                                       {
+                                               x86_64_movq_xreg_reg(inst, 
_jit_reg_info[reg].cpu_reg,
+                                                                               
         _jit_reg_info[src_reg].cpu_reg);
+                                       }
+                                       else if(IS_XMM_REG(src_reg))
+                                       {
+                                               x86_64_movaps_reg_reg(inst, 
_jit_reg_info[reg].cpu_reg,
+                                                                               
          _jit_reg_info[src_reg].cpu_reg);
+                                       }
+                                       else
+                                       {
+                                               fputs("Unsupported struct/union 
reg - reg move\n", stderr);
+                                       }
+                               }
+                               else
+                               {
+                                       fputs("Unsupported struct/union reg - 
reg move\n", stderr);
+                               }
+                       }
                }
        }
        else
@@ -1936,7 +1972,6 @@
        if(DEBUG_FIXUPS && fixup)
        {
                fprintf(stderr, "Block: %lx\n", (jit_nint)block);
-               fprintf(stderr, "Limit: %lx\n", 
(jit_nint)_JIT_GET_FIXVALUE(gen));
        }
        while(fixup != 0)
        {
@@ -1974,6 +2009,10 @@
 {
        switch(jit_type_remove_tags(type)->kind)
        {
+               case JIT_TYPE_SBYTE:
+               case JIT_TYPE_UBYTE:
+               case JIT_TYPE_SHORT:
+               case JIT_TYPE_USHORT:
                case JIT_TYPE_INT:
                case JIT_TYPE_UINT:
                case JIT_TYPE_LONG:
@@ -1995,85 +2034,6 @@
  */
 
 /*
- * Flag that a parameter is passed on the stack.
- */
-#define JIT_ARG_CLASS_STACK    0xFFFF
-
-/*
- * Define the way the parameter is passed to a specific function
- */
-typedef struct
-{
-       jit_value_t value;
-       jit_ushort arg_class;
-       jit_ushort stack_pad;           /* Number of stack words needed for 
padding */
-       union
-       {
-               unsigned char reg[4];
-               jit_int offset;
-       } un;
-} _jit_param_t;
-
-/*
- * Structure that is used to help with parameter passing.
- */
-typedef struct
-{
-       int                             stack_size;                     /* 
Number of bytes needed on the */
-                                                                               
/* stack for parameter passing */
-       int                             stack_pad;                      /* 
Number of stack words we have */
-                                                                               
/* to push before pushing the */
-                                                                               
/* parameters for keeping the stack */
-                                                                               
/* aligned */
-       unsigned int    word_index;                     /* Number of word 
registers */
-                                                                               
/* allocated */
-       unsigned int    max_word_regs;          /* Number of word registers */
-                                                                               
/* available for parameter passing */
-       const int          *word_regs;
-       unsigned int    float_index;
-       unsigned int    max_float_regs;
-       const int          *float_regs;
-       _jit_param_t   *params;
-
-} jit_param_passing_t;
-
-/*
- * Allcate the slot for a parameter passed on the stack.
- */
-static void
-_jit_alloc_param_slot(jit_param_passing_t *passing, _jit_param_t *param,
-                                         jit_type_t type)
-{
-       jit_int size = jit_type_get_size(type);
-       jit_int alignment = jit_type_get_alignment(type);
-
-       /* Expand the size to a multiple of the stack slot size */
-       size = ROUND_STACK(size);
-
-       /* Expand the alignment to a multiple of the stack slot size */
-       /* We expect the alignment to be a power of two after this step */
-       alignment = ROUND_STACK(alignment);
-
-       /* Make sure the current offset is aligned propperly for the type */
-       if((passing->stack_size & (alignment -1)) != 0)
-       {
-               /* We need padding on the stack to fix the alignment constraint 
*/
-               jit_int padding = passing->stack_size & (alignment -1);
-
-               /* Add the padding to the stack region */
-               passing->stack_size += padding;
-
-               /* record the number of pad words needed after pushing this arg 
*/
-               param->stack_pad = STACK_SLOTS_USED(padding);
-       }
-       /* Record the offset of the parameter in the arg region. */
-       param->un.offset = passing->stack_size;
-
-       /* And increase the argument region used. */
-       passing->stack_size += size;
-}
-
-/*
  * Determine if a type corresponds to a structure or union.
  */
 static int
@@ -2090,618 +2050,194 @@
        return 0;
 }
 
-/*
- * Classify the argument type.
- * The type has to be in it's normalized form.
- */
 static int
-_jit_classify_arg(jit_type_t arg_type, int is_return)
+_jit_classify_struct_return(jit_param_passing_t *passing,
+                                       _jit_param_t *param, jit_type_t 
return_type)
 {
-       switch(arg_type->kind)
-       {
-               case JIT_TYPE_SBYTE:
-               case JIT_TYPE_UBYTE:
-               case JIT_TYPE_SHORT:
-               case JIT_TYPE_USHORT:
-               case JIT_TYPE_INT:
-               case JIT_TYPE_UINT:
-               case JIT_TYPE_NINT:
-               case JIT_TYPE_NUINT:
-               case JIT_TYPE_LONG:
-               case JIT_TYPE_ULONG:
-               case JIT_TYPE_SIGNATURE:
-               case JIT_TYPE_PTR:
-               {
-                       return X86_64_ARG_INTEGER;
-               }
-               break;
+       /* Initialize the param passing structure */
+       jit_memset(passing, 0, sizeof(jit_param_passing_t));
+       jit_memset(param, 0, sizeof(_jit_param_t));
 
-               case JIT_TYPE_FLOAT32:
-               case JIT_TYPE_FLOAT64:
-               {
-                       return X86_64_ARG_SSE;
-               }
-               break;
+       passing->word_regs = _jit_word_return_regs;
+       passing->max_word_regs = _jit_num_word_return_regs;
+       passing->float_regs = _jit_sse_return_regs;
+       passing->max_float_regs = _jit_num_sse_return_regs;
 
-               case JIT_TYPE_NFLOAT:
-               {
-                       /* we assume the nfloat type to be long double (80bit) 
*/
-                       if(is_return)
-                       {
-                               return X86_64_ARG_X87;
-                       }
-                       else
+       if(!(_jit_classify_struct(passing, param, return_type)))
                        {
-                               return X86_64_ARG_MEMORY;
-                       }
+               return 0;
                }
-               break;
-
-               case JIT_TYPE_STRUCT:
-               case JIT_TYPE_UNION:
-               {
-                       int size = jit_type_get_size(arg_type);
 
-                       if(size > 16)
-                       {
-                               return X86_64_ARG_MEMORY;
-                       }
-                       else if(size <= 8)
-                       {
-                               return X86_64_ARG_INTEGER;
-                       }
-                       /* For structs and unions with sizes between 8 ant 16 
bytes */
-                       /* we have to look at the elements. */
-                       /* TODO */
-               }
-       }
-       return X86_64_ARG_NO_CLASS;
+       return 1;
 }
 
 /*
- * On X86_64 the alignment of native types matches their size.
- * This leads to the result that all types except nfloats and aggregates
- * (structs and unions) must start and end in an eightbyte (or the part
- * we are looking at).
+ * Load a struct to the register(s) in which it will be returned.
  */
-static int
-_jit_classify_structpart(jit_type_t struct_type, unsigned int start,
-                                                unsigned int start_offset, 
unsigned int end_offset)
+static unsigned char *
+return_struct(unsigned char *inst, jit_function_t func, int ptr_reg)
 {
-       int arg_class = X86_64_ARG_NO_CLASS;
-       unsigned int num_fields = jit_type_num_fields(struct_type);
-       unsigned int current_field;
+       jit_type_t return_type;
+       jit_type_t signature = jit_function_get_signature(func);
        
-       for(current_field = 0; current_field < num_fields; ++current_field)
+       return_type = jit_type_get_return(signature);
+       if(is_struct_or_union(return_type))
        {
-               jit_nuint field_offset = jit_type_get_offset(struct_type,
-                                                                               
                         current_field);
+               jit_nuint size;
+               jit_param_passing_t passing;
+               _jit_param_t return_param;
 
-               if(field_offset <= end_offset)
+               if(!_jit_classify_struct_return(&passing, &return_param,
+                                                                               
return_type))
                {
-                       /* The field starts at a place that's inerresting for 
us */
-                       jit_type_t field_type = jit_type_get_field(struct_type,
-                                                                               
                           current_field);
-                       jit_nuint field_size = jit_type_get_size(field_type); 
+                       /* It's an error so simply return insn */
+                       return inst;    
+               }
 
-                       if(field_offset + field_size > start_offset)
+               size = jit_type_get_size(return_type);
+               if(size <= 8)
                        {
-                               /* The field is at least partially in the part 
we are */
-                               /* looking at */
-                               int arg_class2 = X86_64_ARG_NO_CLASS;
-
-                               if(is_struct_or_union(field_type))
+                       /* one register is used for returning the value */
+                       if(IS_GENERAL_REG(return_param.un.reg_info[0].reg))
                                {
-                                       /* We have to check this struct 
recursively */
-                                       unsigned int current_start;
-                                       unsigned int nested_struct_start;
-                                       unsigned int nested_struct_end;
+                               int reg = 
_jit_reg_info[return_param.un.reg_info[0].reg].cpu_reg;
 
-                                       current_start = start + start_offset;
-                                       if(field_offset < current_start)
+                               if(size <= 4)
                                        {
-                                               nested_struct_start = 
current_start - field_offset;
+                                       x86_64_mov_reg_regp_size(inst, reg, 
ptr_reg, 4);
                                        }
                                        else
                                        {
-                                               nested_struct_start = 0;
+                                       x86_64_mov_reg_regp_size(inst, reg, 
ptr_reg, 8);
+                               }
                                        }
-                                       if(field_offset + field_size - 1 > 
end_offset)
+                       else
+                       {
+                               int reg = 
_jit_reg_info[return_param.un.reg_info[0].reg].cpu_reg;
+
+                               if(size <= 4)
                                        {
-                                               /* The struct ends beyond the 
part we are looking at */
-                                               nested_struct_end = 
field_offset + field_size -
-                                                                               
                (nested_struct_start + 1);
+                                       x86_64_movss_reg_regp(inst, reg, 
ptr_reg);
                                        }
                                        else
                                        {
-                                               nested_struct_end = field_size 
- 1;
+                                       x86_64_movsd_reg_regp(inst, reg, 
ptr_reg);
+                               }
                                        }
-                                       arg_class2 = 
_jit_classify_structpart(field_type,
-                                                                               
                                  start + field_offset,
-                                                                               
                                  nested_struct_start,
-                                                                               
                                  nested_struct_end);
                                }
                                else
                                {
-                                       if((start + start_offset) & (field_size 
- 1))
+                       /* In this case we might need up to two registers */
+                       if(return_param.arg_class == 1)
+                       {
+                               /* This must be one xmm register */
+                               int reg = 
_jit_reg_info[return_param.un.reg_info[0].reg].cpu_reg;
+                               int alignment = 
jit_type_get_alignment(return_type);
+
+                               if((alignment & 0xf) == 0)
+                               {
+                                       /* The type is aligned on a 16 byte 
boundary */
+                                       x86_64_movaps_reg_regp(inst, reg, 
ptr_reg);
+                               }
+                               else
                                        {
-                                               /* The field is misaligned */
-                                               return X86_64_ARG_MEMORY;
+                                       x86_64_movups_reg_regp(inst, reg, 
ptr_reg);
                                        }
-                                       arg_class2 = 
_jit_classify_arg(field_type, 0);
                                }
-                               if(arg_class == X86_64_ARG_NO_CLASS)
+                       else
+                       {
+                               int reg = 
_jit_reg_info[return_param.un.reg_info[0].reg].cpu_reg;
+
+                               
if(IS_GENERAL_REG(return_param.un.reg_info[0].reg))
+                               {
+                                       x86_64_mov_reg_regp_size(inst, reg,
+                                                                               
         ptr_reg, 8);
+                               }
+                               else
                                {
-                                       arg_class = arg_class2;
+                                       x86_64_movsd_reg_regp(inst, reg, 
ptr_reg);
                                }
-                               else if(arg_class != arg_class2)
+                               size -= 8;
+                               reg = 
_jit_reg_info[return_param.un.reg_info[1].reg].cpu_reg;
+                               
if(IS_GENERAL_REG(return_param.un.reg_info[1].reg))
                                {
-                                       if(arg_class == X86_64_ARG_MEMORY ||
-                                          arg_class2 == X86_64_ARG_MEMORY)
+                                       if(size <= 4)
                                        {
-                                               arg_class = X86_64_ARG_MEMORY;
+                                               
x86_64_mov_reg_membase_size(inst, reg, ptr_reg,
+                                                                               
                        8, 4);
                                        }
-                                       else if(arg_class == X86_64_ARG_INTEGER 
||
-                                          arg_class2 == X86_64_ARG_INTEGER)
+                                       else
                                        {
-                                               arg_class = X86_64_ARG_INTEGER;
+                                               
x86_64_mov_reg_membase_size(inst, reg, ptr_reg,
+                                                                               
                        8, 8);
                                        }
-                                       else if(arg_class == X86_64_ARG_X87 ||
-                                          arg_class2 == X86_64_ARG_X87)
+                               }
+                               else
                                        {
-                                               arg_class = X86_64_ARG_MEMORY;
+                                       if(size <= 4)
+                                       {
+                                               x86_64_movss_reg_membase(inst, 
reg,
+                                                                               
                 ptr_reg, 8);
                                        }
                                        else
                                        {
-                                               arg_class = X86_64_ARG_SSE;
+                                               x86_64_movsd_reg_membase(inst, 
reg,
+                                                                               
                 ptr_reg, 8);
                                        }
                                }
                        }
                }
        }
-       return arg_class;
+       return inst;
 }
 
-static int
-_jit_classify_struct(jit_param_passing_t *passing,
-                                       _jit_param_t *param, jit_type_t 
param_type)
+/*
+ * Flush a struct return value from the registers to the value
+ * on the stack.
+ */
+static unsigned char *
+flush_return_struct(unsigned char *inst, jit_value_t value)
 {
-       jit_nuint size = (jit_nuint)jit_type_get_size(param_type);
+       jit_type_t return_type;
 
-       if(size <= 8)
+       return_type = jit_value_get_type(value);
+       if(is_struct_or_union(return_type))
        {
-               int arg_class;
+               jit_nuint size;
+               jit_nint offset;
+               jit_param_passing_t passing;
+               _jit_param_t return_param;
        
-               arg_class = _jit_classify_structpart(param_type, 0, 0, size - 
1);
-               if(arg_class == X86_64_ARG_NO_CLASS)
+               if(!_jit_classify_struct_return(&passing, &return_param, 
return_type))
                {
-                       arg_class = X86_64_ARG_SSE;
+                       /* It's an error so simply return insn */
+                       return inst;    
                }
-               if(arg_class == X86_64_ARG_INTEGER)
-               {
-                       if(passing->word_index < passing->max_word_regs)
-                       {
-                               /* Set the arg class to the number of registers 
used */
-                               param->arg_class = 1;
 
-                               /* Set the first register to the register used 
*/
-                               param->un.reg[0] = 
passing->word_regs[passing->word_index];
-                               ++(passing->word_index);
-                       }
-                       else
-                       {
-                               /* Set the arg class to stack */
-                               param->arg_class = JIT_ARG_CLASS_STACK;
+               return_param.value = value;
 
-                               /* Allocate the slot in the arg passing frame */
-                               _jit_alloc_param_slot(passing, param, 
param_type);
-                       }                       
-               }
-               else if(arg_class == X86_64_ARG_SSE)
+               _jit_gen_fix_value(value);
+               size = jit_type_get_size(return_type);
+               offset = value->frame_offset;
+               if(size <= 8)
                {
-                       if(passing->float_index < passing->max_float_regs)
+                       /* one register is used for returning the value */
+                       if(IS_GENERAL_REG(return_param.un.reg_info[0].reg))
                        {
-                               /* Set the arg class to the number of registers 
used */
-                               param->arg_class = 1;
+                               int reg = 
_jit_reg_info[return_param.un.reg_info[0].reg].cpu_reg;
 
-                               /* Set the first register to the register used 
*/
-                               param->un.reg[0] =      
passing->float_regs[passing->float_index];
-                               ++(passing->float_index);
+                               if(size <= 4)
+                               {
+                                       x86_64_mov_membase_reg_size(inst, 
X86_64_RBP, offset, reg, 4);
                        }
                        else
                        {
-                               /* Set the arg class to stack */
-                               param->arg_class = JIT_ARG_CLASS_STACK;
-
-                               /* Allocate the slot in the arg passing frame */
-                               _jit_alloc_param_slot(passing, param, 
param_type);
+                                       x86_64_mov_membase_reg_size(inst, 
X86_64_RBP, offset, reg, 8);
                        }
                }
                else
                {
-                       /* Set the arg class to stack */
-                       param->arg_class = JIT_ARG_CLASS_STACK;
-
-                       /* Allocate the slot in the arg passing frame */
-                       _jit_alloc_param_slot(passing, param, param_type);
-               }
-       }
-       else if(size <= 16)
-       {
-               int arg_class1;
-               int arg_class2;
-
-               arg_class1 = _jit_classify_structpart(param_type, 0, 0, 7);
-               arg_class2 = _jit_classify_structpart(param_type, 0, 8, size - 
1);
-               if(arg_class1 == X86_64_ARG_NO_CLASS)
-               {
-                       arg_class1 = X86_64_ARG_SSE;
-               }
-               if(arg_class2 == X86_64_ARG_NO_CLASS)
-               {
-                       arg_class2 = X86_64_ARG_SSE;
-               }
-               if(arg_class1 == X86_64_ARG_SSE && arg_class2 == X86_64_ARG_SSE)
-               {
-                       /* We use only one sse register in this case */
-                       if(passing->float_index < passing->max_float_regs)
-                       {
-                               /* Set the arg class to the number of registers 
used */
-                               param->arg_class = 1;
-
-                               /* Set the first register to the register used 
*/
-                               param->un.reg[0] =      
passing->float_regs[passing->float_index];
-                               ++(passing->float_index);
-                       }
-                       else
-                       {
-                               /* Set the arg class to stack */
-                               param->arg_class = JIT_ARG_CLASS_STACK;
-
-                               /* Allocate the slot in the arg passing frame */
-                               _jit_alloc_param_slot(passing, param, 
param_type);
-                       }
-               }
-               else if(arg_class1 == X86_64_ARG_MEMORY ||
-                               arg_class2 == X86_64_ARG_MEMORY)
-               {
-                       /* Set the arg class to stack */
-                       param->arg_class = JIT_ARG_CLASS_STACK;
-
-                       /* Allocate the slot in the arg passing frame */
-                       _jit_alloc_param_slot(passing, param, param_type);
-               }
-               else if(arg_class1 == X86_64_ARG_INTEGER &&
-                               arg_class2 == X86_64_ARG_INTEGER)
-               {
-                       /* We need two general purpose registers in this case */
-                       if((passing->word_index + 1) < passing->max_word_regs)
-                       {
-                               /* Set the arg class to the number of registers 
used */
-                               param->arg_class = 2;
-
-                               /* Assign the registers */
-                               param->un.reg[0] = 
passing->word_regs[passing->word_index];
-                               ++(passing->word_index);
-                               param->un.reg[1] = 
passing->word_regs[passing->word_index];
-                               ++(passing->word_index);
-                       }
-                       else
-                       {
-                               /* Set the arg class to stack */
-                               param->arg_class = JIT_ARG_CLASS_STACK;
-
-                               /* Allocate the slot in the arg passing frame */
-                               _jit_alloc_param_slot(passing, param, 
param_type);
-                       }                       
-               }
-               else
-               {
-                       /* We need one xmm and one general purpose register */
-                       if((passing->word_index < passing->max_word_regs) &&
-                          (passing->float_index < passing->max_float_regs))
-                       {
-                               /* Set the arg class to the number of registers 
used */
-                               param->arg_class = 2;
-
-                               if(arg_class1 == X86_64_ARG_INTEGER)
-                               {
-                                       param->un.reg[0] = 
passing->word_regs[passing->word_index];
-                                       ++(passing->word_index);
-                                       param->un.reg[1] =      
passing->float_regs[passing->float_index];
-                                       ++(passing->float_index);
-                               }
-                               else
-                               {
-                                       param->un.reg[0] =      
passing->float_regs[passing->float_index];
-                                       ++(passing->float_index);
-                                       param->un.reg[1] = 
passing->word_regs[passing->word_index];
-                                       ++(passing->word_index);
-                               }
-                       }
-                       else
-                       {
-                               /* Set the arg class to stack */
-                               param->arg_class = JIT_ARG_CLASS_STACK;
-
-                               /* Allocate the slot in the arg passing frame */
-                               _jit_alloc_param_slot(passing, param, 
param_type);
-                       }
-               }
-       }
-       else
-       {
-               /* Set the arg class to stack */
-               param->arg_class = JIT_ARG_CLASS_STACK;
-
-               /* Allocate the slot in the arg passing frame */
-               _jit_alloc_param_slot(passing, param, param_type);
-       }
-       return 1;
-}
-
-int
-_jit_classify_param(jit_param_passing_t *passing,
-                                       _jit_param_t *param, jit_type_t 
param_type)
-{
-       if(is_struct_or_union(param_type))
-       {
-               return _jit_classify_struct(passing, param, param_type);
-       }
-       else
-       {
-               int arg_class;
-
-               arg_class = _jit_classify_arg(param_type, 0);
-
-               switch(arg_class)
-               {
-                       case X86_64_ARG_INTEGER:
-                       {
-                               if(passing->word_index < passing->max_word_regs)
-                               {
-                                       /* Set the arg class to the number of 
registers used */
-                                       param->arg_class = 1;
-
-                                       /* Set the first register to the 
register used */
-                                       param->un.reg[0] = 
passing->word_regs[passing->word_index];
-                                       ++(passing->word_index);
-                               }
-                               else
-                               {
-                                       /* Set the arg class to stack */
-                                       param->arg_class = JIT_ARG_CLASS_STACK;
-
-                                       /* Allocate the slot in the arg passing 
frame */
-                                       _jit_alloc_param_slot(passing, param, 
param_type);
-                               }
-                       }
-                       break;
-
-                       case X86_64_ARG_SSE:
-                       {
-                               if(passing->float_index < 
passing->max_float_regs)
-                               {
-                                       /* Set the arg class to the number of 
registers used */
-                                       param->arg_class = 1;
-
-                                       /* Set the first register to the 
register used */
-                                       param->un.reg[0] =      
passing->float_regs[passing->float_index];
-                                       ++(passing->float_index);
-                               }
-                               else
-                               {
-                                       /* Set the arg class to stack */
-                                       param->arg_class = JIT_ARG_CLASS_STACK;
-
-                                       /* Allocate the slot in the arg passing 
frame */
-                                       _jit_alloc_param_slot(passing, param, 
param_type);
-                               }
-                       }
-                       break;
-
-                       case X86_64_ARG_MEMORY:
-                       {
-                               /* Set the arg class to stack */
-                               param->arg_class = JIT_ARG_CLASS_STACK;
-
-                               /* Allocate the slot in the arg passing frame */
-                               _jit_alloc_param_slot(passing, param, 
param_type);
-                       }
-                       break;
-               }
-       }
-       return 1;
-}
-
-static int
-_jit_classify_struct_return(jit_param_passing_t *passing,
-                                       _jit_param_t *param, jit_type_t 
return_type)
-{
-       /* Initialize the param passing structure */
-       jit_memset(passing, 0, sizeof(jit_param_passing_t));
-       jit_memset(param, 0, sizeof(_jit_param_t));
-
-       passing->word_regs = _jit_word_return_regs;
-       passing->max_word_regs = _jit_num_word_return_regs;
-       passing->float_regs = _jit_sse_return_regs;
-       passing->max_float_regs = _jit_num_sse_return_regs;
-
-       if(!(_jit_classify_struct(passing, param, return_type)))
-       {
-               return 0;
-       }
-
-       return 1;
-}
-
-/*
- * Load a struct to the register(s) in which it will be returned.
- */
-static unsigned char *
-return_struct(unsigned char *inst, jit_function_t func, int ptr_reg)
-{
-       jit_type_t return_type;
-       jit_type_t signature = jit_function_get_signature(func);
-
-       return_type = jit_type_get_return(signature);
-       if(is_struct_or_union(return_type))
-       {
-               jit_nuint size;
-               jit_param_passing_t passing;
-               _jit_param_t return_param;
-
-               if(!_jit_classify_struct_return(&passing, &return_param,
-                                                                               
return_type))
-               {
-                       /* It's an error so simply return insn */
-                       return inst;    
-               }
-               
-               size = jit_type_get_size(return_type);
-               if(size <= 8)
-               {
-                       /* one register is used for returning the value */
-                       if(IS_GENERAL_REG(return_param.un.reg[0]))
-                       {
-                               int reg = 
_jit_reg_info[return_param.un.reg[0]].cpu_reg;
-
-                               if(size <= 4)
-                               {
-                                       x86_64_mov_reg_regp_size(inst, reg, 
ptr_reg, 4);
-                               }
-                               else
-                               {
-                                       x86_64_mov_reg_regp_size(inst, reg, 
ptr_reg, 8);
-                               }
-                       }
-                       else
-                       {
-                               int reg = 
_jit_reg_info[return_param.un.reg[0]].cpu_reg;
-
-                               if(size <= 4)
-                               {
-                                       x86_64_movss_reg_regp(inst, reg, 
ptr_reg);
-                               }
-                               else
-                               {
-                                       x86_64_movsd_reg_regp(inst, reg, 
ptr_reg);
-                               }
-                       }
-               }
-               else
-               {
-                       /* In this case we might need up to two registers */
-                       if(return_param.arg_class == 1)
-                       {
-                               /* This must be one xmm register */
-                               int reg = 
_jit_reg_info[return_param.un.reg[0]].cpu_reg;
-                               int alignment = 
jit_type_get_alignment(return_type);
-
-                               if((alignment & 0xf) == 0)
-                               {
-                                       /* The type is aligned on a 16 byte 
boundary */
-                                       x86_64_movaps_reg_regp(inst, reg, 
ptr_reg);
-                               }
-                               else
-                               {
-                                       x86_64_movups_reg_regp(inst, reg, 
ptr_reg);
-                               }
-                       }
-                       else
-                       {
-                               int reg = 
_jit_reg_info[return_param.un.reg[0]].cpu_reg;
-
-                               if(IS_GENERAL_REG(return_param.un.reg[0]))
-                               {
-                                       x86_64_mov_reg_regp_size(inst, reg,
-                                                                               
         ptr_reg, 8);
-                               }
-                               else
-                               {
-                                       x86_64_movsd_reg_regp(inst, reg, 
ptr_reg);
-                               }
-                               size -= 8;
-                               reg = 
_jit_reg_info[return_param.un.reg[1]].cpu_reg;
-                               if(IS_GENERAL_REG(return_param.un.reg[1]))
-                               {
-                                       if(size <= 4)
-                                       {
-                                               
x86_64_mov_reg_membase_size(inst, reg, ptr_reg,
-                                                                               
                        8, 4);
-                                       }
-                                       else
-                                       {
-                                               
x86_64_mov_reg_membase_size(inst, reg, ptr_reg,
-                                                                               
                        8, 8);
-                                       }
-                               }
-                               else
-                               {
-                                       if(size <= 4)
-                                       {
-                                               x86_64_movss_reg_membase(inst, 
reg,
-                                                                               
                 ptr_reg, 8);
-                                       }
-                                       else
-                                       {
-                                               x86_64_movsd_reg_membase(inst, 
reg,
-                                                                               
                 ptr_reg, 8);
-                                       }
-                               }
-                       }
-               }
-       }
-       return inst;
-}
-
-/*
- * Flush a struct return value from the registers to the value
- * on the stack.
- */
-static unsigned char *
-flush_return_struct(unsigned char *inst, jit_value_t value)
-{
-       jit_type_t return_type;
-
-       return_type = jit_value_get_type(value);
-       if(is_struct_or_union(return_type))
-       {
-               jit_nuint size;
-               jit_nint offset;
-               jit_param_passing_t passing;
-               _jit_param_t return_param;
-
-               if(!_jit_classify_struct_return(&passing, &return_param, 
return_type))
-               {
-                       /* It's an error so simply return insn */
-                       return inst;    
-               }
-
-               return_param.value = value;
-
-               _jit_gen_fix_value(value);
-               size = jit_type_get_size(return_type);
-               offset = value->frame_offset;
-               if(size <= 8)
-               {
-                       /* one register is used for returning the value */
-                       if(IS_GENERAL_REG(return_param.un.reg[0]))
-                       {
-                               int reg = 
_jit_reg_info[return_param.un.reg[0]].cpu_reg;
-
-                               if(size <= 4)
-                               {
-                                       x86_64_mov_membase_reg_size(inst, 
X86_64_RBP, offset, reg, 4);
-                               }
-                               else
-                               {
-                                       x86_64_mov_membase_reg_size(inst, 
X86_64_RBP, offset, reg, 8);
-                               }
-                       }
-                       else
-                       {
-                               int reg = 
_jit_reg_info[return_param.un.reg[0]].cpu_reg;
+                               int reg = 
_jit_reg_info[return_param.un.reg_info[0].reg].cpu_reg;
 
                                if(size <= 4)
                                {
@@ -2719,7 +2255,7 @@
                        if(return_param.arg_class == 1)
                        {
                                /* This must be one xmm register */
-                               int reg = 
_jit_reg_info[return_param.un.reg[0]].cpu_reg;
+                               int reg = 
_jit_reg_info[return_param.un.reg_info[0].reg].cpu_reg;
                                int alignment = 
jit_type_get_alignment(return_type);
 
                                if((alignment & 0xf) == 0)
@@ -2734,9 +2270,9 @@
                        }
                        else
                        {
-                               int reg = 
_jit_reg_info[return_param.un.reg[0]].cpu_reg;
+                               int reg = 
_jit_reg_info[return_param.un.reg_info[0].reg].cpu_reg;
 
-                               if(IS_GENERAL_REG(return_param.un.reg[0]))
+                               
if(IS_GENERAL_REG(return_param.un.reg_info[0].reg))
                                {
                                        x86_64_mov_membase_reg_size(inst, 
X86_64_RBP, offset,
                                                                                
                reg, 8);
@@ -2746,8 +2282,8 @@
                                        x86_64_movsd_membase_reg(inst, 
X86_64_RBP, offset, reg);
                                }
                                size -= 8;
-                               reg = 
_jit_reg_info[return_param.un.reg[1]].cpu_reg;
-                               if(IS_GENERAL_REG(return_param.un.reg[1]))
+                               reg = 
_jit_reg_info[return_param.un.reg_info[1].reg].cpu_reg;
+                               
if(IS_GENERAL_REG(return_param.un.reg_info[1].reg))
                                {
                                        if(size <= 4)
                                        {
@@ -2932,62 +2468,121 @@
 }
 
 int
-_jit_setup_incoming_param(jit_function_t func, _jit_param_t *param,
+_jit_setup_reg_param(jit_function_t func, _jit_param_t *param,
                                                  jit_type_t param_type)
 {
-       if(param->arg_class == JIT_ARG_CLASS_STACK)
+       if(param->arg_class == 1)
        {
-               /* The parameter is passed on the stack */
-               if(!jit_insn_incoming_frame_posn
-                               (func, param->value, param->un.offset))
+               param->un.reg_info[0].value = param->value;
+       }
+       else if(param->arg_class == 2)
+       {
+               jit_nint size = jit_type_get_size(param_type);
+               jit_value_t value_ptr;
+
+               if(!(value_ptr = jit_insn_address_of(func, param->value)))
+               {
+                       return 0;
+               }
+               if(IS_GENERAL_REG(param->un.reg_info[0].reg))
+               {
+                       param->un.reg_info[0].value =
+                               jit_insn_load_relative(func, value_ptr, 0, 
jit_type_long);
+                       if(!(param->un.reg_info[0].value))
                {
                        return 0;
                }
        }
        else
        {
-               param_type = jit_type_remove_tags(param_type);
-
-               switch(param_type->kind)
+                       param->un.reg_info[0].value =
+                               jit_insn_load_relative(func, value_ptr, 0, 
jit_type_float64);
+                       if(!(param->un.reg_info[0].value))
                {
-                       case JIT_TYPE_STRUCT:
-                       case JIT_TYPE_UNION:
+                               return 0;
+                       }
+               }
+               size -= 8;
+               if(IS_GENERAL_REG(param->un.reg_info[1].reg))
                        {
-                               if(param->arg_class == 1)
+                       if(size <= 4)
                                {
-                                       if(!jit_insn_incoming_reg(func, 
param->value, param->un.reg[0]))
+                               param->un.reg_info[1].value =
+                                       jit_insn_load_relative(func, value_ptr, 
8, jit_type_int);
+                               if(!(param->un.reg_info[1].value))
                                        {
                                                return 0;
                                        }
                                }
                                else
                                {
-                                       /* These cases have to be handled 
specially */
+                               param->un.reg_info[1].value =
+                                       jit_insn_load_relative(func, value_ptr, 
8, jit_type_long);
+                               if(!(param->un.reg_info[1].value))
+                               {
+                                       return 0;
                                }
                        }
-                       break;
+               }
+               else
+               {
+                       if(size <= 4)
+                       {
+                               param->un.reg_info[1].value =
+                                       jit_insn_load_relative(func, value_ptr, 
8, jit_type_float32);
+                               if(!(param->un.reg_info[1].value))
+                               {
+                                       return 0;
+                               }
+                       }
+                       else
+                       {
+                               param->un.reg_info[1].value =
+                                       jit_insn_load_relative(func, value_ptr, 
8, jit_type_float64);
+                               if(!(param->un.reg_info[1].value))
+                               {
+                                       return 0;
+                               }
+                       }
+               }
+       }
+       return 1;
+}
 
-                       default:
+int
+_jit_flush_incoming_struct(jit_function_t func, _jit_param_t *param,
+                                                 jit_type_t param_type)
+{
+       if(param->arg_class == 2)
                        {
-                               if(!jit_insn_incoming_reg(func, param->value, 
param->un.reg[0]))
+               jit_value_t address;
+
+               /* Now store the two values in place */
+               if(!(address = jit_insn_address_of(func, param->value)))
                                {
                                        return 0;
                                }
+               if(!jit_insn_store_relative(func, address, 0, 
param->un.reg_info[0].value))
+               {
+                       return 0;
                        }
-                       break;
+               if(!jit_insn_store_relative(func, address, 8, 
param->un.reg_info[1].value))
+               {
+                       return 0;
                }
        }
        return 1;
 }
 
 int
-_jit_setup_outgoing_param(jit_function_t func, _jit_param_t *param,
+_jit_setup_incoming_param(jit_function_t func, _jit_param_t *param,
                                                  jit_type_t param_type)
 {
        if(param->arg_class == JIT_ARG_CLASS_STACK)
        {
                /* The parameter is passed on the stack */
-               if(!push_param(func, param, param_type))
+               if(!jit_insn_incoming_frame_posn
+                               (func, param->value, param->un.offset))
                {
                        return 0;
                }
@@ -3001,166 +2596,130 @@
                        case JIT_TYPE_STRUCT:
                        case JIT_TYPE_UNION:
                        {
-                               /* These cases have to be handled specially */
                                if(param->arg_class == 1)
                                {
-                                       /* Only one xmm register is used for 
passing this argument */
-                                       if(!jit_insn_outgoing_reg(func, 
param->value, param->un.reg[0]))
+                                       if(!jit_insn_incoming_reg(func, 
param->value, param->un.reg_info[0].reg))
                                        {
                                                return 0;
                                        }
                                }
                                else
                                {
-                                       /* We need two registers for passing 
the value */
-                                       jit_nuint size = 
(jit_nuint)jit_type_get_size(param_type);
-
-                                       jit_value_t struct_ptr;
+                                       /* These cases have to be handled 
specially */
+                                       /* The struct is passed in two 
registers */
+                                       jit_nuint size = 
jit_type_get_size(param_type);
 
-                                       if(!(struct_ptr = 
jit_insn_address_of(func, param->value)))
+                                       /* The first part is allways a full 
eightbyte */
+                                       
if(IS_GENERAL_REG(param->un.reg_info[0].reg))
+                                       {
+                                               
if(!(param->un.reg_info[0].value = jit_value_create(func, jit_type_long)))
                                        {
                                                return 0;
                                        }
-                                       if(IS_GENERAL_REG(param->un.reg[0]))
+                                       }
+                                       else
                                        {
-                                               jit_value_t param_value;
-
-                                               param_value = 
jit_insn_load_relative(func, struct_ptr,
-                                                                               
                                         0, jit_type_ulong);
-                                               if(!param_value)
+                                               
if(!(param->un.reg_info[0].value = jit_value_create(func, jit_type_float64)))
                                                {
                                                        return 0;
                                                }
-                                               if(!jit_insn_outgoing_reg(func, 
param_value, param->un.reg[0]))
+                                       }
+                                       size -= 8;
+                                       /* The second part might be of any size 
<= 8 */
+                                       
if(IS_GENERAL_REG(param->un.reg_info[1].reg))
+                                       {
+                                               if(size <= 4)
+                                               {
+                                                       
if(!(param->un.reg_info[1].value = 
+                                                                       
jit_value_create(func, jit_type_int)))
                                                {
                                                        return 0;
                                                }
                                        }
                                        else
                                        {
-                                               jit_value_t param_value;
-
-                                               param_value = 
jit_insn_load_relative(func, struct_ptr,
-                                                                               
                                         0, jit_type_float64);
-                                               if(!param_value)
+                                                       
if(!(param->un.reg_info[1].value =
+                                                                       
jit_value_create(func, jit_type_long)))
                                                {
                                                        return 0;
                                                }
-                                               if(!jit_insn_outgoing_reg(func, 
param_value, param->un.reg[0]))
-                                               {
-                                                       return 0;
                                                }
                                        }
-                                       size -= 8;
-                                       if(IS_GENERAL_REG(param->un.reg[1]))
-                                       {
-                                               if(size == 1)
+                                       else
                                                {
-                                                       jit_value_t param_value;
-
-                                                       param_value = 
jit_insn_load_relative(func, struct_ptr,
-                                                                               
                                                 8, jit_type_ubyte);
-                                                       if(!param_value)
+                                               if(size <= 4)
                                                        {
-                                                               return 0;
-                                                       }
-                                                       
if(!jit_insn_outgoing_reg(func, param_value, param->un.reg[1]))
+                                                       
if(!(param->un.reg_info[1].value =
+                                                                       
jit_value_create(func, jit_type_float32)))
                                                        {
                                                                return 0;
                                                        }
                                                }
-                                               else if(size == 2)
+                                               else
                                                {
-                                                       jit_value_t param_value;
-
-                                                       param_value = 
jit_insn_load_relative(func, struct_ptr,
-                                                                               
                                                 8, jit_type_ushort);
-                                                       if(!param_value)
+                                                       
if(!(param->un.reg_info[1].value =
+                                                                       
jit_value_create(func, jit_type_float64)))
                                                        {
                                                                return 0;
                                                        }
-                                                       
if(!jit_insn_outgoing_reg(func, param_value, param->un.reg[0]))
-                                                       {
-                                                               return 0;
                                                        }
                                                }
-                                               else if(size <= 4)
-                                               {
-                                                       jit_value_t param_value;
-
-                                                       param_value = 
jit_insn_load_relative(func, struct_ptr,
-                                                                               
                                                 8, jit_type_uint);
-                                                       if(!param_value)
+                                       if(!jit_insn_incoming_reg(func,
+                                                                               
          param->un.reg_info[0].value,
+                                                                               
          param->un.reg_info[0].reg))
                                                        {
                                                                return 0;
                                                        }
-                                                       
if(!jit_insn_outgoing_reg(func, param_value, param->un.reg[0]))
+                                       if(!jit_insn_incoming_reg(func,
+                                                                               
          param->un.reg_info[1].value,
+                                                                               
          param->un.reg_info[1].reg))
                                                        {
                                                                return 0;
                                                        }
                                                }
-                                               else
-                                               {
-                                                       jit_value_t param_value;
+                       }
+                       break;
 
-                                                       param_value = 
jit_insn_load_relative(func, struct_ptr,
-                                                                               
                                                 8, jit_type_ulong);
-                                                       if(!param_value)
+                       default:
                                                        {
-                                                               return 0;
-                                                       }
-                                                       
if(!jit_insn_outgoing_reg(func, param_value, param->un.reg[0]))
+                               if(!jit_insn_incoming_reg(func, param->value, 
param->un.reg_info[0].reg))
                                                        {
                                                                return 0;
                                                        }
                                                }
+                       break;
+               }
                                        }
-                                       else
-                                       {
-                                               if(size <= 4)
-                                               {
-                                                       jit_value_t param_value;
+       return 1;
+}
 
-                                                       param_value = 
jit_insn_load_relative(func, struct_ptr,
-                                                                               
                                                 8, jit_type_float32);
-                                                       if(!param_value)
+int
+_jit_setup_outgoing_param(jit_function_t func, _jit_param_t *param,
+                                                 jit_type_t param_type)
+{
+       if(param->arg_class == JIT_ARG_CLASS_STACK)
                                                        {
-                                                               return 0;
-                                                       }
-                                                       
if(!jit_insn_outgoing_reg(func, param_value, param->un.reg[0]))
+               /* The parameter is passed on the stack */
+               if(!push_param(func, param, param_type))
                                                        {
                                                                return 0;
                                                        }
                                                }
                                                else
                                                {
-                                                       jit_value_t param_value;
-
-                                                       param_value = 
jit_insn_load_relative(func, struct_ptr,
-                                                                               
                                                 8, jit_type_float64);
-                                                       if(!param_value)
+               if(!jit_insn_outgoing_reg(func, param->un.reg_info[0].value,
+                                                                               
param->un.reg_info[0].reg))
                                                        {
                                                                return 0;
                                                        }
-                                                       
if(!jit_insn_outgoing_reg(func, param_value, param->un.reg[0]))
+               if(param->arg_class == 2)
                                                        {
-                                                               return 0;
-                                                       }
-                                               }
-                                       }
-                               }
-                       }
-                       break;
-
-                       default:
-                       {
-                               if(!jit_insn_outgoing_reg(func, param->value, 
param->un.reg[0]))
+                       if(!jit_insn_outgoing_reg(func, 
param->un.reg_info[1].value,
+                                                                               
        param->un.reg_info[1].reg))
                                {
                                        return 0;
                                }
                        }
-                       break;
-               }
        }
        return 1;
 }
@@ -3186,7 +2745,7 @@
                if(return_param.arg_class == 1)
                {
                        if(!jit_insn_return_reg(func, return_value,
-                                                                       
return_param.un.reg[0]))
+                                                                       
return_param.un.reg_info[0].reg))
                        {
                                return 0;
                        }
@@ -3236,6 +2795,8 @@
 int
 _jit_create_entry_insns(jit_function_t func)
 {
+       jit_value_t value;
+       int has_struct_return = 0;
        jit_type_t signature = func->signature;
        int abi = jit_type_get_abi(signature);
        unsigned int num_args = jit_type_num_params(signature);
@@ -3271,7 +2832,7 @@
        }
 
        /* Allocate the structure return pointer */
-       if(jit_value_get_struct_pointer(func))
+       if((value = jit_value_get_struct_pointer(func)))
        {
                jit_memset(&struct_return_param, 0, sizeof(_jit_param_t));
                if(!(_jit_classify_param(&passing, &struct_return_param,
@@ -3279,6 +2840,8 @@
                {
                        return 0;
                }
+               struct_return_param.value = value;
+               has_struct_return = 1;
        }
 
        /* Let the backend classify the parameters */
@@ -3315,6 +2878,30 @@
                }
        }
 
+       if(has_struct_return)
+       {
+               if(!_jit_setup_incoming_param(func, &struct_return_param, 
jit_type_void_ptr))
+               {
+                       return 0;
+               }
+       }
+
+       /* Now we flush the incoming structs passed in registers */
+       for(current_param = 0; current_param < num_args; current_param++)
+       {
+               if(param[current_param].arg_class != JIT_ARG_CLASS_STACK)
+               {
+                       jit_type_t param_type;
+
+                       param_type = jit_type_get_param(signature, 
current_param);
+                       if(!_jit_flush_incoming_struct(func, 
&(param[current_param]),
+                                                                               
   param_type))
+                       {
+                               return 0;
+                       }
+               }
+       }
+
        return 1;
 }
 
@@ -3372,12 +2959,12 @@
                        return 0;
                }
                jit_memset(&struct_return_param, 0, sizeof(_jit_param_t));
+               struct_return_param.value = return_ptr;
                if(!(_jit_classify_param(&passing, &struct_return_param,
                                                                 
jit_type_void_ptr)))
                {
                        return 0;
                }
-               struct_return_param.value = return_ptr;
        }
        else
        {
@@ -3425,27 +3012,97 @@
 #endif
 
        /* Now setup the arguments on the stack or in the registers in reverse 
order */
+       /* First process the params passed on the stack */
        current_param = num_args;
        while(current_param > 0)
        {
+               --current_param;
+               if(param[current_param].arg_class == JIT_ARG_CLASS_STACK)
+               {
                jit_type_t param_type;
 
-               --current_param;
                param_type = jit_type_get_param(signature, current_param);
                if(!_jit_setup_outgoing_param(func, &(param[current_param]), 
param_type))
                {
                        return 0;
                }
        }
+       }
+
+       /* Handle the structure return pointer if it's passed on the stack */
+       if(return_ptr)
+       {
+               if(struct_return_param.arg_class == JIT_ARG_CLASS_STACK)
+               {
+                       if(!_jit_setup_outgoing_param(func, 
&struct_return_param,
+                                                                               
  jit_type_void_ptr))
+                       {
+                               return 0;
+                       }
+               }
+       }
+
+       /* Now setup the values passed in registers */
+       current_param = num_args;
+       while(current_param > 0)
+       {
+               --current_param;
+
+               if(param[current_param].arg_class != JIT_ARG_CLASS_STACK)
+               {
+                       jit_type_t param_type;
+
+                       param_type = jit_type_get_param(signature, 
current_param);
+                       if(!_jit_setup_reg_param(func, &(param[current_param]), 
param_type))
+                       {
+                               return 0;
+                       }
+               }
+       }
+
+       /* Handle the structure return pointer if required */
+       if(return_ptr)
+       {
+               if(struct_return_param.arg_class != JIT_ARG_CLASS_STACK)
+               {
+                       if(!_jit_setup_reg_param(func, &struct_return_param,
+                                                                        
jit_type_void_ptr))
+                       {
+                               return 0;
+                       }
+               }
+       }
+
+       /* And finally assign the registers */
+       current_param = num_args;
+       while(current_param > 0)
+       {
+               --current_param;
+               if(param[current_param].arg_class != JIT_ARG_CLASS_STACK)
+               {
+                       jit_type_t param_type;
+
+                       param_type = jit_type_get_param(signature, 
current_param);
+                       if(!_jit_setup_outgoing_param(func, 
&(param[current_param]),
+                                                                               
  param_type))
+                       {
+                               return 0;
+                       }
+               }
+       }
 
        /* Add the structure return pointer if required */
        if(return_ptr)
        {
-               if(!_jit_setup_outgoing_param(func, &struct_return_param, 
return_type))
+               if(struct_return_param.arg_class != JIT_ARG_CLASS_STACK)
+               {
+                       if(!_jit_setup_outgoing_param(func, 
&struct_return_param,
+                                                                               
  jit_type_void_ptr))
                {
                        return 0;
                }
        }
+       }
 
        return 1;
 }

Index: jit/jit-rules-x86-64.ins
===================================================================
RCS file: /cvsroot/dotgnu-pnet/libjit/jit/jit-rules-x86-64.ins,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- jit/jit-rules-x86-64.ins    2 Mar 2008 17:07:06 -0000       1.1
+++ jit/jit-rules-x86-64.ins    24 Mar 2008 12:42:51 -0000      1.2
@@ -23,6 +23,7 @@
 %regclass reg x86_64_reg
 %regclass creg x86_64_creg
 %regclass rreg x86_64_rreg
+%regclass sreg x86_64_sreg
 %regclass freg x86_64_freg
 %regclass xreg x86_64_xreg
  
@@ -93,7 +94,7 @@
 JIT_OP_NFLOAT_TO_INT: stack
        [=reg, freg] -> {
                /* allocate space on the stack for 2 shorts and 1 int */
-               x86_64_sub_reg_imm_size(inst, X86_ESP, 8, 8);
+               x86_64_sub_reg_imm_size(inst, X86_64_RSP, 8, 8);
                /* store FPU control word */
                x86_64_fnstcw_membase(inst, X86_64_RSP, 0);
                /* set "round toward zero" mode */
@@ -177,6 +178,9 @@
        [reg] -> {}
 
 JIT_OP_COPY_LONG: copy
+       [=local, imm, if("$2 >= jit_min_int && $2 <= jit_max_int")] -> {
+               x86_64_mov_membase_imm_size(inst, X86_64_RBP, $1, $2, 8);
+       }
        [reg] -> {}
 
 JIT_OP_COPY_FLOAT32: copy
@@ -230,7 +234,7 @@
 
 JIT_OP_PUSH_LONG: note
        [imm] -> {
-               if(($1 >= jit_min_int) && ($1 <= jit_max_int))
+               if(($1 >= (jit_nint)jit_min_int) && ($1 <= 
(jit_nint)jit_max_int))
                {
                        x86_64_push_imm(inst, $1);
                }
@@ -252,7 +256,7 @@
                gen->stack_changed = 1;
        }
 
-JIT_OP_PUSH_FLOAT32: note, stack
+JIT_OP_PUSH_FLOAT32: note
        [imm] -> {
                jit_int *ptr = (jit_int *)($1);
                x86_64_push_imm_size(inst, ptr[0], 4);
@@ -267,13 +271,8 @@
                x86_64_movss_membase_reg(inst, X86_64_RSP, 0, $1);
                gen->stack_changed = 1;
        }
-       [freg] -> {
-               x86_64_sub_reg_imm_size(inst, X86_64_RSP, 8, 8);
-               x86_64_fstp_membase_size(inst, X86_64_RSP, 0, 4);
-               gen->stack_changed = 1;
-       }
 
-JIT_OP_PUSH_FLOAT64: note, stack
+JIT_OP_PUSH_FLOAT64: note
        [imm] -> {
                jit_int *ptr = (jit_int *)($1);
                x86_64_sub_reg_imm_size(inst, X86_64_RSP, 8, 8);
@@ -290,11 +289,6 @@
                x86_64_movsd_membase_reg(inst, X86_64_RSP, 0, $1);
                gen->stack_changed = 1;
        }
-       [freg] -> {
-               x86_64_sub_reg_imm_size(inst, X86_64_RSP, 8, 8);
-               x86_64_fstp_membase_size(inst, X86_64_RSP, 0, 8);
-               gen->stack_changed = 1;
-       }
 
 JIT_OP_PUSH_NFLOAT: note, stack
        [imm] -> {
@@ -541,7 +535,7 @@
                                                                 
jit_value_get_type(insn->dest), $4, $5);
        }
        [=frame, reg, imm, clobber(creg), clobber(xreg)] -> {
-               inst = memory_copy(gen, inst, X86_EBP, $1, $2, $3,
+               inst = memory_copy(gen, inst, X86_64_RBP, $1, $2, $3,
                                   
jit_type_get_size(jit_value_get_type(insn->dest)));
        }
 
@@ -612,7 +606,7 @@
        }
 
 JIT_OP_STORE_RELATIVE_LONG: ternary
-       [reg, imm, imm, if("$2 >= jit_min_int && $2 <= jit_max_int")] -> {
+       [reg, imm, imm, if("$2 >= (jit_nint)jit_min_int && $2 <= 
(jit_nint)jit_max_int")] -> {
                if($3 == 0)
                {
                        x86_64_mov_regp_imm_size(inst, $1, $2, 8);
@@ -683,8 +677,8 @@
        }
 
 JIT_OP_ADD_RELATIVE:
-       [reg, imm, if("$2 >= jit_min_int && $2 <= jit_max_int")] -> {
-               if(insn->value2->address != 0)
+       [reg, imm, if("$2 >= (jit_nint)jit_min_int && $2 <= 
(jit_nint)jit_max_int")] -> {
+               if($2 != 0)
                {
                        x86_64_add_reg_imm_size(inst, $1, $2, 8);
                }
@@ -751,7 +745,7 @@
 
 JIT_OP_STORE_ELEMENT_LONG: ternary
        [reg, reg, imm] -> {
-               if($3 >= jit_min_int && $3 <= jit_max_int)
+               if($3 >= (jit_nint)jit_min_int && $3 <= (jit_nint)jit_max_int)
                {
                        x86_64_mov_memindex_imm_size(inst, $1, 0, $2, 3, $3, 8);
                }
@@ -831,7 +825,7 @@
  */
 
 JIT_OP_LADD: commutative
-       [reg, imm, if("$2 >= jit_min_int && $2 <= jit_max_int")] -> {
+       [reg, imm, if("$2 >= (jit_nint)jit_min_int && $2 <= 
(jit_nint)jit_max_int")] -> {
                if($2 == 1)
                {
                        x86_64_inc_reg_size(inst, $1, 8);
@@ -849,7 +843,7 @@
        }
 
 JIT_OP_LSUB:
-       [reg, imm, if("$2 >= jit_min_int && $2 <= jit_max_int")] -> {
+       [reg, imm, if("$2 >= (jit_nint)jit_min_int && $2 <= 
(jit_nint)jit_max_int")] -> {
                if($2 == 1)
                {
                        x86_64_dec_reg_size(inst, $1, 8);
@@ -1008,8 +1002,32 @@
                x86_64_not_reg_size(inst, $1, 4);
        }
 
+JIT_OP_ISHL:
+       [reg, imm] -> {
+               x86_64_shl_reg_imm_size(inst, $1, ($2 & 0x1F), 4);
+       }
+       [sreg, reg("rcx")] -> {
+               x86_64_shl_reg_size(inst, $1, 4);
+       }
+
+JIT_OP_ISHR:
+       [reg, imm] -> {
+               x86_64_sar_reg_imm_size(inst, $1, ($2 & 0x1F), 4);
+       }
+       [sreg, reg("rcx")] -> {
+               x86_64_sar_reg_size(inst, $1, 4);
+       }
+
+JIT_OP_ISHR_UN:
+       [reg, imm] -> {
+               x86_64_shr_reg_imm_size(inst, $1, ($2 & 0x1F), 4);
+       }
+       [sreg, reg("rcx")] -> {
+               x86_64_shr_reg_size(inst, $1, 4);
+       }
+
 JIT_OP_LAND: commutative
-       [reg, imm, if("($2 >= jit_min_int && $2 <= jit_max_int)")] -> {
+       [reg, imm, if("($2 >= (jit_nint)jit_min_int && $2 <= 
(jit_nint)jit_max_int)")] -> {
                x86_64_and_reg_imm_size(inst, $1, $2, 8);
        }
        [reg, local] -> {
@@ -1020,7 +1038,7 @@
        }
 
 JIT_OP_LOR: commutative
-       [reg, imm, if("($2 >= jit_min_int && $2 <= jit_max_int)")] -> {
+       [reg, imm, if("($2 >= (jit_nint)jit_min_int && $2 <= 
(jit_nint)jit_max_int)")] -> {
                x86_64_or_reg_imm_size(inst, $1, $2, 8);
        }
        [reg, local] -> {
@@ -1031,7 +1049,7 @@
        }
 
 JIT_OP_LXOR: commutative
-       [reg, imm, if("($2 >= jit_min_int && $2 <= jit_max_int)")] -> {
+       [reg, imm, if("($2 >= (jit_nint)jit_min_int && $2 <= 
(jit_nint)jit_max_int)")] -> {
                x86_64_xor_reg_imm_size(inst, $1, $2, 8);
        }
        [reg, local] -> {
@@ -1046,7 +1064,29 @@
                x86_64_not_reg_size(inst, $1, 8);
        }
 
+JIT_OP_LSHL:
+       [reg, imm] -> {
+               x86_64_shl_reg_imm_size(inst, $1, ($2 & 0x3F), 8);
+       }
+       [sreg, reg("rcx")] -> {
+               x86_64_shl_reg_size(inst, $1, 8);
+       }
+
+JIT_OP_LSHR:
+       [reg, imm] -> {
+               x86_64_sar_reg_imm_size(inst, $1, ($2 & 0x3F), 8);
+       }
+       [sreg, reg("rcx")] -> {
+               x86_64_sar_reg_size(inst, $1, 8);
+       }
 
+JIT_OP_LSHR_UN:
+       [reg, imm] -> {
+               x86_64_shr_reg_imm_size(inst, $1, ($2 & 0x3F), 8);
+       }
+       [sreg, reg("rcx")] -> {
+               x86_64_shr_reg_size(inst, $1, 8);
+       }
 
 /*
  * Branch opcodes.
@@ -1234,7 +1274,7 @@
                x86_64_or_reg_reg_size(inst, $1, $1, 8);
                inst = output_branch(func, inst, 0x74 /* eq */, insn);
        }
-       [reg, imm, if("($2 >= jit_min_int && $2 <= jit_max_int)")] -> {
+       [reg, imm, if("($2 >= (jit_nint)jit_min_int && $2 <= 
(jit_nint)jit_max_int)")] -> {
                x86_64_cmp_reg_imm_size(inst, $1, $2, 8);
                inst = output_branch(func, inst, 0x74 /* eq */, insn);
        }
@@ -1252,7 +1292,7 @@
                x86_64_or_reg_reg_size(inst, $1, $1, 8);
                inst = output_branch(func, inst, 0x75 /* ne */, insn);
        }
-       [reg, imm, if("($2 >= jit_min_int && $2 <= jit_max_int)")] -> {
+       [reg, imm, if("($2 >= (jit_nint)jit_min_int && $2 <= 
(jit_nint)jit_max_int)")] -> {
                x86_64_cmp_reg_imm_size(inst, $1, $2, 8);
                inst = output_branch(func, inst, 0x75 /* ne */, insn);
        }
@@ -1266,7 +1306,7 @@
        }
 
 JIT_OP_BR_LLT: branch
-       [reg, imm, if("($2 >= jit_min_int && $2 <= jit_max_int)")] -> {
+       [reg, imm, if("($2 >= (jit_nint)jit_min_int && $2 <= 
(jit_nint)jit_max_int)")] -> {
                x86_64_cmp_reg_imm_size(inst, $1, $2, 8);
                inst = output_branch(func, inst, 0x7C /* lt */, insn);
        }
@@ -1280,7 +1320,7 @@
        }
 
 JIT_OP_BR_LLT_UN: branch
-       [reg, imm, if("($2 >= jit_min_int && $2 <= jit_max_int)")] -> {
+       [reg, imm, if("($2 >= (jit_nint)jit_min_int && $2 <= 
(jit_nint)jit_max_int)")] -> {
                x86_64_cmp_reg_imm_size(inst, $1, $2, 8);
                inst = output_branch(func, inst, 0x72 /* lt_un */, insn);
        }
@@ -1294,7 +1334,7 @@
        }
 
 JIT_OP_BR_LLE: branch
-       [reg, imm, if("($2 >= jit_min_int && $2 <= jit_max_int)")] -> {
+       [reg, imm, if("($2 >= (jit_nint)jit_min_int && $2 <= 
(jit_nint)jit_max_int)")] -> {
                x86_64_cmp_reg_imm_size(inst, $1, $2, 8);
                inst = output_branch(func, inst, 0x7E /* le */, insn);
        }
@@ -1308,7 +1348,7 @@
        }
 
 JIT_OP_BR_LLE_UN: branch
-       [reg, imm, if("($2 >= jit_min_int && $2 <= jit_max_int)")] -> {
+       [reg, imm, if("($2 >= (jit_nint)jit_min_int && $2 <= 
(jit_nint)jit_max_int)")] -> {
                x86_64_cmp_reg_imm_size(inst, $1, $2, 8);
                inst = output_branch(func, inst, 0x76 /* le_un */, insn);
        }
@@ -1322,7 +1362,7 @@
        }
 
 JIT_OP_BR_LGT: branch
-       [reg, imm, if("($2 >= jit_min_int && $2 <= jit_max_int)")] -> {
+       [reg, imm, if("($2 >= (jit_nint)jit_min_int && $2 <= 
(jit_nint)jit_max_int)")] -> {
                x86_64_cmp_reg_imm_size(inst, $1, $2, 8);
                inst = output_branch(func, inst, 0x7F /* gt */, insn);
        }
@@ -1336,7 +1376,7 @@
        }
 
 JIT_OP_BR_LGT_UN: branch
-       [reg, imm, if("($2 >= jit_min_int && $2 <= jit_max_int)")] -> {
+       [reg, imm, if("($2 >= (jit_nint)jit_min_int && $2 <= 
(jit_nint)jit_max_int)")] -> {
                x86_64_cmp_reg_imm_size(inst, $1, $2, 8);
                inst = output_branch(func, inst, 0x77 /* gt_un */, insn);
        }
@@ -1350,7 +1390,7 @@
        }
 
 JIT_OP_BR_LGE: branch
-       [reg, imm, if("($2 >= jit_min_int && $2 <= jit_max_int)")] -> {
+       [reg, imm, if("($2 >= (jit_nint)jit_min_int && $2 <= 
(jit_nint)jit_max_int)")] -> {
                x86_64_cmp_reg_imm_size(inst, $1, $2, 8);
                inst = output_branch(func, inst, 0x7D /* ge */, insn);
        }
@@ -1364,7 +1404,7 @@
        }
 
 JIT_OP_BR_LGE_UN: branch
-       [reg, imm, if("($2 >= jit_min_int && $2 <= jit_max_int)")] -> {
+       [reg, imm, if("($2 >= (jit_nint)jit_min_int && $2 <= 
(jit_nint)jit_max_int)")] -> {
                x86_64_cmp_reg_imm_size(inst, $1, $2, 8);
                inst = output_branch(func, inst, 0x73 /* ge_un */, insn);
        }
@@ -1534,7 +1574,7 @@
                x86_64_or_reg_reg_size(inst, $2, $2, 8);
                inst = setcc_reg(inst, $1, X86_CC_EQ, 0);
        }
-       [=reg, reg, imm, if("$3 >= jit_min_int && $3 <= jit_max_int")] -> {
+       [=reg, reg, imm, if("$3 >= (jit_nint)jit_min_int && $3 <= 
(jit_nint)jit_max_int")] -> {
                x86_64_cmp_reg_imm_size(inst, $2, $3, 8);
                inst = setcc_reg(inst, $1, X86_CC_EQ, 0);
        }
@@ -1552,7 +1592,7 @@
                x86_64_or_reg_reg_size(inst, $2, $2, 8);
                inst = setcc_reg(inst, $1, X86_CC_NE, 0);
        }
-       [=reg, reg, imm, if("$3 >= jit_min_int && $3 <= jit_max_int")] -> {
+       [=reg, reg, imm, if("$3 >= (jit_nint)jit_min_int && $3 <= 
(jit_nint)jit_max_int")] -> {
                x86_64_cmp_reg_imm_size(inst, $2, $3, 8);
                inst = setcc_reg(inst, $1, X86_CC_NE, 0);
        }
@@ -1566,7 +1606,7 @@
        }
 
 JIT_OP_LLT:
-       [=reg, reg, imm, if("$3 >= jit_min_int && $3 <= jit_max_int")] -> {
+       [=reg, reg, imm, if("$3 >= (jit_nint)jit_min_int && $3 <= 
(jit_nint)jit_max_int")] -> {
                x86_64_cmp_reg_imm_size(inst, $2, $3, 8);
                inst = setcc_reg(inst, $1, X86_CC_LT, 1);
        }
@@ -1580,7 +1620,7 @@
        }
 
 JIT_OP_LLT_UN:
-       [=reg, reg, imm, if("$3 >= jit_min_int && $3 <= jit_max_int")] -> {
+       [=reg, reg, imm, if("$3 >= (jit_nint)jit_min_int && $3 <= 
(jit_nint)jit_max_int")] -> {
                x86_64_cmp_reg_imm_size(inst, $2, $3, 8);
                inst = setcc_reg(inst, $1, X86_CC_LT, 0);
        }
@@ -1594,7 +1634,7 @@
        }
 
 JIT_OP_LLE:
-       [=reg, reg, imm, if("$3 >= jit_min_int && $3 <= jit_max_int")] -> {
+       [=reg, reg, imm, if("$3 >= (jit_nint)jit_min_int && $3 <= 
(jit_nint)jit_max_int")] -> {
                x86_64_cmp_reg_imm_size(inst, $2, $3, 8);
                inst = setcc_reg(inst, $1, X86_CC_LE, 1);
        }
@@ -1608,7 +1648,7 @@
        }
 
 JIT_OP_LLE_UN:
-       [=reg, reg, imm, if("$3 >= jit_min_int && $3 <= jit_max_int")] -> {
+       [=reg, reg, imm, if("$3 >= (jit_nint)jit_min_int && $3 <= 
(jit_nint)jit_max_int")] -> {
                x86_64_cmp_reg_imm_size(inst, $2, $3, 8);
                inst = setcc_reg(inst, $1, X86_CC_LE, 0);
        }
@@ -1622,7 +1662,7 @@
        }
 
 JIT_OP_LGT:
-       [=reg, reg, imm, if("$3 >= jit_min_int && $3 <= jit_max_int")] -> {
+       [=reg, reg, imm, if("$3 >= (jit_nint)jit_min_int && $3 <= 
(jit_nint)jit_max_int")] -> {
                x86_64_cmp_reg_imm_size(inst, $2, $3, 8);
                inst = setcc_reg(inst, $1, X86_CC_GT, 1);
        }
@@ -1636,7 +1676,7 @@
        }
 
 JIT_OP_LGT_UN:
-       [=reg, reg, imm, if("$3 >= jit_min_int && $3 <= jit_max_int")] -> {
+       [=reg, reg, imm, if("$3 >= (jit_nint)jit_min_int && $3 <= 
(jit_nint)jit_max_int")] -> {
                x86_64_cmp_reg_imm_size(inst, $2, $3, 8);
                inst = setcc_reg(inst, $1, X86_CC_GT, 0);
        }
@@ -1650,7 +1690,7 @@
        }
 
 JIT_OP_LGE:
-       [=reg, reg, imm, if("$3 >= jit_min_int && $3 <= jit_max_int")] -> {
+       [=reg, reg, imm, if("$3 >= (jit_nint)jit_min_int && $3 <= 
(jit_nint)jit_max_int")] -> {
                x86_64_cmp_reg_imm_size(inst, $2, $3, 8);
                inst = setcc_reg(inst, $1, X86_CC_GE, 1);
        }
@@ -1664,7 +1704,7 @@
        }
 
 JIT_OP_LGE_UN:
-       [=reg, reg, imm, if("$3 >= jit_min_int && $3 <= jit_max_int")] -> {
+       [=reg, reg, imm, if("$3 >= (jit_nint)jit_min_int && $3 <= 
(jit_nint)jit_max_int")] -> {
                x86_64_cmp_reg_imm_size(inst, $2, $3, 8);
                inst = setcc_reg(inst, $1, X86_CC_GE, 0);
        }
@@ -1873,6 +1913,14 @@
        [reg, reg, imm, clobber(creg), clobber(xreg)] -> {
                inst = memory_copy(gen, inst, $1, 0, $2, 0, $3);
        }
+       [reg("rdi"), reg("rsi"), reg("rdx"), clobber(creg), clobber(xreg)] -> {
+               inst = x86_64_call_code(inst, (jit_nint)jit_memcpy);
+       }
+
+JIT_OP_MEMSET: ternary
+       [reg("rdi"), reg("rsi"), reg("rdx"), clobber(creg), clobber(xreg)] -> {
+               inst = x86_64_call_code(inst, (jit_nint)jit_memset);
+       }
 
 JIT_OP_JUMP_TABLE: ternary, branch
        [reg, imm, imm, scratch reg, space("64")] -> {




reply via email to

[Prev in Thread] Current Thread [Next in Thread]