[ppc] Fix passing of structure parameters as per the ELF ABI v2. Add 5 new test...
authorBill Seurer <seurer@linux.vnet.ibm.com>
Mon, 31 Aug 2015 21:07:02 +0000 (16:07 -0500)
committerBill Seurer <seurer@linux.vnet.ibm.com>
Thu, 10 Sep 2015 16:57:02 +0000 (11:57 -0500)
mono/mini/mini-ppc.c
mono/mini/mini-ppc.h
mono/tests/Makefile.am
mono/tests/libtest.c
mono/tests/pinvoke_ppcc.cs [new file with mode: 0644]
mono/tests/pinvoke_ppcd.cs [new file with mode: 0644]
mono/tests/pinvoke_ppcf.cs [new file with mode: 0644]
mono/tests/pinvoke_ppci.cs [new file with mode: 0644]
mono/tests/pinvoke_ppcs.cs [new file with mode: 0644]

index b905b412e660822a27650d885108a1716085e920..70c4d8cd5d0a8cf8e6fca67fee73f04e01e7fc64 100644 (file)
@@ -206,7 +206,7 @@ emit_memcpy (guint8 *code, int size, int dreg, int doffset, int sreg, int soffse
        }
 #ifdef __mono_ppc64__
        /* the hardware has multiple load/store units and the move is long
-          enough to use more then one regiester, then use load/load/store/store
+          enough to use more then one register, then use load/load/store/store
           to execute 2 instructions per cycle. */
        if ((cpu_hw_caps & PPC_MULTIPLE_LS_UNITS) && (dreg != ppc_r11) && (sreg != ppc_r11)) { 
                while (size >= 16) {
@@ -872,18 +872,19 @@ enum {
        RegTypeBase,
        RegTypeFP,
        RegTypeStructByVal,
-       RegTypeStructByAddr
+       RegTypeStructByAddr,
+       RegTypeFPStructByVal,  // For the v2 ABI, floats should be passed in FRs instead of GRs.  Only valid for ABI v2!
 };
 
 typedef struct {
        gint32  offset;
        guint32 vtsize; /* in param area */
        guint8  reg;
-       guint8  vtregs; /* number of registers used to pass a RegTypeStructByVal */
+       guint8  vtregs; /* number of registers used to pass a RegTypeStructByVal/RegTypeFPStructByVal */
        guint8  regtype : 4; /* 0 general, 1 basereg, 2 floating point register, see RegType* */
-       guint8  size    : 4; /* 1, 2, 4, 8, or regs used by RegTypeStructByVal */
+       guint8  size    : 4; /* 1, 2, 4, 8, or regs used by RegTypeStructByVal/RegTypeFPStructByVal */
        guint8  bytes   : 4; /* size in bytes - only valid for
-                               RegTypeStructByVal if the struct fits
+                               RegTypeStructByVal/RegTypeFPStructByVal if the struct fits
                                in one word, otherwise it's 0*/
 } ArgInfo;
 
@@ -939,7 +940,7 @@ add_general (guint *gr, guint *stack_size, ArgInfo *ainfo, gboolean simple)
        (*gr) ++;
 }
 
-#if defined(__APPLE__) || defined(__mono_ppc64__)
+#if defined(__APPLE__) || (defined(__mono_ppc64__) && !PPC_PASS_SMALL_FLOAT_STRUCTS_IN_FR_REGS)
 static gboolean
 has_only_a_r48_field (MonoClass *klass)
 {
@@ -1076,9 +1077,7 @@ get_call_info (MonoMethodSignature *sig)
                case MONO_TYPE_VALUETYPE:
                case MONO_TYPE_TYPEDBYREF: {
                        gint size;
-                       MonoClass *klass;
-
-                       klass = mono_class_from_mono_type (sig->params [i]);
+                       MonoClass *klass = mono_class_from_mono_type (sig->params [i]);
                        if (simpletype->type == MONO_TYPE_TYPEDBYREF)
                                size = sizeof (MonoTypedRef);
                        else if (is_pinvoke)
@@ -1086,7 +1085,7 @@ get_call_info (MonoMethodSignature *sig)
                        else
                            size = mono_class_value_size (klass, NULL);
 
-#if defined(__APPLE__) || defined(__mono_ppc64__)
+#if defined(__APPLE__) || (defined(__mono_ppc64__) && !PPC_PASS_SMALL_FLOAT_STRUCTS_IN_FR_REGS)
                        if ((size == 4 || size == 8) && has_only_a_r48_field (klass)) {
                                cinfo->args [n].size = size;
 
@@ -1119,24 +1118,57 @@ get_call_info (MonoMethodSignature *sig)
                                int align_size = size;
                                int nregs = 0;
                                int rest = PPC_LAST_ARG_REG - gr + 1;
-                               int n_in_regs;
-
-                               align_size += (sizeof (gpointer) - 1);
-                               align_size &= ~(sizeof (gpointer) - 1);
-                               nregs = (align_size + sizeof (gpointer) -1 ) / sizeof (gpointer);
-                               n_in_regs = MIN (rest, nregs);
-                               if (n_in_regs < 0)
-                                       n_in_regs = 0;
+                               int n_in_regs = 0;
+
+#if PPC_PASS_SMALL_FLOAT_STRUCTS_IN_FR_REGS
+                               int mbr_cnt = 0;
+                               int mbr_size = 0;
+                               gboolean is_all_floats = mini_type_is_hfa (sig->params [i], &mbr_cnt, &mbr_size);
+
+                               if (is_all_floats && (mbr_cnt <= 8)) {
+                                       rest = PPC_LAST_FPARG_REG - fr + 1;
+                               }
+                               // Pass small (<= 8 member) structures entirely made up of either float or double members
+                               // in FR registers.  There have to be at least mbr_cnt registers left.
+                               if (is_all_floats &&
+                                        (rest >= mbr_cnt) &&
+                                        (mbr_cnt <= 8)) {
+                                       nregs = mbr_cnt;
+                                       n_in_regs = MIN (rest, nregs);
+                                       cinfo->args [n].regtype = RegTypeFPStructByVal;
+                                       cinfo->args [n].vtregs = n_in_regs;
+                                       cinfo->args [n].size = mbr_size;
+                                       cinfo->args [n].vtsize = nregs - n_in_regs;
+                                       cinfo->args [n].reg = fr;
+                                       fr += n_in_regs;
+                                       if (mbr_size == 4) {
+                                               // floats
+                                               FP_ALSO_IN_REG (gr += (n_in_regs+1)/2);
+                                       } else {
+                                               // doubles
+                                               FP_ALSO_IN_REG (gr += (n_in_regs));
+                                       }
+                               } else
+#endif
+                               {
+                                       align_size += (sizeof (gpointer) - 1);
+                                       align_size &= ~(sizeof (gpointer) - 1);
+                                       nregs = (align_size + sizeof (gpointer) -1 ) / sizeof (gpointer);
+                                       n_in_regs = MIN (rest, nregs);
+                                       if (n_in_regs < 0)
+                                               n_in_regs = 0;
 #ifdef __APPLE__
-                               /* FIXME: check this */
-                               if (size >= 3 && size % 4 != 0)
-                                       n_in_regs = 0;
+                                       /* FIXME: check this */
+                                       if (size >= 3 && size % 4 != 0)
+                                               n_in_regs = 0;
 #endif
-                               cinfo->args [n].regtype = RegTypeStructByVal;
-                               cinfo->args [n].vtregs = n_in_regs;
-                               cinfo->args [n].size = n_in_regs;
-                               cinfo->args [n].vtsize = nregs - n_in_regs;
-                               cinfo->args [n].reg = gr;
+                                       cinfo->args [n].regtype = RegTypeStructByVal;
+                                       cinfo->args [n].vtregs = n_in_regs;
+                                       cinfo->args [n].size = n_in_regs;
+                                       cinfo->args [n].vtsize = nregs - n_in_regs;
+                                       cinfo->args [n].reg = gr;
+                                       gr += n_in_regs;
+                               }
 
 #ifdef __mono_ppc64__
                                if (nregs == 1 && is_pinvoke)
@@ -1144,7 +1176,6 @@ get_call_info (MonoMethodSignature *sig)
                                else
 #endif
                                        cinfo->args [n].bytes = 0;
-                               gr += n_in_regs;
                                cinfo->args [n].offset = PPC_STACK_PARAM_OFFSET + stack_size;
                                /*g_print ("offset for arg %d at %d\n", n, PPC_STACK_PARAM_OFFSET + stack_size);*/
                                stack_size += nregs * sizeof (gpointer);
@@ -1605,6 +1636,17 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call)
                        ins->inst_p1 = mono_mempool_alloc (cfg->mempool, sizeof (ArgInfo));
                        memcpy (ins->inst_p1, ainfo, sizeof (ArgInfo));
                        MONO_ADD_INS (cfg->cbb, ins);
+               } else if (ainfo->regtype == RegTypeFPStructByVal) {
+                       /* this is further handled in mono_arch_emit_outarg_vt () */
+                       MONO_INST_NEW (cfg, ins, OP_OUTARG_VT);
+                       ins->opcode = OP_OUTARG_VT;
+                       ins->sreg1 = in->dreg;
+                       ins->klass = in->klass;
+                       ins->inst_p0 = call;
+                       ins->inst_p1 = mono_mempool_alloc (cfg->mempool, sizeof (ArgInfo));
+                       memcpy (ins->inst_p1, ainfo, sizeof (ArgInfo));
+                       MONO_ADD_INS (cfg->cbb, ins);
+                       cfg->flags |= MONO_CFG_HAS_FPOUT;
                } else if (ainfo->regtype == RegTypeBase) {
                        if (!t->byref && ((t->type == MONO_TYPE_I8) || (t->type == MONO_TYPE_U8))) {
                                MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI8_MEMBASE_REG, ppc_r1, ainfo->offset, in->dreg);
@@ -1708,20 +1750,39 @@ mono_arch_emit_outarg_vt (MonoCompile *cfg, MonoInst *ins, MonoInst *src)
                } else
 #endif
                        for (i = 0; i < ainfo->vtregs; ++i) {
+                               dreg = mono_alloc_ireg (cfg);
+#if G_BYTE_ORDER == G_BIG_ENDIAN
                                int antipadding = 0;
                                if (ainfo->bytes) {
                                        g_assert (i == 0);
                                        antipadding = sizeof (gpointer) - ainfo->bytes;
                                }
-                               dreg = mono_alloc_ireg (cfg);
                                MONO_EMIT_NEW_LOAD_MEMBASE (cfg, dreg, src->dreg, soffset);
                                if (antipadding)
                                        MONO_EMIT_NEW_BIALU_IMM (cfg, OP_SHR_UN_IMM, dreg, dreg, antipadding * 8);
+#else
+                               MONO_EMIT_NEW_LOAD_MEMBASE (cfg, dreg, src->dreg, soffset);
+#endif
                                mono_call_inst_add_outarg_reg (cfg, call, dreg, ainfo->reg + i, FALSE);
                                soffset += sizeof (gpointer);
                        }
                if (ovf_size != 0)
                        mini_emit_memcpy (cfg, ppc_r1, doffset + soffset, src->dreg, soffset, ovf_size * sizeof (gpointer), 0);
+       } else if (ainfo->regtype == RegTypeFPStructByVal) {
+               soffset = 0;
+               for (i = 0; i < ainfo->vtregs; ++i) {
+                       int tmpr = mono_alloc_freg (cfg);
+                       if (ainfo->size == 4)
+                               MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADR4_MEMBASE, tmpr, src->dreg, soffset);
+                       else // ==8
+                               MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADR8_MEMBASE, tmpr, src->dreg, soffset);
+                       dreg = mono_alloc_freg (cfg);
+                       MONO_EMIT_NEW_UNALU (cfg, OP_FMOVE, dreg, tmpr);
+                       mono_call_inst_add_outarg_reg (cfg, call, dreg, ainfo->reg+i, TRUE);
+                       soffset += ainfo->size;
+                       }
+               if (ovf_size != 0)
+                       mini_emit_memcpy (cfg, ppc_r1, doffset + soffset, src->dreg, soffset, ovf_size * sizeof (gpointer), 0);
        } else if (ainfo->regtype == RegTypeFP) {
                int tmpr = mono_alloc_freg (cfg);
                if (ainfo->size == 4)
@@ -1890,6 +1951,7 @@ mono_arch_instrument_epilog_full (MonoCompile *cfg, void *func, void *p, gboolea
                if (enable_arguments) {
                        /* FIXME: get the actual address  */
                        ppc_mr (code, ppc_r4, ppc_r3);
+                       // FIXME: Support the new v2 ABI!
                }
                break;
        case SAVE_NONE:
@@ -3882,6 +3944,16 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        ppc_ldptr (code, ppc_r2, 8, ins->sreg1);
                        ppc_mtlr (code, ppc_r0);
 #else
+#if (_CALL_ELF == 2)
+                       if (ins->flags & MONO_INST_HAS_METHOD) {
+                         // Not a global entry point
+                       } else {
+                                // Need to set up r12 with function entry address for global entry point
+                                if (ppc_r12 != ins->sreg1) {
+                                        ppc_mr(code,ppc_r12,ins->sreg1);
+                                }
+                       }
+#endif
                        ppc_mtlr (code, ins->sreg1);
 #endif
                        ppc_blrl (code);
@@ -5030,6 +5102,25 @@ mono_arch_emit_prolog (MonoCompile *cfg)
                                        ppc_stfs (code, ainfo->reg, inst->inst_offset, inst->inst_basereg);
                                else
                                        g_assert_not_reached ();
+                        } else if (ainfo->regtype == RegTypeFPStructByVal) {
+                               int doffset = inst->inst_offset;
+                               int soffset = 0;
+                               int cur_reg;
+                               int size = 0;
+                               g_assert (ppc_is_imm16 (inst->inst_offset));
+                               g_assert (ppc_is_imm16 (inst->inst_offset + ainfo->vtregs * sizeof (gpointer)));
+                               /* FIXME: what if there is no class? */
+                               if (sig->pinvoke && mono_class_from_mono_type (inst->inst_vtype))
+                                       size = mono_class_native_size (mono_class_from_mono_type (inst->inst_vtype), NULL);
+                               for (cur_reg = 0; cur_reg < ainfo->vtregs; ++cur_reg) {
+                                       if (ainfo->size == 4) {
+                                               ppc_stfs (code, ainfo->reg + cur_reg, doffset, inst->inst_basereg);
+                                       } else {
+                                               ppc_stfd (code, ainfo->reg + cur_reg, doffset, inst->inst_basereg);
+                                       }
+                                       soffset += ainfo->size;
+                                       doffset += ainfo->size;
+                               }
                        } else if (ainfo->regtype == RegTypeStructByVal) {
                                int doffset = inst->inst_offset;
                                int soffset = 0;
@@ -5059,9 +5150,21 @@ mono_arch_emit_prolog (MonoCompile *cfg)
 #ifdef __mono_ppc64__
                                                if (ainfo->bytes) {
                                                        g_assert (cur_reg == 0);
+#if G_BYTE_ORDER == G_BIG_ENDIAN
                                                        ppc_sldi (code, ppc_r0, ainfo->reg,
-                                                                       (sizeof (gpointer) - ainfo->bytes) * 8);
+                                                                        (sizeof (gpointer) - ainfo->bytes) * 8);
                                                        ppc_stptr (code, ppc_r0, doffset, inst->inst_basereg);
+#else
+                                                       if (mono_class_native_size (inst->klass, NULL) == 1) {
+                                                         ppc_stb (code, ainfo->reg + cur_reg, doffset, inst->inst_basereg);
+                                                       } else if (mono_class_native_size (inst->klass, NULL) == 2) {
+                                                               ppc_sth (code, ainfo->reg + cur_reg, doffset, inst->inst_basereg);
+                                                       } else if (mono_class_native_size (inst->klass, NULL) == 4) {  // WDS -- maybe <=4?
+                                                               ppc_stw (code, ainfo->reg + cur_reg, doffset, inst->inst_basereg);
+                                                       } else {
+                                                               ppc_stptr (code, ainfo->reg + cur_reg, doffset, inst->inst_basereg);  // WDS -- Better way?
+                                                       }
+#endif
                                                } else
 #endif
                                                {
@@ -6039,3 +6142,16 @@ mono_arch_opcode_supported (int opcode)
                return FALSE;
        }
 }
+
+
+#if 0
+// FIXME: To get the test case  finally_block_ending_in_dead_bb  to work properly we need to define the following
+// (in mini-ppc.h) and then implement the fuction mono_arch_create_handler_block_trampoline.
+//  #define MONO_ARCH_HAVE_HANDLER_BLOCK_GUARD 1
+
+gpointer
+mono_arch_create_handler_block_trampoline (void)
+{
+       . . .
+}
+#endif
index 45e5dc3e60acc2d8147222b66a121de57e5a22b0..0c0c21084d39d8c464bc28c5eef7dd64f930fbe6 100644 (file)
@@ -135,6 +135,8 @@ typedef struct MonoCompileArch {
 #define PPC_FIRST_FPARG_REG ppc_f1
 #define PPC_LAST_FPARG_REG ppc_f13
 #define PPC_PASS_STRUCTS_BY_VALUE 1
+#define PPC_PASS_SMALL_FLOAT_STRUCTS_IN_FR_REGS 0
+#define MONO_ARCH_HAVE_DECOMPOSE_VTYPE_OPTS 0
 #else
 /* Linux */
 #ifdef __mono_ppc64__
@@ -143,9 +145,19 @@ typedef struct MonoCompileArch {
  #if (_CALL_ELF == 2)
   #define PPC_STACK_PARAM_OFFSET 32
   #define PPC_MINIMAL_STACK_SIZE 32
+  #define PPC_PASS_SMALL_FLOAT_STRUCTS_IN_FR_REGS 1
+  #define MONO_ARCH_HAVE_DECOMPOSE_VTYPE_OPTS 1
+// FIXME: To get the test case  finally_block_ending_in_dead_bb  to work properly we need to define the following
+// and then implement the fuction mono_arch_create_handler_block_trampoline.
+//  #define MONO_ARCH_HAVE_HANDLER_BLOCK_GUARD 1
+
+//  #define DEBUG_ELFABIV2
+
  #else
   #define PPC_STACK_PARAM_OFFSET 48
   #define PPC_MINIMAL_STACK_SIZE 48
+  #define PPC_PASS_SMALL_FLOAT_STRUCTS_IN_FR_REGS 0
+  #define MONO_ARCH_HAVE_DECOMPOSE_VTYPE_OPTS 0
  #endif
 #define MONO_ARCH_HAVE_SETUP_ASYNC_CALLBACK 1
 #define PPC_MINIMAL_PARAM_AREA_SIZE 64
@@ -160,6 +172,13 @@ typedef struct MonoCompileArch {
 #define PPC_MINIMAL_PARAM_AREA_SIZE 0
 #define PPC_LAST_FPARG_REG ppc_f8
 #define PPC_PASS_STRUCTS_BY_VALUE 0
+#define PPC_LARGEST_STRUCT_SIZE_TO_RETURN_VIA_REGISTERS 0
+#define PPC_MOST_FLOAT_STRUCT_MEMBERS_TO_RETURN_VIA_REGISTERS 0
+#define PPC_PASS_SMALL_FLOAT_STRUCTS_IN_FR_REGS 0
+#define PPC_RETURN_SMALL_FLOAT_STRUCTS_IN_FR_REGS 0
+#define PPC_RETURN_SMALL_STRUCTS_IN_REGS 0
+#define MONO_ARCH_HAVE_DECOMPOSE_VTYPE_OPTS 0
+#define MONO_ARCH_RETURN_CAN_USE_MULTIPLE_REGISTERS 0
 #define PPC_THREAD_PTR_REG ppc_r2
 #endif
 #define PPC_FIRST_ARG_REG ppc_r3
@@ -198,6 +217,7 @@ typedef struct MonoCompileArch {
 #define MONO_ARCH_HAVE_OP_TAIL_CALL 1
 
 #define PPC_NUM_REG_ARGS (PPC_LAST_ARG_REG-PPC_FIRST_ARG_REG+1)
+#define PPC_NUM_REG_FPARGS (PPC_LAST_FPARG_REG-PPC_FIRST_FPARG_REG+1)
 
 #ifdef MONO_CROSS_COMPILE
 
@@ -323,4 +343,31 @@ void mono_ppc_patch_plt_entry (guint8 *code, gpointer *got, mgreg_t *regs, guint
 
 void mono_ppc_set_func_into_sigctx (void *sigctx, void *func);
 
+
+// Debugging macros for ELF ABI v2
+#ifdef DEBUG_ELFABIV2
+
+#define DEBUG_ELFABIV2_printf(a, ...) \
+{if (getenv("DEBUG_ELFABIV2")) { printf(a, ##__VA_ARGS__); fflush(stdout); } }
+
+#define DEBUG_ELFABIV2_mono_print_ins(a) \
+{if (getenv("DEBUG_ELFABIV2")) { if (!a) {printf("null\n");} else {mono_print_ins(a);} fflush(stdout); } }
+
+extern char* mono_type_full_name (MonoType *type);
+
+#define DEBUG_ELFABIV2_mono_print_type(a) \
+{if (getenv("DEBUG_ELFABIV2")) { printf("%s, size: %d\n", mono_type_get_name(&a->klass->byval_arg), mini_type_stack_size (NULL, a, 0)); fflush(stdout); } }
+
+#define DEBUG_ELFABIV2_mono_print_class(a) \
+{if (getenv("DEBUG_ELFABIV2")) { printf("%s\n", mono_type_get_name(&a->byval_arg)); fflush(stdout); } }
+
+#else
+
+#define DEBUG_ELFABIV2_printf(a, ...)
+#define DEBUG_ELFABIV2_mono_print_ins(a)
+#define DEBUG_ELFABIV2_mono_print_type(a)
+#define DEBUG_ELFABIV2_mono_print_class(a)
+
+#endif
+
 #endif /* __MONO_MINI_PPC_H__ */
index 7908b246f4640e711f6f9d0aa71391272d8d131e..02057eb5c205d655ae227a8fca2e21cfac21d518 100644 (file)
@@ -417,7 +417,12 @@ BASE_TEST_CS_SRC=          \
        sleep.cs \
        bug-27147.cs    \
        bug-30085.cs    \
-       bug-17537.cs
+       bug-17537.cs    \
+       pinvoke_ppcc.cs \
+       pinvoke_ppcs.cs \
+       pinvoke_ppci.cs \
+       pinvoke_ppcf.cs \
+       pinvoke_ppcd.cs
 
 TEST_CS_SRC_DIST=      \
        $(BASE_TEST_CS_SRC)     \
@@ -464,8 +469,8 @@ PLATFORM_DISABLED_TESTS=finalizer-abort.exe finalizer-exception.exe finalizer-ex
 endif
 
 if POWERPC64
-# These tests hang
-PLATFORM_DISABLED_TESTS=monitor.exe finalizer-abort.exe finalizer-exception.exe finalizer-exit.exe
+# FIXME: These tests hang/fail for unknown reasons
+PLATFORM_DISABLED_TESTS=monitor.exe threadpool-exceptions5.exe
 endif
 
 if ARM
@@ -857,6 +862,10 @@ runtest-managed: test-runner.exe $(TESTSI_CS) $(TESTSI_IL) $(TESTBS) libtest.la
        @if [ "x$$CI" = "x1" ]; then disabled_tests="$(DISABLED_TESTS_WRENCH)"; else disabled_tests="$(DISABLED_TESTS)"; fi; \
        $(RUNTIME) ./test-runner.exe -j a --disabled "$${disabled_tests}" $(TESTSI_CS) $(TESTBS) $(TESTSI_IL)
 
+runtest-managed-serial: test-runner.exe $(TESTSI_CS) $(TESTSI_IL) $(TESTBS) libtest.la $(PREREQSI_IL) $(PREREQSI_CS)
+       @if [ "x$$CI" = "x1" ]; then disabled_tests="$(DISABLED_TESTS_WRENCH)"; else disabled_tests="$(DISABLED_TESTS)"; fi; \
+       $(RUNTIME) ./test-runner.exe -j 1 --disabled "$${disabled_tests}" $(TESTSI_CS) $(TESTBS) $(TESTSI_IL)
+
 testjit:
        @if test x$(M) != x0; then $(MAKE) runtest-managed; else $(MAKE) runtest; fi
 
index 0e4320f743979da553ed706f4cd3726640ed264f..16e402318e5e095d539618c58accb994a50be04e 100644 (file)
@@ -5550,3 +5550,1675 @@ mono_test_has_thiscall (void)
 
 #endif
 
+
+typedef struct {
+       char f1;
+} sbyte1;
+
+LIBTEST_API char STDCALL
+mono_return_sbyte1 (sbyte1 s1, int addend) {
+       if (s1.f1 != 1) {
+               fprintf(stderr, "mono_return_sbyte1 s1.f1: got %d but expected %d\n", s1.f1, 1);
+               return 1;
+       }
+               return 2*addend;
+}
+
+typedef struct {
+       char f1,f2;
+} sbyte2;
+
+LIBTEST_API char STDCALL
+mono_return_sbyte2 (sbyte2 s2, int addend) {
+       if (s2.f1 != 1) {
+               fprintf(stderr, "mono_return_sbyte2 s2.f1: got %d but expected %d\n", s2.f1, 1);
+               return 1;
+       }
+       if (s2.f2 != 2) {
+               fprintf(stderr, "mono_return_sbyte2 s2.f2: got %d but expected %d\n", s2.f2, 2);
+               return 1;
+       }
+               return 2*addend;
+}
+
+typedef struct {
+       char f1,f2,f3;
+} sbyte3;
+
+LIBTEST_API char STDCALL
+mono_return_sbyte3 (sbyte3 s3, int addend) {
+       if (s3.f1 != 1) {
+               fprintf(stderr, "mono_return_sbyte3 s3.f1: got %d but expected %d\n", s3.f1, 1);
+               return 1;
+       }
+       if (s3.f2 != 2) {
+               fprintf(stderr, "mono_return_sbyte3 s3.f2: got %d but expected %d\n", s3.f2, 2);
+               return 1;
+       }
+       if (s3.f3 != 3) {
+               fprintf(stderr, "mono_return_sbyte3 s3.f3: got %d but expected %d\n", s3.f3, 3);
+               return 1;
+       }
+               return 2*addend;
+}
+
+typedef struct {
+       char f1,f2,f3,f4;
+} sbyte4;
+
+LIBTEST_API char STDCALL
+mono_return_sbyte4 (sbyte4 s4, int addend) {
+       if (s4.f1 != 1) {
+               fprintf(stderr, "mono_return_sbyte4 s4.f1: got %d but expected %d\n", s4.f1, 1);
+               return 1;
+       }
+       if (s4.f2 != 2) {
+               fprintf(stderr, "mono_return_sbyte4 s4.f2: got %d but expected %d\n", s4.f2, 2);
+               return 1;
+       }
+       if (s4.f3 != 3) {
+               fprintf(stderr, "mono_return_sbyte4 s4.f3: got %d but expected %d\n", s4.f3, 3);
+               return 1;
+       }
+       if (s4.f4 != 4) {
+               fprintf(stderr, "mono_return_sbyte4 s4.f4: got %d but expected %d\n", s4.f4, 4);
+               return 1;
+       }
+               return 2*addend;
+}
+
+typedef struct {
+       char f1,f2,f3,f4,f5;
+} sbyte5;
+
+LIBTEST_API char STDCALL
+mono_return_sbyte5 (sbyte5 s5, int addend) {
+       if (s5.f1 != 1) {
+               fprintf(stderr, "mono_return_sbyte5 s5.f1: got %d but expected %d\n", s5.f1, 1);
+               return 1;
+       }
+       if (s5.f2 != 2) {
+               fprintf(stderr, "mono_return_sbyte5 s5.f2: got %d but expected %d\n", s5.f2, 2);
+               return 1;
+       }
+       if (s5.f3 != 3) {
+               fprintf(stderr, "mono_return_sbyte5 s5.f3: got %d but expected %d\n", s5.f3, 3);
+               return 1;
+       }
+       if (s5.f4 != 4) {
+               fprintf(stderr, "mono_return_sbyte5 s5.f4: got %d but expected %d\n", s5.f4, 4);
+               return 1;
+       }
+       if (s5.f5 != 5) {
+               fprintf(stderr, "mono_return_sbyte5 s5.f5: got %d but expected %d\n", s5.f5, 5);
+               return 1;
+       }
+               return 2*addend;
+}
+
+typedef struct {
+       char f1,f2,f3,f4,f5,f6;
+} sbyte6;
+
+LIBTEST_API char STDCALL
+mono_return_sbyte6 (sbyte6 s6, int addend) {
+       if (s6.f1 != 1) {
+               fprintf(stderr, "mono_return_sbyte6 s6.f1: got %d but expected %d\n", s6.f1, 1);
+               return 1;
+       }
+       if (s6.f2 != 2) {
+               fprintf(stderr, "mono_return_sbyte6 s6.f2: got %d but expected %d\n", s6.f2, 2);
+               return 1;
+       }
+       if (s6.f3 != 3) {
+               fprintf(stderr, "mono_return_sbyte6 s6.f3: got %d but expected %d\n", s6.f3, 3);
+               return 1;
+       }
+       if (s6.f4 != 4) {
+               fprintf(stderr, "mono_return_sbyte6 s6.f4: got %d but expected %d\n", s6.f4, 4);
+               return 1;
+       }
+       if (s6.f5 != 5) {
+               fprintf(stderr, "mono_return_sbyte6 s6.f5: got %d but expected %d\n", s6.f5, 5);
+               return 1;
+       }
+       if (s6.f6 != 6) {
+               fprintf(stderr, "mono_return_sbyte6 s6.f6: got %d but expected %d\n", s6.f6, 6);
+               return 1;
+       }
+               return 2*addend;
+}
+
+typedef struct {
+       char f1,f2,f3,f4,f5,f6,f7;
+} sbyte7;
+
+LIBTEST_API char STDCALL
+mono_return_sbyte7 (sbyte7 s7, int addend) {
+       if (s7.f1 != 1) {
+               fprintf(stderr, "mono_return_sbyte7 s7.f1: got %d but expected %d\n", s7.f1, 1);
+               return 1;
+       }
+       if (s7.f2 != 2) {
+               fprintf(stderr, "mono_return_sbyte7 s7.f2: got %d but expected %d\n", s7.f2, 2);
+               return 1;
+       }
+       if (s7.f3 != 3) {
+               fprintf(stderr, "mono_return_sbyte7 s7.f3: got %d but expected %d\n", s7.f3, 3);
+               return 1;
+       }
+       if (s7.f4 != 4) {
+               fprintf(stderr, "mono_return_sbyte7 s7.f4: got %d but expected %d\n", s7.f4, 4);
+               return 1;
+       }
+       if (s7.f5 != 5) {
+               fprintf(stderr, "mono_return_sbyte7 s7.f5: got %d but expected %d\n", s7.f5, 5);
+               return 1;
+       }
+       if (s7.f6 != 6) {
+               fprintf(stderr, "mono_return_sbyte7 s7.f6: got %d but expected %d\n", s7.f6, 6);
+               return 1;
+       }
+       if (s7.f7 != 7) {
+               fprintf(stderr, "mono_return_sbyte7 s7.f7: got %d but expected %d\n", s7.f7, 7);
+               return 1;
+       }
+               return 2*addend;
+}
+
+typedef struct {
+       char f1,f2,f3,f4,f5,f6,f7,f8;
+} sbyte8;
+
+LIBTEST_API char STDCALL
+mono_return_sbyte8 (sbyte8 s8, int addend) {
+       if (s8.f1 != 1) {
+               fprintf(stderr, "mono_return_sbyte8 s8.f1: got %d but expected %d\n", s8.f1, 1);
+               return 1;
+       }
+       if (s8.f2 != 2) {
+               fprintf(stderr, "mono_return_sbyte8 s8.f2: got %d but expected %d\n", s8.f2, 2);
+               return 1;
+       }
+       if (s8.f3 != 3) {
+               fprintf(stderr, "mono_return_sbyte8 s8.f3: got %d but expected %d\n", s8.f3, 3);
+               return 1;
+       }
+       if (s8.f4 != 4) {
+               fprintf(stderr, "mono_return_sbyte8 s8.f4: got %d but expected %d\n", s8.f4, 4);
+               return 1;
+       }
+       if (s8.f5 != 5) {
+               fprintf(stderr, "mono_return_sbyte8 s8.f5: got %d but expected %d\n", s8.f5, 5);
+               return 1;
+       }
+       if (s8.f6 != 6) {
+               fprintf(stderr, "mono_return_sbyte8 s8.f6: got %d but expected %d\n", s8.f6, 6);
+               return 1;
+       }
+       if (s8.f7 != 7) {
+               fprintf(stderr, "mono_return_sbyte8 s8.f7: got %d but expected %d\n", s8.f7, 7);
+               return 1;
+       }
+       if (s8.f8 != 8) {
+               fprintf(stderr, "mono_return_sbyte8 s8.f8: got %d but expected %d\n", s8.f8, 8);
+               return 1;
+       }
+               return 2*addend;
+}
+
+typedef struct {
+       char f1,f2,f3,f4,f5,f6,f7,f8,f9;
+} sbyte9;
+
+LIBTEST_API char STDCALL
+mono_return_sbyte9 (sbyte9 s9, int addend) {
+       if (s9.f1 != 1) {
+               fprintf(stderr, "mono_return_sbyte9 s9.f1: got %d but expected %d\n", s9.f1, 1);
+               return 1;
+       }
+       if (s9.f2 != 2) {
+               fprintf(stderr, "mono_return_sbyte9 s9.f2: got %d but expected %d\n", s9.f2, 2);
+               return 1;
+       }
+       if (s9.f3 != 3) {
+               fprintf(stderr, "mono_return_sbyte9 s9.f3: got %d but expected %d\n", s9.f3, 3);
+               return 1;
+       }
+       if (s9.f4 != 4) {
+               fprintf(stderr, "mono_return_sbyte9 s9.f4: got %d but expected %d\n", s9.f4, 4);
+               return 1;
+       }
+       if (s9.f5 != 5) {
+               fprintf(stderr, "mono_return_sbyte9 s9.f5: got %d but expected %d\n", s9.f5, 5);
+               return 1;
+       }
+       if (s9.f6 != 6) {
+               fprintf(stderr, "mono_return_sbyte9 s9.f6: got %d but expected %d\n", s9.f6, 6);
+               return 1;
+       }
+       if (s9.f7 != 7) {
+               fprintf(stderr, "mono_return_sbyte9 s9.f7: got %d but expected %d\n", s9.f7, 7);
+               return 1;
+       }
+       if (s9.f8 != 8) {
+               fprintf(stderr, "mono_return_sbyte9 s9.f8: got %d but expected %d\n", s9.f8, 8);
+               return 1;
+       }
+       if (s9.f9 != 9) {
+               fprintf(stderr, "mono_return_sbyte9 s9.f9: got %d but expected %d\n", s9.f9, 9);
+               return 1;
+       }
+               return 2*addend;
+}
+
+typedef struct {
+       char f1,f2,f3,f4,f5,f6,f7,f8,f9,f10;
+} sbyte10;
+
+LIBTEST_API char STDCALL
+mono_return_sbyte10 (sbyte10 s10, int addend) {
+       if (s10.f1 != 1) {
+               fprintf(stderr, "mono_return_sbyte10 s10.f1: got %d but expected %d\n", s10.f1, 1);
+               return 1;
+       }
+       if (s10.f2 != 2) {
+               fprintf(stderr, "mono_return_sbyte10 s10.f2: got %d but expected %d\n", s10.f2, 2);
+               return 1;
+       }
+       if (s10.f3 != 3) {
+               fprintf(stderr, "mono_return_sbyte10 s10.f3: got %d but expected %d\n", s10.f3, 3);
+               return 1;
+       }
+       if (s10.f4 != 4) {
+               fprintf(stderr, "mono_return_sbyte10 s10.f4: got %d but expected %d\n", s10.f4, 4);
+               return 1;
+       }
+       if (s10.f5 != 5) {
+               fprintf(stderr, "mono_return_sbyte10 s10.f5: got %d but expected %d\n", s10.f5, 5);
+               return 1;
+       }
+       if (s10.f6 != 6) {
+               fprintf(stderr, "mono_return_sbyte10 s10.f6: got %d but expected %d\n", s10.f6, 6);
+               return 1;
+       }
+       if (s10.f7 != 7) {
+               fprintf(stderr, "mono_return_sbyte10 s10.f7: got %d but expected %d\n", s10.f7, 7);
+               return 1;
+       }
+       if (s10.f8 != 8) {
+               fprintf(stderr, "mono_return_sbyte10 s10.f8: got %d but expected %d\n", s10.f8, 8);
+               return 1;
+       }
+       if (s10.f9 != 9) {
+               fprintf(stderr, "mono_return_sbyte10 s10.f9: got %d but expected %d\n", s10.f9, 9);
+               return 1;
+       }
+       if (s10.f10 != 10) {
+               fprintf(stderr, "mono_return_sbyte10 s10.f10: got %d but expected %d\n", s10.f10, 10);
+               return 1;
+       }
+               return 2*addend;
+}
+
+typedef struct {
+       char f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11;
+} sbyte11;
+
+LIBTEST_API char STDCALL
+mono_return_sbyte11 (sbyte11 s11, int addend) {
+       if (s11.f1 != 1) {
+               fprintf(stderr, "mono_return_sbyte11 s11.f1: got %d but expected %d\n", s11.f1, 1);
+               return 1;
+       }
+       if (s11.f2 != 2) {
+               fprintf(stderr, "mono_return_sbyte11 s11.f2: got %d but expected %d\n", s11.f2, 2);
+               return 1;
+       }
+       if (s11.f3 != 3) {
+               fprintf(stderr, "mono_return_sbyte11 s11.f3: got %d but expected %d\n", s11.f3, 3);
+               return 1;
+       }
+       if (s11.f4 != 4) {
+               fprintf(stderr, "mono_return_sbyte11 s11.f4: got %d but expected %d\n", s11.f4, 4);
+               return 1;
+       }
+       if (s11.f5 != 5) {
+               fprintf(stderr, "mono_return_sbyte11 s11.f5: got %d but expected %d\n", s11.f5, 5);
+               return 1;
+       }
+       if (s11.f6 != 6) {
+               fprintf(stderr, "mono_return_sbyte11 s11.f6: got %d but expected %d\n", s11.f6, 6);
+               return 1;
+       }
+       if (s11.f7 != 7) {
+               fprintf(stderr, "mono_return_sbyte11 s11.f7: got %d but expected %d\n", s11.f7, 7);
+               return 1;
+       }
+       if (s11.f8 != 8) {
+               fprintf(stderr, "mono_return_sbyte11 s11.f8: got %d but expected %d\n", s11.f8, 8);
+               return 1;
+       }
+       if (s11.f9 != 9) {
+               fprintf(stderr, "mono_return_sbyte11 s11.f9: got %d but expected %d\n", s11.f9, 9);
+               return 1;
+       }
+       if (s11.f10 != 10) {
+               fprintf(stderr, "mono_return_sbyte11 s11.f10: got %d but expected %d\n", s11.f10, 10);
+               return 1;
+       }
+       if (s11.f11 != 11) {
+               fprintf(stderr, "mono_return_sbyte11 s11.f11: got %d but expected %d\n", s11.f11, 11);
+               return 1;
+       }
+               return 2*addend;
+}
+
+typedef struct {
+       char f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12;
+} sbyte12;
+
+LIBTEST_API char STDCALL
+mono_return_sbyte12 (sbyte12 s12, int addend) {
+       if (s12.f1 != 1) {
+               fprintf(stderr, "mono_return_sbyte12 s12.f1: got %d but expected %d\n", s12.f1, 1);
+               return 1;
+       }
+       if (s12.f2 != 2) {
+               fprintf(stderr, "mono_return_sbyte12 s12.f2: got %d but expected %d\n", s12.f2, 2);
+               return 1;
+       }
+       if (s12.f3 != 3) {
+               fprintf(stderr, "mono_return_sbyte12 s12.f3: got %d but expected %d\n", s12.f3, 3);
+               return 1;
+       }
+       if (s12.f4 != 4) {
+               fprintf(stderr, "mono_return_sbyte12 s12.f4: got %d but expected %d\n", s12.f4, 4);
+               return 1;
+       }
+       if (s12.f5 != 5) {
+               fprintf(stderr, "mono_return_sbyte12 s12.f5: got %d but expected %d\n", s12.f5, 5);
+               return 1;
+       }
+       if (s12.f6 != 6) {
+               fprintf(stderr, "mono_return_sbyte12 s12.f6: got %d but expected %d\n", s12.f6, 6);
+               return 1;
+       }
+       if (s12.f7 != 7) {
+               fprintf(stderr, "mono_return_sbyte12 s12.f7: got %d but expected %d\n", s12.f7, 7);
+               return 1;
+       }
+       if (s12.f8 != 8) {
+               fprintf(stderr, "mono_return_sbyte12 s12.f8: got %d but expected %d\n", s12.f8, 8);
+               return 1;
+       }
+       if (s12.f9 != 9) {
+               fprintf(stderr, "mono_return_sbyte12 s12.f9: got %d but expected %d\n", s12.f9, 9);
+               return 1;
+       }
+       if (s12.f10 != 10) {
+               fprintf(stderr, "mono_return_sbyte12 s12.f10: got %d but expected %d\n", s12.f10, 10);
+               return 1;
+       }
+       if (s12.f11 != 11) {
+               fprintf(stderr, "mono_return_sbyte12 s12.f11: got %d but expected %d\n", s12.f11, 11);
+               return 1;
+       }
+       if (s12.f12 != 12) {
+               fprintf(stderr, "mono_return_sbyte12 s12.f12: got %d but expected %d\n", s12.f12, 12);
+               return 1;
+       }
+               return 2*addend;
+}
+
+typedef struct {
+       char f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13;
+} sbyte13;
+
+LIBTEST_API char STDCALL
+mono_return_sbyte13 (sbyte13 s13, int addend) {
+       if (s13.f1 != 1) {
+               fprintf(stderr, "mono_return_sbyte13 s13.f1: got %d but expected %d\n", s13.f1, 1);
+               return 1;
+       }
+       if (s13.f2 != 2) {
+               fprintf(stderr, "mono_return_sbyte13 s13.f2: got %d but expected %d\n", s13.f2, 2);
+               return 1;
+       }
+       if (s13.f3 != 3) {
+               fprintf(stderr, "mono_return_sbyte13 s13.f3: got %d but expected %d\n", s13.f3, 3);
+               return 1;
+       }
+       if (s13.f4 != 4) {
+               fprintf(stderr, "mono_return_sbyte13 s13.f4: got %d but expected %d\n", s13.f4, 4);
+               return 1;
+       }
+       if (s13.f5 != 5) {
+               fprintf(stderr, "mono_return_sbyte13 s13.f5: got %d but expected %d\n", s13.f5, 5);
+               return 1;
+       }
+       if (s13.f6 != 6) {
+               fprintf(stderr, "mono_return_sbyte13 s13.f6: got %d but expected %d\n", s13.f6, 6);
+               return 1;
+       }
+       if (s13.f7 != 7) {
+               fprintf(stderr, "mono_return_sbyte13 s13.f7: got %d but expected %d\n", s13.f7, 7);
+               return 1;
+       }
+       if (s13.f8 != 8) {
+               fprintf(stderr, "mono_return_sbyte13 s13.f8: got %d but expected %d\n", s13.f8, 8);
+               return 1;
+       }
+       if (s13.f9 != 9) {
+               fprintf(stderr, "mono_return_sbyte13 s13.f9: got %d but expected %d\n", s13.f9, 9);
+               return 1;
+       }
+       if (s13.f10 != 10) {
+               fprintf(stderr, "mono_return_sbyte13 s13.f10: got %d but expected %d\n", s13.f10, 10);
+               return 1;
+       }
+       if (s13.f11 != 11) {
+               fprintf(stderr, "mono_return_sbyte13 s13.f11: got %d but expected %d\n", s13.f11, 11);
+               return 1;
+       }
+       if (s13.f12 != 12) {
+               fprintf(stderr, "mono_return_sbyte13 s13.f12: got %d but expected %d\n", s13.f12, 12);
+               return 1;
+       }
+       if (s13.f13 != 13) {
+               fprintf(stderr, "mono_return_sbyte13 s13.f13: got %d but expected %d\n", s13.f13, 13);
+               return 1;
+       }
+               return 2*addend;
+}
+
+typedef struct {
+       char f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13,f14;
+} sbyte14;
+
+LIBTEST_API char STDCALL
+mono_return_sbyte14 (sbyte14 s14, int addend) {
+       if (s14.f1 != 1) {
+               fprintf(stderr, "mono_return_sbyte14 s14.f1: got %d but expected %d\n", s14.f1, 1);
+               return 1;
+       }
+       if (s14.f2 != 2) {
+               fprintf(stderr, "mono_return_sbyte14 s14.f2: got %d but expected %d\n", s14.f2, 2);
+               return 1;
+       }
+       if (s14.f3 != 3) {
+               fprintf(stderr, "mono_return_sbyte14 s14.f3: got %d but expected %d\n", s14.f3, 3);
+               return 1;
+       }
+       if (s14.f4 != 4) {
+               fprintf(stderr, "mono_return_sbyte14 s14.f4: got %d but expected %d\n", s14.f4, 4);
+               return 1;
+       }
+       if (s14.f5 != 5) {
+               fprintf(stderr, "mono_return_sbyte14 s14.f5: got %d but expected %d\n", s14.f5, 5);
+               return 1;
+       }
+       if (s14.f6 != 6) {
+               fprintf(stderr, "mono_return_sbyte14 s14.f6: got %d but expected %d\n", s14.f6, 6);
+               return 1;
+       }
+       if (s14.f7 != 7) {
+               fprintf(stderr, "mono_return_sbyte14 s14.f7: got %d but expected %d\n", s14.f7, 7);
+               return 1;
+       }
+       if (s14.f8 != 8) {
+               fprintf(stderr, "mono_return_sbyte14 s14.f8: got %d but expected %d\n", s14.f8, 8);
+               return 1;
+       }
+       if (s14.f9 != 9) {
+               fprintf(stderr, "mono_return_sbyte14 s14.f9: got %d but expected %d\n", s14.f9, 9);
+               return 1;
+       }
+       if (s14.f10 != 10) {
+               fprintf(stderr, "mono_return_sbyte14 s14.f10: got %d but expected %d\n", s14.f10, 10);
+               return 1;
+       }
+       if (s14.f11 != 11) {
+               fprintf(stderr, "mono_return_sbyte14 s14.f11: got %d but expected %d\n", s14.f11, 11);
+               return 1;
+       }
+       if (s14.f12 != 12) {
+               fprintf(stderr, "mono_return_sbyte14 s14.f12: got %d but expected %d\n", s14.f12, 12);
+               return 1;
+       }
+       if (s14.f13 != 13) {
+               fprintf(stderr, "mono_return_sbyte14 s14.f13: got %d but expected %d\n", s14.f13, 13);
+               return 1;
+       }
+       if (s14.f14 != 14) {
+               fprintf(stderr, "mono_return_sbyte14 s14.f14: got %d but expected %d\n", s14.f14, 14);
+               return 1;
+       }
+               return 2*addend;
+}
+
+typedef struct {
+       char f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13,f14,f15;
+} sbyte15;
+
+LIBTEST_API char STDCALL
+mono_return_sbyte15 (sbyte15 s15, int addend) {
+       if (s15.f1 != 1) {
+               fprintf(stderr, "mono_return_sbyte15 s15.f1: got %d but expected %d\n", s15.f1, 1);
+               return 1;
+       }
+       if (s15.f2 != 2) {
+               fprintf(stderr, "mono_return_sbyte15 s15.f2: got %d but expected %d\n", s15.f2, 2);
+               return 1;
+       }
+       if (s15.f3 != 3) {
+               fprintf(stderr, "mono_return_sbyte15 s15.f3: got %d but expected %d\n", s15.f3, 3);
+               return 1;
+       }
+       if (s15.f4 != 4) {
+               fprintf(stderr, "mono_return_sbyte15 s15.f4: got %d but expected %d\n", s15.f4, 4);
+               return 1;
+       }
+       if (s15.f5 != 5) {
+               fprintf(stderr, "mono_return_sbyte15 s15.f5: got %d but expected %d\n", s15.f5, 5);
+               return 1;
+       }
+       if (s15.f6 != 6) {
+               fprintf(stderr, "mono_return_sbyte15 s15.f6: got %d but expected %d\n", s15.f6, 6);
+               return 1;
+       }
+       if (s15.f7 != 7) {
+               fprintf(stderr, "mono_return_sbyte15 s15.f7: got %d but expected %d\n", s15.f7, 7);
+               return 1;
+       }
+       if (s15.f8 != 8) {
+               fprintf(stderr, "mono_return_sbyte15 s15.f8: got %d but expected %d\n", s15.f8, 8);
+               return 1;
+       }
+       if (s15.f9 != 9) {
+               fprintf(stderr, "mono_return_sbyte15 s15.f9: got %d but expected %d\n", s15.f9, 9);
+               return 1;
+       }
+       if (s15.f10 != 10) {
+               fprintf(stderr, "mono_return_sbyte15 s15.f10: got %d but expected %d\n", s15.f10, 10);
+               return 1;
+       }
+       if (s15.f11 != 11) {
+               fprintf(stderr, "mono_return_sbyte15 s15.f11: got %d but expected %d\n", s15.f11, 11);
+               return 1;
+       }
+       if (s15.f12 != 12) {
+               fprintf(stderr, "mono_return_sbyte15 s15.f12: got %d but expected %d\n", s15.f12, 12);
+               return 1;
+       }
+       if (s15.f13 != 13) {
+               fprintf(stderr, "mono_return_sbyte15 s15.f13: got %d but expected %d\n", s15.f13, 13);
+               return 1;
+       }
+       if (s15.f14 != 14) {
+               fprintf(stderr, "mono_return_sbyte15 s15.f14: got %d but expected %d\n", s15.f14, 14);
+               return 1;
+       }
+       if (s15.f15 != 15) {
+               fprintf(stderr, "mono_return_sbyte15 s15.f15: got %d but expected %d\n", s15.f15, 15);
+               return 1;
+       }
+               return 2*addend;
+}
+
+typedef struct {
+       char f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13,f14,f15,f16;
+} sbyte16;
+
+LIBTEST_API char STDCALL
+mono_return_sbyte16 (sbyte16 s16, int addend) {
+       if (s16.f1 != 1) {
+               fprintf(stderr, "mono_return_sbyte16 s16.f1: got %d but expected %d\n", s16.f1, 1);
+               return 1;
+       }
+       if (s16.f2 != 2) {
+               fprintf(stderr, "mono_return_sbyte16 s16.f2: got %d but expected %d\n", s16.f2, 2);
+               return 1;
+       }
+       if (s16.f3 != 3) {
+               fprintf(stderr, "mono_return_sbyte16 s16.f3: got %d but expected %d\n", s16.f3, 3);
+               return 1;
+       }
+       if (s16.f4 != 4) {
+               fprintf(stderr, "mono_return_sbyte16 s16.f4: got %d but expected %d\n", s16.f4, 4);
+               return 1;
+       }
+       if (s16.f5 != 5) {
+               fprintf(stderr, "mono_return_sbyte16 s16.f5: got %d but expected %d\n", s16.f5, 5);
+               return 1;
+       }
+       if (s16.f6 != 6) {
+               fprintf(stderr, "mono_return_sbyte16 s16.f6: got %d but expected %d\n", s16.f6, 6);
+               return 1;
+       }
+       if (s16.f7 != 7) {
+               fprintf(stderr, "mono_return_sbyte16 s16.f7: got %d but expected %d\n", s16.f7, 7);
+               return 1;
+       }
+       if (s16.f8 != 8) {
+               fprintf(stderr, "mono_return_sbyte16 s16.f8: got %d but expected %d\n", s16.f8, 8);
+               return 1;
+       }
+       if (s16.f9 != 9) {
+               fprintf(stderr, "mono_return_sbyte16 s16.f9: got %d but expected %d\n", s16.f9, 9);
+               return 1;
+       }
+       if (s16.f10 != 10) {
+               fprintf(stderr, "mono_return_sbyte16 s16.f10: got %d but expected %d\n", s16.f10, 10);
+               return 1;
+       }
+       if (s16.f11 != 11) {
+               fprintf(stderr, "mono_return_sbyte16 s16.f11: got %d but expected %d\n", s16.f11, 11);
+               return 1;
+       }
+       if (s16.f12 != 12) {
+               fprintf(stderr, "mono_return_sbyte16 s16.f12: got %d but expected %d\n", s16.f12, 12);
+               return 1;
+       }
+       if (s16.f13 != 13) {
+               fprintf(stderr, "mono_return_sbyte16 s16.f13: got %d but expected %d\n", s16.f13, 13);
+               return 1;
+       }
+       if (s16.f14 != 14) {
+               fprintf(stderr, "mono_return_sbyte16 s16.f14: got %d but expected %d\n", s16.f14, 14);
+               return 1;
+       }
+       if (s16.f15 != 15) {
+               fprintf(stderr, "mono_return_sbyte16 s16.f15: got %d but expected %d\n", s16.f15, 15);
+               return 1;
+       }
+       if (s16.f16 != 16) {
+               fprintf(stderr, "mono_return_sbyte16 s16.f16: got %d but expected %d\n", s16.f16, 16);
+               return 1;
+       }
+               return 2*addend;
+}
+
+typedef struct {
+       char f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13,f14,f15,f16,f17;
+} sbyte17;
+
+LIBTEST_API char STDCALL
+mono_return_sbyte17 (sbyte17 s17, int addend) {
+       if (s17.f1 != 1) {
+               fprintf(stderr, "mono_return_sbyte17 s17.f1: got %d but expected %d\n", s17.f1, 1);
+               return 1;
+       }
+       if (s17.f2 != 2) {
+               fprintf(stderr, "mono_return_sbyte17 s17.f2: got %d but expected %d\n", s17.f2, 2);
+               return 1;
+       }
+       if (s17.f3 != 3) {
+               fprintf(stderr, "mono_return_sbyte17 s17.f3: got %d but expected %d\n", s17.f3, 3);
+               return 1;
+       }
+       if (s17.f4 != 4) {
+               fprintf(stderr, "mono_return_sbyte17 s17.f4: got %d but expected %d\n", s17.f4, 4);
+               return 1;
+       }
+       if (s17.f5 != 5) {
+               fprintf(stderr, "mono_return_sbyte17 s17.f5: got %d but expected %d\n", s17.f5, 5);
+               return 1;
+       }
+       if (s17.f6 != 6) {
+               fprintf(stderr, "mono_return_sbyte17 s17.f6: got %d but expected %d\n", s17.f6, 6);
+               return 1;
+       }
+       if (s17.f7 != 7) {
+               fprintf(stderr, "mono_return_sbyte17 s17.f7: got %d but expected %d\n", s17.f7, 7);
+               return 1;
+       }
+       if (s17.f8 != 8) {
+               fprintf(stderr, "mono_return_sbyte17 s17.f8: got %d but expected %d\n", s17.f8, 8);
+               return 1;
+       }
+       if (s17.f9 != 9) {
+               fprintf(stderr, "mono_return_sbyte17 s17.f9: got %d but expected %d\n", s17.f9, 9);
+               return 1;
+       }
+       if (s17.f10 != 10) {
+               fprintf(stderr, "mono_return_sbyte17 s17.f10: got %d but expected %d\n", s17.f10, 10);
+               return 1;
+       }
+       if (s17.f11 != 11) {
+               fprintf(stderr, "mono_return_sbyte17 s17.f11: got %d but expected %d\n", s17.f11, 11);
+               return 1;
+       }
+       if (s17.f12 != 12) {
+               fprintf(stderr, "mono_return_sbyte17 s17.f12: got %d but expected %d\n", s17.f12, 12);
+               return 1;
+       }
+       if (s17.f13 != 13) {
+               fprintf(stderr, "mono_return_sbyte17 s17.f13: got %d but expected %d\n", s17.f13, 13);
+               return 1;
+       }
+       if (s17.f14 != 14) {
+               fprintf(stderr, "mono_return_sbyte17 s17.f14: got %d but expected %d\n", s17.f14, 14);
+               return 1;
+       }
+       if (s17.f15 != 15) {
+               fprintf(stderr, "mono_return_sbyte17 s17.f15: got %d but expected %d\n", s17.f15, 15);
+               return 1;
+       }
+       if (s17.f16 != 16) {
+               fprintf(stderr, "mono_return_sbyte17 s17.f16: got %d but expected %d\n", s17.f16, 16);
+               return 1;
+       }
+       if (s17.f17 != 17) {
+               fprintf(stderr, "mono_return_sbyte17 s17.f17: got %d but expected %d\n", s17.f17, 17);
+               return 1;
+       }
+               return 2*addend;
+}
+
+typedef struct {
+       short f1;
+} short1;
+
+LIBTEST_API short STDCALL
+mono_return_short1 (short1 s1, int addend) {
+       if (s1.f1 != 1) {
+               fprintf(stderr, "mono_return_short1 s1.f1: got %d but expected %d\n", s1.f1, 1);
+               return 1;
+       }
+               return 2*addend;
+}
+
+typedef struct {
+       short f1,f2;
+} short2;
+
+LIBTEST_API short STDCALL
+mono_return_short2 (short2 s2, int addend) {
+       if (s2.f1 != 1) {
+               fprintf(stderr, "mono_return_short2 s2.f1: got %d but expected %d\n", s2.f1, 1);
+               return 1;
+       }
+       if (s2.f2 != 2) {
+               fprintf(stderr, "mono_return_short2 s2.f2: got %d but expected %d\n", s2.f2, 2);
+               return 1;
+       }
+               return 2*addend;
+}
+
+typedef struct {
+       short f1,f2,f3;
+} short3;
+
+LIBTEST_API short STDCALL
+mono_return_short3 (short3 s3, int addend) {
+       if (s3.f1 != 1) {
+               fprintf(stderr, "mono_return_short3 s3.f1: got %d but expected %d\n", s3.f1, 1);
+               return 1;
+       }
+       if (s3.f2 != 2) {
+               fprintf(stderr, "mono_return_short3 s3.f2: got %d but expected %d\n", s3.f2, 2);
+               return 1;
+       }
+       if (s3.f3 != 3) {
+               fprintf(stderr, "mono_return_short3 s3.f3: got %d but expected %d\n", s3.f3, 3);
+               return 1;
+       }
+               return 2*addend;
+}
+
+typedef struct {
+       short f1,f2,f3,f4;
+} short4;
+
+LIBTEST_API short STDCALL
+mono_return_short4 (short4 s4, int addend) {
+       if (s4.f1 != 1) {
+               fprintf(stderr, "mono_return_short4 s4.f1: got %d but expected %d\n", s4.f1, 1);
+               return 1;
+       }
+       if (s4.f2 != 2) {
+               fprintf(stderr, "mono_return_short4 s4.f2: got %d but expected %d\n", s4.f2, 2);
+               return 1;
+       }
+       if (s4.f3 != 3) {
+               fprintf(stderr, "mono_return_short4 s4.f3: got %d but expected %d\n", s4.f3, 3);
+               return 1;
+       }
+       if (s4.f4 != 4) {
+               fprintf(stderr, "mono_return_short4 s4.f4: got %d but expected %d\n", s4.f4, 4);
+               return 1;
+       }
+               return 2*addend;
+}
+
+typedef struct {
+       short f1,f2,f3,f4,f5;
+} short5;
+
+LIBTEST_API short STDCALL
+mono_return_short5 (short5 s5, int addend) {
+       if (s5.f1 != 1) {
+               fprintf(stderr, "mono_return_short5 s5.f1: got %d but expected %d\n", s5.f1, 1);
+               return 1;
+       }
+       if (s5.f2 != 2) {
+               fprintf(stderr, "mono_return_short5 s5.f2: got %d but expected %d\n", s5.f2, 2);
+               return 1;
+       }
+       if (s5.f3 != 3) {
+               fprintf(stderr, "mono_return_short5 s5.f3: got %d but expected %d\n", s5.f3, 3);
+               return 1;
+       }
+       if (s5.f4 != 4) {
+               fprintf(stderr, "mono_return_short5 s5.f4: got %d but expected %d\n", s5.f4, 4);
+               return 1;
+       }
+       if (s5.f5 != 5) {
+               fprintf(stderr, "mono_return_short5 s5.f5: got %d but expected %d\n", s5.f5, 5);
+               return 1;
+       }
+               return 2*addend;
+}
+
+typedef struct {
+       short f1,f2,f3,f4,f5,f6;
+} short6;
+
+LIBTEST_API short STDCALL
+mono_return_short6 (short6 s6, int addend) {
+       if (s6.f1 != 1) {
+               fprintf(stderr, "mono_return_short6 s6.f1: got %d but expected %d\n", s6.f1, 1);
+               return 1;
+       }
+       if (s6.f2 != 2) {
+               fprintf(stderr, "mono_return_short6 s6.f2: got %d but expected %d\n", s6.f2, 2);
+               return 1;
+       }
+       if (s6.f3 != 3) {
+               fprintf(stderr, "mono_return_short6 s6.f3: got %d but expected %d\n", s6.f3, 3);
+               return 1;
+       }
+       if (s6.f4 != 4) {
+               fprintf(stderr, "mono_return_short6 s6.f4: got %d but expected %d\n", s6.f4, 4);
+               return 1;
+       }
+       if (s6.f5 != 5) {
+               fprintf(stderr, "mono_return_short6 s6.f5: got %d but expected %d\n", s6.f5, 5);
+               return 1;
+       }
+       if (s6.f6 != 6) {
+               fprintf(stderr, "mono_return_short6 s6.f6: got %d but expected %d\n", s6.f6, 6);
+               return 1;
+       }
+               return 2*addend;
+}
+
+typedef struct {
+       short f1,f2,f3,f4,f5,f6,f7;
+} short7;
+
+LIBTEST_API short STDCALL
+mono_return_short7 (short7 s7, int addend) {
+       if (s7.f1 != 1) {
+               fprintf(stderr, "mono_return_short7 s7.f1: got %d but expected %d\n", s7.f1, 1);
+               return 1;
+       }
+       if (s7.f2 != 2) {
+               fprintf(stderr, "mono_return_short7 s7.f2: got %d but expected %d\n", s7.f2, 2);
+               return 1;
+       }
+       if (s7.f3 != 3) {
+               fprintf(stderr, "mono_return_short7 s7.f3: got %d but expected %d\n", s7.f3, 3);
+               return 1;
+       }
+       if (s7.f4 != 4) {
+               fprintf(stderr, "mono_return_short7 s7.f4: got %d but expected %d\n", s7.f4, 4);
+               return 1;
+       }
+       if (s7.f5 != 5) {
+               fprintf(stderr, "mono_return_short7 s7.f5: got %d but expected %d\n", s7.f5, 5);
+               return 1;
+       }
+       if (s7.f6 != 6) {
+               fprintf(stderr, "mono_return_short7 s7.f6: got %d but expected %d\n", s7.f6, 6);
+               return 1;
+       }
+       if (s7.f7 != 7) {
+               fprintf(stderr, "mono_return_short7 s7.f7: got %d but expected %d\n", s7.f7, 7);
+               return 1;
+       }
+               return 2*addend;
+}
+
+typedef struct {
+       short f1,f2,f3,f4,f5,f6,f7,f8;
+} short8;
+
+LIBTEST_API short STDCALL
+mono_return_short8 (short8 s8, int addend) {
+       if (s8.f1 != 1) {
+               fprintf(stderr, "mono_return_short8 s8.f1: got %d but expected %d\n", s8.f1, 1);
+               return 1;
+       }
+       if (s8.f2 != 2) {
+               fprintf(stderr, "mono_return_short8 s8.f2: got %d but expected %d\n", s8.f2, 2);
+               return 1;
+       }
+       if (s8.f3 != 3) {
+               fprintf(stderr, "mono_return_short8 s8.f3: got %d but expected %d\n", s8.f3, 3);
+               return 1;
+       }
+       if (s8.f4 != 4) {
+               fprintf(stderr, "mono_return_short8 s8.f4: got %d but expected %d\n", s8.f4, 4);
+               return 1;
+       }
+       if (s8.f5 != 5) {
+               fprintf(stderr, "mono_return_short8 s8.f5: got %d but expected %d\n", s8.f5, 5);
+               return 1;
+       }
+       if (s8.f6 != 6) {
+               fprintf(stderr, "mono_return_short8 s8.f6: got %d but expected %d\n", s8.f6, 6);
+               return 1;
+       }
+       if (s8.f7 != 7) {
+               fprintf(stderr, "mono_return_short8 s8.f7: got %d but expected %d\n", s8.f7, 7);
+               return 1;
+       }
+       if (s8.f8 != 8) {
+               fprintf(stderr, "mono_return_short8 s8.f8: got %d but expected %d\n", s8.f8, 8);
+               return 1;
+       }
+               return 2*addend;
+}
+
+typedef struct {
+       short f1,f2,f3,f4,f5,f6,f7,f8,f9;
+} short9;
+
+LIBTEST_API short STDCALL
+mono_return_short9 (short9 s9, int addend) {
+       if (s9.f1 != 1) {
+               fprintf(stderr, "mono_return_short9 s9.f1: got %d but expected %d\n", s9.f1, 1);
+               return 1;
+       }
+       if (s9.f2 != 2) {
+               fprintf(stderr, "mono_return_short9 s9.f2: got %d but expected %d\n", s9.f2, 2);
+               return 1;
+       }
+       if (s9.f3 != 3) {
+               fprintf(stderr, "mono_return_short9 s9.f3: got %d but expected %d\n", s9.f3, 3);
+               return 1;
+       }
+       if (s9.f4 != 4) {
+               fprintf(stderr, "mono_return_short9 s9.f4: got %d but expected %d\n", s9.f4, 4);
+               return 1;
+       }
+       if (s9.f5 != 5) {
+               fprintf(stderr, "mono_return_short9 s9.f5: got %d but expected %d\n", s9.f5, 5);
+               return 1;
+       }
+       if (s9.f6 != 6) {
+               fprintf(stderr, "mono_return_short9 s9.f6: got %d but expected %d\n", s9.f6, 6);
+               return 1;
+       }
+       if (s9.f7 != 7) {
+               fprintf(stderr, "mono_return_short9 s9.f7: got %d but expected %d\n", s9.f7, 7);
+               return 1;
+       }
+       if (s9.f8 != 8) {
+               fprintf(stderr, "mono_return_short9 s9.f8: got %d but expected %d\n", s9.f8, 8);
+               return 1;
+       }
+       if (s9.f9 != 9) {
+               fprintf(stderr, "mono_return_short9 s9.f9: got %d but expected %d\n", s9.f9, 9);
+               return 1;
+       }
+               return 2*addend;
+}
+
+typedef struct {
+       int f1;
+} int1;
+
+LIBTEST_API int STDCALL
+mono_return_int1 (int1 s1, int addend) {
+       if (s1.f1 != 1) {
+               fprintf(stderr, "mono_return_int1 s1.f1: got %d but expected %d\n", s1.f1, 1);
+               return 1;
+       }
+               return 2*addend;
+}
+
+typedef struct {
+       int f1,f2;
+} int2;
+
+LIBTEST_API int STDCALL
+mono_return_int2 (int2 s2, int addend) {
+       if (s2.f1 != 1) {
+               fprintf(stderr, "mono_return_int2 s2.f1: got %d but expected %d\n", s2.f1, 1);
+               return 1;
+       }
+       if (s2.f2 != 2) {
+               fprintf(stderr, "mono_return_int2 s2.f2: got %d but expected %d\n", s2.f2, 2);
+               return 1;
+       }
+               return 2*addend;
+}
+
+typedef struct {
+       int f1,f2,f3;
+} int3;
+
+LIBTEST_API int STDCALL
+mono_return_int3 (int3 s3, int addend) {
+       if (s3.f1 != 1) {
+               fprintf(stderr, "mono_return_int3 s3.f1: got %d but expected %d\n", s3.f1, 1);
+               return 1;
+       }
+       if (s3.f2 != 2) {
+               fprintf(stderr, "mono_return_int3 s3.f2: got %d but expected %d\n", s3.f2, 2);
+               return 1;
+       }
+       if (s3.f3 != 3) {
+               fprintf(stderr, "mono_return_int3 s3.f3: got %d but expected %d\n", s3.f3, 3);
+               return 1;
+       }
+               return 2*addend;
+}
+
+typedef struct {
+       int f1,f2,f3,f4;
+} int4;
+
+LIBTEST_API int STDCALL
+mono_return_int4 (int4 s4, int addend) {
+       if (s4.f1 != 1) {
+               fprintf(stderr, "mono_return_int4 s4.f1: got %d but expected %d\n", s4.f1, 1);
+               return 1;
+       }
+       if (s4.f2 != 2) {
+               fprintf(stderr, "mono_return_int4 s4.f2: got %d but expected %d\n", s4.f2, 2);
+               return 1;
+       }
+       if (s4.f3 != 3) {
+               fprintf(stderr, "mono_return_int4 s4.f3: got %d but expected %d\n", s4.f3, 3);
+               return 1;
+       }
+       if (s4.f4 != 4) {
+               fprintf(stderr, "mono_return_int4 s4.f4: got %d but expected %d\n", s4.f4, 4);
+               return 1;
+       }
+               return 2*addend;
+}
+
+typedef struct {
+       int f1,f2,f3,f4,f5;
+} int5;
+
+LIBTEST_API int STDCALL
+mono_return_int5 (int5 s5, int addend) {
+       if (s5.f1 != 1) {
+               fprintf(stderr, "mono_return_int5 s5.f1: got %d but expected %d\n", s5.f1, 1);
+               return 1;
+       }
+       if (s5.f2 != 2) {
+               fprintf(stderr, "mono_return_int5 s5.f2: got %d but expected %d\n", s5.f2, 2);
+               return 1;
+       }
+       if (s5.f3 != 3) {
+               fprintf(stderr, "mono_return_int5 s5.f3: got %d but expected %d\n", s5.f3, 3);
+               return 1;
+       }
+       if (s5.f4 != 4) {
+               fprintf(stderr, "mono_return_int5 s5.f4: got %d but expected %d\n", s5.f4, 4);
+               return 1;
+       }
+       if (s5.f5 != 5) {
+               fprintf(stderr, "mono_return_int5 s5.f5: got %d but expected %d\n", s5.f5, 5);
+               return 1;
+       }
+               return 2*addend;
+}
+
+typedef struct {
+       float f1;
+} float1;
+
+LIBTEST_API float STDCALL
+mono_return_float1 (float1 s1, int addend) {
+       if (s1.f1 != 1) {
+               fprintf(stderr, "mono_return_float1 s1.f1: got %f but expected %d\n", s1.f1, 1);
+               return 1;
+       }
+               return 2*addend;
+}
+
+typedef struct {
+       float f1,f2;
+} float2;
+
+LIBTEST_API float STDCALL
+mono_return_float2 (float2 s2, int addend) {
+       if (s2.f1 != 1) {
+               fprintf(stderr, "mono_return_float2 s2.f1: got %f but expected %d\n", s2.f1, 1);
+               return 1;
+       }
+       if (s2.f2 != 2) {
+               fprintf(stderr, "mono_return_float2 s2.f2: got %f but expected %d\n", s2.f2, 2);
+               return 1;
+       }
+               return 2*addend;
+}
+
+typedef struct {
+       float f1,f2,f3;
+} float3;
+
+LIBTEST_API float STDCALL
+mono_return_float3 (float3 s3, int addend) {
+       if (s3.f1 != 1) {
+               fprintf(stderr, "mono_return_float3 s3.f1: got %f but expected %d\n", s3.f1, 1);
+               return 1;
+       }
+       if (s3.f2 != 2) {
+               fprintf(stderr, "mono_return_float3 s3.f2: got %f but expected %d\n", s3.f2, 2);
+               return 1;
+       }
+       if (s3.f3 != 3) {
+               fprintf(stderr, "mono_return_float3 s3.f3: got %f but expected %d\n", s3.f3, 3);
+               return 1;
+       }
+               return 2*addend;
+}
+
+typedef struct {
+       float f1,f2,f3,f4;
+} float4;
+
+LIBTEST_API float STDCALL
+mono_return_float4 (float4 s4, int addend) {
+       if (s4.f1 != 1) {
+               fprintf(stderr, "mono_return_float4 s4.f1: got %f but expected %d\n", s4.f1, 1);
+               return 1;
+       }
+       if (s4.f2 != 2) {
+               fprintf(stderr, "mono_return_float4 s4.f2: got %f but expected %d\n", s4.f2, 2);
+               return 1;
+       }
+       if (s4.f3 != 3) {
+               fprintf(stderr, "mono_return_float4 s4.f3: got %f but expected %d\n", s4.f3, 3);
+               return 1;
+       }
+       if (s4.f4 != 4) {
+               fprintf(stderr, "mono_return_float4 s4.f4: got %f but expected %d\n", s4.f4, 4);
+               return 1;
+       }
+               return 2*addend;
+}
+
+typedef struct {
+       float f1,f2,f3,f4,f5;
+} float5;
+
+LIBTEST_API float STDCALL
+mono_return_float5 (float5 s5, int addend) {
+       if (s5.f1 != 1) {
+               fprintf(stderr, "mono_return_float5 s5.f1: got %f but expected %d\n", s5.f1, 1);
+               return 1;
+       }
+       if (s5.f2 != 2) {
+               fprintf(stderr, "mono_return_float5 s5.f2: got %f but expected %d\n", s5.f2, 2);
+               return 1;
+       }
+       if (s5.f3 != 3) {
+               fprintf(stderr, "mono_return_float5 s5.f3: got %f but expected %d\n", s5.f3, 3);
+               return 1;
+       }
+       if (s5.f4 != 4) {
+               fprintf(stderr, "mono_return_float5 s5.f4: got %f but expected %d\n", s5.f4, 4);
+               return 1;
+       }
+       if (s5.f5 != 5) {
+               fprintf(stderr, "mono_return_float5 s5.f5: got %f but expected %d\n", s5.f5, 5);
+               return 1;
+       }
+               return 2*addend;
+}
+
+typedef struct {
+       float f1,f2,f3,f4,f5,f6;
+} float6;
+
+LIBTEST_API float STDCALL
+mono_return_float6 (float6 s6, int addend) {
+       if (s6.f1 != 1) {
+               fprintf(stderr, "mono_return_float6 s6.f1: got %f but expected %d\n", s6.f1, 1);
+               return 1;
+       }
+       if (s6.f2 != 2) {
+               fprintf(stderr, "mono_return_float6 s6.f2: got %f but expected %d\n", s6.f2, 2);
+               return 1;
+       }
+       if (s6.f3 != 3) {
+               fprintf(stderr, "mono_return_float6 s6.f3: got %f but expected %d\n", s6.f3, 3);
+               return 1;
+       }
+       if (s6.f4 != 4) {
+               fprintf(stderr, "mono_return_float6 s6.f4: got %f but expected %d\n", s6.f4, 4);
+               return 1;
+       }
+       if (s6.f5 != 5) {
+               fprintf(stderr, "mono_return_float6 s6.f5: got %f but expected %d\n", s6.f5, 5);
+               return 1;
+       }
+       if (s6.f6 != 6) {
+               fprintf(stderr, "mono_return_float6 s6.f6: got %f but expected %d\n", s6.f6, 6);
+               return 1;
+       }
+               return 2*addend;
+}
+
+typedef struct {
+       float f1,f2,f3,f4,f5,f6,f7;
+} float7;
+
+LIBTEST_API float STDCALL
+mono_return_float7 (float7 s7, int addend) {
+       if (s7.f1 != 1) {
+               fprintf(stderr, "mono_return_float7 s7.f1: got %f but expected %d\n", s7.f1, 1);
+               return 1;
+       }
+       if (s7.f2 != 2) {
+               fprintf(stderr, "mono_return_float7 s7.f2: got %f but expected %d\n", s7.f2, 2);
+               return 1;
+       }
+       if (s7.f3 != 3) {
+               fprintf(stderr, "mono_return_float7 s7.f3: got %f but expected %d\n", s7.f3, 3);
+               return 1;
+       }
+       if (s7.f4 != 4) {
+               fprintf(stderr, "mono_return_float7 s7.f4: got %f but expected %d\n", s7.f4, 4);
+               return 1;
+       }
+       if (s7.f5 != 5) {
+               fprintf(stderr, "mono_return_float7 s7.f5: got %f but expected %d\n", s7.f5, 5);
+               return 1;
+       }
+       if (s7.f6 != 6) {
+               fprintf(stderr, "mono_return_float7 s7.f6: got %f but expected %d\n", s7.f6, 6);
+               return 1;
+       }
+       if (s7.f7 != 7) {
+               fprintf(stderr, "mono_return_float7 s7.f7: got %f but expected %d\n", s7.f7, 7);
+               return 1;
+       }
+               return 2*addend;
+}
+
+typedef struct {
+       float f1,f2,f3,f4,f5,f6,f7,f8;
+} float8;
+
+LIBTEST_API float STDCALL
+mono_return_float8 (float8 s8, int addend) {
+       if (s8.f1 != 1) {
+               fprintf(stderr, "mono_return_float8 s8.f1: got %f but expected %d\n", s8.f1, 1);
+               return 1;
+       }
+       if (s8.f2 != 2) {
+               fprintf(stderr, "mono_return_float8 s8.f2: got %f but expected %d\n", s8.f2, 2);
+               return 1;
+       }
+       if (s8.f3 != 3) {
+               fprintf(stderr, "mono_return_float8 s8.f3: got %f but expected %d\n", s8.f3, 3);
+               return 1;
+       }
+       if (s8.f4 != 4) {
+               fprintf(stderr, "mono_return_float8 s8.f4: got %f but expected %d\n", s8.f4, 4);
+               return 1;
+       }
+       if (s8.f5 != 5) {
+               fprintf(stderr, "mono_return_float8 s8.f5: got %f but expected %d\n", s8.f5, 5);
+               return 1;
+       }
+       if (s8.f6 != 6) {
+               fprintf(stderr, "mono_return_float8 s8.f6: got %f but expected %d\n", s8.f6, 6);
+               return 1;
+       }
+       if (s8.f7 != 7) {
+               fprintf(stderr, "mono_return_float8 s8.f7: got %f but expected %d\n", s8.f7, 7);
+               return 1;
+       }
+       if (s8.f8 != 8) {
+               fprintf(stderr, "mono_return_float8 s8.f8: got %f but expected %d\n", s8.f8, 8);
+               return 1;
+       }
+               return 2*addend;
+}
+
+typedef struct {
+       float f1,f2,f3,f4,f5,f6,f7,f8,f9;
+} float9;
+
+LIBTEST_API float STDCALL
+mono_return_float9 (float9 s9, int addend) {
+       if (s9.f1 != 1) {
+               fprintf(stderr, "mono_return_float9 s9.f1: got %f but expected %d\n", s9.f1, 1);
+               return 1;
+       }
+       if (s9.f2 != 2) {
+               fprintf(stderr, "mono_return_float9 s9.f2: got %f but expected %d\n", s9.f2, 2);
+               return 1;
+       }
+       if (s9.f3 != 3) {
+               fprintf(stderr, "mono_return_float9 s9.f3: got %f but expected %d\n", s9.f3, 3);
+               return 1;
+       }
+       if (s9.f4 != 4) {
+               fprintf(stderr, "mono_return_float9 s9.f4: got %f but expected %d\n", s9.f4, 4);
+               return 1;
+       }
+       if (s9.f5 != 5) {
+               fprintf(stderr, "mono_return_float9 s9.f5: got %f but expected %d\n", s9.f5, 5);
+               return 1;
+       }
+       if (s9.f6 != 6) {
+               fprintf(stderr, "mono_return_float9 s9.f6: got %f but expected %d\n", s9.f6, 6);
+               return 1;
+       }
+       if (s9.f7 != 7) {
+               fprintf(stderr, "mono_return_float9 s9.f7: got %f but expected %d\n", s9.f7, 7);
+               return 1;
+       }
+       if (s9.f8 != 8) {
+               fprintf(stderr, "mono_return_float9 s9.f8: got %f but expected %d\n", s9.f8, 8);
+               return 1;
+       }
+       if (s9.f9 != 9) {
+               fprintf(stderr, "mono_return_float9 s9.f9: got %f but expected %d\n", s9.f9, 9);
+               return 1;
+       }
+               return 2*addend;
+}
+
+typedef struct {
+       double f1;
+} double1;
+
+LIBTEST_API double STDCALL
+mono_return_double1 (double1 s1, int addend) {
+       if (s1.f1 != 1) {
+               fprintf(stderr, "mono_return_double1 s1.f1: got %f but expected %d\n", s1.f1, 1);
+               return 1;
+       }
+               return 2*addend;
+}
+
+typedef struct {
+       double f1,f2;
+} double2;
+
+LIBTEST_API double STDCALL
+mono_return_double2 (double2 s2, int addend) {
+       if (s2.f1 != 1) {
+               fprintf(stderr, "mono_return_double2 s2.f1: got %f but expected %d\n", s2.f1, 1);
+               return 1;
+       }
+       if (s2.f2 != 2) {
+               fprintf(stderr, "mono_return_double2 s2.f2: got %f but expected %d\n", s2.f2, 2);
+               return 1;
+       }
+               return 2*addend;
+}
+
+typedef struct {
+       double f1,f2,f3;
+} double3;
+
+LIBTEST_API double STDCALL
+mono_return_double3 (double3 s3, int addend) {
+       if (s3.f1 != 1) {
+               fprintf(stderr, "mono_return_double3 s3.f1: got %f but expected %d\n", s3.f1, 1);
+               return 1;
+       }
+       if (s3.f2 != 2) {
+               fprintf(stderr, "mono_return_double3 s3.f2: got %f but expected %d\n", s3.f2, 2);
+               return 1;
+       }
+       if (s3.f3 != 3) {
+               fprintf(stderr, "mono_return_double3 s3.f3: got %f but expected %d\n", s3.f3, 3);
+               return 1;
+       }
+               return 2*addend;
+}
+
+typedef struct {
+       double f1,f2,f3,f4;
+} double4;
+
+LIBTEST_API double STDCALL
+mono_return_double4 (double4 s4, int addend) {
+       if (s4.f1 != 1) {
+               fprintf(stderr, "mono_return_double4 s4.f1: got %f but expected %d\n", s4.f1, 1);
+               return 1;
+       }
+       if (s4.f2 != 2) {
+               fprintf(stderr, "mono_return_double4 s4.f2: got %f but expected %d\n", s4.f2, 2);
+               return 1;
+       }
+       if (s4.f3 != 3) {
+               fprintf(stderr, "mono_return_double4 s4.f3: got %f but expected %d\n", s4.f3, 3);
+               return 1;
+       }
+       if (s4.f4 != 4) {
+               fprintf(stderr, "mono_return_double4 s4.f4: got %f but expected %d\n", s4.f4, 4);
+               return 1;
+       }
+               return 2*addend;
+}
+
+typedef struct {
+       double f1,f2,f3,f4,f5;
+} double5;
+
+LIBTEST_API double STDCALL
+mono_return_double5 (double5 s5, int addend) {
+       if (s5.f1 != 1) {
+               fprintf(stderr, "mono_return_double5 s5.f1: got %f but expected %d\n", s5.f1, 1);
+               return 1;
+       }
+       if (s5.f2 != 2) {
+               fprintf(stderr, "mono_return_double5 s5.f2: got %f but expected %d\n", s5.f2, 2);
+               return 1;
+       }
+       if (s5.f3 != 3) {
+               fprintf(stderr, "mono_return_double5 s5.f3: got %f but expected %d\n", s5.f3, 3);
+               return 1;
+       }
+       if (s5.f4 != 4) {
+               fprintf(stderr, "mono_return_double5 s5.f4: got %f but expected %d\n", s5.f4, 4);
+               return 1;
+       }
+       if (s5.f5 != 5) {
+               fprintf(stderr, "mono_return_double5 s5.f5: got %f but expected %d\n", s5.f5, 5);
+               return 1;
+       }
+               return 2*addend;
+}
+
+typedef struct {
+       double f1,f2,f3,f4,f5,f6;
+} double6;
+
+LIBTEST_API double STDCALL
+mono_return_double6 (double6 s6, int addend) {
+       if (s6.f1 != 1) {
+               fprintf(stderr, "mono_return_double6 s6.f1: got %f but expected %d\n", s6.f1, 1);
+               return 1;
+       }
+       if (s6.f2 != 2) {
+               fprintf(stderr, "mono_return_double6 s6.f2: got %f but expected %d\n", s6.f2, 2);
+               return 1;
+       }
+       if (s6.f3 != 3) {
+               fprintf(stderr, "mono_return_double6 s6.f3: got %f but expected %d\n", s6.f3, 3);
+               return 1;
+       }
+       if (s6.f4 != 4) {
+               fprintf(stderr, "mono_return_double6 s6.f4: got %f but expected %d\n", s6.f4, 4);
+               return 1;
+       }
+       if (s6.f5 != 5) {
+               fprintf(stderr, "mono_return_double6 s6.f5: got %f but expected %d\n", s6.f5, 5);
+               return 1;
+       }
+       if (s6.f6 != 6) {
+               fprintf(stderr, "mono_return_double6 s6.f6: got %f but expected %d\n", s6.f6, 6);
+               return 1;
+       }
+               return 2*addend;
+}
+
+typedef struct {
+       double f1,f2,f3,f4,f5,f6,f7;
+} double7;
+
+LIBTEST_API double STDCALL
+mono_return_double7 (double7 s7, int addend) {
+       if (s7.f1 != 1) {
+               fprintf(stderr, "mono_return_double7 s7.f1: got %f but expected %d\n", s7.f1, 1);
+               return 1;
+       }
+       if (s7.f2 != 2) {
+               fprintf(stderr, "mono_return_double7 s7.f2: got %f but expected %d\n", s7.f2, 2);
+               return 1;
+       }
+       if (s7.f3 != 3) {
+               fprintf(stderr, "mono_return_double7 s7.f3: got %f but expected %d\n", s7.f3, 3);
+               return 1;
+       }
+       if (s7.f4 != 4) {
+               fprintf(stderr, "mono_return_double7 s7.f4: got %f but expected %d\n", s7.f4, 4);
+               return 1;
+       }
+       if (s7.f5 != 5) {
+               fprintf(stderr, "mono_return_double7 s7.f5: got %f but expected %d\n", s7.f5, 5);
+               return 1;
+       }
+       if (s7.f6 != 6) {
+               fprintf(stderr, "mono_return_double7 s7.f6: got %f but expected %d\n", s7.f6, 6);
+               return 1;
+       }
+       if (s7.f7 != 7) {
+               fprintf(stderr, "mono_return_double7 s7.f7: got %f but expected %d\n", s7.f7, 7);
+               return 1;
+       }
+               return 2*addend;
+}
+
+typedef struct {
+       double f1,f2,f3,f4,f5,f6,f7,f8;
+} double8;
+
+LIBTEST_API double STDCALL
+mono_return_double8 (double8 s8, int addend) {
+       if (s8.f1 != 1) {
+               fprintf(stderr, "mono_return_double8 s8.f1: got %f but expected %d\n", s8.f1, 1);
+               return 1;
+       }
+       if (s8.f2 != 2) {
+               fprintf(stderr, "mono_return_double8 s8.f2: got %f but expected %d\n", s8.f2, 2);
+               return 1;
+       }
+       if (s8.f3 != 3) {
+               fprintf(stderr, "mono_return_double8 s8.f3: got %f but expected %d\n", s8.f3, 3);
+               return 1;
+       }
+       if (s8.f4 != 4) {
+               fprintf(stderr, "mono_return_double8 s8.f4: got %f but expected %d\n", s8.f4, 4);
+               return 1;
+       }
+       if (s8.f5 != 5) {
+               fprintf(stderr, "mono_return_double8 s8.f5: got %f but expected %d\n", s8.f5, 5);
+               return 1;
+       }
+       if (s8.f6 != 6) {
+               fprintf(stderr, "mono_return_double8 s8.f6: got %f but expected %d\n", s8.f6, 6);
+               return 1;
+       }
+       if (s8.f7 != 7) {
+               fprintf(stderr, "mono_return_double8 s8.f7: got %f but expected %d\n", s8.f7, 7);
+               return 1;
+       }
+       if (s8.f8 != 8) {
+               fprintf(stderr, "mono_return_double8 s8.f8: got %f but expected %d\n", s8.f8, 8);
+               return 1;
+       }
+               return 2*addend;
+}
+
+typedef struct {
+       double f1,f2,f3,f4,f5,f6,f7,f8,f9;
+} double9;
+
+LIBTEST_API double STDCALL
+mono_return_double9 (double9 s9, int addend) {
+       if (s9.f1 != 1) {
+               fprintf(stderr, "mono_return_double9 s9.f1: got %f but expected %d\n", s9.f1, 1);
+               return 1;
+       }
+       if (s9.f2 != 2) {
+               fprintf(stderr, "mono_return_double9 s9.f2: got %f but expected %d\n", s9.f2, 2);
+               return 1;
+       }
+       if (s9.f3 != 3) {
+               fprintf(stderr, "mono_return_double9 s9.f3: got %f but expected %d\n", s9.f3, 3);
+               return 1;
+       }
+       if (s9.f4 != 4) {
+               fprintf(stderr, "mono_return_double9 s9.f4: got %f but expected %d\n", s9.f4, 4);
+               return 1;
+       }
+       if (s9.f5 != 5) {
+               fprintf(stderr, "mono_return_double9 s9.f5: got %f but expected %d\n", s9.f5, 5);
+               return 1;
+       }
+       if (s9.f6 != 6) {
+               fprintf(stderr, "mono_return_double9 s9.f6: got %f but expected %d\n", s9.f6, 6);
+               return 1;
+       }
+       if (s9.f7 != 7) {
+               fprintf(stderr, "mono_return_double9 s9.f7: got %f but expected %d\n", s9.f7, 7);
+               return 1;
+       }
+       if (s9.f8 != 8) {
+               fprintf(stderr, "mono_return_double9 s9.f8: got %f but expected %d\n", s9.f8, 8);
+               return 1;
+       }
+       if (s9.f9 != 9) {
+               fprintf(stderr, "mono_return_double9 s9.f9: got %f but expected %d\n", s9.f9, 9);
+               return 1;
+       }
+               return 2*addend;
+}
+
+
+
+// WDS debug
+// To use add:
+//     [DllImport ("libtest", EntryPoint="ppc_dbg")]
+//     public static extern void ppc_dbg ();
+// Then just call:
+//     ppc_dbg();
+LIBTEST_API void STDCALL
+ppc_dbg(void)
+{
+       static int cnt=0;
+        ++cnt;
+       printf("@#@#@# ppc_dbg call#%d\n", cnt);
+       return;
+}
+// WDS debug
+
diff --git a/mono/tests/pinvoke_ppcc.cs b/mono/tests/pinvoke_ppcc.cs
new file mode 100644 (file)
index 0000000..09ccba0
--- /dev/null
@@ -0,0 +1,426 @@
+// pinvoke_ppcc.cs - Test cases for passing structures to and and returning
+//                   structures from functions.  This particular test is for
+//                   structures consisting wholy of 1 byte fields.
+//
+//                   The Power ABI version 2 allows for special parameter
+//                   passing and returning optimizations for certain
+//                   structures of homogenous composition (like all ints).
+//                   This set of tests checks all the possible combinations
+//                   that use the special parm/return rules and one beyond.
+//
+// Bill Seurer (seurer@linux.vnet.ibm.com)
+//
+// (C) {Copyright holder}
+//
+
+using System;
+using System.Runtime.InteropServices;
+
+
+public class Test_sbyte {
+
+       [DllImport ("libtest", EntryPoint="mono_return_sbyte1")]
+       public static extern sbyte mono_return_sbyte1 (sbyte1 s, int addend);
+       [StructLayout(LayoutKind.Sequential)]
+       public struct sbyte1 {
+               public sbyte f1;
+       }
+       [DllImport ("libtest", EntryPoint="mono_return_sbyte2")]
+       public static extern sbyte mono_return_sbyte2 (sbyte2 s, int addend);
+       [StructLayout(LayoutKind.Sequential)]
+       public struct sbyte2 {
+               public sbyte f1,f2;
+       }
+       [DllImport ("libtest", EntryPoint="mono_return_sbyte3")]
+       public static extern sbyte mono_return_sbyte3 (sbyte3 s, int addend);
+       [StructLayout(LayoutKind.Sequential)]
+       public struct sbyte3 {
+               public sbyte f1,f2,f3;
+       }
+       [DllImport ("libtest", EntryPoint="mono_return_sbyte4")]
+       public static extern sbyte mono_return_sbyte4 (sbyte4 s, int addend);
+       [StructLayout(LayoutKind.Sequential)]
+       public struct sbyte4 {
+               public sbyte f1,f2,f3,f4;
+       }
+       [DllImport ("libtest", EntryPoint="mono_return_sbyte5")]
+       public static extern sbyte mono_return_sbyte5 (sbyte5 s, int addend);
+       [StructLayout(LayoutKind.Sequential)]
+       public struct sbyte5 {
+               public sbyte f1,f2,f3,f4,f5;
+       }
+       [DllImport ("libtest", EntryPoint="mono_return_sbyte6")]
+       public static extern sbyte mono_return_sbyte6 (sbyte6 s, int addend);
+       [StructLayout(LayoutKind.Sequential)]
+       public struct sbyte6 {
+               public sbyte f1,f2,f3,f4,f5,f6;
+       }
+       [DllImport ("libtest", EntryPoint="mono_return_sbyte7")]
+       public static extern sbyte mono_return_sbyte7 (sbyte7 s, int addend);
+       [StructLayout(LayoutKind.Sequential)]
+       public struct sbyte7 {
+               public sbyte f1,f2,f3,f4,f5,f6,f7;
+       }
+       [DllImport ("libtest", EntryPoint="mono_return_sbyte8")]
+       public static extern sbyte mono_return_sbyte8 (sbyte8 s, int addend);
+       [StructLayout(LayoutKind.Sequential)]
+       public struct sbyte8 {
+               public sbyte f1,f2,f3,f4,f5,f6,f7,f8;
+       }
+       [DllImport ("libtest", EntryPoint="mono_return_sbyte9")]
+       public static extern sbyte mono_return_sbyte9 (sbyte9 s, int addend);
+       [StructLayout(LayoutKind.Sequential)]
+       public struct sbyte9 {
+               public sbyte f1,f2,f3,f4,f5,f6,f7,f8,f9;
+       }
+       [DllImport ("libtest", EntryPoint="mono_return_sbyte10")]
+       public static extern sbyte mono_return_sbyte10 (sbyte10 s, int addend);
+       [StructLayout(LayoutKind.Sequential)]
+       public struct sbyte10 {
+               public sbyte f1,f2,f3,f4,f5,f6,f7,f8,f9,f10;
+       }
+       [DllImport ("libtest", EntryPoint="mono_return_sbyte11")]
+       public static extern sbyte mono_return_sbyte11 (sbyte11 s, int addend);
+       [StructLayout(LayoutKind.Sequential)]
+       public struct sbyte11 {
+               public sbyte f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11;
+       }
+       [DllImport ("libtest", EntryPoint="mono_return_sbyte12")]
+       public static extern sbyte mono_return_sbyte12 (sbyte12 s, int addend);
+       [StructLayout(LayoutKind.Sequential)]
+       public struct sbyte12 {
+               public sbyte f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12;
+       }
+       [DllImport ("libtest", EntryPoint="mono_return_sbyte13")]
+       public static extern sbyte mono_return_sbyte13 (sbyte13 s, int addend);
+       [StructLayout(LayoutKind.Sequential)]
+       public struct sbyte13 {
+               public sbyte f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13;
+       }
+       [DllImport ("libtest", EntryPoint="mono_return_sbyte14")]
+       public static extern sbyte mono_return_sbyte14 (sbyte14 s, int addend);
+       [StructLayout(LayoutKind.Sequential)]
+       public struct sbyte14 {
+               public sbyte f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13,f14;
+       }
+       [DllImport ("libtest", EntryPoint="mono_return_sbyte15")]
+       public static extern sbyte mono_return_sbyte15 (sbyte15 s, int addend);
+       [StructLayout(LayoutKind.Sequential)]
+       public struct sbyte15 {
+               public sbyte f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13,f14,f15;
+       }
+       [DllImport ("libtest", EntryPoint="mono_return_sbyte16")]
+       public static extern sbyte mono_return_sbyte16 (sbyte16 s, int addend);
+       [StructLayout(LayoutKind.Sequential)]
+       public struct sbyte16 {
+               public sbyte f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13,f14,f15,f16;
+       }
+       // This structure is 1 element too large to use the special return
+       //  rules.
+       [DllImport ("libtest", EntryPoint="mono_return_sbyte17")]
+       public static extern sbyte mono_return_sbyte17 (sbyte17 s, int addend);
+       [StructLayout(LayoutKind.Sequential)]
+       public struct sbyte17 {
+               public sbyte f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13,f14,f15,f16,f17;
+       }
+
+       // This structure has nested structures within it but they are
+       //  homogenous and thus should still use the special rules.
+       public struct sbyte16_nested1 {
+               public sbyte f1;
+       };
+       public struct sbyte16_nested2 {
+               public sbyte f16;
+       };
+       [DllImport ("libtest", EntryPoint="mono_return_sbyte16_nested")]
+       public static extern sbyte16_nested mono_return_sbyte16_nested (sbyte16_nested s, int addend);
+       [StructLayout(LayoutKind.Sequential)]
+       public struct sbyte16_nested {
+               public sbyte16_nested1 nested1;
+               public sbyte f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13,f14,f15;
+               public sbyte16_nested2 nested2;
+       }
+
+       public static int Main (string[] args) {
+
+               sbyte1 s1;
+               s1.f1 = 1;
+               sbyte retval1 = mono_return_sbyte1(s1, 9);
+               if (retval1 != 2*9) {
+                       Console.WriteLine("   sbyte1 retval1: got {0} but expected {1}", retval1, 2*9);
+                       return 1;
+               }
+
+               sbyte2 s2;
+               s2.f1 = 1;
+               s2.f2 = 2;
+               sbyte retval2 = mono_return_sbyte2(s2, 9);
+               if (retval2 != 2*9) {
+                       Console.WriteLine("   sbyte2 retval2: got {0} but expected {1}", retval2, 2*9);
+                       return 1;
+               }
+
+               sbyte3 s3;
+               s3.f1 = 1;
+               s3.f2 = 2;
+               s3.f3 = 3;
+               sbyte retval3 = mono_return_sbyte3(s3, 9);
+               if (retval3 != 2*9) {
+                       Console.WriteLine("   sbyte3 retval3: got {0} but expected {1}", retval3, 2*9);
+                       return 1;
+               }
+
+               sbyte4 s4;
+               s4.f1 = 1;
+               s4.f2 = 2;
+               s4.f3 = 3;
+               s4.f4 = 4;
+               sbyte retval4 = mono_return_sbyte4(s4, 9);
+               if (retval4 != 2*9) {
+                       Console.WriteLine("   sbyte4 retval4: got {0} but expected {1}", retval4, 2*9);
+                       return 1;
+               }
+
+               sbyte5 s5;
+               s5.f1 = 1;
+               s5.f2 = 2;
+               s5.f3 = 3;
+               s5.f4 = 4;
+               s5.f5 = 5;
+               sbyte retval5 = mono_return_sbyte5(s5, 9);
+               if (retval5 != 2*9) {
+                       Console.WriteLine("   sbyte5 retval5: got {0} but expected {1}", retval5, 2*9);
+                       return 1;
+               }
+
+               sbyte6 s6;
+               s6.f1 = 1;
+               s6.f2 = 2;
+               s6.f3 = 3;
+               s6.f4 = 4;
+               s6.f5 = 5;
+               s6.f6 = 6;
+               sbyte retval6 = mono_return_sbyte6(s6, 9);
+               if (retval6 != 2*9) {
+                       Console.WriteLine("   sbyte6 retval6: got {0} but expected {1}", retval6, 2*9);
+                       return 1;
+               }
+
+               sbyte7 s7;
+               s7.f1 = 1;
+               s7.f2 = 2;
+               s7.f3 = 3;
+               s7.f4 = 4;
+               s7.f5 = 5;
+               s7.f6 = 6;
+               s7.f7 = 7;
+               sbyte retval7 = mono_return_sbyte7(s7, 9);
+               if (retval7 != 2*9) {
+                       Console.WriteLine("   sbyte7 retval7: got {0} but expected {1}", retval7, 2*9);
+                       return 1;
+               }
+
+               sbyte8 s8;
+               s8.f1 = 1;
+               s8.f2 = 2;
+               s8.f3 = 3;
+               s8.f4 = 4;
+               s8.f5 = 5;
+               s8.f6 = 6;
+               s8.f7 = 7;
+               s8.f8 = 8;
+               sbyte retval8 = mono_return_sbyte8(s8, 9);
+               if (retval8 != 2*9) {
+                       Console.WriteLine("   sbyte8 retval8: got {0} but expected {1}", retval8, 2*9);
+                       return 1;
+               }
+
+               sbyte9 s9;
+               s9.f1 = 1;
+               s9.f2 = 2;
+               s9.f3 = 3;
+               s9.f4 = 4;
+               s9.f5 = 5;
+               s9.f6 = 6;
+               s9.f7 = 7;
+               s9.f8 = 8;
+               s9.f9 = 9;
+               sbyte retval9 = mono_return_sbyte9(s9, 9);
+               if (retval9 != 2*9) {
+                       Console.WriteLine("   sbyte9 retval9: got {0} but expected {1}", retval9, 2*9);
+                       return 1;
+               }
+
+               sbyte10 s10;
+               s10.f1 = 1;
+               s10.f2 = 2;
+               s10.f3 = 3;
+               s10.f4 = 4;
+               s10.f5 = 5;
+               s10.f6 = 6;
+               s10.f7 = 7;
+               s10.f8 = 8;
+               s10.f9 = 9;
+               s10.f10 = 10;
+               sbyte retval10 = mono_return_sbyte10(s10, 9);
+               if (retval10 != 2*9) {
+                       Console.WriteLine("   sbyte10 retval10: got {0} but expected {1}", retval10, 2*9);
+                       return 1;
+               }
+
+               sbyte11 s11;
+               s11.f1 = 1;
+               s11.f2 = 2;
+               s11.f3 = 3;
+               s11.f4 = 4;
+               s11.f5 = 5;
+               s11.f6 = 6;
+               s11.f7 = 7;
+               s11.f8 = 8;
+               s11.f9 = 9;
+               s11.f10 = 10;
+               s11.f11 = 11;
+               sbyte retval11 = mono_return_sbyte11(s11, 9);
+               if (retval11 != 2*9) {
+                       Console.WriteLine("   sbyte11 retval11: got {0} but expected {1}", retval11, 2*9);
+                       return 1;
+               }
+
+               sbyte12 s12;
+               s12.f1 = 1;
+               s12.f2 = 2;
+               s12.f3 = 3;
+               s12.f4 = 4;
+               s12.f5 = 5;
+               s12.f6 = 6;
+               s12.f7 = 7;
+               s12.f8 = 8;
+               s12.f9 = 9;
+               s12.f10 = 10;
+               s12.f11 = 11;
+               s12.f12 = 12;
+               sbyte retval12 = mono_return_sbyte12(s12, 9);
+               if (retval12 != 2*9) {
+                       Console.WriteLine("   sbyte12 retval12: got {0} but expected {1}", retval12, 2*9);
+                       return 1;
+               }
+
+               sbyte13 s13;
+               s13.f1 = 1;
+               s13.f2 = 2;
+               s13.f3 = 3;
+               s13.f4 = 4;
+               s13.f5 = 5;
+               s13.f6 = 6;
+               s13.f7 = 7;
+               s13.f8 = 8;
+               s13.f9 = 9;
+               s13.f10 = 10;
+               s13.f11 = 11;
+               s13.f12 = 12;
+               s13.f13 = 13;
+               sbyte retval13 = mono_return_sbyte13(s13, 9);
+               if (retval13 != 2*9) {
+                       Console.WriteLine("   sbyte13 retval13: got {0} but expected {1}", retval13, 2*9);
+                       return 1;
+               }
+
+               sbyte14 s14;
+               s14.f1 = 1;
+               s14.f2 = 2;
+               s14.f3 = 3;
+               s14.f4 = 4;
+               s14.f5 = 5;
+               s14.f6 = 6;
+               s14.f7 = 7;
+               s14.f8 = 8;
+               s14.f9 = 9;
+               s14.f10 = 10;
+               s14.f11 = 11;
+               s14.f12 = 12;
+               s14.f13 = 13;
+               s14.f14 = 14;
+               sbyte retval14 = mono_return_sbyte14(s14, 9);
+               if (retval14 != 2*9) {
+                       Console.WriteLine("   sbyte14 retval14: got {0} but expected {1}", retval14, 2*9);
+                       return 1;
+               }
+
+               sbyte15 s15;
+               s15.f1 = 1;
+               s15.f2 = 2;
+               s15.f3 = 3;
+               s15.f4 = 4;
+               s15.f5 = 5;
+               s15.f6 = 6;
+               s15.f7 = 7;
+               s15.f8 = 8;
+               s15.f9 = 9;
+               s15.f10 = 10;
+               s15.f11 = 11;
+               s15.f12 = 12;
+               s15.f13 = 13;
+               s15.f14 = 14;
+               s15.f15 = 15;
+               sbyte retval15 = mono_return_sbyte15(s15, 9);
+               if (retval15 != 2*9) {
+                       Console.WriteLine("   sbyte15 retval15: got {0} but expected {1}", retval15, 2*9);
+                       return 1;
+               }
+
+               sbyte16 s16;
+               s16.f1 = 1;
+               s16.f2 = 2;
+               s16.f3 = 3;
+               s16.f4 = 4;
+               s16.f5 = 5;
+               s16.f6 = 6;
+               s16.f7 = 7;
+               s16.f8 = 8;
+               s16.f9 = 9;
+               s16.f10 = 10;
+               s16.f11 = 11;
+               s16.f12 = 12;
+               s16.f13 = 13;
+               s16.f14 = 14;
+               s16.f15 = 15;
+               s16.f16 = 16;
+               sbyte retval16 = mono_return_sbyte16(s16, 9);
+               if (retval16 != 2*9) {
+                       Console.WriteLine("   sbyte16 retval16: got {0} but expected {1}", retval16, 2*9);
+                       return 1;
+               }
+
+               sbyte17 s17;
+               s17.f1 = 1;
+               s17.f2 = 2;
+               s17.f3 = 3;
+               s17.f4 = 4;
+               s17.f5 = 5;
+               s17.f6 = 6;
+               s17.f7 = 7;
+               s17.f8 = 8;
+               s17.f9 = 9;
+               s17.f10 = 10;
+               s17.f11 = 11;
+               s17.f12 = 12;
+               s17.f13 = 13;
+               s17.f14 = 14;
+               s17.f15 = 15;
+               s17.f16 = 16;
+               s17.f17 = 17;
+               sbyte retval17 = mono_return_sbyte17(s17, 9);
+               if (retval17 != 2*9) {
+                       Console.WriteLine("   sbyte17 retval17: got {0} but expected {1}", retval17, 2*9);
+                       return 1;
+               }
+
+
+               return 0;
+       } // end Main
+} // end class Test_sbyte
+
+
+
+
+
diff --git a/mono/tests/pinvoke_ppcd.cs b/mono/tests/pinvoke_ppcd.cs
new file mode 100644 (file)
index 0000000..dc9f9ac
--- /dev/null
@@ -0,0 +1,215 @@
+// pinvoke_ppcd.cs - Test cases for passing structures to and and returning
+//                   structures from functions.  This particular test is for
+//                   structures consisting wholy of 8 byte fields.
+//
+//                   The Power ABI version 2 allows for special parameter
+//                   passing and returning optimizations for certain
+//                   structures of homogenous composition (like all ints).
+//                   This set of tests checks all the possible combinations
+//                   that use the special parm/return rules and one beyond.
+//
+// Bill Seurer (seurer@linux.vnet.ibm.com)
+//
+// (C) {Copyright holder}
+//
+
+using System;
+using System.Runtime.InteropServices;
+
+
+public class Test_double {
+
+       [DllImport ("libtest", EntryPoint="mono_return_double1")]
+       public static extern double mono_return_double1 (double1 s, int addend);
+       [StructLayout(LayoutKind.Sequential)]
+       public struct double1 {
+               public double f1;
+       }
+       [DllImport ("libtest", EntryPoint="mono_return_double2")]
+       public static extern double mono_return_double2 (double2 s, int addend);
+       [StructLayout(LayoutKind.Sequential)]
+       public struct double2 {
+               public double f1,f2;
+       }
+       // This structure is 1 element too large to use the special return
+       //  rules.
+       [DllImport ("libtest", EntryPoint="mono_return_double3")]
+       public static extern double mono_return_double3 (double3 s, int addend);
+       [StructLayout(LayoutKind.Sequential)]
+       public struct double3 {
+               public double f1,f2,f3;
+       }
+       [DllImport ("libtest", EntryPoint="mono_return_double4")]
+       public static extern double mono_return_double4 (double4 s, int addend);
+       [StructLayout(LayoutKind.Sequential)]
+       public struct double4 {
+               public double f1,f2,f3,f4;
+       }
+       [DllImport ("libtest", EntryPoint="mono_return_double5")]
+       public static extern double mono_return_double5 (double5 s, int addend);
+       [StructLayout(LayoutKind.Sequential)]
+       public struct double5 {
+               public double f1,f2,f3,f4,f5;
+       }
+       [DllImport ("libtest", EntryPoint="mono_return_double6")]
+       public static extern double mono_return_double6 (double6 s, int addend);
+       [StructLayout(LayoutKind.Sequential)]
+       public struct double6 {
+               public double f1,f2,f3,f4,f5,f6;
+       }
+       [DllImport ("libtest", EntryPoint="mono_return_double7")]
+       public static extern double mono_return_double7 (double7 s, int addend);
+       [StructLayout(LayoutKind.Sequential)]
+       public struct double7 {
+               public double f1,f2,f3,f4,f5,f6,f7;
+       }
+       [DllImport ("libtest", EntryPoint="mono_return_double8")]
+       public static extern double mono_return_double8 (double8 s, int addend);
+       [StructLayout(LayoutKind.Sequential)]
+       public struct double8 {
+               public double f1,f2,f3,f4,f5,f6,f7,f8;
+       }
+       // This structure is 1 element too large to use the special parameter
+       //  passing rules.
+       [DllImport ("libtest", EntryPoint="mono_return_double9")]
+       public static extern double mono_return_double9 (double9 s, int addend);
+       [StructLayout(LayoutKind.Sequential)]
+       public struct double9 {
+               public double f1,f2,f3,f4,f5,f6,f7,f8,f9;
+       }
+
+       // This structure has nested structures within it but they are
+       //  homogenous and thus should still use the special rules.
+       public struct double2_nested1 {
+               public double f1;
+       };
+       public struct double2_nested2 {
+               public double f2;
+       };
+       [DllImport ("libtest", EntryPoint="mono_return_double2_nested")]
+       public static extern double2_nested mono_return_double2_nested (double2_nested s, int addend);
+       [StructLayout(LayoutKind.Sequential)]
+       public struct double2_nested {
+               public double2_nested1 nested1;
+               public double2_nested2 nested2;
+       }
+
+       public static int Main (string[] args) {
+
+               double1 s1;
+               s1.f1 = 1;
+               double retval1 = mono_return_double1(s1, 9);
+               if (retval1 != 2*9) {
+                       Console.WriteLine("   double1 retval1: got {0} but expected {1}", retval1, 2*9);
+                       return 1;
+               }
+
+               double2 s2;
+               s2.f1 = 1;
+               s2.f2 = 2;
+               double retval2 = mono_return_double2(s2, 9);
+               if (retval2 != 2*9) {
+                       Console.WriteLine("   double2 retval2: got {0} but expected {1}", retval2, 2*9);
+                       return 1;
+               }
+
+               double3 s3;
+               s3.f1 = 1;
+               s3.f2 = 2;
+               s3.f3 = 3;
+               double retval3 = mono_return_double3(s3, 9);
+               if (retval3 != 2*9) {
+                       Console.WriteLine("   double3 retval3: got {0} but expected {1}", retval3, 2*9);
+                       return 1;
+               }
+
+               double4 s4;
+               s4.f1 = 1;
+               s4.f2 = 2;
+               s4.f3 = 3;
+               s4.f4 = 4;
+               double retval4 = mono_return_double4(s4, 9);
+               if (retval4 != 2*9) {
+                       Console.WriteLine("   double4 retval4: got {0} but expected {1}", retval4, 2*9);
+                       return 1;
+               }
+
+               double5 s5;
+               s5.f1 = 1;
+               s5.f2 = 2;
+               s5.f3 = 3;
+               s5.f4 = 4;
+               s5.f5 = 5;
+               double retval5 = mono_return_double5(s5, 9);
+               if (retval5 != 2*9) {
+                       Console.WriteLine("   double5 retval5: got {0} but expected {1}", retval5, 2*9);
+                       return 1;
+               }
+
+               double6 s6;
+               s6.f1 = 1;
+               s6.f2 = 2;
+               s6.f3 = 3;
+               s6.f4 = 4;
+               s6.f5 = 5;
+               s6.f6 = 6;
+               double retval6 = mono_return_double6(s6, 9);
+               if (retval6 != 2*9) {
+                       Console.WriteLine("   double6 retval6: got {0} but expected {1}", retval6, 2*9);
+                       return 1;
+               }
+
+               double7 s7;
+               s7.f1 = 1;
+               s7.f2 = 2;
+               s7.f3 = 3;
+               s7.f4 = 4;
+               s7.f5 = 5;
+               s7.f6 = 6;
+               s7.f7 = 7;
+               double retval7 = mono_return_double7(s7, 9);
+               if (retval7 != 2*9) {
+                       Console.WriteLine("   double7 retval7: got {0} but expected {1}", retval7, 2*9);
+                       return 1;
+               }
+
+               double8 s8;
+               s8.f1 = 1;
+               s8.f2 = 2;
+               s8.f3 = 3;
+               s8.f4 = 4;
+               s8.f5 = 5;
+               s8.f6 = 6;
+               s8.f7 = 7;
+               s8.f8 = 8;
+               double retval8 = mono_return_double8(s8, 9);
+               if (retval8 != 2*9) {
+                       Console.WriteLine("   double8 retval8: got {0} but expected {1}", retval8, 2*9);
+                       return 1;
+               }
+
+               double9 s9;
+               s9.f1 = 1;
+               s9.f2 = 2;
+               s9.f3 = 3;
+               s9.f4 = 4;
+               s9.f5 = 5;
+               s9.f6 = 6;
+               s9.f7 = 7;
+               s9.f8 = 8;
+               s9.f9 = 9;
+               double retval9 = mono_return_double9(s9, 9);
+               if (retval9 != 2*9) {
+                       Console.WriteLine("   double9 retval9: got {0} but expected {1}", retval9, 2*9);
+                       return 1;
+               }
+
+
+               return 0;
+       } // end Main
+} // end class Test_double
+
+
+
+
+
diff --git a/mono/tests/pinvoke_ppcf.cs b/mono/tests/pinvoke_ppcf.cs
new file mode 100644 (file)
index 0000000..97a34c5
--- /dev/null
@@ -0,0 +1,216 @@
+// pinvoke_ppcf.cs - Test cases for passing structures to and and returning
+//                   structures from functions.  This particular test is for
+//                   structures consisting wholy of 4 byte fields.
+//
+//                   The Power ABI version 2 allows for special parameter
+//                   passing and returning optimizations for certain
+//                   structures of homogenous composition (like all ints).
+//                   This set of tests checks all the possible combinations
+//                   that use the special parm/return rules and one beyond.
+//
+// Bill Seurer (seurer@linux.vnet.ibm.com)
+//
+// (C) {Copyright holder}
+//
+
+using System;
+using System.Runtime.InteropServices;
+
+
+public class Test_float {
+
+       [DllImport ("libtest", EntryPoint="mono_return_float1")]
+       public static extern float mono_return_float1 (float1 s, int addend);
+       [StructLayout(LayoutKind.Sequential)]
+       public struct float1 {
+               public float f1;
+       }
+       [DllImport ("libtest", EntryPoint="mono_return_float2")]
+       public static extern float mono_return_float2 (float2 s, int addend);
+       [StructLayout(LayoutKind.Sequential)]
+       public struct float2 {
+               public float f1,f2;
+       }
+       [DllImport ("libtest", EntryPoint="mono_return_float3")]
+       public static extern float mono_return_float3 (float3 s, int addend);
+       [StructLayout(LayoutKind.Sequential)]
+       public struct float3 {
+               public float f1,f2,f3;
+       }
+       [DllImport ("libtest", EntryPoint="mono_return_float4")]
+       public static extern float mono_return_float4 (float4 s, int addend);
+       [StructLayout(LayoutKind.Sequential)]
+       public struct float4 {
+               public float f1,f2,f3,f4;
+       }
+       // This structure is 1 element too large to use the special return
+       //  rules.
+       [DllImport ("libtest", EntryPoint="mono_return_float5")]
+       public static extern float mono_return_float5 (float5 s, int addend);
+       [StructLayout(LayoutKind.Sequential)]
+       public struct float5 {
+               public float f1,f2,f3,f4,f5;
+       }
+       [DllImport ("libtest", EntryPoint="mono_return_float6")]
+       public static extern float mono_return_float6 (float6 s, int addend);
+       [StructLayout(LayoutKind.Sequential)]
+       public struct float6 {
+               public float f1,f2,f3,f4,f5,f6;
+       }
+       [DllImport ("libtest", EntryPoint="mono_return_float7")]
+       public static extern float mono_return_float7 (float7 s, int addend);
+       [StructLayout(LayoutKind.Sequential)]
+       public struct float7 {
+               public float f1,f2,f3,f4,f5,f6,f7;
+       }
+       [DllImport ("libtest", EntryPoint="mono_return_float8")]
+       public static extern float mono_return_float8 (float8 s, int addend);
+       [StructLayout(LayoutKind.Sequential)]
+       public struct float8 {
+               public float f1,f2,f3,f4,f5,f6,f7,f8;
+       }
+       // This structure is 1 element too large to use the special parameter
+       //  passing rules.
+       [DllImport ("libtest", EntryPoint="mono_return_float9")]
+       public static extern float mono_return_float9 (float9 s, int addend);
+       [StructLayout(LayoutKind.Sequential)]
+       public struct float9 {
+               public float f1,f2,f3,f4,f5,f6,f7,f8,f9;
+       }
+
+       // This structure has nested structures within it but they are
+       //  homogenous and thus should still use the special rules.
+       public struct float4_nested1 {
+               public float f1;
+       };
+       public struct float4_nested2 {
+               public float f4;
+       };
+       [DllImport ("libtest", EntryPoint="mono_return_float4_nested")]
+       public static extern float4_nested mono_return_float4_nested (float4_nested s, int addend);
+       [StructLayout(LayoutKind.Sequential)]
+       public struct float4_nested {
+               public float4_nested1 nested1;
+               public float f2,f3;
+               public float4_nested2 nested2;
+       }
+
+       public static int Main (string[] args) {
+
+               float1 s1;
+               s1.f1 = 1;
+               float retval1 = mono_return_float1(s1, 906);
+               if (retval1 != 2*906) {
+                       Console.WriteLine("   float1 retval1: got {0} but expected {1}", retval1, 2*906);
+                       return 1;
+               }
+
+               float2 s2;
+               s2.f1 = 1;
+               s2.f2 = 2;
+               float retval2 = mono_return_float2(s2, 906);
+               if (retval2 != 2*906) {
+                       Console.WriteLine("   float2 retval2: got {0} but expected {1}", retval2, 2*906);
+                       return 1;
+               }
+
+               float3 s3;
+               s3.f1 = 1;
+               s3.f2 = 2;
+               s3.f3 = 3;
+               float retval3 = mono_return_float3(s3, 906);
+               if (retval3 != 2*906) {
+                       Console.WriteLine("   float3 retval3: got {0} but expected {1}", retval3, 2*906);
+                       return 1;
+               }
+
+               float4 s4;
+               s4.f1 = 1;
+               s4.f2 = 2;
+               s4.f3 = 3;
+               s4.f4 = 4;
+               float retval4 = mono_return_float4(s4, 906);
+               if (retval4 != 2*906) {
+                       Console.WriteLine("   float4 retval4: got {0} but expected {1}", retval4, 2*906);
+                       return 1;
+               }
+
+               float5 s5;
+               s5.f1 = 1;
+               s5.f2 = 2;
+               s5.f3 = 3;
+               s5.f4 = 4;
+               s5.f5 = 5;
+               float retval5 = mono_return_float5(s5, 906);
+               if (retval5 != 2*906) {
+                       Console.WriteLine("   float5 retval5: got {0} but expected {1}", retval5, 2*906);
+                       return 1;
+               }
+
+               float6 s6;
+               s6.f1 = 1;
+               s6.f2 = 2;
+               s6.f3 = 3;
+               s6.f4 = 4;
+               s6.f5 = 5;
+               s6.f6 = 6;
+               float retval6 = mono_return_float6(s6, 906);
+               if (retval6 != 2*906) {
+                       Console.WriteLine("   float6 retval6: got {0} but expected {1}", retval6, 2*906);
+                       return 1;
+               }
+
+               float7 s7;
+               s7.f1 = 1;
+               s7.f2 = 2;
+               s7.f3 = 3;
+               s7.f4 = 4;
+               s7.f5 = 5;
+               s7.f6 = 6;
+               s7.f7 = 7;
+               float retval7 = mono_return_float7(s7, 906);
+               if (retval7 != 2*906) {
+                       Console.WriteLine("   float7 retval7: got {0} but expected {1}", retval7, 2*906);
+                       return 1;
+               }
+
+               float8 s8;
+               s8.f1 = 1;
+               s8.f2 = 2;
+               s8.f3 = 3;
+               s8.f4 = 4;
+               s8.f5 = 5;
+               s8.f6 = 6;
+               s8.f7 = 7;
+               s8.f8 = 8;
+               float retval8 = mono_return_float8(s8, 906);
+               if (retval8 != 2*906) {
+                       Console.WriteLine("   float8 retval8: got {0} but expected {1}", retval8, 2*906);
+                       return 1;
+               }
+
+               float9 s9;
+               s9.f1 = 1;
+               s9.f2 = 2;
+               s9.f3 = 3;
+               s9.f4 = 4;
+               s9.f5 = 5;
+               s9.f6 = 6;
+               s9.f7 = 7;
+               s9.f8 = 8;
+               s9.f9 = 9;
+               float retval9 = mono_return_float9(s9, 906);
+               if (retval9 != 2*906) {
+                       Console.WriteLine("   float9 retval9: got {0} but expected {1}", retval9, 2*906);
+                       return 1;
+               }
+
+
+               return 0;
+       } // end Main
+} // end class Test_float
+
+
+
+
+
diff --git a/mono/tests/pinvoke_ppci.cs b/mono/tests/pinvoke_ppci.cs
new file mode 100644 (file)
index 0000000..db3df3e
--- /dev/null
@@ -0,0 +1,132 @@
+// pinvoke_ppci.cs - Test cases for passing structures to and and returning
+//                   structures from functions.  This particular test is for
+//                   structures consisting wholy of 4 byte fields.
+//
+//                   The Power ABI version 2 allows for special parameter
+//                   passing and returning optimizations for certain
+//                   structures of homogenous composition (like all ints).
+//                   This set of tests checks all the possible combinations
+//                   that use the special parm/return rules and one beyond.
+//
+// Bill Seurer (seurer@linux.vnet.ibm.com)
+//
+// (C) {Copyright holder}
+//
+
+using System;
+using System.Runtime.InteropServices;
+
+
+public class Test_int {
+
+       [DllImport ("libtest", EntryPoint="mono_return_int1")]
+       public static extern int mono_return_int1 (int1 s, int addend);
+       [StructLayout(LayoutKind.Sequential)]
+       public struct int1 {
+               public int f1;
+       }
+       [DllImport ("libtest", EntryPoint="mono_return_int2")]
+       public static extern int mono_return_int2 (int2 s, int addend);
+       [StructLayout(LayoutKind.Sequential)]
+       public struct int2 {
+               public int f1,f2;
+       }
+       [DllImport ("libtest", EntryPoint="mono_return_int3")]
+       public static extern int mono_return_int3 (int3 s, int addend);
+       [StructLayout(LayoutKind.Sequential)]
+       public struct int3 {
+               public int f1,f2,f3;
+       }
+       [DllImport ("libtest", EntryPoint="mono_return_int4")]
+       public static extern int mono_return_int4 (int4 s, int addend);
+       [StructLayout(LayoutKind.Sequential)]
+       public struct int4 {
+               public int f1,f2,f3,f4;
+       }
+       // This structure is 1 element too large to use the special return
+       //  rules.
+       [DllImport ("libtest", EntryPoint="mono_return_int5")]
+       public static extern int mono_return_int5 (int5 s, int addend);
+       [StructLayout(LayoutKind.Sequential)]
+       public struct int5 {
+               public int f1,f2,f3,f4,f5;
+       }
+
+       // This structure has nested structures within it but they are
+       //  homogenous and thus should still use the special rules.
+       public struct int4_nested1 {
+               public int f1;
+       };
+       public struct int4_nested2 {
+               public int f4;
+       };
+       [DllImport ("libtest", EntryPoint="mono_return_int4_nested")]
+       public static extern int4_nested mono_return_int4_nested (int4_nested s, int addend);
+       [StructLayout(LayoutKind.Sequential)]
+       public struct int4_nested {
+               public int4_nested1 nested1;
+               public int f2,f3;
+               public int4_nested2 nested2;
+       }
+
+       public static int Main (string[] args) {
+
+               int1 s1;
+               s1.f1 = 1;
+               int retval1 = mono_return_int1(s1, 906);
+               if (retval1 != 2*906) {
+                       Console.WriteLine("   int1 retval1: got {0} but expected {1}", retval1, 2*906);
+                       return 1;
+               }
+
+               int2 s2;
+               s2.f1 = 1;
+               s2.f2 = 2;
+               int retval2 = mono_return_int2(s2, 906);
+               if (retval2 != 2*906) {
+                       Console.WriteLine("   int2 retval2: got {0} but expected {1}", retval2, 2*906);
+                       return 1;
+               }
+
+               int3 s3;
+               s3.f1 = 1;
+               s3.f2 = 2;
+               s3.f3 = 3;
+               int retval3 = mono_return_int3(s3, 906);
+               if (retval3 != 2*906) {
+                       Console.WriteLine("   int3 retval3: got {0} but expected {1}", retval3, 2*906);
+                       return 1;
+               }
+
+               int4 s4;
+               s4.f1 = 1;
+               s4.f2 = 2;
+               s4.f3 = 3;
+               s4.f4 = 4;
+               int retval4 = mono_return_int4(s4, 906);
+               if (retval4 != 2*906) {
+                       Console.WriteLine("   int4 retval4: got {0} but expected {1}", retval4, 2*906);
+                       return 1;
+               }
+
+               int5 s5;
+               s5.f1 = 1;
+               s5.f2 = 2;
+               s5.f3 = 3;
+               s5.f4 = 4;
+               s5.f5 = 5;
+               int retval5 = mono_return_int5(s5, 906);
+               if (retval5 != 2*906) {
+                       Console.WriteLine("   int5 retval5: got {0} but expected {1}", retval5, 2*906);
+                       return 1;
+               }
+
+
+               return 0;
+       } // end Main
+} // end class Test_int
+
+
+
+
+
diff --git a/mono/tests/pinvoke_ppcs.cs b/mono/tests/pinvoke_ppcs.cs
new file mode 100644 (file)
index 0000000..91a0284
--- /dev/null
@@ -0,0 +1,214 @@
+// pinvoke_ppcs.cs - Test cases for passing structures to and and returning
+//                   structures from functions.  This particular test is for
+//                   structures consisting wholy of 2 byte fields.
+//
+//                   The Power ABI version 2 allows for special parameter
+//                   passing and returning optimizations for certain
+//                   structures of homogenous composition (like all ints).
+//                   This set of tests checks all the possible combinations
+//                   that use the special parm/return rules and one beyond.
+//
+// Bill Seurer (seurer@linux.vnet.ibm.com)
+//
+// (C) {Copyright holder}
+//
+
+using System;
+using System.Runtime.InteropServices;
+
+
+public class Test_short {
+
+       [DllImport ("libtest", EntryPoint="mono_return_short1")]
+       public static extern short mono_return_short1 (short1 s, int addend);
+       [StructLayout(LayoutKind.Sequential)]
+       public struct short1 {
+               public short f1;
+       }
+       [DllImport ("libtest", EntryPoint="mono_return_short2")]
+       public static extern short mono_return_short2 (short2 s, int addend);
+       [StructLayout(LayoutKind.Sequential)]
+       public struct short2 {
+               public short f1,f2;
+       }
+       [DllImport ("libtest", EntryPoint="mono_return_short3")]
+       public static extern short mono_return_short3 (short3 s, int addend);
+       [StructLayout(LayoutKind.Sequential)]
+       public struct short3 {
+               public short f1,f2,f3;
+       }
+       [DllImport ("libtest", EntryPoint="mono_return_short4")]
+       public static extern short mono_return_short4 (short4 s, int addend);
+       [StructLayout(LayoutKind.Sequential)]
+       public struct short4 {
+               public short f1,f2,f3,f4;
+       }
+       [DllImport ("libtest", EntryPoint="mono_return_short5")]
+       public static extern short mono_return_short5 (short5 s, int addend);
+       [StructLayout(LayoutKind.Sequential)]
+       public struct short5 {
+               public short f1,f2,f3,f4,f5;
+       }
+       [DllImport ("libtest", EntryPoint="mono_return_short6")]
+       public static extern short mono_return_short6 (short6 s, int addend);
+       [StructLayout(LayoutKind.Sequential)]
+       public struct short6 {
+               public short f1,f2,f3,f4,f5,f6;
+       }
+       [DllImport ("libtest", EntryPoint="mono_return_short7")]
+       public static extern short mono_return_short7 (short7 s, int addend);
+       [StructLayout(LayoutKind.Sequential)]
+       public struct short7 {
+               public short f1,f2,f3,f4,f5,f6,f7;
+       }
+       [DllImport ("libtest", EntryPoint="mono_return_short8")]
+       public static extern short mono_return_short8 (short8 s, int addend);
+       [StructLayout(LayoutKind.Sequential)]
+       public struct short8 {
+               public short f1,f2,f3,f4,f5,f6,f7,f8;
+       }
+       // This structure is 1 element too large to use the special return
+       //  rules.
+       [DllImport ("libtest", EntryPoint="mono_return_short9")]
+       public static extern short mono_return_short9 (short9 s, int addend);
+       [StructLayout(LayoutKind.Sequential)]
+       public struct short9 {
+               public short f1,f2,f3,f4,f5,f6,f7,f8,f9;
+       }
+
+       // This structure has nested structures within it but they are
+       //  homogenous and thus should still use the special rules.
+       public struct short8_nested1 {
+               public short f1;
+       };
+       public struct short8_nested2 {
+               public short f8;
+       };
+       [DllImport ("libtest", EntryPoint="mono_return_short8_nested")]
+       public static extern short8_nested mono_return_short8_nested (short8_nested s, int addend);
+       [StructLayout(LayoutKind.Sequential)]
+       public struct short8_nested {
+               public short8_nested1 nested1;
+               public short f2,f3,f4,f5,f6,f7;
+               public short8_nested2 nested2;
+       }
+
+       public static int Main (string[] args) {
+
+               short1 s1;
+               s1.f1 = 1;
+               short retval1 = mono_return_short1(s1, 90);
+               if (retval1 != 2*90) {
+                       Console.WriteLine("   short1 retval1: got {0} but expected {1}", retval1, 2*90);
+                       return 1;
+               }
+
+               short2 s2;
+               s2.f1 = 1;
+               s2.f2 = 2;
+               short retval2 = mono_return_short2(s2, 90);
+               if (retval2 != 2*90) {
+                       Console.WriteLine("   short2 retval2: got {0} but expected {1}", retval2, 2*90);
+                       return 1;
+               }
+
+               short3 s3;
+               s3.f1 = 1;
+               s3.f2 = 2;
+               s3.f3 = 3;
+               short retval3 = mono_return_short3(s3, 90);
+               if (retval3 != 2*90) {
+                       Console.WriteLine("   short3 retval3: got {0} but expected {1}", retval3, 2*90);
+                       return 1;
+               }
+
+               short4 s4;
+               s4.f1 = 1;
+               s4.f2 = 2;
+               s4.f3 = 3;
+               s4.f4 = 4;
+               short retval4 = mono_return_short4(s4, 90);
+               if (retval4 != 2*90) {
+                       Console.WriteLine("   short4 retval4: got {0} but expected {1}", retval4, 2*90);
+                       return 1;
+               }
+
+               short5 s5;
+               s5.f1 = 1;
+               s5.f2 = 2;
+               s5.f3 = 3;
+               s5.f4 = 4;
+               s5.f5 = 5;
+               short retval5 = mono_return_short5(s5, 90);
+               if (retval5 != 2*90) {
+                       Console.WriteLine("   short5 retval5: got {0} but expected {1}", retval5, 2*90);
+                       return 1;
+               }
+
+               short6 s6;
+               s6.f1 = 1;
+               s6.f2 = 2;
+               s6.f3 = 3;
+               s6.f4 = 4;
+               s6.f5 = 5;
+               s6.f6 = 6;
+               short retval6 = mono_return_short6(s6, 90);
+               if (retval6 != 2*90) {
+                       Console.WriteLine("   short6 retval6: got {0} but expected {1}", retval6, 2*90);
+                       return 1;
+               }
+
+               short7 s7;
+               s7.f1 = 1;
+               s7.f2 = 2;
+               s7.f3 = 3;
+               s7.f4 = 4;
+               s7.f5 = 5;
+               s7.f6 = 6;
+               s7.f7 = 7;
+               short retval7 = mono_return_short7(s7, 90);
+               if (retval7 != 2*90) {
+                       Console.WriteLine("   short7 retval7: got {0} but expected {1}", retval7, 2*90);
+                       return 1;
+               }
+
+               short8 s8;
+               s8.f1 = 1;
+               s8.f2 = 2;
+               s8.f3 = 3;
+               s8.f4 = 4;
+               s8.f5 = 5;
+               s8.f6 = 6;
+               s8.f7 = 7;
+               s8.f8 = 8;
+               short retval8 = mono_return_short8(s8, 90);
+               if (retval8 != 2*90) {
+                       Console.WriteLine("   short8 retval8: got {0} but expected {1}", retval8, 2*90);
+                       return 1;
+               }
+
+               short9 s9;
+               s9.f1 = 1;
+               s9.f2 = 2;
+               s9.f3 = 3;
+               s9.f4 = 4;
+               s9.f5 = 5;
+               s9.f6 = 6;
+               s9.f7 = 7;
+               s9.f8 = 8;
+               s9.f9 = 9;
+               short retval9 = mono_return_short9(s9, 90);
+               if (retval9 != 2*90) {
+                       Console.WriteLine("   short9 retval9: got {0} but expected {1}", retval9, 2*90);
+                       return 1;
+               }
+
+
+               return 0;
+       } // end Main
+} // end class Test_short
+
+
+
+
+