* [i386, PATCH] Support new psABI for IA MCU.
@ 2015-06-22 13:52 Kirill Yukhin
2015-06-22 14:38 ` [i386, PATCH, 1/3] IA MCU psABI support: GCC changes Kirill Yukhin
` (2 more replies)
0 siblings, 3 replies; 7+ messages in thread
From: Kirill Yukhin @ 2015-06-22 13:52 UTC (permalink / raw)
To: Uros Bizjak, Joseph S. Myers; +Cc: H.J. Lu, GCC Patches
Hello,
I am starting (hopefully small) serie of patches to support
new ABI dedicated for Intel's MicroController Units [1].
Support for new arch was introduced into Binutils in a few threads, e.g. [2].
This patchset includes:
- Support in GCC: new switch (-miamcu), macro etc.
- Changes to libraries.
- Testsuite.
Whole patch is in the bottom.
[1] - https://groups.google.com/forum/#!topic/ia32-abi/cn7TM6J_TIg
[2] - https://sourceware.org/ml/binutils/2015-05/msg00063.html
--
Thanks, K
diff --git a/config/dfp.m4 b/config/dfp.m4
index 48683f0..5b29089 100644
--- a/config/dfp.m4
+++ b/config/dfp.m4
@@ -21,7 +21,7 @@ Valid choices are 'yes', 'bid', 'dpd', and 'no'.]) ;;
[
case $1 in
powerpc*-*-linux* | i?86*-*-linux* | x86_64*-*-linux* | s390*-*-linux* | \
- i?86*-*-gnu* | \
+ i?86*-*-elfiamcu | i?86*-*-gnu* | \
i?86*-*-mingw* | x86_64*-*-mingw* | \
i?86*-*-cygwin* | x86_64*-*-cygwin*)
enable_decimal_float=yes
diff --git a/configure b/configure
index bced9de..82e45f3 100755
--- a/configure
+++ b/configure
@@ -6914,7 +6914,7 @@ case "${enable_target_optspace}:${target}" in
:d30v-*)
ospace_frag="config/mt-d30v"
;;
- :m32r-* | :d10v-* | :fr30-*)
+ :m32r-* | :d10v-* | :fr30-* | :i?86*-*-elfiamcu)
ospace_frag="config/mt-ospace"
;;
no:* | :*)
diff --git a/configure.ac b/configure.ac
index 7c06e6b..dc77a1b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2560,7 +2560,7 @@ case "${enable_target_optspace}:${target}" in
:d30v-*)
ospace_frag="config/mt-d30v"
;;
- :m32r-* | :d10v-* | :fr30-*)
+ :m32r-* | :d10v-* | :fr30-* | :i?86*-*-elfiamcu)
ospace_frag="config/mt-ospace"
;;
no:* | :*)
diff --git a/gcc/common/config/i386/i386-common.c b/gcc/common/config/i386/i386-common.c
index 0f8c3e1..79b2472 100644
--- a/gcc/common/config/i386/i386-common.c
+++ b/gcc/common/config/i386/i386-common.c
@@ -223,7 +223,7 @@ along with GCC; see the file COPYING3. If not see
bool
ix86_handle_option (struct gcc_options *opts,
- struct gcc_options *opts_set ATTRIBUTE_UNUSED,
+ struct gcc_options *opts_set,
const struct cl_decoded_option *decoded,
location_t loc)
{
@@ -232,6 +232,20 @@ ix86_handle_option (struct gcc_options *opts,
switch (code)
{
+ case OPT_miamcu:
+ if (value)
+ {
+ /* Turn off x87/MMX/SSE/AVX codegen for -miamcu. */
+ opts->x_target_flags &= ~MASK_80387;
+ opts_set->x_target_flags |= MASK_80387;
+ opts->x_ix86_isa_flags &= ~(OPTION_MASK_ISA_MMX_UNSET
+ | OPTION_MASK_ISA_SSE_UNSET);
+ opts->x_ix86_isa_flags_explicit |= (OPTION_MASK_ISA_MMX_UNSET
+ | OPTION_MASK_ISA_SSE_UNSET);
+
+ }
+ return true;
+
case OPT_mmmx:
if (value)
{
diff --git a/gcc/config.gcc b/gcc/config.gcc
index 805638d..2b3af82 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -1389,6 +1389,9 @@ x86_64-*-darwin*)
tmake_file="${tmake_file} ${cpu_type}/t-darwin64 t-slibgcc"
tm_file="${tm_file} ${cpu_type}/darwin64.h"
;;
+i[34567]86-*-elfiamcu)
+ tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h newlib-stdint.h i386/iamcu.h"
+ ;;
i[34567]86-*-elf*)
tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h newlib-stdint.h i386/i386elf.h"
;;
diff --git a/gcc/config/i386/i386-c.c b/gcc/config/i386/i386-c.c
index 0228f4b..66f7e37 100644
--- a/gcc/config/i386/i386-c.c
+++ b/gcc/config/i386/i386-c.c
@@ -426,6 +426,11 @@ ix86_target_macros_internal (HOST_WIDE_INT isa_flag,
def_or_undef (parse_in, "__CLWB__");
if (isa_flag & OPTION_MASK_ISA_MWAITX)
def_or_undef (parse_in, "__MWAITX__");
+ if (TARGET_IAMCU)
+ {
+ def_or_undef (parse_in, "__iamcu");
+ def_or_undef (parse_in, "__iamcu__");
+ }
}
\f
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 24fccfc..26ffa67 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -3433,6 +3433,10 @@ ix86_option_override_internal (bool main_args_p,
|| TARGET_16BIT_P (opts->x_ix86_isa_flags))
opts->x_ix86_isa_flags &= ~OPTION_MASK_ABI_X32;
#endif
+ if (TARGET_64BIT_P (opts->x_ix86_isa_flags)
+ && TARGET_IAMCU_P (opts->x_target_flags))
+ sorry ("Intel MCU psABI isn%'t supported in %s mode",
+ TARGET_X32_P (opts->x_ix86_isa_flags) ? "x32" : "64-bit");
}
#endif
@@ -3817,6 +3821,20 @@ ix86_option_override_internal (bool main_args_p,
if (TARGET_X32 && (ix86_isa_flags & OPTION_MASK_ISA_MPX))
error ("Intel MPX does not support x32");
+ if (TARGET_IAMCU_P (opts->x_target_flags))
+ {
+ /* Verify that x87/MMX/SSE/AVX is off for -miamcu. */
+ if (TARGET_80387_P (opts->x_target_flags))
+ sorry ("X87 FPU isn%'t supported in Intel MCU psABI");
+ else if ((opts->x_ix86_isa_flags & (OPTION_MASK_ISA_MMX
+ | OPTION_MASK_ISA_SSE
+ | OPTION_MASK_ISA_AVX)))
+ sorry ("%s isn%'t supported in Intel MCU psABI",
+ TARGET_MMX_P (opts->x_ix86_isa_flags)
+ ? "MMX"
+ : TARGET_SSE_P (opts->x_ix86_isa_flags) ? "SSE" : "AVX");
+ }
+
if (!strcmp (opts->x_ix86_arch_string, "generic"))
error ("generic CPU can be used only for %stune=%s %s",
prefix, suffix, sw);
@@ -3904,7 +3922,16 @@ ix86_option_override_internal (bool main_args_p,
if (opts->x_flag_asynchronous_unwind_tables == 2)
opts->x_flag_asynchronous_unwind_tables = !USE_IX86_FRAME_POINTER;
if (opts->x_flag_pcc_struct_return == 2)
- opts->x_flag_pcc_struct_return = DEFAULT_PCC_STRUCT_RETURN;
+ {
+ /* Intel MCU psABI specifies that -freg-struct-return should
+ be on. Instead of setting DEFAULT_PCC_STRUCT_RETURN to 1,
+ we check -miamcu so that -freg-struct-return is always
+ turned on if -miamcu is used. */
+ if (TARGET_IAMCU_P (opts->x_target_flags))
+ opts->x_flag_pcc_struct_return = 0;
+ else
+ opts->x_flag_pcc_struct_return = DEFAULT_PCC_STRUCT_RETURN;
+ }
}
ix86_tune_cost = processor_target_table[ix86_tune].cost;
@@ -3923,6 +3950,8 @@ ix86_option_override_internal (bool main_args_p,
{
if (TARGET_64BIT_P (opts->x_ix86_isa_flags))
warning (0, "-mregparm is ignored in 64-bit mode");
+ else if (TARGET_IAMCU_P (opts->x_target_flags))
+ warning (0, "-mregparm is ignored for Intel MCU psABI");
if (opts->x_ix86_regparm > REGPARM_MAX)
{
error ("-mregparm=%d is not between 0 and %d",
@@ -3930,7 +3959,8 @@ ix86_option_override_internal (bool main_args_p,
opts->x_ix86_regparm = 0;
}
}
- if (TARGET_64BIT_P (opts->x_ix86_isa_flags))
+ if (TARGET_IAMCU_P (opts->x_target_flags)
+ || TARGET_64BIT_P (opts->x_ix86_isa_flags))
opts->x_ix86_regparm = REGPARM_MAX;
/* Default align_* from the processor table. */
@@ -4334,8 +4364,9 @@ ix86_option_override_internal (bool main_args_p,
opts->x_recip_mask &= ~(RECIP_MASK_ALL & ~opts->x_recip_mask_explicit);
/* Default long double to 64-bit for 32-bit Bionic and to __float128
- for 64-bit Bionic. */
- if (TARGET_HAS_BIONIC
+ for 64-bit Bionic. Also default long double to 64-bit for Intel
+ MCU psABI. */
+ if ((TARGET_HAS_BIONIC || TARGET_IAMCU)
&& !(opts_set->x_target_flags
& (MASK_LONG_DOUBLE_64 | MASK_LONG_DOUBLE_128)))
opts->x_target_flags |= (TARGET_64BIT
@@ -7455,6 +7486,15 @@ function_arg_advance_32 (CUMULATIVE_ARGS *cum, machine_mode mode,
int res = 0;
bool error_p = NULL;
+ if (TARGET_IAMCU)
+ {
+ /* Intel MCU psABI passes scalars and aggregates no larger than 8
+ bytes in registers. */
+ if (bytes <= 8)
+ goto pass_in_reg;
+ return res;
+ }
+
switch (mode)
{
default:
@@ -7469,6 +7509,7 @@ function_arg_advance_32 (CUMULATIVE_ARGS *cum, machine_mode mode,
case SImode:
case HImode:
case QImode:
+pass_in_reg:
cum->words += words;
cum->nregs -= words;
cum->regno += words;
@@ -7702,6 +7743,15 @@ function_arg_32 (CUMULATIVE_ARGS *cum, machine_mode mode,
if (mode == VOIDmode)
return constm1_rtx;
+ if (TARGET_IAMCU)
+ {
+ /* Intel MCU psABI passes scalars and aggregates no larger than 8
+ bytes in registers. */
+ if (bytes <= 8)
+ goto pass_in_reg;
+ return NULL_RTX;
+ }
+
switch (mode)
{
default:
@@ -7715,6 +7765,7 @@ function_arg_32 (CUMULATIVE_ARGS *cum, machine_mode mode,
case SImode:
case HImode:
case QImode:
+pass_in_reg:
if (words <= cum->nregs)
{
int regno = cum->regno;
@@ -8561,11 +8612,16 @@ ix86_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
}
else
{
+ size = int_size_in_bytes (type);
+
+ /* Intel MCU psABI returns scalars and aggregates no larger than 8
+ bytes in registers. */
+ if (TARGET_IAMCU)
+ return size > 8;
+
if (mode == BLKmode)
return true;
- size = int_size_in_bytes (type);
-
if (MS_AGGREGATE_RETURN && AGGREGATE_TYPE_P (type) && size <= 8)
return false;
@@ -27341,6 +27397,34 @@ ix86_constant_alignment (tree exp, int align)
return align;
}
+/* Compute the alignment for a variable for Intel MCU psABI. TYPE is
+ the data type, and ALIGN is the alignment that the object would
+ ordinarily have. */
+
+static int
+iamcu_alignment (tree type, int align)
+{
+ enum machine_mode mode;
+
+ if (align < 32 || TYPE_USER_ALIGN (type))
+ return align;
+
+ /* Intel MCU psABI specifies scalar types > 4 bytes aligned to 4
+ bytes. */
+ mode = TYPE_MODE (strip_array_types (type));
+ switch (GET_MODE_CLASS (mode))
+ {
+ case MODE_INT:
+ case MODE_COMPLEX_INT:
+ case MODE_COMPLEX_FLOAT:
+ case MODE_FLOAT:
+ case MODE_DECIMAL_FLOAT:
+ return 32;
+ default:
+ return align;
+ }
+}
+
/* Compute the alignment for a static variable.
TYPE is the data type, and ALIGN is the alignment that
the object would ordinarily have. The value of this function is used
@@ -27375,6 +27459,9 @@ ix86_data_alignment (tree type, int align, bool opt)
case ix86_align_data_type_cacheline: break;
}
+ if (TARGET_IAMCU)
+ align = iamcu_alignment (type, align);
+
if (opt
&& AGGREGATE_TYPE_P (type)
&& TYPE_SIZE (type)
@@ -27484,6 +27571,10 @@ ix86_local_alignment (tree exp, machine_mode mode,
return align;
}
+ /* Don't increase alignment for Intel MCU psABI. */
+ if (TARGET_IAMCU)
+ return align;
+
/* x86-64 ABI requires arrays greater than 16 bytes to be aligned
to 16byte boundary. Exact wording is:
@@ -43182,6 +43273,8 @@ x86_field_alignment (tree field, int computed)
if (TARGET_64BIT || TARGET_ALIGN_DOUBLE)
return computed;
+ if (TARGET_IAMCU)
+ return iamcu_alignment (type, computed);
mode = TYPE_MODE (strip_array_types (type));
if (mode == DFmode || mode == DCmode
|| GET_MODE_CLASS (mode) == MODE_INT
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index e0af36c..d710b3d 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -756,7 +756,8 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);
/* It should be MIN_STACK_BOUNDARY. But we set it to 128 bits for
both 32bit and 64bit, to support codes that need 128 bit stack
alignment for SSE instructions, but can't realign the stack. */
-#define PREFERRED_STACK_BOUNDARY_DEFAULT 128
+#define PREFERRED_STACK_BOUNDARY_DEFAULT \
+ (TARGET_IAMCU ? MIN_STACK_BOUNDARY : 128)
/* 1 if -mstackrealign should be turned on by default. It will
generate an alternate prologue and epilogue that realigns the
@@ -803,7 +804,7 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);
TARGET_ABSOLUTE_BIGGEST_ALIGNMENT. */
#define BIGGEST_ALIGNMENT \
- (TARGET_AVX512F ? 512 : (TARGET_AVX ? 256 : 128))
+ (TARGET_AVX512F ? 512 : (TARGET_AVX ? 256 : (TARGET_IAMCU ? 32 : 128)))
/* Maximum stack alignment. */
#define MAX_STACK_ALIGNMENT MAX_OFILE_ALIGNMENT
diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt
index dd46e26..042f3c1 100644
--- a/gcc/config/i386/i386.opt
+++ b/gcc/config/i386/i386.opt
@@ -514,6 +514,10 @@ Clear all tune features
mdump-tune-features
Target RejectNegative Var(ix86_dump_tunes) Init(0)
+miamcu
+Target Report Mask(IAMCU)
+Generate code that conforms to Intel MCU psABI
+
mabi=
Target RejectNegative Joined Var(ix86_abi) Enum(calling_abi) Init(SYSV_ABI)
Generate code that conforms to the given ABI
diff --git a/gcc/config/i386/iamcu.h b/gcc/config/i386/iamcu.h
new file mode 100644
index 0000000..a1c83f4
--- /dev/null
+++ b/gcc/config/i386/iamcu.h
@@ -0,0 +1,42 @@
+/* Definitions of target machine for Intel MCU psABI.
+ Copyright (C) 2015 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+<http://www.gnu.org/licenses/>. */
+
+/* Intel MCU has no 80387. Default to Intel MCU psABI. */
+#undef TARGET_SUBTARGET_DEFAULT
+#define TARGET_SUBTARGET_DEFAULT MASK_IAMCU
+
+#undef ASM_SPEC
+#define ASM_SPEC "--32 -march=iamcu"
+
+#undef LINK_SPEC
+#define LINK_SPEC "-m elf_iamcu"
+
+#undef ENDFILE_SPEC
+#define ENDFILE_SPEC ""
+
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC "crt0.o%s"
+
+#undef LIB_SPEC
+#define LIB_SPEC "--start-group -lc -lgloss --end-group"
diff --git a/gcc/configure b/gcc/configure
index b26a86f..64eeac6 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -7317,7 +7317,7 @@ else
case $target in
powerpc*-*-linux* | i?86*-*-linux* | x86_64*-*-linux* | s390*-*-linux* | \
- i?86*-*-gnu* | \
+ i?86*-*-elfiamcu | i?86*-*-gnu* | \
i?86*-*-mingw* | x86_64*-*-mingw* | \
i?86*-*-cygwin* | x86_64*-*-cygwin*)
enable_decimal_float=yes
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index b99ab1c..e4f816f 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -1096,7 +1096,7 @@ See RS/6000 and PowerPC Options.
-mpc32 -mpc64 -mpc80 -mstackrealign @gol
-momit-leaf-frame-pointer -mno-red-zone -mno-tls-direct-seg-refs @gol
-mcmodel=@var{code-model} -mabi=@var{name} -maddress-mode=@var{mode} @gol
--m32 -m64 -mx32 -m16 -mlarge-data-threshold=@var{num} @gol
+-m32 -m64 -mx32 -m16 -miamcu -mlarge-data-threshold=@var{num} @gol
-msse2avx -mfentry -mrecord-mcount -mnop-mcount -m8bit-idiv @gol
-mavx256-split-unaligned-load -mavx256-split-unaligned-store @gol
-malign-data=@var{type} -mstack-protector-guard=@var{guard}}
@@ -23267,10 +23267,12 @@ on x86-64 processors in 64-bit environments.
@itemx -m64
@itemx -mx32
@itemx -m16
+@itemx -miamcu
@opindex m32
@opindex m64
@opindex mx32
@opindex m16
+@opindex miamcu
Generate code for a 16-bit, 32-bit or 64-bit environment.
The @option{-m32} option sets @code{int}, @code{long}, and pointer types
to 32 bits, and
@@ -23289,6 +23291,9 @@ The @option{-m16} option is the same as @option{-m32}, except for that
it outputs the @code{.code16gcc} assembly directive at the beginning of
the assembly output so that the binary can run in 16-bit mode.
+The @option{-miamcu} option generates code which conforms to Intel MCU
+psABI. It requires the @option{-m32} option to be turned on.
+
@item -mno-red-zone
@opindex mno-red-zone
Do not use a so-called ``red zone'' for x86-64 code. The red zone is mandated
diff --git a/gcc/testsuite/gcc.target/i386/iamcu/abi-iamcu.exp b/gcc/testsuite/gcc.target/i386/iamcu/abi-iamcu.exp
new file mode 100644
index 0000000..b5b3261
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/iamcu/abi-iamcu.exp
@@ -0,0 +1,42 @@
+# Copyright (C) 2015 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
+# The Intel MCU psABI testsuite needs one additional assembler file for
+# most testcases. For simplicity we will just link it into each test.
+
+load_lib c-torture.exp
+load_lib target-supports.exp
+load_lib torture-options.exp
+
+if { (![istarget x86_64-*-linux*] && ![istarget i?86-*-linux*])
+ || ![is-effective-target ia32] } then {
+ return
+}
+
+
+torture-init
+set-torture-options $C_TORTURE_OPTIONS
+set additional_flags "-miamcu -W -Wall -Wno-abi"
+
+foreach src [lsort [glob -nocomplain $srcdir/$subdir/test_*.c]] {
+ if {[runtest_file_p $runtests $src]} {
+ c-torture-execute [list $src \
+ $srcdir/$subdir/asm-support.S] \
+ $additional_flags
+ }
+}
+
+torture-finish
diff --git a/gcc/testsuite/gcc.target/i386/iamcu/args.h b/gcc/testsuite/gcc.target/i386/iamcu/args.h
new file mode 100644
index 0000000..f8abde4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/iamcu/args.h
@@ -0,0 +1,77 @@
+#ifndef INCLUDED_ARGS_H
+#define INCLUDED_ARGS_H
+
+/* This defines the calling sequences for integers and floats. */
+#define I0 eax
+#define I1 edx
+#define I2 ecx
+
+typedef unsigned int size_t;
+
+extern void (*callthis)(void);
+extern unsigned long eax,ebx,ecx,edx,esi,edi,esp,ebp;
+extern unsigned long sret_eax;
+extern volatile unsigned long volatile_var;
+extern void snapshot (void);
+extern void snapshot_ret (void);
+extern void *iamcu_memset (void *, int, size_t);
+#define WRAP_CALL(N) \
+ (callthis = (void (*)()) (N), (typeof (&N)) snapshot)
+#define WRAP_RET(N) \
+ (callthis = (void (*)()) (N), (typeof (&N)) snapshot_ret)
+
+/* Clear all scratch integer registers. */
+#define clear_int_hardware_registers \
+ asm __volatile__ ("xor %%eax, %%eax\n\t" \
+ "xor %%edx, %%edx\n\t" \
+ "xor %%ecx, %%ecx\n\t" \
+ ::: "eax", "edx", "ecx");
+
+/* Clear all scratch integer registers, excluding the one used to return
+ aggregate. */
+#define clear_non_sret_int_hardware_registers \
+ asm __volatile__ ("xor %%edx, %%ebx\n\t" \
+ "xor %%ecx, %%ecx\n\t" \
+ ::: "edx", "ecx");
+
+/* This is the list of registers available for passing arguments. Not all of
+ these are used or even really available. */
+struct IntegerRegisters
+{
+ unsigned long eax, ebx, ecx, edx, esi, edi;
+};
+
+/* Implemented in scalarargs.c */
+extern struct IntegerRegisters iregs, iregbits;
+extern unsigned int num_iregs;
+
+#define check_int_arguments do { \
+ assert (num_iregs <= 0 || (iregs.I0 & iregbits.I0) == (I0 & iregbits.I0)); \
+ assert (num_iregs <= 1 || (iregs.I1 & iregbits.I1) == (I1 & iregbits.I1)); \
+ assert (num_iregs <= 2 || (iregs.I2 & iregbits.I2) == (I2 & iregbits.I2)); \
+ } while (0)
+
+#define check_char_arguments check_int_arguments
+#define check_short_arguments check_int_arguments
+#define check_long_arguments check_int_arguments
+#define check_float_arguments check_int_arguments
+#define check_double_arguments check_int_arguments
+#define check_ldouble_arguments check_int_arguments
+
+/* Clear register struct. */
+#define clear_struct_registers \
+ eax = edx = ecx = 0; \
+ iamcu_memset (&iregs, 0, sizeof iregs);
+
+/* Clear both hardware and register structs for integers. */
+#define clear_int_registers \
+ clear_struct_registers \
+ clear_int_hardware_registers
+
+/* Clear both hardware and register structs for integers, excluding the
+ one used to return aggregate. */
+#define clear_non_sret_int_registers \
+ clear_struct_registers \
+ clear_non_sret_int_hardware_registers
+
+#endif /* INCLUDED_ARGS_H */
diff --git a/gcc/testsuite/gcc.target/i386/iamcu/asm-support.S b/gcc/testsuite/gcc.target/i386/iamcu/asm-support.S
new file mode 100644
index 0000000..b4a4a14
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/iamcu/asm-support.S
@@ -0,0 +1,302 @@
+ .comm callthis,4,4
+ .comm eax,4,4
+ .comm ebx,4,4
+ .comm ecx,4,4
+ .comm edx,4,4
+ .comm esi,4,4
+ .comm edi,4,4
+ .comm esp,4,4
+ .comm ebp,4,4
+ .comm sret_eax,4,4
+ .comm volatile_var,4,4
+
+ .text
+ .p2align 4,,15
+.globl snapshot
+ .type snapshot, @function
+snapshot:
+ movl %eax, eax
+ movl %ebx, ebx
+ movl %ecx, ecx
+ movl %edx, edx
+ movl %edi, edi
+ movl %esi, esi
+ movl %ebp, ebp
+ movl %esp, esp
+ jmp *callthis
+ .size snapshot, .-snapshot
+
+ .p2align 4,,15
+.globl snapshot_ret
+ .type snapshot_ret, @function
+snapshot_ret:
+ movl %eax, sret_eax
+ call *callthis
+ movl %eax, eax
+ movl %edx, edx
+ ret
+ .size snapshot_ret, .-snapshot_ret
+
+ .p2align 4,,15
+ .globl __nesf2
+ .type __nesf2, @function
+__nesf2:
+ .cfi_startproc
+ subl $4, %esp
+ .cfi_def_cfa_offset 8
+ movl %eax, (%esp)
+ movl $1, %eax
+ fildl (%esp)
+ movl %edx, (%esp)
+ xorl %edx, %edx
+ fildl (%esp)
+ fucomip %st(1), %st
+ fstp %st(0)
+ setp %dl
+ cmove %edx, %eax
+ addl $4, %esp
+ .cfi_def_cfa_offset 4
+ ret
+ .cfi_endproc
+ .size __nesf2, .-__nesf2
+
+ .p2align 4,,15
+ .globl __nedf2
+ .type __nedf2, @function
+__nedf2:
+ .cfi_startproc
+ pushl %ebp
+ .cfi_def_cfa_offset 8
+ .cfi_offset 5, -8
+ movl %esp, %ebp
+ .cfi_def_cfa_register 5
+ andl $-8, %esp
+ subl $8, %esp
+ movl %eax, (%esp)
+ movl $1, %eax
+ movl %edx, 4(%esp)
+ xorl %edx, %edx
+ fildq (%esp)
+ fildq 8(%ebp)
+ fucomip %st(1), %st
+ fstp %st(0)
+ setp %dl
+ cmove %edx, %eax
+ leave
+ .cfi_restore 5
+ .cfi_def_cfa 4, 4
+ ret
+ .cfi_endproc
+ .size __nedf2, .-__nedf2
+
+ .p2align 4,,15
+ .globl __addsf3
+ .type __addsf3, @function
+__addsf3:
+ .cfi_startproc
+ subl $4, %esp
+ .cfi_def_cfa_offset 8
+ movl %eax, (%esp)
+ flds (%esp)
+ movl %edx, (%esp)
+ flds (%esp)
+ faddp %st, %st(1)
+ fstps (%esp)
+ movl (%esp), %eax
+ addl $4, %esp
+ .cfi_def_cfa_offset 4
+ ret
+ .cfi_endproc
+ .size __addsf3, .-__addsf3
+
+ .p2align 4,,15
+ .globl __adddf3
+ .type __adddf3, @function
+__adddf3:
+ .cfi_startproc
+ pushl %ebp
+ .cfi_def_cfa_offset 8
+ .cfi_offset 5, -8
+ movl %esp, %ebp
+ .cfi_def_cfa_register 5
+ andl $-8, %esp
+ subl $8, %esp
+ movl %eax, (%esp)
+ movl %edx, 4(%esp)
+ fldl (%esp)
+ faddl 8(%ebp)
+ fstpl (%esp)
+ movl (%esp), %eax
+ movl 4(%esp), %edx
+ leave
+ .cfi_restore 5
+ .cfi_def_cfa 4, 4
+ ret
+ .cfi_endproc
+ .size __adddf3, .-__adddf3
+
+ .p2align 4,,15
+ .globl __floatsisf
+ .type __floatsisf, @function
+__floatsisf:
+ .cfi_startproc
+ subl $4, %esp
+ .cfi_def_cfa_offset 8
+ movl %eax, (%esp)
+ fildl (%esp)
+ addl $4, %esp
+ .cfi_def_cfa_offset 4
+ ret
+ .cfi_endproc
+ .size __floatsisf, .-__floatsisf
+
+ .p2align 4,,15
+ .globl __floatunsisf
+ .type __floatunsisf, @function
+__floatunsisf:
+ .cfi_startproc
+ subl $8, %esp
+ .cfi_def_cfa_offset 12
+ xorl %edx, %edx
+ movl %eax, (%esp)
+ movl %edx, 4(%esp)
+ fildq (%esp)
+ addl $8, %esp
+ .cfi_def_cfa_offset 4
+ ret
+ .cfi_endproc
+ .size __floatunsisf, .-__floatunsisf
+
+ .globl __extendsfdf2
+ .type __extendsfdf2, @function
+__extendsfdf2:
+ .cfi_startproc
+ pushl %ebp
+ .cfi_def_cfa_offset 8
+ .cfi_offset 5, -8
+ movl %esp, %ebp
+ .cfi_def_cfa_register 5
+ andl $-8, %esp
+ subl $8, %esp
+ movl %eax, (%esp)
+ flds (%esp)
+ fstpl (%esp)
+ movl (%esp), %eax
+ movl 4(%esp), %edx
+ leave
+ .cfi_restore 5
+ .cfi_def_cfa 4, 4
+ ret
+ .cfi_endproc
+ .size __extendsfdf2, .-__extendsfdf2
+
+ .p2align 4,,15
+ .globl __truncdfsf2
+ .type __truncdfsf2, @function
+__truncdfsf2:
+ .cfi_startproc
+ pushl %ebp
+ .cfi_def_cfa_offset 8
+ .cfi_offset 5, -8
+ movl %esp, %ebp
+ .cfi_def_cfa_register 5
+ andl $-8, %esp
+ subl $12, %esp
+ movl %eax, (%esp)
+ movl %edx, 4(%esp)
+ fldl (%esp)
+ fstps (%esp)
+ movl (%esp), %eax
+ leave
+ .cfi_restore 5
+ .cfi_def_cfa 4, 4
+ ret
+ .cfi_endproc
+ .size __truncdfsf2, .-__truncdfsf2
+
+ .p2align 4,,15
+ .globl iamcu_memset
+ .type iamcu_memset, @function
+iamcu_memset:
+ .cfi_startproc
+ pushl %edi
+ .cfi_adjust_cfa_offset 4
+ .cfi_rel_offset %edi, 0
+ movl %eax, %edi
+ movzbl %dl, %eax
+ movl %edi, %edx
+ rep stosb
+ movl %edx, %eax
+ popl %edi
+ .cfi_adjust_cfa_offset -4
+ .cfi_restore %edi
+ ret
+ .cfi_endproc
+ .size iamcu_memset, .-iamcu_memset
+
+ .p2align 4,,15
+ .globl iamcu_noprintf
+ .type iamcu_noprintf, @function
+iamcu_noprintf:
+ .cfi_startproc
+ pushl %ebp
+ .cfi_def_cfa_offset 8
+ .cfi_offset 5, -8
+ movl %esp, %ebp
+ .cfi_def_cfa_register 5
+ cmpl $-1414676753, 8(%ebp)
+ fldl 16(%ebp)
+ fldl 28(%ebp)
+ jne 7f
+ cmpl $256, 12(%ebp)
+ jne 8f
+ flds .LCiamcu_noprintf0
+ movl $1, %eax
+ fucomip %st(2), %st
+ fstp %st(1)
+ setp %dl
+ cmovne %eax, %edx
+ testb %dl, %dl
+ jne 9f
+ cmpl $-1146241297, 24(%ebp)
+ jne 10f
+ flds .LCiamcu_noprintf1
+ fucomip %st(1), %st
+ fstp %st(0)
+ setp %dl
+ cmove %edx, %eax
+ testb %al, %al
+ jne 2f
+ cmpl $259, 36(%ebp)
+ jne 2f
+ popl %ebp
+ .cfi_remember_state
+ .cfi_restore 5
+ .cfi_def_cfa 4, 4
+ ret
+7:
+ .cfi_restore_state
+ fstp %st(0)
+ fstp %st(0)
+ jmp 2f
+8:
+ fstp %st(0)
+ fstp %st(0)
+ .p2align 4,,3
+ jmp 2f
+9:
+ fstp %st(0)
+ jmp 2f
+10:
+ fstp %st(0)
+2:
+ call abort
+ .cfi_endproc
+ .size iamcu_noprintf, .-iamcu_noprintf
+ .section .rodata.cst4,"aM",@progbits,4
+ .align 4
+.LCiamcu_noprintf0:
+ .long 1132494848
+ .align 4
+.LCiamcu_noprintf1:
+ .long 1132527616
diff --git a/gcc/testsuite/gcc.target/i386/iamcu/defines.h b/gcc/testsuite/gcc.target/i386/iamcu/defines.h
new file mode 100644
index 0000000..e715f42
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/iamcu/defines.h
@@ -0,0 +1,110 @@
+#ifndef DEFINED_DEFINES_H
+#define DEFINED_DEFINES_H
+
+typedef unsigned long long ulonglong;
+typedef long double ldouble;
+
+/* These defines determines what part of the test should be run. When
+ GCC implements these parts, the defines should be uncommented to
+ enable testing. */
+
+/* Scalar type long double. */
+#define CHECK_LONG_DOUBLE
+
+/* Scalar type __float128. */
+#define CHECK_FLOAT128
+
+/* Returning of complex type. */
+#define CHECK_COMPLEX
+
+/* Structs with size > 8. */
+#define CHECK_LARGER_STRUCTS
+
+/* Checks for passing floats and doubles. */
+#define CHECK_FLOAT_DOUBLE_PASSING
+
+/* Union passing with not-extremely-simple unions. */
+#define CHECK_LARGER_UNION_PASSING
+
+/* Variable args. */
+#define CHECK_VARARGS
+
+/* Check argument passing and returning for scalar types with sizeof > 8. */
+#define CHECK_LARGE_SCALAR_PASSING
+
+/* Defines for sizing and alignment. */
+
+#define TYPE_SIZE_CHAR 1
+#define TYPE_SIZE_SHORT 2
+#define TYPE_SIZE_INT 4
+#define TYPE_SIZE_LONG 4
+#define TYPE_SIZE_LONG_LONG 8
+#define TYPE_SIZE_FLOAT 4
+#define TYPE_SIZE_DOUBLE 8
+#define TYPE_SIZE_LONG_DOUBLE 8
+#define TYPE_SIZE_FLOAT128 16
+#define TYPE_SIZE_ENUM 4
+#define TYPE_SIZE_POINTER 4
+
+#define TYPE_ALIGN_CHAR 1
+#define TYPE_ALIGN_SHORT 2
+#define TYPE_ALIGN_INT 4
+#define TYPE_ALIGN_LONG 4
+#define TYPE_ALIGN_LONG_LONG 4
+#define TYPE_ALIGN_FLOAT 4
+#define TYPE_ALIGN_DOUBLE 4
+#define TYPE_ALIGN_LONG_DOUBLE 4
+#define TYPE_ALIGN_FLOAT128 4
+#define TYPE_ALIGN_ENUM 4
+#define TYPE_ALIGN_POINTER 4
+
+/* These defines control the building of the list of types to check. There
+ is a string identifying the type (with a comma after), a size of the type
+ (also with a comma and an integer for adding to the total amount of types)
+ and an alignment of the type (which is currently not really needed since
+ the abi specifies that alignof == sizeof for all scalar types). */
+#ifdef CHECK_LONG_DOUBLE
+#define CLD_STR "long double",
+#define CLD_SIZ TYPE_SIZE_LONG_DOUBLE,
+#define CLD_ALI TYPE_ALIGN_LONG_DOUBLE,
+#define CLD_RET "???",
+#else
+#define CLD_STR
+#define CLD_SIZ
+#define CLD_ALI
+#define CLD_RET
+#endif
+#ifdef CHECK_FLOAT128
+#define CF128_STR "__float128",
+#define CF128_SIZ TYPE_SIZE_FLOAT128,
+#define CF128_ALI TYPE_ALIGN_FLOAT128,
+#define CF128_RET "???",
+#else
+#define CF128_STR
+#define CF128_SIZ
+#define CF128_ALI
+#define CF128_RET
+#endif
+
+/* Used in size and alignment tests. */
+enum dummytype { enumtype };
+
+extern void abort (void);
+
+/* Assertion macro. */
+#define assert(test) if (!(test)) abort()
+
+#ifdef __GNUC__
+#define ATTRIBUTE_UNUSED __attribute__((__unused__))
+#else
+#define ATTRIBUTE_UNUSED
+#endif
+
+#ifdef __GNUC__
+#define PACKED __attribute__((__packed__))
+#else
+#warning Some tests will fail due to missing __packed__ support
+#define PACKED
+#endif
+
+#endif /* DEFINED_DEFINES_H */
diff --git a/gcc/testsuite/gcc.target/i386/iamcu/macros.h b/gcc/testsuite/gcc.target/i386/iamcu/macros.h
new file mode 100644
index 0000000..98fbc66
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/iamcu/macros.h
@@ -0,0 +1,53 @@
+#ifndef MACROS_H
+
+#define check_size(_t, _size) assert(sizeof(_t) == (_size))
+
+#define check_align(_t, _align) assert(__alignof__(_t) == (_align))
+
+#define check_align_lv(_t, _align) assert(__alignof__(_t) == (_align) \
+ && (((unsigned long)&(_t)) & ((_align) - 1) ) == 0)
+
+#define check_basic_struct_size_and_align(_type, _size, _align) { \
+ struct _str { _type dummy; } _t; \
+ check_size(_t, _size); \
+ check_align_lv(_t, _align); \
+}
+
+#define check_array_size_and_align(_type, _size, _align) { \
+ _type _a[1]; _type _b[2]; _type _c[16]; \
+ struct _str { _type _a[1]; } _s; \
+ check_align_lv(_a[0], _align); \
+ check_size(_a, _size); \
+ check_size(_b, (_size*2)); \
+ check_size(_c, (_size*16)); \
+ check_size(_s, _size); \
+ check_align_lv(_s._a[0], _align); \
+}
+
+#define check_basic_union_size_and_align(_type, _size, _align) { \
+ union _union { _type dummy; } _u; \
+ check_size(_u, _size); \
+ check_align_lv(_u, _align); \
+}
+
+#define run_signed_tests2(_function, _arg1, _arg2) \
+ _function(_arg1, _arg2); \
+ _function(signed _arg1, _arg2); \
+ _function(unsigned _arg1, _arg2);
+
+#define run_signed_tests3(_function, _arg1, _arg2, _arg3) \
+ _function(_arg1, _arg2, _arg3); \
+ _function(signed _arg1, _arg2, _arg3); \
+ _function(unsigned _arg1, _arg2, _arg3);
+
+/* Check size of a struct and a union of three types. */
+
+#define check_struct_and_union3(type1, type2, type3, struct_size, align_size) \
+{ \
+ struct _str { type1 t1; type2 t2; type3 t3; } _t; \
+ union _uni { type1 t1; type2 t2; type3 t3; } _u; \
+ check_size(_t, struct_size); \
+ check_size(_u, align_size); \
+}
+
+#endif // MACROS_H
diff --git a/gcc/testsuite/gcc.target/i386/iamcu/test_3_element_struct_and_unions.c b/gcc/testsuite/gcc.target/i386/iamcu/test_3_element_struct_and_unions.c
new file mode 100644
index 0000000..7bec211
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/iamcu/test_3_element_struct_and_unions.c
@@ -0,0 +1,521 @@
+#include "defines.h"
+#include "macros.h"
+
+/* Check structs and unions of all permutations of 3 basic types. */
+int
+main (void)
+{
+ check_struct_and_union3(char, char, char, 3, 1);
+ check_struct_and_union3(char, char, short, 4, 2);
+ check_struct_and_union3(char, char, int, 8, 4);
+ check_struct_and_union3(char, char, long, 8, 4);
+ check_struct_and_union3(char, char, long long, 12, 8);
+ check_struct_and_union3(char, char, float, 8, 4);
+ check_struct_and_union3(char, char, double, 12, 8);
+ check_struct_and_union3(char, char, long double, 12, 8);
+ check_struct_and_union3(char, short, char, 6, 2);
+ check_struct_and_union3(char, short, short, 6, 2);
+ check_struct_and_union3(char, short, int, 8, 4);
+ check_struct_and_union3(char, short, long, 8, 4);
+ check_struct_and_union3(char, short, long long, 12, 8);
+ check_struct_and_union3(char, short, float, 8, 4);
+ check_struct_and_union3(char, short, double, 12, 8);
+ check_struct_and_union3(char, short, long double, 12, 8);
+ check_struct_and_union3(char, int, char, 12, 4);
+ check_struct_and_union3(char, int, short, 12, 4);
+ check_struct_and_union3(char, int, int, 12, 4);
+ check_struct_and_union3(char, int, long, 12, 4);
+ check_struct_and_union3(char, int, long long, 16, 8);
+ check_struct_and_union3(char, int, float, 12, 4);
+ check_struct_and_union3(char, int, double, 16, 8);
+ check_struct_and_union3(char, int, long double, 16, 8);
+ check_struct_and_union3(char, long, char, 12, 4);
+ check_struct_and_union3(char, long, short, 12, 4);
+ check_struct_and_union3(char, long, int, 12, 4);
+ check_struct_and_union3(char, long, long, 12, 4);
+ check_struct_and_union3(char, long, long long, 16, 8);
+ check_struct_and_union3(char, long, float, 12, 4);
+ check_struct_and_union3(char, long, double, 16, 8);
+ check_struct_and_union3(char, long, long double, 16, 8);
+ check_struct_and_union3(char, long long, char, 16, 8);
+ check_struct_and_union3(char, long long, short, 16, 8);
+ check_struct_and_union3(char, long long, int, 16, 8);
+ check_struct_and_union3(char, long long, long, 16, 8);
+ check_struct_and_union3(char, long long, long long, 20, 8);
+ check_struct_and_union3(char, long long, float, 16, 8);
+ check_struct_and_union3(char, long long, double, 20, 8);
+ check_struct_and_union3(char, long long, long double, 20, 8);
+ check_struct_and_union3(char, float, char, 12, 4);
+ check_struct_and_union3(char, float, short, 12, 4);
+ check_struct_and_union3(char, float, int, 12, 4);
+ check_struct_and_union3(char, float, long, 12, 4);
+ check_struct_and_union3(char, float, long long, 16, 8);
+ check_struct_and_union3(char, float, float, 12, 4);
+ check_struct_and_union3(char, float, double, 16, 8);
+ check_struct_and_union3(char, float, long double, 16, 8);
+ check_struct_and_union3(char, double, char, 16, 8);
+ check_struct_and_union3(char, double, short, 16, 8);
+ check_struct_and_union3(char, double, int, 16, 8);
+ check_struct_and_union3(char, double, long, 16, 8);
+ check_struct_and_union3(char, double, long long, 20, 8);
+ check_struct_and_union3(char, double, float, 16, 8);
+ check_struct_and_union3(char, double, double, 20, 8);
+ check_struct_and_union3(char, double, long double, 20, 8);
+ check_struct_and_union3(char, long double, char, 16, 8);
+ check_struct_and_union3(char, long double, short, 16, 8);
+ check_struct_and_union3(char, long double, int, 16, 8);
+ check_struct_and_union3(char, long double, long, 16, 8);
+ check_struct_and_union3(char, long double, long long, 20, 8);
+ check_struct_and_union3(char, long double, float, 16, 8);
+ check_struct_and_union3(char, long double, double, 20, 8);
+ check_struct_and_union3(char, long double, long double, 20, 8);
+ check_struct_and_union3(short, char, char, 4, 2);
+ check_struct_and_union3(short, char, short, 6, 2);
+ check_struct_and_union3(short, char, int, 8, 4);
+ check_struct_and_union3(short, char, long, 8, 4);
+ check_struct_and_union3(short, char, long long, 12, 8);
+ check_struct_and_union3(short, char, float, 8, 4);
+ check_struct_and_union3(short, char, double, 12, 8);
+ check_struct_and_union3(short, char, long double, 12, 8);
+ check_struct_and_union3(short, short, char, 6, 2);
+ check_struct_and_union3(short, short, short, 6, 2);
+ check_struct_and_union3(short, short, int, 8, 4);
+ check_struct_and_union3(short, short, long, 8, 4);
+ check_struct_and_union3(short, short, long long, 12, 8);
+ check_struct_and_union3(short, short, float, 8, 4);
+ check_struct_and_union3(short, short, double, 12, 8);
+ check_struct_and_union3(short, short, long double, 12, 8);
+ check_struct_and_union3(short, int, char, 12, 4);
+ check_struct_and_union3(short, int, short, 12, 4);
+ check_struct_and_union3(short, int, int, 12, 4);
+ check_struct_and_union3(short, int, long, 12, 4);
+ check_struct_and_union3(short, int, long long, 16, 8);
+ check_struct_and_union3(short, int, float, 12, 4);
+ check_struct_and_union3(short, int, double, 16, 8);
+ check_struct_and_union3(short, int, long double, 16, 8);
+ check_struct_and_union3(short, long, char, 12, 4);
+ check_struct_and_union3(short, long, short, 12, 4);
+ check_struct_and_union3(short, long, int, 12, 4);
+ check_struct_and_union3(short, long, long, 12, 4);
+ check_struct_and_union3(short, long, long long, 16, 8);
+ check_struct_and_union3(short, long, float, 12, 4);
+ check_struct_and_union3(short, long, double, 16, 8);
+ check_struct_and_union3(short, long, long double, 16, 8);
+ check_struct_and_union3(short, long long, char, 16, 8);
+ check_struct_and_union3(short, long long, short, 16, 8);
+ check_struct_and_union3(short, long long, int, 16, 8);
+ check_struct_and_union3(short, long long, long, 16, 8);
+ check_struct_and_union3(short, long long, long long, 20, 8);
+ check_struct_and_union3(short, long long, float, 16, 8);
+ check_struct_and_union3(short, long long, double, 20, 8);
+ check_struct_and_union3(short, long long, long double, 20, 8);
+ check_struct_and_union3(short, float, char, 12, 4);
+ check_struct_and_union3(short, float, short, 12, 4);
+ check_struct_and_union3(short, float, int, 12, 4);
+ check_struct_and_union3(short, float, long, 12, 4);
+ check_struct_and_union3(short, float, long long, 16, 8);
+ check_struct_and_union3(short, float, float, 12, 4);
+ check_struct_and_union3(short, float, double, 16, 8);
+ check_struct_and_union3(short, float, long double, 16, 8);
+ check_struct_and_union3(short, double, char, 16, 8);
+ check_struct_and_union3(short, double, short, 16, 8);
+ check_struct_and_union3(short, double, int, 16, 8);
+ check_struct_and_union3(short, double, long, 16, 8);
+ check_struct_and_union3(short, double, long long, 20, 8);
+ check_struct_and_union3(short, double, float, 16, 8);
+ check_struct_and_union3(short, double, double, 20, 8);
+ check_struct_and_union3(short, double, long double, 20, 8);
+ check_struct_and_union3(short, long double, char, 16, 8);
+ check_struct_and_union3(short, long double, short, 16, 8);
+ check_struct_and_union3(short, long double, int, 16, 8);
+ check_struct_and_union3(short, long double, long, 16, 8);
+ check_struct_and_union3(short, long double, long long, 20, 8);
+ check_struct_and_union3(short, long double, float, 16, 8);
+ check_struct_and_union3(short, long double, double, 20, 8);
+ check_struct_and_union3(short, long double, long double, 20, 8);
+ check_struct_and_union3(int, char, char, 8, 4);
+ check_struct_and_union3(int, char, short, 8, 4);
+ check_struct_and_union3(int, char, int, 12, 4);
+ check_struct_and_union3(int, char, long, 12, 4);
+ check_struct_and_union3(int, char, long long, 16, 8);
+ check_struct_and_union3(int, char, float, 12, 4);
+ check_struct_and_union3(int, char, double, 16, 8);
+ check_struct_and_union3(int, char, long double, 16, 8);
+ check_struct_and_union3(int, short, char, 8, 4);
+ check_struct_and_union3(int, short, short, 8, 4);
+ check_struct_and_union3(int, short, int, 12, 4);
+ check_struct_and_union3(int, short, long, 12, 4);
+ check_struct_and_union3(int, short, long long, 16, 8);
+ check_struct_and_union3(int, short, float, 12, 4);
+ check_struct_and_union3(int, short, double, 16, 8);
+ check_struct_and_union3(int, short, long double, 16, 8);
+ check_struct_and_union3(int, int, char, 12, 4);
+ check_struct_and_union3(int, int, short, 12, 4);
+ check_struct_and_union3(int, int, int, 12, 4);
+ check_struct_and_union3(int, int, long, 12, 4);
+ check_struct_and_union3(int, int, long long, 16, 8);
+ check_struct_and_union3(int, int, float, 12, 4);
+ check_struct_and_union3(int, int, double, 16, 8);
+ check_struct_and_union3(int, int, long double, 16, 8);
+ check_struct_and_union3(int, long, char, 12, 4);
+ check_struct_and_union3(int, long, short, 12, 4);
+ check_struct_and_union3(int, long, int, 12, 4);
+ check_struct_and_union3(int, long, long, 12, 4);
+ check_struct_and_union3(int, long, long long, 16, 8);
+ check_struct_and_union3(int, long, float, 12, 4);
+ check_struct_and_union3(int, long, double, 16, 8);
+ check_struct_and_union3(int, long, long double, 16, 8);
+ check_struct_and_union3(int, long long, char, 16, 8);
+ check_struct_and_union3(int, long long, short, 16, 8);
+ check_struct_and_union3(int, long long, int, 16, 8);
+ check_struct_and_union3(int, long long, long, 16, 8);
+ check_struct_and_union3(int, long long, long long, 20, 8);
+ check_struct_and_union3(int, long long, float, 16, 8);
+ check_struct_and_union3(int, long long, double, 20, 8);
+ check_struct_and_union3(int, long long, long double, 20, 8);
+ check_struct_and_union3(int, float, char, 12, 4);
+ check_struct_and_union3(int, float, short, 12, 4);
+ check_struct_and_union3(int, float, int, 12, 4);
+ check_struct_and_union3(int, float, long, 12, 4);
+ check_struct_and_union3(int, float, long long, 16, 8);
+ check_struct_and_union3(int, float, float, 12, 4);
+ check_struct_and_union3(int, float, double, 16, 8);
+ check_struct_and_union3(int, float, long double, 16, 8);
+ check_struct_and_union3(int, double, char, 16, 8);
+ check_struct_and_union3(int, double, short, 16, 8);
+ check_struct_and_union3(int, double, int, 16, 8);
+ check_struct_and_union3(int, double, long, 16, 8);
+ check_struct_and_union3(int, double, long long, 20, 8);
+ check_struct_and_union3(int, double, float, 16, 8);
+ check_struct_and_union3(int, double, double, 20, 8);
+ check_struct_and_union3(int, double, long double, 20, 8);
+ check_struct_and_union3(int, long double, char, 16, 8);
+ check_struct_and_union3(int, long double, short, 16, 8);
+ check_struct_and_union3(int, long double, int, 16, 8);
+ check_struct_and_union3(int, long double, long, 16, 8);
+ check_struct_and_union3(int, long double, long long, 20, 8);
+ check_struct_and_union3(int, long double, float, 16, 8);
+ check_struct_and_union3(int, long double, double, 20, 8);
+ check_struct_and_union3(int, long double, long double, 20, 8);
+ check_struct_and_union3(long, char, char, 8, 4);
+ check_struct_and_union3(long, char, short, 8, 4);
+ check_struct_and_union3(long, char, int, 12, 4);
+ check_struct_and_union3(long, char, long, 12, 4);
+ check_struct_and_union3(long, char, long long, 16, 8);
+ check_struct_and_union3(long, char, float, 12, 4);
+ check_struct_and_union3(long, char, double, 16, 8);
+ check_struct_and_union3(long, char, long double, 16, 8);
+ check_struct_and_union3(long, short, char, 8, 4);
+ check_struct_and_union3(long, short, short, 8, 4);
+ check_struct_and_union3(long, short, int, 12, 4);
+ check_struct_and_union3(long, short, long, 12, 4);
+ check_struct_and_union3(long, short, long long, 16, 8);
+ check_struct_and_union3(long, short, float, 12, 4);
+ check_struct_and_union3(long, short, double, 16, 8);
+ check_struct_and_union3(long, short, long double, 16, 8);
+ check_struct_and_union3(long, int, char, 12, 4);
+ check_struct_and_union3(long, int, short, 12, 4);
+ check_struct_and_union3(long, int, int, 12, 4);
+ check_struct_and_union3(long, int, long, 12, 4);
+ check_struct_and_union3(long, int, long long, 16, 8);
+ check_struct_and_union3(long, int, float, 12, 4);
+ check_struct_and_union3(long, int, double, 16, 8);
+ check_struct_and_union3(long, int, long double, 16, 8);
+ check_struct_and_union3(long, long, char, 12, 4);
+ check_struct_and_union3(long, long, short, 12, 4);
+ check_struct_and_union3(long, long, int, 12, 4);
+ check_struct_and_union3(long, long, long, 12, 4);
+ check_struct_and_union3(long, long, long long, 16, 8);
+ check_struct_and_union3(long, long, float, 12, 4);
+ check_struct_and_union3(long, long, double, 16, 8);
+ check_struct_and_union3(long, long, long double, 16, 8);
+ check_struct_and_union3(long, long long, char, 16, 8);
+ check_struct_and_union3(long, long long, short, 16, 8);
+ check_struct_and_union3(long, long long, int, 16, 8);
+ check_struct_and_union3(long, long long, long, 16, 8);
+ check_struct_and_union3(long, long long, long long, 20, 8);
+ check_struct_and_union3(long, long long, float, 16, 8);
+ check_struct_and_union3(long, long long, double, 20, 8);
+ check_struct_and_union3(long, long long, long double, 20, 8);
+ check_struct_and_union3(long, float, char, 12, 4);
+ check_struct_and_union3(long, float, short, 12, 4);
+ check_struct_and_union3(long, float, int, 12, 4);
+ check_struct_and_union3(long, float, long, 12, 4);
+ check_struct_and_union3(long, float, long long, 16, 8);
+ check_struct_and_union3(long, float, float, 12, 4);
+ check_struct_and_union3(long, float, double, 16, 8);
+ check_struct_and_union3(long, float, long double, 16, 8);
+ check_struct_and_union3(long, double, char, 16, 8);
+ check_struct_and_union3(long, double, short, 16, 8);
+ check_struct_and_union3(long, double, int, 16, 8);
+ check_struct_and_union3(long, double, long, 16, 8);
+ check_struct_and_union3(long, double, long long, 20, 8);
+ check_struct_and_union3(long, double, float, 16, 8);
+ check_struct_and_union3(long, double, double, 20, 8);
+ check_struct_and_union3(long, double, long double, 20, 8);
+ check_struct_and_union3(long, long double, char, 16, 8);
+ check_struct_and_union3(long, long double, short, 16, 8);
+ check_struct_and_union3(long, long double, int, 16, 8);
+ check_struct_and_union3(long, long double, long, 16, 8);
+ check_struct_and_union3(long, long double, long long, 20, 8);
+ check_struct_and_union3(long, long double, float, 16, 8);
+ check_struct_and_union3(long, long double, double, 20, 8);
+ check_struct_and_union3(long, long double, long double, 20, 8);
+ check_struct_and_union3(long long, char, char, 12, 8);
+ check_struct_and_union3(long long, char, short, 12, 8);
+ check_struct_and_union3(long long, char, int, 16, 8);
+ check_struct_and_union3(long long, char, long, 16, 8);
+ check_struct_and_union3(long long, char, long long, 20, 8);
+ check_struct_and_union3(long long, char, float, 16, 8);
+ check_struct_and_union3(long long, char, double, 20, 8);
+ check_struct_and_union3(long long, char, long double, 20, 8);
+ check_struct_and_union3(long long, short, char, 12, 8);
+ check_struct_and_union3(long long, short, short, 12, 8);
+ check_struct_and_union3(long long, short, int, 16, 8);
+ check_struct_and_union3(long long, short, long, 16, 8);
+ check_struct_and_union3(long long, short, long long, 20, 8);
+ check_struct_and_union3(long long, short, float, 16, 8);
+ check_struct_and_union3(long long, short, double, 20, 8);
+ check_struct_and_union3(long long, short, long double, 20, 8);
+ check_struct_and_union3(long long, int, char, 16, 8);
+ check_struct_and_union3(long long, int, short, 16, 8);
+ check_struct_and_union3(long long, int, int, 16, 8);
+ check_struct_and_union3(long long, int, long, 16, 8);
+ check_struct_and_union3(long long, int, long long, 20, 8);
+ check_struct_and_union3(long long, int, float, 16, 8);
+ check_struct_and_union3(long long, int, double, 20, 8);
+ check_struct_and_union3(long long, int, long double, 20, 8);
+ check_struct_and_union3(long long, long, char, 16, 8);
+ check_struct_and_union3(long long, long, short, 16, 8);
+ check_struct_and_union3(long long, long, int, 16, 8);
+ check_struct_and_union3(long long, long, long, 16, 8);
+ check_struct_and_union3(long long, long, long long, 20, 8);
+ check_struct_and_union3(long long, long, float, 16, 8);
+ check_struct_and_union3(long long, long, double, 20, 8);
+ check_struct_and_union3(long long, long, long double, 20, 8);
+ check_struct_and_union3(long long, long long, char, 20, 8);
+ check_struct_and_union3(long long, long long, short, 20, 8);
+ check_struct_and_union3(long long, long long, int, 20, 8);
+ check_struct_and_union3(long long, long long, long, 20, 8);
+ check_struct_and_union3(long long, long long, long long, 24, 8);
+ check_struct_and_union3(long long, long long, float, 20, 8);
+ check_struct_and_union3(long long, long long, double, 24, 8);
+ check_struct_and_union3(long long, long long, long double, 24, 8);
+ check_struct_and_union3(long long, float, char, 16, 8);
+ check_struct_and_union3(long long, float, short, 16, 8);
+ check_struct_and_union3(long long, float, int, 16, 8);
+ check_struct_and_union3(long long, float, long, 16, 8);
+ check_struct_and_union3(long long, float, long long, 20, 8);
+ check_struct_and_union3(long long, float, float, 16, 8);
+ check_struct_and_union3(long long, float, double, 20, 8);
+ check_struct_and_union3(long long, float, long double, 20, 8);
+ check_struct_and_union3(long long, double, char, 20, 8);
+ check_struct_and_union3(long long, double, short, 20, 8);
+ check_struct_and_union3(long long, double, int, 20, 8);
+ check_struct_and_union3(long long, double, long, 20, 8);
+ check_struct_and_union3(long long, double, long long, 24, 8);
+ check_struct_and_union3(long long, double, float, 20, 8);
+ check_struct_and_union3(long long, double, double, 24, 8);
+ check_struct_and_union3(long long, double, long double, 24, 8);
+ check_struct_and_union3(long long, long double, char, 20, 8);
+ check_struct_and_union3(long long, long double, short, 20, 8);
+ check_struct_and_union3(long long, long double, int, 20, 8);
+ check_struct_and_union3(long long, long double, long, 20, 8);
+ check_struct_and_union3(long long, long double, long long, 24, 8);
+ check_struct_and_union3(long long, long double, float, 20, 8);
+ check_struct_and_union3(long long, long double, double, 24, 8);
+ check_struct_and_union3(long long, long double, long double, 24, 8);
+ check_struct_and_union3(float, char, char, 8, 4);
+ check_struct_and_union3(float, char, short, 8, 4);
+ check_struct_and_union3(float, char, int, 12, 4);
+ check_struct_and_union3(float, char, long, 12, 4);
+ check_struct_and_union3(float, char, long long, 16, 8);
+ check_struct_and_union3(float, char, float, 12, 4);
+ check_struct_and_union3(float, char, double, 16, 8);
+ check_struct_and_union3(float, char, long double, 16, 8);
+ check_struct_and_union3(float, short, char, 8, 4);
+ check_struct_and_union3(float, short, short, 8, 4);
+ check_struct_and_union3(float, short, int, 12, 4);
+ check_struct_and_union3(float, short, long, 12, 4);
+ check_struct_and_union3(float, short, long long, 16, 8);
+ check_struct_and_union3(float, short, float, 12, 4);
+ check_struct_and_union3(float, short, double, 16, 8);
+ check_struct_and_union3(float, short, long double, 16, 8);
+ check_struct_and_union3(float, int, char, 12, 4);
+ check_struct_and_union3(float, int, short, 12, 4);
+ check_struct_and_union3(float, int, int, 12, 4);
+ check_struct_and_union3(float, int, long, 12, 4);
+ check_struct_and_union3(float, int, long long, 16, 8);
+ check_struct_and_union3(float, int, float, 12, 4);
+ check_struct_and_union3(float, int, double, 16, 8);
+ check_struct_and_union3(float, int, long double, 16, 8);
+ check_struct_and_union3(float, long, char, 12, 4);
+ check_struct_and_union3(float, long, short, 12, 4);
+ check_struct_and_union3(float, long, int, 12, 4);
+ check_struct_and_union3(float, long, long, 12, 4);
+ check_struct_and_union3(float, long, long long, 16, 8);
+ check_struct_and_union3(float, long, float, 12, 4);
+ check_struct_and_union3(float, long, double, 16, 8);
+ check_struct_and_union3(float, long, long double, 16, 8);
+ check_struct_and_union3(float, long long, char, 16, 8);
+ check_struct_and_union3(float, long long, short, 16, 8);
+ check_struct_and_union3(float, long long, int, 16, 8);
+ check_struct_and_union3(float, long long, long, 16, 8);
+ check_struct_and_union3(float, long long, long long, 20, 8);
+ check_struct_and_union3(float, long long, float, 16, 8);
+ check_struct_and_union3(float, long long, double, 20, 8);
+ check_struct_and_union3(float, long long, long double, 20, 8);
+ check_struct_and_union3(float, float, char, 12, 4);
+ check_struct_and_union3(float, float, short, 12, 4);
+ check_struct_and_union3(float, float, int, 12, 4);
+ check_struct_and_union3(float, float, long, 12, 4);
+ check_struct_and_union3(float, float, long long, 16, 8);
+ check_struct_and_union3(float, float, float, 12, 4);
+ check_struct_and_union3(float, float, double, 16, 8);
+ check_struct_and_union3(float, float, long double, 16, 8);
+ check_struct_and_union3(float, double, char, 16, 8);
+ check_struct_and_union3(float, double, short, 16, 8);
+ check_struct_and_union3(float, double, int, 16, 8);
+ check_struct_and_union3(float, double, long, 16, 8);
+ check_struct_and_union3(float, double, long long, 20, 8);
+ check_struct_and_union3(float, double, float, 16, 8);
+ check_struct_and_union3(float, double, double, 20, 8);
+ check_struct_and_union3(float, double, long double, 20, 8);
+ check_struct_and_union3(float, long double, char, 16, 8);
+ check_struct_and_union3(float, long double, short, 16, 8);
+ check_struct_and_union3(float, long double, int, 16, 8);
+ check_struct_and_union3(float, long double, long, 16, 8);
+ check_struct_and_union3(float, long double, long long, 20, 8);
+ check_struct_and_union3(float, long double, float, 16, 8);
+ check_struct_and_union3(float, long double, double, 20, 8);
+ check_struct_and_union3(float, long double, long double, 20, 8);
+ check_struct_and_union3(double, char, char, 12, 8);
+ check_struct_and_union3(double, char, short, 12, 8);
+ check_struct_and_union3(double, char, int, 16, 8);
+ check_struct_and_union3(double, char, long, 16, 8);
+ check_struct_and_union3(double, char, long long, 20, 8);
+ check_struct_and_union3(double, char, float, 16, 8);
+ check_struct_and_union3(double, char, double, 20, 8);
+ check_struct_and_union3(double, char, long double, 20, 8);
+ check_struct_and_union3(double, short, char, 12, 8);
+ check_struct_and_union3(double, short, short, 12, 8);
+ check_struct_and_union3(double, short, int, 16, 8);
+ check_struct_and_union3(double, short, long, 16, 8);
+ check_struct_and_union3(double, short, long long, 20, 8);
+ check_struct_and_union3(double, short, float, 16, 8);
+ check_struct_and_union3(double, short, double, 20, 8);
+ check_struct_and_union3(double, short, long double, 20, 8);
+ check_struct_and_union3(double, int, char, 16, 8);
+ check_struct_and_union3(double, int, short, 16, 8);
+ check_struct_and_union3(double, int, int, 16, 8);
+ check_struct_and_union3(double, int, long, 16, 8);
+ check_struct_and_union3(double, int, long long, 20, 8);
+ check_struct_and_union3(double, int, float, 16, 8);
+ check_struct_and_union3(double, int, double, 20, 8);
+ check_struct_and_union3(double, int, long double, 20, 8);
+ check_struct_and_union3(double, long, char, 16, 8);
+ check_struct_and_union3(double, long, short, 16, 8);
+ check_struct_and_union3(double, long, int, 16, 8);
+ check_struct_and_union3(double, long, long, 16, 8);
+ check_struct_and_union3(double, long, long long, 20, 8);
+ check_struct_and_union3(double, long, float, 16, 8);
+ check_struct_and_union3(double, long, double, 20, 8);
+ check_struct_and_union3(double, long, long double, 20, 8);
+ check_struct_and_union3(double, long long, char, 20, 8);
+ check_struct_and_union3(double, long long, short, 20, 8);
+ check_struct_and_union3(double, long long, int, 20, 8);
+ check_struct_and_union3(double, long long, long, 20, 8);
+ check_struct_and_union3(double, long long, long long, 24, 8);
+ check_struct_and_union3(double, long long, float, 20, 8);
+ check_struct_and_union3(double, long long, double, 24, 8);
+ check_struct_and_union3(double, long long, long double, 24, 8);
+ check_struct_and_union3(double, float, char, 16, 8);
+ check_struct_and_union3(double, float, short, 16, 8);
+ check_struct_and_union3(double, float, int, 16, 8);
+ check_struct_and_union3(double, float, long, 16, 8);
+ check_struct_and_union3(double, float, long long, 20, 8);
+ check_struct_and_union3(double, float, float, 16, 8);
+ check_struct_and_union3(double, float, double, 20, 8);
+ check_struct_and_union3(double, float, long double, 20, 8);
+ check_struct_and_union3(double, double, char, 20, 8);
+ check_struct_and_union3(double, double, short, 20, 8);
+ check_struct_and_union3(double, double, int, 20, 8);
+ check_struct_and_union3(double, double, long, 20, 8);
+ check_struct_and_union3(double, double, long long, 24, 8);
+ check_struct_and_union3(double, double, float, 20, 8);
+ check_struct_and_union3(double, double, double, 24, 8);
+ check_struct_and_union3(double, double, long double, 24, 8);
+ check_struct_and_union3(double, long double, char, 20, 8);
+ check_struct_and_union3(double, long double, short, 20, 8);
+ check_struct_and_union3(double, long double, int, 20, 8);
+ check_struct_and_union3(double, long double, long, 20, 8);
+ check_struct_and_union3(double, long double, long long, 24, 8);
+ check_struct_and_union3(double, long double, float, 20, 8);
+ check_struct_and_union3(double, long double, double, 24, 8);
+ check_struct_and_union3(double, long double, long double, 24, 8);
+ check_struct_and_union3(long double, char, char, 12, 8);
+ check_struct_and_union3(long double, char, short, 12, 8);
+ check_struct_and_union3(long double, char, int, 16, 8);
+ check_struct_and_union3(long double, char, long, 16, 8);
+ check_struct_and_union3(long double, char, long long, 20, 8);
+ check_struct_and_union3(long double, char, float, 16, 8);
+ check_struct_and_union3(long double, char, double, 20, 8);
+ check_struct_and_union3(long double, char, long double, 20, 8);
+ check_struct_and_union3(long double, short, char, 12, 8);
+ check_struct_and_union3(long double, short, short, 12, 8);
+ check_struct_and_union3(long double, short, int, 16, 8);
+ check_struct_and_union3(long double, short, long, 16, 8);
+ check_struct_and_union3(long double, short, long long, 20, 8);
+ check_struct_and_union3(long double, short, float, 16, 8);
+ check_struct_and_union3(long double, short, double, 20, 8);
+ check_struct_and_union3(long double, short, long double, 20, 8);
+ check_struct_and_union3(long double, int, char, 16, 8);
+ check_struct_and_union3(long double, int, short, 16, 8);
+ check_struct_and_union3(long double, int, int, 16, 8);
+ check_struct_and_union3(long double, int, long, 16, 8);
+ check_struct_and_union3(long double, int, long long, 20, 8);
+ check_struct_and_union3(long double, int, float, 16, 8);
+ check_struct_and_union3(long double, int, double, 20, 8);
+ check_struct_and_union3(long double, int, long double, 20, 8);
+ check_struct_and_union3(long double, long, char, 16, 8);
+ check_struct_and_union3(long double, long, short, 16, 8);
+ check_struct_and_union3(long double, long, int, 16, 8);
+ check_struct_and_union3(long double, long, long, 16, 8);
+ check_struct_and_union3(long double, long, long long, 20, 8);
+ check_struct_and_union3(long double, long, float, 16, 8);
+ check_struct_and_union3(long double, long, double, 20, 8);
+ check_struct_and_union3(long double, long, long double, 20, 8);
+ check_struct_and_union3(long double, long long, char, 20, 8);
+ check_struct_and_union3(long double, long long, short, 20, 8);
+ check_struct_and_union3(long double, long long, int, 20, 8);
+ check_struct_and_union3(long double, long long, long, 20, 8);
+ check_struct_and_union3(long double, long long, long long, 24, 8);
+ check_struct_and_union3(long double, long long, float, 20, 8);
+ check_struct_and_union3(long double, long long, double, 24, 8);
+ check_struct_and_union3(long double, long long, long double, 24, 8);
+ check_struct_and_union3(long double, float, char, 16, 8);
+ check_struct_and_union3(long double, float, short, 16, 8);
+ check_struct_and_union3(long double, float, int, 16, 8);
+ check_struct_and_union3(long double, float, long, 16, 8);
+ check_struct_and_union3(long double, float, long long, 20, 8);
+ check_struct_and_union3(long double, float, float, 16, 8);
+ check_struct_and_union3(long double, float, double, 20, 8);
+ check_struct_and_union3(long double, float, long double, 20, 8);
+ check_struct_and_union3(long double, double, char, 20, 8);
+ check_struct_and_union3(long double, double, short, 20, 8);
+ check_struct_and_union3(long double, double, int, 20, 8);
+ check_struct_and_union3(long double, double, long, 20, 8);
+ check_struct_and_union3(long double, double, long long, 24, 8);
+ check_struct_and_union3(long double, double, float, 20, 8);
+ check_struct_and_union3(long double, double, double, 24, 8);
+ check_struct_and_union3(long double, double, long double, 24, 8);
+ check_struct_and_union3(long double, long double, char, 20, 8);
+ check_struct_and_union3(long double, long double, short, 20, 8);
+ check_struct_and_union3(long double, long double, int, 20, 8);
+ check_struct_and_union3(long double, long double, long, 20, 8);
+ check_struct_and_union3(long double, long double, long long, 24, 8);
+ check_struct_and_union3(long double, long double, float, 20, 8);
+ check_struct_and_union3(long double, long double, double, 24, 8);
+ check_struct_and_union3(long double, long double, long double, 24, 8);
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/iamcu/test_basic_64bit_returning.c b/gcc/testsuite/gcc.target/i386/iamcu/test_basic_64bit_returning.c
new file mode 100644
index 0000000..ecece94
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/iamcu/test_basic_64bit_returning.c
@@ -0,0 +1,57 @@
+#include "defines.h"
+#include "macros.h"
+#include "args.h"
+
+struct IntegerRegisters iregbits = { ~0, ~0, ~0, ~0, ~0, ~0 };
+struct IntegerRegisters iregs;
+unsigned int num_iregs;
+
+long long
+fun_test_returning_long_long (void)
+{
+ volatile_var++;
+ return (long long) 0xabadbeefabadbeefLL;
+}
+
+double
+fun_test_returning_double (void)
+{
+ volatile_var++;
+ return (double) 12345678.0;
+}
+
+union
+{
+ long long ll;
+ double d;
+} test_64;
+
+int
+main (void)
+{
+ unsigned failed = 0;
+ long long ll;
+ double d;
+
+ clear_struct_registers;
+ test_64.ll = 0xabadbeefabadbeefLL;
+
+ ll = WRAP_RET (fun_test_returning_long_long)();
+ if (ll != test_64.ll
+ || (test_64.ll & 0xffffffff) != eax
+ || ((test_64.ll >> 32) & 0xffffffff) != edx)
+ failed++;
+
+ clear_struct_registers;
+ test_64.d = 12345678.0;
+
+ d = WRAP_RET (fun_test_returning_double)();
+ if (d != test_64.d
+ || (test_64.ll & 0xffffffff) != eax
+ || ((test_64.ll >> 32) & 0xffffffff) != edx)
+ printf ("fail double\n"), failed++;
+
+ if (failed)
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/iamcu/test_basic_alignment.c b/gcc/testsuite/gcc.target/i386/iamcu/test_basic_alignment.c
new file mode 100644
index 0000000..f14cf17
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/iamcu/test_basic_alignment.c
@@ -0,0 +1,33 @@
+/* This checks alignment of basic types. */
+
+#include "defines.h"
+#include "macros.h"
+
+
+int
+main (void)
+{
+ /* Integral types. */
+ run_signed_tests2(check_align, char, TYPE_ALIGN_CHAR);
+ run_signed_tests2(check_align, short, TYPE_ALIGN_SHORT);
+ run_signed_tests2(check_align, int, TYPE_ALIGN_INT);
+ run_signed_tests2(check_align, long, TYPE_ALIGN_LONG);
+ run_signed_tests2(check_align, long long, TYPE_ALIGN_LONG_LONG);
+ check_align(enumtype, TYPE_ALIGN_ENUM);
+
+ /* Floating point types. */
+ check_align(float, TYPE_ALIGN_FLOAT);
+ check_align(double, TYPE_ALIGN_DOUBLE);
+#ifdef CHECK_LONG_DOUBLE
+ check_align(long double, TYPE_ALIGN_LONG_DOUBLE);
+#endif
+#ifdef CHECK_FLOAT128
+ check_align(__float128, TYPE_ALIGN_FLOAT128);
+#endif
+
+ /* Pointer types. */
+ check_align(void *, TYPE_ALIGN_POINTER);
+ check_align(void (*)(), TYPE_ALIGN_POINTER);
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/iamcu/test_basic_array_size_and_align.c b/gcc/testsuite/gcc.target/i386/iamcu/test_basic_array_size_and_align.c
new file mode 100644
index 0000000..e4b6369
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/iamcu/test_basic_array_size_and_align.c
@@ -0,0 +1,32 @@
+/* Test of simple arrays, size and alignment. */
+
+#include "defines.h"
+#include "macros.h"
+
+
+int
+main (void)
+{
+ /* Integral types. */
+ run_signed_tests3(check_array_size_and_align, char, TYPE_SIZE_CHAR, TYPE_ALIGN_CHAR);
+ run_signed_tests3(check_array_size_and_align, short, TYPE_SIZE_SHORT, TYPE_ALIGN_SHORT);
+ run_signed_tests3(check_array_size_and_align, int, TYPE_SIZE_INT, TYPE_ALIGN_INT);
+ run_signed_tests3(check_array_size_and_align, long, TYPE_SIZE_LONG, TYPE_ALIGN_LONG);
+ run_signed_tests3(check_array_size_and_align, long long, TYPE_SIZE_LONG_LONG, TYPE_ALIGN_LONG_LONG);
+ check_array_size_and_align(enum dummytype, TYPE_SIZE_ENUM, TYPE_ALIGN_ENUM);
+
+ /* Floating point types. */
+ check_array_size_and_align(float, TYPE_SIZE_FLOAT, TYPE_ALIGN_FLOAT);
+ check_array_size_and_align(double, TYPE_SIZE_DOUBLE, TYPE_ALIGN_DOUBLE);
+#ifdef CHECK_LONG_DOUBLE
+ check_array_size_and_align(long double, TYPE_SIZE_LONG_DOUBLE, TYPE_ALIGN_LONG_DOUBLE);
+#endif
+#ifdef CHECK_FLOAT128
+ check_array_size_and_align(__float128, TYPE_SIZE_FLOAT128, TYPE_ALIGN_FLOAT128);
+#endif
+
+ /* Pointer types. The function pointer doesn't work with these macros. */
+ check_array_size_and_align(void *, TYPE_SIZE_POINTER, TYPE_ALIGN_POINTER);
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/iamcu/test_basic_returning.c b/gcc/testsuite/gcc.target/i386/iamcu/test_basic_returning.c
new file mode 100644
index 0000000..23efa6e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/iamcu/test_basic_returning.c
@@ -0,0 +1,52 @@
+#include "defines.h"
+#include "macros.h"
+#include "args.h"
+
+char
+fun_test_returning_char (void)
+{
+ volatile_var++;
+ return 64;
+}
+
+short
+fun_test_returning_short (void)
+{
+ volatile_var++;
+ return 65;
+}
+
+int
+fun_test_returning_int (void)
+{
+ volatile_var++;
+ return 66;
+}
+
+long
+fun_test_returning_long (void)
+{
+ volatile_var++;
+ return 67;
+}
+
+float
+fun_test_returning_float (void)
+{
+ volatile_var++;
+ return 68;
+}
+
+#define def_test_returning_type(fun, type, ret, reg) \
+ { type var = WRAP_RET (fun) (); \
+ assert (ret == (type) reg && ret == var); }
+int
+main (void)
+{
+ def_test_returning_type(fun_test_returning_char, char, 64, eax);
+ def_test_returning_type(fun_test_returning_short, short, 65, eax);
+ def_test_returning_type(fun_test_returning_int, int, 66, eax);
+ def_test_returning_type(fun_test_returning_long, long, 67, eax);
+ def_test_returning_type(fun_test_returning_float, float, 68, eax);
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/iamcu/test_basic_sizes.c b/gcc/testsuite/gcc.target/i386/iamcu/test_basic_sizes.c
new file mode 100644
index 0000000..6582fc6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/iamcu/test_basic_sizes.c
@@ -0,0 +1,36 @@
+/* This checks sizes of basic types. */
+
+#include "defines.h"
+#include "macros.h"
+
+
+int
+main (void)
+{
+ /* Integral types. */
+ run_signed_tests2(check_size, char, TYPE_SIZE_CHAR);
+ run_signed_tests2(check_size, short, TYPE_SIZE_SHORT);
+ run_signed_tests2(check_size, int, TYPE_SIZE_INT);
+ run_signed_tests2(check_size, long, TYPE_SIZE_LONG);
+ run_signed_tests2(check_size, long long, TYPE_SIZE_LONG_LONG);
+#ifdef CHECK_INT128
+ run_signed_tests2(check_size, __int128, TYPE_SIZE_INT128);
+#endif
+ check_size(enumtype, TYPE_SIZE_ENUM);
+
+ /* Floating point types. */
+ check_size(float, TYPE_SIZE_FLOAT);
+ check_size(double, TYPE_SIZE_DOUBLE);
+#ifdef CHECK_LONG_DOUBLE
+ check_size(long double, TYPE_SIZE_LONG_DOUBLE);
+#endif
+#ifdef CHECK_FLOAT128
+ check_size(__float128, TYPE_SIZE_FLOAT128);
+#endif
+
+ /* Pointer types. */
+ check_size(void *, TYPE_SIZE_POINTER);
+ check_size(void (*)(), TYPE_SIZE_POINTER);
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/iamcu/test_basic_struct_size_and_align.c b/gcc/testsuite/gcc.target/i386/iamcu/test_basic_struct_size_and_align.c
new file mode 100644
index 0000000..3b5027f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/iamcu/test_basic_struct_size_and_align.c
@@ -0,0 +1,33 @@
+/* This checks size and alignment of structs with a single basic type
+ element. All basic types are checked. */
+
+#include "defines.h"
+#include "macros.h"
+
+
+int
+main (void)
+{
+ /* Integral types. */
+ run_signed_tests3(check_basic_struct_size_and_align, char, TYPE_SIZE_CHAR, TYPE_ALIGN_CHAR);
+ run_signed_tests3(check_basic_struct_size_and_align, short, TYPE_SIZE_SHORT, TYPE_ALIGN_SHORT);
+ run_signed_tests3(check_basic_struct_size_and_align, int, TYPE_SIZE_INT, TYPE_ALIGN_INT);
+ run_signed_tests3(check_basic_struct_size_and_align, long, TYPE_SIZE_LONG, TYPE_ALIGN_LONG);
+ run_signed_tests3(check_basic_struct_size_and_align, long long, TYPE_SIZE_LONG_LONG, TYPE_ALIGN_LONG_LONG);
+ check_basic_struct_size_and_align(enum dummytype, TYPE_SIZE_ENUM, TYPE_ALIGN_ENUM);
+
+ /* Floating point types. */
+ check_basic_struct_size_and_align(float, TYPE_SIZE_FLOAT, TYPE_ALIGN_FLOAT);
+ check_basic_struct_size_and_align(double, TYPE_SIZE_DOUBLE, TYPE_ALIGN_DOUBLE);
+#ifdef CHECK_LONG_DOUBLE
+ check_basic_struct_size_and_align(long double, TYPE_SIZE_LONG_DOUBLE, TYPE_ALIGN_LONG_DOUBLE);
+#endif
+#ifdef CHECK_FLOAT128
+ check_basic_struct_size_and_align(__float128, TYPE_SIZE_FLOAT128, TYPE_ALIGN_FLOAT128);
+#endif
+
+ /* Pointer types. The function pointer doesn't work with these macros. */
+ check_basic_struct_size_and_align(void *, TYPE_SIZE_POINTER, TYPE_ALIGN_POINTER);
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/iamcu/test_basic_union_size_and_align.c b/gcc/testsuite/gcc.target/i386/iamcu/test_basic_union_size_and_align.c
new file mode 100644
index 0000000..93ba5ff
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/iamcu/test_basic_union_size_and_align.c
@@ -0,0 +1,32 @@
+/* Test of simple unions, size and alignment. */
+
+#include "defines.h"
+#include "macros.h"
+
+
+int
+main (void)
+{
+ /* Integral types. */
+ run_signed_tests3(check_basic_union_size_and_align, char, TYPE_SIZE_CHAR, TYPE_ALIGN_CHAR);
+ run_signed_tests3(check_basic_union_size_and_align, short, TYPE_SIZE_SHORT, TYPE_ALIGN_SHORT);
+ run_signed_tests3(check_basic_union_size_and_align, int, TYPE_SIZE_INT, TYPE_ALIGN_INT);
+ run_signed_tests3(check_basic_union_size_and_align, long, TYPE_SIZE_LONG, TYPE_ALIGN_LONG);
+ run_signed_tests3(check_basic_union_size_and_align, long long, TYPE_SIZE_LONG_LONG, TYPE_ALIGN_LONG_LONG);
+ check_basic_union_size_and_align(enum dummytype, TYPE_SIZE_ENUM, TYPE_ALIGN_ENUM);
+
+ /* Floating point types. */
+ check_basic_union_size_and_align(float, TYPE_SIZE_FLOAT, TYPE_ALIGN_FLOAT);
+ check_basic_union_size_and_align(double, TYPE_SIZE_DOUBLE, TYPE_ALIGN_DOUBLE);
+#ifdef CHECK_LONG_DOUBLE
+ check_basic_union_size_and_align(long double, TYPE_SIZE_LONG_DOUBLE, TYPE_ALIGN_LONG_DOUBLE);
+#endif
+#ifdef CHECK_FLOAT128
+ check_basic_union_size_and_align(__float128, TYPE_SIZE_FLOAT128, TYPE_ALIGN_FLOAT128);
+#endif
+
+ /* Pointer types. The function pointer doesn't work with these macros. */
+ check_basic_union_size_and_align(void *, TYPE_SIZE_POINTER, TYPE_ALIGN_POINTER);
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/iamcu/test_bitfields.c b/gcc/testsuite/gcc.target/i386/iamcu/test_bitfields.c
new file mode 100644
index 0000000..0b1c293
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/iamcu/test_bitfields.c
@@ -0,0 +1,162 @@
+/* This is a small test to see if bitfields are working. It is only a
+ few structs and a union and a test to see if they have the correct
+ size, if values can be read and written and a couple of argument
+ passing tests. No alignment testing is done. */
+
+#include "defines.h"
+#include "macros.h"
+
+
+/* These five bitfields are taken from the System V ABI, Intel 386
+ architecture supplement. */
+
+/* Word aligned, sizeof is 4. */
+struct RightToLeft
+{
+ int j:5;
+ int k:6;
+ int m:7;
+};
+
+/* Word aligned, sizeof is 12. */
+struct BoundaryAlignment
+{
+ short s:9;
+ int j:9;
+ char c;
+ short t:9;
+ short u:9;
+ char d;
+};
+
+/* Halfword aligned, sizeof is 2. */
+struct StorageUnitSharing
+{
+ char c;
+ short s:8;
+};
+
+/* Halfword aligned, sizeof is 2. */
+union Allocation
+{
+ char c;
+ short s:8;
+};
+
+/* Byte aligned, sizeof is 9. */
+struct Unnamed
+{
+ char c;
+ int :0;
+ char d;
+ short :9;
+ char e;
+ char :0;
+};
+
+/* Extra struct testing bitfields in larger types.
+ Doubleword aligned, sizeof is 8. */
+struct LargerTypes
+{
+ long long l:33;
+ int i:31;
+};
+
+
+void
+passing1 (struct RightToLeft str, int j, int k, int m)
+{
+ assert (str.j == j);
+ assert (str.k == k);
+ assert (str.m == m);
+}
+
+void
+passing2 (struct BoundaryAlignment str, short s, int j, char c, short t,
+ short u, char d)
+{
+ assert (str.s == s);
+ assert (str.j == j);
+ assert (str.c == c);
+ assert (str.t == t);
+ assert (str.u == u);
+ assert (str.d == d);
+}
+
+void
+passing3 (struct StorageUnitSharing str, char c, short s)
+{
+ assert (str.c == c);
+ assert (str.s == s);
+}
+
+void
+passing4 (struct Unnamed str, char c, char d, char e)
+{
+ assert (str.c == c);
+ assert (str.d == d);
+ assert (str.e == e);
+}
+
+void
+passing5 (struct LargerTypes str, long long l, int i)
+{
+ assert (str.l == l);
+ assert (str.i == i);
+}
+
+
+void
+passingU (union Allocation u, char c)
+{
+ assert (u.c == c);
+ assert (u.s == c);
+}
+
+
+int
+main (void)
+{
+ struct RightToLeft str1;
+ struct BoundaryAlignment str2;
+ struct StorageUnitSharing str3;
+ struct Unnamed str4;
+ struct LargerTypes str5;
+ union Allocation u;
+
+ /* Check sizeof's. */
+ check_size(str1, 4);
+ check_size(str2, 12);
+ check_size(str3, 2);
+ check_size(str4, 9);
+ check_size(str5, 8);
+ check_size(u, 2);
+
+ /* Check alignof's. */
+ check_align_lv(str1, 4);
+ check_align_lv(str2, 4);
+ check_align_lv(str3, 2);
+ check_align_lv(str4, 1);
+ check_align_lv(str5, 4);
+ check_align_lv(u, 2);
+
+ /* Check passing. */
+ str1.j = str2.s = str3.c = str4.c = str5.l = 4;
+ str1.k = str2.j = str3.s = str4.d = str5.i = 5;
+ str1.m = str2.c = str4.e = 6;
+ str2.t = 7;
+ str2.u = 8;
+ str2.d = 9;
+ passing1 (str1, 4, 5, 6);
+ passing2 (str2, 4, 5, 6, 7, 8, 9);
+ passing3 (str3, 4, 5);
+ passing4 (str4, 4, 5, 6);
+ passing5 (str5, 4, 5);
+
+ u.c = 5;
+ passingU (u, 5);
+ u.s = 6;
+ passingU (u, 6);
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/iamcu/test_complex_returning.c b/gcc/testsuite/gcc.target/i386/iamcu/test_complex_returning.c
new file mode 100644
index 0000000..9e9678d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/iamcu/test_complex_returning.c
@@ -0,0 +1,83 @@
+/* This is a small test case for returning a complex number. Written by
+ Andreas Jaeger. */
+
+#include "defines.h"
+
+
+#define BUILD_F_COMPLEX(real, imag) \
+ ({ __complex__ float __retval; \
+ __real__ __retval = (real); \
+ __imag__ __retval = (imag); \
+ __retval; })
+
+#define BUILD_D_COMPLEX(real, imag) \
+ ({ __complex__ double __retval; \
+ __real__ __retval = (real); \
+ __imag__ __retval = (imag); \
+ __retval; })
+
+#define BUILD_LD_COMPLEX(real, imag) \
+ ({ __complex__ long double __retval; \
+ __real__ __retval = (real); \
+ __imag__ __retval = (imag); \
+ __retval; })
+
+__complex__ float
+aj_f_times2 (__complex__ float x)
+{
+ __complex__ float res;
+
+ __real__ res = (2.0 * __real__ x);
+ __imag__ res = (2.0 * __imag__ x);
+
+ return res;
+}
+
+__complex__ double
+aj_d_times2 (__complex__ double x)
+{
+ __complex__ double res;
+
+ __real__ res = (2.0 * __real__ x);
+ __imag__ res = (2.0 * __imag__ x);
+
+ return res;
+}
+
+__complex__ long double
+aj_ld_times2 (__complex__ long double x)
+{
+ __complex__ long double res;
+
+ __real__ res = (2.0 * __real__ x);
+ __imag__ res = (2.0 * __imag__ x);
+
+ return res;
+}
+
+int
+main (void)
+{
+#ifdef CHECK_COMPLEX
+ _Complex float fc, fd;
+ _Complex double dc, dd;
+ _Complex long double ldc, ldd;
+
+ fc = BUILD_LD_COMPLEX (2.0f, 3.0f);
+ fd = aj_f_times2 (fc);
+
+ assert (__real__ fd == 4.0f && __imag__ fd == 6.0f);
+
+ dc = BUILD_LD_COMPLEX (2.0, 3.0);
+ dd = aj_ld_times2 (dc);
+
+ assert (__real__ dd == 4.0 && __imag__ dd == 6.0);
+
+ ldc = BUILD_LD_COMPLEX (2.0L, 3.0L);
+ ldd = aj_ld_times2 (ldc);
+
+ assert (__real__ ldd == 4.0L && __imag__ ldd == 6.0L);
+#endif
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/iamcu/test_passing_floats.c b/gcc/testsuite/gcc.target/i386/iamcu/test_passing_floats.c
new file mode 100644
index 0000000..6bb24cc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/iamcu/test_passing_floats.c
@@ -0,0 +1,608 @@
+#include "defines.h"
+#include "macros.h"
+#include "args.h"
+
+struct IntegerRegisters iregbits = { ~0, ~0, ~0, ~0, ~0, ~0 };
+struct IntegerRegisters iregs;
+unsigned int num_iregs;
+
+/* This struct holds values for argument checking. */
+struct
+{
+ float f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17, f18, f19, f20, f21, f22, f23;
+} values_float;
+
+struct
+{
+ double f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17, f18, f19, f20, f21, f22, f23;
+} values_double;
+
+struct
+{
+ ldouble f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17, f18, f19, f20, f21, f22, f23;
+} values_ldouble;
+
+void
+fun_check_float_passing_float8_values (float f0 ATTRIBUTE_UNUSED, float f1 ATTRIBUTE_UNUSED, float f2 ATTRIBUTE_UNUSED, float f3 ATTRIBUTE_UNUSED, float f4 ATTRIBUTE_UNUSED, float f5 ATTRIBUTE_UNUSED, float f6 ATTRIBUTE_UNUSED, float f7 ATTRIBUTE_UNUSED)
+{
+ /* Check argument values. */
+ assert (values_float.f0 == f0);
+ assert (values_float.f1 == f1);
+ assert (values_float.f2 == f2);
+ assert (values_float.f3 == f3);
+ assert (values_float.f4 == f4);
+ assert (values_float.f5 == f5);
+ assert (values_float.f6 == f6);
+ assert (values_float.f7 == f7);
+
+}
+
+void
+fun_check_float_passing_float8_regs (float f0 ATTRIBUTE_UNUSED, float f1 ATTRIBUTE_UNUSED, float f2 ATTRIBUTE_UNUSED, float f3 ATTRIBUTE_UNUSED, float f4 ATTRIBUTE_UNUSED, float f5 ATTRIBUTE_UNUSED, float f6 ATTRIBUTE_UNUSED, float f7 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_float_arguments;
+}
+
+void
+fun_check_float_passing_float16_values (float f0 ATTRIBUTE_UNUSED, float f1 ATTRIBUTE_UNUSED, float f2 ATTRIBUTE_UNUSED, float f3 ATTRIBUTE_UNUSED, float f4 ATTRIBUTE_UNUSED, float f5 ATTRIBUTE_UNUSED, float f6 ATTRIBUTE_UNUSED, float f7 ATTRIBUTE_UNUSED, float f8 ATTRIBUTE_UNUSED, float f9 ATTRIBUTE_UNUSED, float f10 ATTRIBUTE_UNUSED, float f11 ATTRIBUTE_UNUSED, float f12 ATTRIBUTE_UNUSED, float f13 ATTRIBUTE_UNUSED, float f14 ATTRIBUTE_UNUSED, float f15 ATTRIBUTE_UNUSED)
+{
+ /* Check argument values. */
+ assert (values_float.f0 == f0);
+ assert (values_float.f1 == f1);
+ assert (values_float.f2 == f2);
+ assert (values_float.f3 == f3);
+ assert (values_float.f4 == f4);
+ assert (values_float.f5 == f5);
+ assert (values_float.f6 == f6);
+ assert (values_float.f7 == f7);
+ assert (values_float.f8 == f8);
+ assert (values_float.f9 == f9);
+ assert (values_float.f10 == f10);
+ assert (values_float.f11 == f11);
+ assert (values_float.f12 == f12);
+ assert (values_float.f13 == f13);
+ assert (values_float.f14 == f14);
+ assert (values_float.f15 == f15);
+
+}
+
+void
+fun_check_float_passing_float16_regs (float f0 ATTRIBUTE_UNUSED, float f1 ATTRIBUTE_UNUSED, float f2 ATTRIBUTE_UNUSED, float f3 ATTRIBUTE_UNUSED, float f4 ATTRIBUTE_UNUSED, float f5 ATTRIBUTE_UNUSED, float f6 ATTRIBUTE_UNUSED, float f7 ATTRIBUTE_UNUSED, float f8 ATTRIBUTE_UNUSED, float f9 ATTRIBUTE_UNUSED, float f10 ATTRIBUTE_UNUSED, float f11 ATTRIBUTE_UNUSED, float f12 ATTRIBUTE_UNUSED, float f13 ATTRIBUTE_UNUSED, float f14 ATTRIBUTE_UNUSED, float f15 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_float_arguments;
+}
+
+void
+fun_check_float_passing_float20_values (float f0 ATTRIBUTE_UNUSED, float f1 ATTRIBUTE_UNUSED, float f2 ATTRIBUTE_UNUSED, float f3 ATTRIBUTE_UNUSED, float f4 ATTRIBUTE_UNUSED, float f5 ATTRIBUTE_UNUSED, float f6 ATTRIBUTE_UNUSED, float f7 ATTRIBUTE_UNUSED, float f8 ATTRIBUTE_UNUSED, float f9 ATTRIBUTE_UNUSED, float f10 ATTRIBUTE_UNUSED, float f11 ATTRIBUTE_UNUSED, float f12 ATTRIBUTE_UNUSED, float f13 ATTRIBUTE_UNUSED, float f14 ATTRIBUTE_UNUSED, float f15 ATTRIBUTE_UNUSED, float f16 ATTRIBUTE_UNUSED, float f17 ATTRIBUTE_UNUSED, float f18 ATTRIBUTE_UNUSED, float f19 ATTRIBUTE_UNUSED)
+{
+ /* Check argument values. */
+ assert (values_float.f0 == f0);
+ assert (values_float.f1 == f1);
+ assert (values_float.f2 == f2);
+ assert (values_float.f3 == f3);
+ assert (values_float.f4 == f4);
+ assert (values_float.f5 == f5);
+ assert (values_float.f6 == f6);
+ assert (values_float.f7 == f7);
+ assert (values_float.f8 == f8);
+ assert (values_float.f9 == f9);
+ assert (values_float.f10 == f10);
+ assert (values_float.f11 == f11);
+ assert (values_float.f12 == f12);
+ assert (values_float.f13 == f13);
+ assert (values_float.f14 == f14);
+ assert (values_float.f15 == f15);
+ assert (values_float.f16 == f16);
+ assert (values_float.f17 == f17);
+ assert (values_float.f18 == f18);
+ assert (values_float.f19 == f19);
+
+}
+
+void
+fun_check_float_passing_float20_regs (float f0 ATTRIBUTE_UNUSED, float f1 ATTRIBUTE_UNUSED, float f2 ATTRIBUTE_UNUSED, float f3 ATTRIBUTE_UNUSED, float f4 ATTRIBUTE_UNUSED, float f5 ATTRIBUTE_UNUSED, float f6 ATTRIBUTE_UNUSED, float f7 ATTRIBUTE_UNUSED, float f8 ATTRIBUTE_UNUSED, float f9 ATTRIBUTE_UNUSED, float f10 ATTRIBUTE_UNUSED, float f11 ATTRIBUTE_UNUSED, float f12 ATTRIBUTE_UNUSED, float f13 ATTRIBUTE_UNUSED, float f14 ATTRIBUTE_UNUSED, float f15 ATTRIBUTE_UNUSED, float f16 ATTRIBUTE_UNUSED, float f17 ATTRIBUTE_UNUSED, float f18 ATTRIBUTE_UNUSED, float f19 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_float_arguments;
+}
+
+void
+fun_check_float_passing_double8_values (double f0 ATTRIBUTE_UNUSED, double f1 ATTRIBUTE_UNUSED, double f2 ATTRIBUTE_UNUSED, double f3 ATTRIBUTE_UNUSED, double f4 ATTRIBUTE_UNUSED, double f5 ATTRIBUTE_UNUSED, double f6 ATTRIBUTE_UNUSED, double f7 ATTRIBUTE_UNUSED)
+{
+ /* Check argument values. */
+ assert (values_double.f0 == f0);
+ assert (values_double.f1 == f1);
+ assert (values_double.f2 == f2);
+ assert (values_double.f3 == f3);
+ assert (values_double.f4 == f4);
+ assert (values_double.f5 == f5);
+ assert (values_double.f6 == f6);
+ assert (values_double.f7 == f7);
+
+}
+
+void
+fun_check_float_passing_double8_regs (double f0 ATTRIBUTE_UNUSED, double f1 ATTRIBUTE_UNUSED, double f2 ATTRIBUTE_UNUSED, double f3 ATTRIBUTE_UNUSED, double f4 ATTRIBUTE_UNUSED, double f5 ATTRIBUTE_UNUSED, double f6 ATTRIBUTE_UNUSED, double f7 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_double_arguments;
+}
+
+void
+fun_check_float_passing_double16_values (double f0 ATTRIBUTE_UNUSED, double f1 ATTRIBUTE_UNUSED, double f2 ATTRIBUTE_UNUSED, double f3 ATTRIBUTE_UNUSED, double f4 ATTRIBUTE_UNUSED, double f5 ATTRIBUTE_UNUSED, double f6 ATTRIBUTE_UNUSED, double f7 ATTRIBUTE_UNUSED, double f8 ATTRIBUTE_UNUSED, double f9 ATTRIBUTE_UNUSED, double f10 ATTRIBUTE_UNUSED, double f11 ATTRIBUTE_UNUSED, double f12 ATTRIBUTE_UNUSED, double f13 ATTRIBUTE_UNUSED, double f14 ATTRIBUTE_UNUSED, double f15 ATTRIBUTE_UNUSED)
+{
+ /* Check argument values. */
+ assert (values_double.f0 == f0);
+ assert (values_double.f1 == f1);
+ assert (values_double.f2 == f2);
+ assert (values_double.f3 == f3);
+ assert (values_double.f4 == f4);
+ assert (values_double.f5 == f5);
+ assert (values_double.f6 == f6);
+ assert (values_double.f7 == f7);
+ assert (values_double.f8 == f8);
+ assert (values_double.f9 == f9);
+ assert (values_double.f10 == f10);
+ assert (values_double.f11 == f11);
+ assert (values_double.f12 == f12);
+ assert (values_double.f13 == f13);
+ assert (values_double.f14 == f14);
+ assert (values_double.f15 == f15);
+
+}
+
+void
+fun_check_float_passing_double16_regs (double f0 ATTRIBUTE_UNUSED, double f1 ATTRIBUTE_UNUSED, double f2 ATTRIBUTE_UNUSED, double f3 ATTRIBUTE_UNUSED, double f4 ATTRIBUTE_UNUSED, double f5 ATTRIBUTE_UNUSED, double f6 ATTRIBUTE_UNUSED, double f7 ATTRIBUTE_UNUSED, double f8 ATTRIBUTE_UNUSED, double f9 ATTRIBUTE_UNUSED, double f10 ATTRIBUTE_UNUSED, double f11 ATTRIBUTE_UNUSED, double f12 ATTRIBUTE_UNUSED, double f13 ATTRIBUTE_UNUSED, double f14 ATTRIBUTE_UNUSED, double f15 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_double_arguments;
+}
+
+void
+fun_check_float_passing_double20_values (double f0 ATTRIBUTE_UNUSED, double f1 ATTRIBUTE_UNUSED, double f2 ATTRIBUTE_UNUSED, double f3 ATTRIBUTE_UNUSED, double f4 ATTRIBUTE_UNUSED, double f5 ATTRIBUTE_UNUSED, double f6 ATTRIBUTE_UNUSED, double f7 ATTRIBUTE_UNUSED, double f8 ATTRIBUTE_UNUSED, double f9 ATTRIBUTE_UNUSED, double f10 ATTRIBUTE_UNUSED, double f11 ATTRIBUTE_UNUSED, double f12 ATTRIBUTE_UNUSED, double f13 ATTRIBUTE_UNUSED, double f14 ATTRIBUTE_UNUSED, double f15 ATTRIBUTE_UNUSED, double f16 ATTRIBUTE_UNUSED, double f17 ATTRIBUTE_UNUSED, double f18 ATTRIBUTE_UNUSED, double f19 ATTRIBUTE_UNUSED)
+{
+ /* Check argument values. */
+ assert (values_double.f0 == f0);
+ assert (values_double.f1 == f1);
+ assert (values_double.f2 == f2);
+ assert (values_double.f3 == f3);
+ assert (values_double.f4 == f4);
+ assert (values_double.f5 == f5);
+ assert (values_double.f6 == f6);
+ assert (values_double.f7 == f7);
+ assert (values_double.f8 == f8);
+ assert (values_double.f9 == f9);
+ assert (values_double.f10 == f10);
+ assert (values_double.f11 == f11);
+ assert (values_double.f12 == f12);
+ assert (values_double.f13 == f13);
+ assert (values_double.f14 == f14);
+ assert (values_double.f15 == f15);
+ assert (values_double.f16 == f16);
+ assert (values_double.f17 == f17);
+ assert (values_double.f18 == f18);
+ assert (values_double.f19 == f19);
+
+}
+
+void
+fun_check_float_passing_double20_regs (double f0 ATTRIBUTE_UNUSED, double f1 ATTRIBUTE_UNUSED, double f2 ATTRIBUTE_UNUSED, double f3 ATTRIBUTE_UNUSED, double f4 ATTRIBUTE_UNUSED, double f5 ATTRIBUTE_UNUSED, double f6 ATTRIBUTE_UNUSED, double f7 ATTRIBUTE_UNUSED, double f8 ATTRIBUTE_UNUSED, double f9 ATTRIBUTE_UNUSED, double f10 ATTRIBUTE_UNUSED, double f11 ATTRIBUTE_UNUSED, double f12 ATTRIBUTE_UNUSED, double f13 ATTRIBUTE_UNUSED, double f14 ATTRIBUTE_UNUSED, double f15 ATTRIBUTE_UNUSED, double f16 ATTRIBUTE_UNUSED, double f17 ATTRIBUTE_UNUSED, double f18 ATTRIBUTE_UNUSED, double f19 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_double_arguments;
+}
+
+void
+fun_check_x87_passing_ldouble8_values (ldouble f0 ATTRIBUTE_UNUSED, ldouble f1 ATTRIBUTE_UNUSED, ldouble f2 ATTRIBUTE_UNUSED, ldouble f3 ATTRIBUTE_UNUSED, ldouble f4 ATTRIBUTE_UNUSED, ldouble f5 ATTRIBUTE_UNUSED, ldouble f6 ATTRIBUTE_UNUSED, ldouble f7 ATTRIBUTE_UNUSED)
+{
+ /* Check argument values. */
+ assert (values_ldouble.f0 == f0);
+ assert (values_ldouble.f1 == f1);
+ assert (values_ldouble.f2 == f2);
+ assert (values_ldouble.f3 == f3);
+ assert (values_ldouble.f4 == f4);
+ assert (values_ldouble.f5 == f5);
+ assert (values_ldouble.f6 == f6);
+ assert (values_ldouble.f7 == f7);
+
+}
+
+void
+fun_check_x87_passing_ldouble8_regs (ldouble f0 ATTRIBUTE_UNUSED, ldouble f1 ATTRIBUTE_UNUSED, ldouble f2 ATTRIBUTE_UNUSED, ldouble f3 ATTRIBUTE_UNUSED, ldouble f4 ATTRIBUTE_UNUSED, ldouble f5 ATTRIBUTE_UNUSED, ldouble f6 ATTRIBUTE_UNUSED, ldouble f7 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_ldouble_arguments;
+}
+
+void
+fun_check_x87_passing_ldouble16_values (ldouble f0 ATTRIBUTE_UNUSED, ldouble f1 ATTRIBUTE_UNUSED, ldouble f2 ATTRIBUTE_UNUSED, ldouble f3 ATTRIBUTE_UNUSED, ldouble f4 ATTRIBUTE_UNUSED, ldouble f5 ATTRIBUTE_UNUSED, ldouble f6 ATTRIBUTE_UNUSED, ldouble f7 ATTRIBUTE_UNUSED, ldouble f8 ATTRIBUTE_UNUSED, ldouble f9 ATTRIBUTE_UNUSED, ldouble f10 ATTRIBUTE_UNUSED, ldouble f11 ATTRIBUTE_UNUSED, ldouble f12 ATTRIBUTE_UNUSED, ldouble f13 ATTRIBUTE_UNUSED, ldouble f14 ATTRIBUTE_UNUSED, ldouble f15 ATTRIBUTE_UNUSED)
+{
+ /* Check argument values. */
+ assert (values_ldouble.f0 == f0);
+ assert (values_ldouble.f1 == f1);
+ assert (values_ldouble.f2 == f2);
+ assert (values_ldouble.f3 == f3);
+ assert (values_ldouble.f4 == f4);
+ assert (values_ldouble.f5 == f5);
+ assert (values_ldouble.f6 == f6);
+ assert (values_ldouble.f7 == f7);
+ assert (values_ldouble.f8 == f8);
+ assert (values_ldouble.f9 == f9);
+ assert (values_ldouble.f10 == f10);
+ assert (values_ldouble.f11 == f11);
+ assert (values_ldouble.f12 == f12);
+ assert (values_ldouble.f13 == f13);
+ assert (values_ldouble.f14 == f14);
+ assert (values_ldouble.f15 == f15);
+
+}
+
+void
+fun_check_x87_passing_ldouble16_regs (ldouble f0 ATTRIBUTE_UNUSED, ldouble f1 ATTRIBUTE_UNUSED, ldouble f2 ATTRIBUTE_UNUSED, ldouble f3 ATTRIBUTE_UNUSED, ldouble f4 ATTRIBUTE_UNUSED, ldouble f5 ATTRIBUTE_UNUSED, ldouble f6 ATTRIBUTE_UNUSED, ldouble f7 ATTRIBUTE_UNUSED, ldouble f8 ATTRIBUTE_UNUSED, ldouble f9 ATTRIBUTE_UNUSED, ldouble f10 ATTRIBUTE_UNUSED, ldouble f11 ATTRIBUTE_UNUSED, ldouble f12 ATTRIBUTE_UNUSED, ldouble f13 ATTRIBUTE_UNUSED, ldouble f14 ATTRIBUTE_UNUSED, ldouble f15 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_ldouble_arguments;
+}
+
+void
+fun_check_x87_passing_ldouble20_values (ldouble f0 ATTRIBUTE_UNUSED, ldouble f1 ATTRIBUTE_UNUSED, ldouble f2 ATTRIBUTE_UNUSED, ldouble f3 ATTRIBUTE_UNUSED, ldouble f4 ATTRIBUTE_UNUSED, ldouble f5 ATTRIBUTE_UNUSED, ldouble f6 ATTRIBUTE_UNUSED, ldouble f7 ATTRIBUTE_UNUSED, ldouble f8 ATTRIBUTE_UNUSED, ldouble f9 ATTRIBUTE_UNUSED, ldouble f10 ATTRIBUTE_UNUSED, ldouble f11 ATTRIBUTE_UNUSED, ldouble f12 ATTRIBUTE_UNUSED, ldouble f13 ATTRIBUTE_UNUSED, ldouble f14 ATTRIBUTE_UNUSED, ldouble f15 ATTRIBUTE_UNUSED, ldouble f16 ATTRIBUTE_UNUSED, ldouble f17 ATTRIBUTE_UNUSED, ldouble f18 ATTRIBUTE_UNUSED, ldouble f19 ATTRIBUTE_UNUSED)
+{
+ /* Check argument values. */
+ assert (values_ldouble.f0 == f0);
+ assert (values_ldouble.f1 == f1);
+ assert (values_ldouble.f2 == f2);
+ assert (values_ldouble.f3 == f3);
+ assert (values_ldouble.f4 == f4);
+ assert (values_ldouble.f5 == f5);
+ assert (values_ldouble.f6 == f6);
+ assert (values_ldouble.f7 == f7);
+ assert (values_ldouble.f8 == f8);
+ assert (values_ldouble.f9 == f9);
+ assert (values_ldouble.f10 == f10);
+ assert (values_ldouble.f11 == f11);
+ assert (values_ldouble.f12 == f12);
+ assert (values_ldouble.f13 == f13);
+ assert (values_ldouble.f14 == f14);
+ assert (values_ldouble.f15 == f15);
+ assert (values_ldouble.f16 == f16);
+ assert (values_ldouble.f17 == f17);
+ assert (values_ldouble.f18 == f18);
+ assert (values_ldouble.f19 == f19);
+
+}
+
+void
+fun_check_x87_passing_ldouble20_regs (ldouble f0 ATTRIBUTE_UNUSED, ldouble f1 ATTRIBUTE_UNUSED, ldouble f2 ATTRIBUTE_UNUSED, ldouble f3 ATTRIBUTE_UNUSED, ldouble f4 ATTRIBUTE_UNUSED, ldouble f5 ATTRIBUTE_UNUSED, ldouble f6 ATTRIBUTE_UNUSED, ldouble f7 ATTRIBUTE_UNUSED, ldouble f8 ATTRIBUTE_UNUSED, ldouble f9 ATTRIBUTE_UNUSED, ldouble f10 ATTRIBUTE_UNUSED, ldouble f11 ATTRIBUTE_UNUSED, ldouble f12 ATTRIBUTE_UNUSED, ldouble f13 ATTRIBUTE_UNUSED, ldouble f14 ATTRIBUTE_UNUSED, ldouble f15 ATTRIBUTE_UNUSED, ldouble f16 ATTRIBUTE_UNUSED, ldouble f17 ATTRIBUTE_UNUSED, ldouble f18 ATTRIBUTE_UNUSED, ldouble f19 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_ldouble_arguments;
+}
+
+#define def_check_float_passing8(_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _func1, _func2, TYPE) \
+ values_ ## TYPE .f0 = _f0; \
+ values_ ## TYPE .f1 = _f1; \
+ values_ ## TYPE .f2 = _f2; \
+ values_ ## TYPE .f3 = _f3; \
+ values_ ## TYPE .f4 = _f4; \
+ values_ ## TYPE .f5 = _f5; \
+ values_ ## TYPE .f6 = _f6; \
+ values_ ## TYPE .f7 = _f7; \
+ WRAP_CALL(_func1) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7); \
+ \
+ clear_int_registers; \
+ if (sizeof (TYPE) == 4) \
+ { \
+ u.f = _f0; \
+ iregs.I0 = u.i[0]; \
+ u.f = _f1; \
+ iregs.I1 = u.i[0]; \
+ u.f = _f2; \
+ iregs.I2 = u.i[0]; \
+ num_iregs = 3; \
+ } \
+ else \
+ { \
+ u.d = _f0; \
+ iregs.I0 = u.i[0]; \
+ iregs.I1 = u.i[1]; \
+ num_iregs = 2; \
+ } \
+ WRAP_CALL(_func2) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7);
+
+#define def_check_float_passing16(_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15, _func1, _func2, TYPE) \
+ values_ ## TYPE .f0 = _f0; \
+ values_ ## TYPE .f1 = _f1; \
+ values_ ## TYPE .f2 = _f2; \
+ values_ ## TYPE .f3 = _f3; \
+ values_ ## TYPE .f4 = _f4; \
+ values_ ## TYPE .f5 = _f5; \
+ values_ ## TYPE .f6 = _f6; \
+ values_ ## TYPE .f7 = _f7; \
+ values_ ## TYPE .f8 = _f8; \
+ values_ ## TYPE .f9 = _f9; \
+ values_ ## TYPE .f10 = _f10; \
+ values_ ## TYPE .f11 = _f11; \
+ values_ ## TYPE .f12 = _f12; \
+ values_ ## TYPE .f13 = _f13; \
+ values_ ## TYPE .f14 = _f14; \
+ values_ ## TYPE .f15 = _f15; \
+ WRAP_CALL(_func1) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15); \
+ \
+ clear_int_registers; \
+ if (sizeof (TYPE) == 4) \
+ { \
+ u.f = _f0; \
+ iregs.I0 = u.i[0]; \
+ u.f = _f1; \
+ iregs.I1 = u.i[0]; \
+ u.f = _f2; \
+ iregs.I2 = u.i[0]; \
+ num_iregs = 3; \
+ } \
+ else \
+ { \
+ u.d = _f0; \
+ iregs.I0 = u.i[0]; \
+ iregs.I1 = u.i[1]; \
+ num_iregs = 2; \
+ } \
+ WRAP_CALL(_func2) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15);
+
+#define def_check_float_passing20(_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15, _f16, _f17, _f18, _f19, _func1, _func2, TYPE) \
+ values_ ## TYPE .f0 = _f0; \
+ values_ ## TYPE .f1 = _f1; \
+ values_ ## TYPE .f2 = _f2; \
+ values_ ## TYPE .f3 = _f3; \
+ values_ ## TYPE .f4 = _f4; \
+ values_ ## TYPE .f5 = _f5; \
+ values_ ## TYPE .f6 = _f6; \
+ values_ ## TYPE .f7 = _f7; \
+ values_ ## TYPE .f8 = _f8; \
+ values_ ## TYPE .f9 = _f9; \
+ values_ ## TYPE .f10 = _f10; \
+ values_ ## TYPE .f11 = _f11; \
+ values_ ## TYPE .f12 = _f12; \
+ values_ ## TYPE .f13 = _f13; \
+ values_ ## TYPE .f14 = _f14; \
+ values_ ## TYPE .f15 = _f15; \
+ values_ ## TYPE .f16 = _f16; \
+ values_ ## TYPE .f17 = _f17; \
+ values_ ## TYPE .f18 = _f18; \
+ values_ ## TYPE .f19 = _f19; \
+ WRAP_CALL(_func1) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15, _f16, _f17, _f18, _f19); \
+ \
+ clear_int_registers; \
+ if (sizeof (TYPE) == 4) \
+ { \
+ u.f = _f0; \
+ iregs.I0 = u.i[0]; \
+ u.f = _f1; \
+ iregs.I1 = u.i[0]; \
+ u.f = _f2; \
+ iregs.I2 = u.i[0]; \
+ num_iregs = 3; \
+ } \
+ else \
+ { \
+ u.d = _f0; \
+ iregs.I0 = u.i[0]; \
+ iregs.I1 = u.i[1]; \
+ num_iregs = 2; \
+ } \
+ WRAP_CALL(_func2) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15, _f16, _f17, _f18, _f19);
+
+#define def_check_x87_passing8(_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _func1, _func2, TYPE) \
+ values_ ## TYPE .f0 = _f0; \
+ values_ ## TYPE .f1 = _f1; \
+ values_ ## TYPE .f2 = _f2; \
+ values_ ## TYPE .f3 = _f3; \
+ values_ ## TYPE .f4 = _f4; \
+ values_ ## TYPE .f5 = _f5; \
+ values_ ## TYPE .f6 = _f6; \
+ values_ ## TYPE .f7 = _f7; \
+ WRAP_CALL(_func1) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7); \
+ \
+ clear_int_registers; \
+ if (sizeof (TYPE) == 4) \
+ { \
+ u.f = _f0; \
+ iregs.I0 = u.i[0]; \
+ u.f = _f1; \
+ iregs.I1 = u.i[0]; \
+ u.f = _f2; \
+ iregs.I2 = u.i[0]; \
+ num_iregs = 3; \
+ } \
+ else \
+ { \
+ u.d = _f0; \
+ iregs.I0 = u.i[0]; \
+ iregs.I1 = u.i[1]; \
+ num_iregs = 2; \
+ } \
+ WRAP_CALL(_func2) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7);
+
+#define def_check_x87_passing16(_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15, _func1, _func2, TYPE) \
+ values_ ## TYPE .f0 = _f0; \
+ values_ ## TYPE .f1 = _f1; \
+ values_ ## TYPE .f2 = _f2; \
+ values_ ## TYPE .f3 = _f3; \
+ values_ ## TYPE .f4 = _f4; \
+ values_ ## TYPE .f5 = _f5; \
+ values_ ## TYPE .f6 = _f6; \
+ values_ ## TYPE .f7 = _f7; \
+ values_ ## TYPE .f8 = _f8; \
+ values_ ## TYPE .f9 = _f9; \
+ values_ ## TYPE .f10 = _f10; \
+ values_ ## TYPE .f11 = _f11; \
+ values_ ## TYPE .f12 = _f12; \
+ values_ ## TYPE .f13 = _f13; \
+ values_ ## TYPE .f14 = _f14; \
+ values_ ## TYPE .f15 = _f15; \
+ WRAP_CALL(_func1) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15); \
+ \
+ clear_int_registers; \
+ if (sizeof (TYPE) == 4) \
+ { \
+ u.f = _f0; \
+ iregs.I0 = u.i[0]; \
+ u.f = _f1; \
+ iregs.I1 = u.i[0]; \
+ u.f = _f2; \
+ iregs.I2 = u.i[0]; \
+ num_iregs = 3; \
+ } \
+ else \
+ { \
+ u.d = _f0; \
+ iregs.I0 = u.i[0]; \
+ iregs.I1 = u.i[1]; \
+ num_iregs = 2; \
+ } \
+ WRAP_CALL(_func2) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15);
+
+#define def_check_x87_passing20(_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15, _f16, _f17, _f18, _f19, _func1, _func2, TYPE) \
+ values_ ## TYPE .f0 = _f0; \
+ values_ ## TYPE .f1 = _f1; \
+ values_ ## TYPE .f2 = _f2; \
+ values_ ## TYPE .f3 = _f3; \
+ values_ ## TYPE .f4 = _f4; \
+ values_ ## TYPE .f5 = _f5; \
+ values_ ## TYPE .f6 = _f6; \
+ values_ ## TYPE .f7 = _f7; \
+ values_ ## TYPE .f8 = _f8; \
+ values_ ## TYPE .f9 = _f9; \
+ values_ ## TYPE .f10 = _f10; \
+ values_ ## TYPE .f11 = _f11; \
+ values_ ## TYPE .f12 = _f12; \
+ values_ ## TYPE .f13 = _f13; \
+ values_ ## TYPE .f14 = _f14; \
+ values_ ## TYPE .f15 = _f15; \
+ values_ ## TYPE .f16 = _f16; \
+ values_ ## TYPE .f17 = _f17; \
+ values_ ## TYPE .f18 = _f18; \
+ values_ ## TYPE .f19 = _f19; \
+ WRAP_CALL(_func1) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15, _f16, _f17, _f18, _f19); \
+ \
+ clear_int_registers; \
+ if (sizeof (TYPE) == 4) \
+ { \
+ u.f = _f0; \
+ iregs.I0 = u.i[0]; \
+ u.f = _f1; \
+ iregs.I1 = u.i[0]; \
+ u.f = _f2; \
+ iregs.I2 = u.i[0]; \
+ num_iregs = 3; \
+ } \
+ else \
+ { \
+ u.d = _f0; \
+ iregs.I0 = u.i[0]; \
+ iregs.I1 = u.i[1]; \
+ num_iregs = 2; \
+ } \
+ WRAP_CALL(_func2) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15, _f16, _f17, _f18, _f19);
+
+void
+test_floats_on_stack ()
+{
+ union
+ {
+ float f;
+ double d;
+ int i[2];
+ } u;
+ def_check_float_passing8(32, 33, 34, 35, 36, 37, 38, 39, fun_check_float_passing_float8_values, fun_check_float_passing_float8_regs, float);
+
+ def_check_float_passing16(32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, fun_check_float_passing_float16_values, fun_check_float_passing_float16_regs, float);
+}
+
+void
+test_too_many_floats ()
+{
+ union
+ {
+ float f;
+ double d;
+ int i[2];
+ } u;
+ def_check_float_passing20(32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, fun_check_float_passing_float20_values, fun_check_float_passing_float20_regs, float);
+}
+
+void
+test_doubles_on_stack ()
+{
+ union
+ {
+ float f;
+ double d;
+ int i[2];
+ } u;
+ def_check_float_passing8(32, 33, 34, 35, 36, 37, 38, 39, fun_check_float_passing_double8_values, fun_check_float_passing_double8_regs, double);
+
+ def_check_float_passing16(32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, fun_check_float_passing_double16_values, fun_check_float_passing_double16_regs, double);
+}
+
+void
+test_too_many_doubles ()
+{
+ union
+ {
+ float f;
+ double d;
+ int i[2];
+ } u;
+ def_check_float_passing20(32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, fun_check_float_passing_double20_values, fun_check_float_passing_double20_regs, double);
+}
+
+void
+test_long_doubles_on_stack ()
+{
+ union
+ {
+ float f;
+ double d;
+ int i[2];
+ } u;
+ def_check_x87_passing8(32, 33, 34, 35, 36, 37, 38, 39, fun_check_x87_passing_ldouble8_values, fun_check_x87_passing_ldouble8_regs, ldouble);
+}
+
+void
+test_too_many_long_doubles ()
+{
+ union
+ {
+ float f;
+ double d;
+ int i[2];
+ } u;
+ def_check_x87_passing20(32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, fun_check_x87_passing_ldouble20_values, fun_check_x87_passing_ldouble20_regs, ldouble);
+}
+
+void
+test_float128s_on_stack ()
+{
+}
+
+void
+test_too_many_float128s ()
+{
+}
+
+
+int
+main (void)
+{
+ test_floats_on_stack ();
+ test_too_many_floats ();
+ test_doubles_on_stack ();
+ test_too_many_doubles ();
+ test_long_doubles_on_stack ();
+ test_too_many_long_doubles ();
+ test_float128s_on_stack ();
+ test_too_many_float128s ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/iamcu/test_passing_integers.c b/gcc/testsuite/gcc.target/i386/iamcu/test_passing_integers.c
new file mode 100644
index 0000000..046e140
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/iamcu/test_passing_integers.c
@@ -0,0 +1,182 @@
+#include "defines.h"
+#include "macros.h"
+#include "args.h"
+
+struct IntegerRegisters iregbits = { ~0, ~0, ~0, ~0, ~0, ~0 };
+struct IntegerRegisters iregs;
+unsigned int num_iregs;
+
+/* This struct holds values for argument checking. */
+struct
+{
+ int i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14, i15, i16, i17, i18, i19, i20, i21, i22, i23;
+} values_int;
+
+struct
+{
+ long i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14, i15, i16, i17, i18, i19, i20, i21, i22, i23;
+} values_long;
+
+void
+fun_check_int_passing_int6_values (int i0 ATTRIBUTE_UNUSED, int i1 ATTRIBUTE_UNUSED, int i2 ATTRIBUTE_UNUSED, int i3 ATTRIBUTE_UNUSED, int i4 ATTRIBUTE_UNUSED, int i5 ATTRIBUTE_UNUSED)
+{
+ /* Check argument values. */
+ assert (values_int.i0 == i0);
+ assert (values_int.i1 == i1);
+ assert (values_int.i2 == i2);
+ assert (values_int.i3 == i3);
+ assert (values_int.i4 == i4);
+ assert (values_int.i5 == i5);
+
+}
+
+void
+fun_check_int_passing_int6_regs (int i0 ATTRIBUTE_UNUSED, int i1 ATTRIBUTE_UNUSED, int i2 ATTRIBUTE_UNUSED, int i3 ATTRIBUTE_UNUSED, int i4 ATTRIBUTE_UNUSED, int i5 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_int_arguments;
+}
+
+void
+fun_check_int_passing_int12_values (int i0 ATTRIBUTE_UNUSED, int i1 ATTRIBUTE_UNUSED, int i2 ATTRIBUTE_UNUSED, int i3 ATTRIBUTE_UNUSED, int i4 ATTRIBUTE_UNUSED, int i5 ATTRIBUTE_UNUSED, int i6 ATTRIBUTE_UNUSED, int i7 ATTRIBUTE_UNUSED, int i8 ATTRIBUTE_UNUSED, int i9 ATTRIBUTE_UNUSED, int i10 ATTRIBUTE_UNUSED, int i11 ATTRIBUTE_UNUSED)
+{
+ /* Check argument values. */
+ assert (values_int.i0 == i0);
+ assert (values_int.i1 == i1);
+ assert (values_int.i2 == i2);
+ assert (values_int.i3 == i3);
+ assert (values_int.i4 == i4);
+ assert (values_int.i5 == i5);
+ assert (values_int.i6 == i6);
+ assert (values_int.i7 == i7);
+ assert (values_int.i8 == i8);
+ assert (values_int.i9 == i9);
+ assert (values_int.i10 == i10);
+ assert (values_int.i11 == i11);
+
+}
+
+void
+fun_check_int_passing_int12_regs (int i0 ATTRIBUTE_UNUSED, int i1 ATTRIBUTE_UNUSED, int i2 ATTRIBUTE_UNUSED, int i3 ATTRIBUTE_UNUSED, int i4 ATTRIBUTE_UNUSED, int i5 ATTRIBUTE_UNUSED, int i6 ATTRIBUTE_UNUSED, int i7 ATTRIBUTE_UNUSED, int i8 ATTRIBUTE_UNUSED, int i9 ATTRIBUTE_UNUSED, int i10 ATTRIBUTE_UNUSED, int i11 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_int_arguments;
+}
+
+void
+fun_check_int_passing_long6_values (long i0 ATTRIBUTE_UNUSED, long i1 ATTRIBUTE_UNUSED, long i2 ATTRIBUTE_UNUSED, long i3 ATTRIBUTE_UNUSED, long i4 ATTRIBUTE_UNUSED, long i5 ATTRIBUTE_UNUSED)
+{
+ /* Check argument values. */
+ assert (values_long.i0 == i0);
+ assert (values_long.i1 == i1);
+ assert (values_long.i2 == i2);
+ assert (values_long.i3 == i3);
+ assert (values_long.i4 == i4);
+ assert (values_long.i5 == i5);
+
+}
+
+void
+fun_check_int_passing_long6_regs (long i0 ATTRIBUTE_UNUSED, long i1 ATTRIBUTE_UNUSED, long i2 ATTRIBUTE_UNUSED, long i3 ATTRIBUTE_UNUSED, long i4 ATTRIBUTE_UNUSED, long i5 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_long_arguments;
+}
+
+void
+fun_check_int_passing_long12_values (long i0 ATTRIBUTE_UNUSED, long i1 ATTRIBUTE_UNUSED, long i2 ATTRIBUTE_UNUSED, long i3 ATTRIBUTE_UNUSED, long i4 ATTRIBUTE_UNUSED, long i5 ATTRIBUTE_UNUSED, long i6 ATTRIBUTE_UNUSED, long i7 ATTRIBUTE_UNUSED, long i8 ATTRIBUTE_UNUSED, long i9 ATTRIBUTE_UNUSED, long i10 ATTRIBUTE_UNUSED, long i11 ATTRIBUTE_UNUSED)
+{
+ /* Check argument values. */
+ assert (values_long.i0 == i0);
+ assert (values_long.i1 == i1);
+ assert (values_long.i2 == i2);
+ assert (values_long.i3 == i3);
+ assert (values_long.i4 == i4);
+ assert (values_long.i5 == i5);
+ assert (values_long.i6 == i6);
+ assert (values_long.i7 == i7);
+ assert (values_long.i8 == i8);
+ assert (values_long.i9 == i9);
+ assert (values_long.i10 == i10);
+ assert (values_long.i11 == i11);
+
+}
+
+void
+fun_check_int_passing_long12_regs (long i0 ATTRIBUTE_UNUSED, long i1 ATTRIBUTE_UNUSED, long i2 ATTRIBUTE_UNUSED, long i3 ATTRIBUTE_UNUSED, long i4 ATTRIBUTE_UNUSED, long i5 ATTRIBUTE_UNUSED, long i6 ATTRIBUTE_UNUSED, long i7 ATTRIBUTE_UNUSED, long i8 ATTRIBUTE_UNUSED, long i9 ATTRIBUTE_UNUSED, long i10 ATTRIBUTE_UNUSED, long i11 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_long_arguments;
+}
+
+#define def_check_int_passing6(_i0, _i1, _i2, _i3, _i4, _i5, _func1, _func2, TYPE) \
+ values_ ## TYPE .i0 = _i0; \
+ values_ ## TYPE .i1 = _i1; \
+ values_ ## TYPE .i2 = _i2; \
+ values_ ## TYPE .i3 = _i3; \
+ values_ ## TYPE .i4 = _i4; \
+ values_ ## TYPE .i5 = _i5; \
+ WRAP_CALL(_func1) (_i0, _i1, _i2, _i3, _i4, _i5); \
+ \
+ clear_int_registers; \
+ iregs.I0 = _i0; \
+ iregs.I1 = _i1; \
+ iregs.I2 = _i2; \
+ num_iregs = 3; \
+ WRAP_CALL(_func2) (_i0, _i1, _i2, _i3, _i4, _i5);
+
+#define def_check_int_passing12(_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, _i9, _i10, _i11, _func1, _func2, TYPE) \
+ values_ ## TYPE .i0 = _i0; \
+ values_ ## TYPE .i1 = _i1; \
+ values_ ## TYPE .i2 = _i2; \
+ values_ ## TYPE .i3 = _i3; \
+ values_ ## TYPE .i4 = _i4; \
+ values_ ## TYPE .i5 = _i5; \
+ values_ ## TYPE .i6 = _i6; \
+ values_ ## TYPE .i7 = _i7; \
+ values_ ## TYPE .i8 = _i8; \
+ values_ ## TYPE .i9 = _i9; \
+ values_ ## TYPE .i10 = _i10; \
+ values_ ## TYPE .i11 = _i11; \
+ WRAP_CALL(_func1) (_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, _i9, _i10, _i11); \
+ \
+ clear_int_registers; \
+ iregs.I0 = _i0; \
+ iregs.I1 = _i1; \
+ iregs.I2 = _i2; \
+ num_iregs = 3; \
+ WRAP_CALL(_func2) (_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, _i9, _i10, _i11);
+
+void
+test_ints_on_stack ()
+{
+ def_check_int_passing6(32, 33, 34, 35, 36, 37, fun_check_int_passing_int6_values, fun_check_int_passing_int6_regs, int);
+}
+
+void
+test_too_many_ints ()
+{
+ def_check_int_passing12(32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, fun_check_int_passing_int12_values, fun_check_int_passing_int12_regs, int);
+}
+
+void
+test_longs_on_stack ()
+{
+ def_check_int_passing6(32, 33, 34, 35, 36, 37, fun_check_int_passing_long6_values, fun_check_int_passing_long6_regs, long);
+}
+
+void
+test_too_many_longs ()
+{
+ def_check_int_passing12(32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, fun_check_int_passing_long12_values, fun_check_int_passing_long12_regs, long);
+}
+
+int
+main (void)
+{
+ test_ints_on_stack ();
+ test_too_many_ints ();
+ test_longs_on_stack ();
+ test_too_many_longs ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/iamcu/test_passing_structs.c b/gcc/testsuite/gcc.target/i386/iamcu/test_passing_structs.c
new file mode 100644
index 0000000..1660a4d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/iamcu/test_passing_structs.c
@@ -0,0 +1,237 @@
+/* This tests passing of structs. */
+
+#include "defines.h"
+#include "args.h"
+#include <complex.h>
+
+struct IntegerRegisters iregbits = { ~0, ~0, ~0, ~0, ~0, ~0 };
+struct IntegerRegisters iregs;
+unsigned int num_iregs;
+
+struct int_struct
+{
+ int i;
+};
+
+struct long_struct
+{
+ long l;
+};
+
+struct longlong2_struct
+{
+ long long ll1, ll2;
+};
+
+struct longlong3_struct
+{
+ long long ll1, ll2, ll3;
+};
+
+/* Check that the struct is passed as the individual members in iregs. */
+void
+check_struct_passing1 (struct int_struct is ATTRIBUTE_UNUSED)
+{
+ check_int_arguments;
+}
+
+void
+check_struct_passing2 (struct long_struct ls ATTRIBUTE_UNUSED)
+{
+ check_int_arguments;
+}
+
+void
+check_struct_passing3 (struct longlong2_struct ls ATTRIBUTE_UNUSED)
+{
+ check_int_arguments;
+}
+
+void
+check_struct_passing4 (struct longlong3_struct ls ATTRIBUTE_UNUSED)
+{
+ /* Check the passing on the stack by comparing the address of the
+ stack elements to the expected place on the stack. */
+ assert ((unsigned long)&ls.ll1 == esp+4);
+ assert ((unsigned long)&ls.ll2 == esp+12);
+ assert ((unsigned long)&ls.ll3 == esp+20);
+}
+
+struct flex1_struct
+{
+ long i;
+ long flex[];
+};
+
+struct flex2_struct
+{
+ long i;
+ long flex[0];
+};
+
+void
+check_struct_passing7 (struct flex1_struct is ATTRIBUTE_UNUSED)
+{
+ check_int_arguments;
+}
+
+void
+check_struct_passing8 (struct flex2_struct is ATTRIBUTE_UNUSED)
+{
+ check_int_arguments;
+}
+
+struct complex1_struct
+{
+ __complex__ float x;
+};
+
+struct complex1a_struct
+{
+ long l;
+ union
+ {
+ float f;
+ int i;
+ } u;
+};
+
+void
+check_struct_passing9 (struct complex1_struct is ATTRIBUTE_UNUSED)
+{
+ check_int_arguments;
+}
+
+struct long3_struct
+{
+ long l1, l2, l3;
+};
+
+void
+check_struct_passing10 (struct long3_struct ls ATTRIBUTE_UNUSED)
+{
+ /* Check the passing on the stack by comparing the address of the
+ stack elements to the expected place on the stack. */
+ assert ((unsigned long)&ls.l1 == esp+4);
+ assert ((unsigned long)&ls.l2 == esp+8);
+ assert ((unsigned long)&ls.l3 == esp+12);
+}
+
+struct char3_struct
+{
+ char c1, c2, c3;
+};
+
+void
+check_struct_passing11 (struct char3_struct is ATTRIBUTE_UNUSED)
+{
+ check_int_arguments;
+}
+
+struct char7_struct
+{
+ char c1, c2, c3, c4, c5, c6, c7;
+};
+
+void
+check_struct_passing12 (struct char7_struct is ATTRIBUTE_UNUSED)
+{
+ check_int_arguments;
+}
+
+static struct flex1_struct f1s = { 60, { } };
+static struct flex2_struct f2s = { 61, { } };
+
+int
+main (void)
+{
+ struct int_struct is = { 48 };
+ struct long_struct ls = { 49 };
+#ifdef CHECK_LARGER_STRUCTS
+ struct longlong2_struct ll2s = { 50, 51 };
+ struct longlong3_struct ll3s = { 52, 53, 54 };
+ struct long3_struct l3s = { 60, 61, 62 };
+#endif
+ struct complex1_struct c1s = { ( -13.4 + 3.5*I ) };
+ union
+ {
+ struct complex1_struct c;
+ struct complex1a_struct u;
+ } c1u;
+ struct char3_struct c3 = { 0x12, 0x34, 0x56 };
+ union
+ {
+ struct char3_struct c;
+ int i;
+ } c3u;
+ struct char7_struct c7 = { 0x12, 0x34, 0x56, 0x78, 0x12, 0x34, 0x56 };
+ union
+ {
+ struct char7_struct c;
+ struct
+ {
+ int i0, i1;
+ } i;
+ } c7u;
+
+ clear_struct_registers;
+ iregs.I0 = is.i;
+ num_iregs = 1;
+ clear_int_hardware_registers;
+ WRAP_CALL (check_struct_passing1)(is);
+
+ clear_struct_registers;
+ iregs.I0 = ls.l;
+ num_iregs = 1;
+ clear_int_hardware_registers;
+ WRAP_CALL (check_struct_passing2)(ls);
+
+#ifdef CHECK_LARGER_STRUCTS
+ clear_struct_registers;
+ num_iregs = 0;
+ clear_int_hardware_registers;
+ WRAP_CALL (check_struct_passing3)(ll2s);
+ WRAP_CALL (check_struct_passing4)(ll3s);
+ WRAP_CALL (check_struct_passing10)(l3s);
+#endif
+
+ clear_struct_registers;
+ iregs.I0 = f1s.i;
+ num_iregs = 1;
+ clear_int_hardware_registers;
+ WRAP_CALL (check_struct_passing7)(f1s);
+
+ clear_struct_registers;
+ iregs.I0 = f2s.i;
+ num_iregs = 1;
+ clear_int_hardware_registers;
+ WRAP_CALL (check_struct_passing8)(f2s);
+
+ clear_struct_registers;
+ c1u.c = c1s;
+ iregs.I0 = c1u.u.l;
+ iregs.I1 = c1u.u.u.i;
+ num_iregs = 2;
+ clear_int_hardware_registers;
+ WRAP_CALL (check_struct_passing9)(c1s);
+
+ clear_struct_registers;
+ c3u.c = c3;
+ iregs.I0 = c3u.i;
+ iregbits.I0 = 0xffffff;
+ num_iregs = 1;
+ clear_int_hardware_registers;
+ WRAP_CALL (check_struct_passing11)(c3);
+
+ clear_struct_registers;
+ c7u.c = c7;
+ iregs.I0 = c7u.i.i0;
+ iregs.I1 = c7u.i.i1;
+ iregbits.I0 = 0xffffffff;
+ iregbits.I1 = 0xffffff;
+ num_iregs = 2;
+ clear_int_hardware_registers;
+ WRAP_CALL (check_struct_passing12)(c7);
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/iamcu/test_passing_structs_and_unions.c b/gcc/testsuite/gcc.target/i386/iamcu/test_passing_structs_and_unions.c
new file mode 100644
index 0000000..ff6354c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/iamcu/test_passing_structs_and_unions.c
@@ -0,0 +1,97 @@
+/* This tests passing of structs. Only integers are tested. */
+
+#include "defines.h"
+#include "args.h"
+
+struct IntegerRegisters iregbits = { ~0, ~0, ~0, ~0, ~0, ~0 };
+struct IntegerRegisters iregs;
+unsigned int num_iregs;
+
+struct int_struct
+{
+ int i;
+};
+
+struct longlong_struct
+{
+ long long ll;
+};
+
+struct long2_struct
+{
+ long long ll1, ll2;
+};
+
+struct long3_struct
+{
+ long l1, l2, l3;
+};
+
+union un1
+{
+ char c;
+ int i;
+};
+
+union un2
+{
+ char c1;
+ long l;
+ char c2;
+};
+
+union un3
+{
+ struct int_struct is;
+ struct longlong_struct ls;
+ union un1 un;
+};
+
+
+void
+check_mixed_passing1 (char c1 ATTRIBUTE_UNUSED, struct int_struct is ATTRIBUTE_UNUSED, char c2 ATTRIBUTE_UNUSED)
+{
+ check_int_arguments;
+}
+
+void
+check_mixed_passing2 (char c1 ATTRIBUTE_UNUSED, struct long3_struct ls ATTRIBUTE_UNUSED, char c2 ATTRIBUTE_UNUSED)
+{
+ check_int_arguments;
+
+ /* Check the passing on the stack by comparing the address of the
+ stack elements to the expected place on the stack. */
+ assert ((unsigned long)&ls.l1 == esp+4);
+ assert ((unsigned long)&ls.l2 == esp+8);
+ assert ((unsigned long)&ls.l3 == esp+12);
+}
+
+int
+main (void)
+{
+ struct int_struct is = { 64 };
+#ifdef CHECK_LARGER_STRUCTS
+ struct long3_struct l3s = { 65, 66, 67 };
+#endif
+
+ clear_struct_registers;
+ iregs.I0 = 8;
+ iregs.I1 = 64;
+ iregs.I2 = 9;
+ num_iregs = 3;
+ clear_int_hardware_registers;
+ WRAP_CALL (check_mixed_passing1)(8, is, 9);
+
+#ifdef CHECK_LARGER_STRUCTS
+ clear_struct_registers;
+ iregs.I0 = 10;
+ iregbits.I0 = 0xff;
+ iregs.I1 = 11;
+ iregbits.I1 = 0xff;
+ num_iregs = 2;
+ clear_int_hardware_registers;
+ WRAP_CALL (check_mixed_passing2)(10, l3s, 11);
+#endif
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/iamcu/test_passing_unions.c b/gcc/testsuite/gcc.target/i386/iamcu/test_passing_unions.c
new file mode 100644
index 0000000..534fc85
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/iamcu/test_passing_unions.c
@@ -0,0 +1,221 @@
+/* This tests passing of structs. */
+
+#include "defines.h"
+#include "args.h"
+
+struct IntegerRegisters iregbits = { ~0, ~0, ~0, ~0, ~0, ~0 };
+struct IntegerRegisters iregs;
+unsigned int num_iregs;
+
+struct int_struct
+{
+ int i;
+};
+
+struct long_struct
+{
+ long l;
+};
+
+union un1
+{
+ char c;
+ int i;
+};
+
+union un2
+{
+ char c1;
+ long l;
+ char c2;
+};
+
+union un3
+{
+ struct int_struct is;
+ struct long_struct ls;
+ union un1 un;
+};
+
+
+void
+check_union_passing1(union un1 u ATTRIBUTE_UNUSED)
+{
+ check_int_arguments;
+}
+
+void
+check_union_passing2(union un2 u1 ATTRIBUTE_UNUSED)
+{
+ check_int_arguments;
+}
+
+void
+check_union_passing3(union un3 u ATTRIBUTE_UNUSED)
+{
+ check_int_arguments;
+}
+
+#define check_union_passing1 WRAP_CALL(check_union_passing1)
+#define check_union_passing2 WRAP_CALL(check_union_passing2)
+#define check_union_passing3 WRAP_CALL(check_union_passing3)
+
+union un4
+{
+ int i;
+ float f;
+};
+
+union un5
+{
+ long long ll;
+ double d;
+};
+
+void
+check_union_passing4(union un4 u1 ATTRIBUTE_UNUSED,
+ union un4 u2 ATTRIBUTE_UNUSED,
+ union un4 u3 ATTRIBUTE_UNUSED,
+ union un4 u4 ATTRIBUTE_UNUSED,
+ union un4 u5 ATTRIBUTE_UNUSED,
+ union un4 u6 ATTRIBUTE_UNUSED,
+ union un4 u7 ATTRIBUTE_UNUSED,
+ union un4 u8 ATTRIBUTE_UNUSED)
+{
+ check_int_arguments;
+}
+
+void
+check_union_passing5(union un5 u ATTRIBUTE_UNUSED)
+{
+ check_int_arguments;
+}
+
+#define check_union_passing4 WRAP_CALL(check_union_passing4)
+#define check_union_passing5 WRAP_CALL(check_union_passing5)
+
+union un6
+{
+ __float128 f128;
+ int i;
+};
+
+
+void
+check_union_passing6(union un6 u ATTRIBUTE_UNUSED)
+{
+ /* Check the passing on the stack by comparing the address of the
+ stack elements to the expected place on the stack. */
+ assert ((unsigned long)&u.f128 == esp+4);
+ assert ((unsigned long)&u.i == esp+4);
+}
+
+#define check_union_passing6 WRAP_CALL(check_union_passing6)
+
+int
+main (void)
+{
+ union un1 u1;
+#ifdef CHECK_LARGER_UNION_PASSING
+ union un2 u2;
+ union un3 u3;
+ struct int_struct is;
+ struct long_struct ls;
+#endif /* CHECK_LARGER_UNION_PASSING */
+ union un4 u4[8];
+ union un5 u5 = { { 48.394, 39.3, -397.9, 3484.9 } };
+ int i;
+ union un6 u6;
+
+ /* Check a union with char, int. */
+ clear_struct_registers;
+ u1.i = 0; /* clear the struct to not have high bits left */
+ u1.c = 32;
+ iregs.I0 = 32;
+ num_iregs = 1;
+ clear_int_hardware_registers;
+ check_union_passing1(u1);
+ u1.i = 0; /* clear the struct to not have high bits left */
+ u1.i = 33;
+ iregs.I0 = 33;
+ num_iregs = 1;
+ clear_int_hardware_registers;
+ check_union_passing1(u1);
+
+ /* Check a union with char, long, char. */
+#ifdef CHECK_LARGER_UNION_PASSING
+ clear_struct_registers;
+ u2.l = 0; /* clear the struct to not have high bits left */
+ u2.c1 = 34;
+ iregs.I0 = 34;
+ num_iregs = 1;
+ clear_int_hardware_registers;
+ check_union_passing2(u2);
+ u2.l = 0; /* clear the struct to not have high bits left */
+ u2.l = 35;
+ iregs.I0 = 35;
+ num_iregs = 1;
+ clear_int_hardware_registers;
+ check_union_passing2(u2);
+ u2.l = 0; /* clear the struct to not have high bits left */
+ u2.c2 = 36;
+ iregs.I0 = 36;
+ num_iregs = 1;
+ clear_int_hardware_registers;
+ check_union_passing2(u2);
+
+ /* check a union containing two structs and a union. */
+ clear_struct_registers;
+ is.i = 37;
+ u3.ls.l = 0; /* clear the struct to not have high bits left */
+ u3.is = is;
+ iregs.I0 = 37;
+ num_iregs = 1;
+ clear_int_hardware_registers;
+ check_union_passing3(u3);
+ ls.l = 38;
+ u3.ls.l = 0; /* clear the struct to not have high bits left */
+ u3.ls = ls;
+ iregs.I0 = 38;
+ num_iregs = 1;
+ clear_int_hardware_registers;
+ check_union_passing3(u3);
+ u1.c = 39;
+ u3.ls.l = 0; /* clear the struct to not have high bits left */
+ u3.un = u1;
+ iregs.I0 = 39;
+ num_iregs = 1;
+ clear_int_hardware_registers;
+ check_union_passing3(u3);
+ u1.i = 40;
+ u3.ls.l = 0; /* clear the struct to not have high bits left */
+ u3.un = u1;
+ iregs.I0 = 40;
+ num_iregs = 1;
+ clear_int_hardware_registers;
+ check_union_passing3(u3);
+#endif /* CHECK_LARGER_UNION_PASSING */
+
+ clear_struct_registers;
+ for (i = 0; i < 8; i++)
+ u4[i].f = 32 + i;
+ iregs.I0 = u4[0].i;
+ iregs.I1 = u4[1].i;
+ iregs.I2 = u4[2].i;
+ num_iregs = 3;
+ clear_int_hardware_registers;
+ check_union_passing4(u4[0], u4[1], u4[2], u4[3],
+ u4[4], u4[5], u4[6], u4[7]);
+
+ clear_struct_registers;
+ iregs.I0 = u5.ll & 0xffffffff;
+ iregs.I1 = (u5.ll >> 32) & 0xffffffff;
+ num_iregs = 2;
+ clear_int_hardware_registers;
+ check_union_passing5(u5);
+
+ u6.i = 2;
+ check_union_passing6(u6);
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/iamcu/test_struct_returning.c b/gcc/testsuite/gcc.target/i386/iamcu/test_struct_returning.c
new file mode 100644
index 0000000..49a6b1f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/iamcu/test_struct_returning.c
@@ -0,0 +1,362 @@
+/* This tests returning of structures. */
+
+#include "defines.h"
+#include "macros.h"
+#include "args.h"
+
+struct IntegerRegisters iregbits = { ~0, ~0, ~0, ~0, ~0, ~0 };
+struct IntegerRegisters iregs;
+unsigned int num_iregs;
+
+int current_test;
+int num_failed = 0;
+
+typedef enum {
+ EAX = 0,
+ EAX_EDX,
+ LONG_LONG,
+ FLOAT,
+ DOUBLE,
+ FLOAT_FLOAT,
+ EAX_FLOAT,
+ FLOAT_EDX,
+ MEM
+} Type;
+
+/* Structures which should be returned in EAX/LONG_LONG/EAX_EDX. */
+#define D(I,MEMBERS,C,B) struct S_ ## I { MEMBERS ; }; Type class_ ## I = C; \
+struct S_ ## I f_ ## I (void) { struct S_ ## I s; iamcu_memset (&s, 0, sizeof(s)); B; return s; }
+
+D(1,char m1, EAX, s.m1=42)
+D(2,short m1, EAX, s.m1=42)
+D(3,int m1, EAX, s.m1=42)
+D(4,char m1[3], EAX, s.m1[0]=42)
+D(5,char m1[4], EAX, s.m1[0]=42)
+D(6,char m1;char m2; char m3, EAX, s.m1=42)
+D(7,char m1;short m2, EAX, s.m1=42)
+
+D(30,long long m1, LONG_LONG, s.m1=0xadadbeefadadbeefLL)
+
+D(50,short m1;int m2, EAX_EDX, s.m1=42; s.m2=43)
+D(51,char m1;int m2, EAX_EDX, s.m1=42; s.m2=43)
+D(52,char m1[5], EAX_EDX, s.m1[0]=42; s.m1[4]=43)
+D(53,char m1[6], EAX_EDX, s.m1[0]=42; s.m1[4]=43)
+D(54,char m1[7], EAX_EDX, s.m1[0]=42; s.m1[4]=43)
+D(55,char m1[8], EAX_EDX, s.m1[0]=42; s.m1[4]=43)
+D(56,char m1;short m2[2], EAX_EDX, s.m1=42; s.m2[1]=43)
+D(57,short m1[4], EAX_EDX, s.m1[0]=42; s.m1[2]=43)
+D(58,int m1[2], EAX_EDX, s.m1[0]=42; s.m1[1]=43)
+D(59,int m1;char m2, EAX_EDX, s.m1=42; s.m2=43)
+D(60,int m1;short m2, EAX_EDX, s.m1=42; s.m2=43)
+D(61,int m1;short m2; char m3, EAX_EDX, s.m1=42; s.m2=43)
+D(62,int m1;char m2; short m3, EAX_EDX, s.m1=42; s.m2=43)
+
+/* Packed members. */
+D(100,short m1[1];int m2 PACKED, EAX_EDX, s.m1[0]=42; s.m2=43)
+D(101,char m1; short m2 PACKED; char m3, EAX_EDX, s.m1=42; s.m3=43)
+
+/* Structures which should be returned in FLOAT/DOUBLE. */
+#undef D
+#define D(I,MEMBERS,C,B) struct S_ ## I { MEMBERS ; }; Type class_ ## I = C; \
+struct S_ ## I f_ ## I (void) { struct S_ ## I s; iamcu_memset (&s, 0, sizeof(s)); B; return s; }
+
+D(200,float f, FLOAT, s.f=42)
+D(201,double d, DOUBLE, s.d=42)
+
+D(300,float m;char m2, FLOAT_EDX, s.m=42; s.m2=43)
+D(301,float m;short m2, FLOAT_EDX, s.m=42; s.m2=43)
+D(302,float m;int m2, FLOAT_EDX, s.m=42; s.m2=43)
+
+D(400,char m1; float m2, EAX_FLOAT, s.m1=42; s.m2=43)
+D(401,short m1; float m2, EAX_FLOAT, s.m1=42; s.m2=43)
+D(402,int m1; float m2, EAX_FLOAT, s.m1=42; s.m2=43)
+
+D(500,float m;float m2, FLOAT_FLOAT, s.m=42; s.m2=43)
+D(501,float f[2], FLOAT, s.f[0]=42; s.f[1]=43)
+
+/* Structures which should be returned in MEM. */
+void *struct_addr;
+#undef D
+#define D(I,MEMBERS) struct S_ ## I { MEMBERS ; }; Type class_ ## I = MEM; \
+struct S_ ## I f_ ## I (void) { union {unsigned char c; struct S_ ## I s;} u; iamcu_memset (&u.s, 0, sizeof(u.s)); u.c = 42; return u.s; }
+
+/* Too large. */
+D(600,char m1[17])
+D(601,short m1[9])
+D(602,int m1[5])
+D(603,long m1[3])
+D(604,short m1[8];char c)
+D(605,char m1[1];int i[4])
+D(606,float m1[5])
+D(607,double m1[3])
+D(608,char m1[1];float f[4])
+D(609,char m1[1];double d[2])
+D(610,__complex long double m1[1])
+
+/* Too large due to padding. */
+D(611,char m1[1]; int i; char c2)
+
+/* Special tests. */
+#undef D
+#define D(I,MEMBERS,B) struct S_ ## I { MEMBERS ; }; Type class_ ## I = MEM; \
+struct S_ ## I f_ ## I (void) { struct S_ ## I s; B; return s; }
+D(700,float f[4], s.f[0] = s.f[1] = s.f[2] = s.f[3] = 42)
+
+void
+check_eax (void)
+{
+ switch (current_test)
+ {
+ case 1:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ eax &= 0xff;
+ break;
+ case 2:
+ eax &= 0xffff;
+ break;
+ case 3:
+ eax &= 0xffff;
+ break;
+ default:
+ abort ();
+ }
+ if (eax != 42)
+ num_failed++;
+}
+
+void
+check_eax_edx (void)
+{
+ unsigned long long ll = eax | ((unsigned long long) edx) << 32;
+ switch (current_test)
+ {
+ case 50:
+ eax &= 0xffff;
+ break;
+ case 52:
+ case 53:
+ case 54:
+ case 55:
+ edx &= 0xff;
+ case 51:
+ eax &= 0xff;
+ break;
+ case 56:
+ eax &= 0xff;
+ edx &= 0xffff;
+ break;
+ case 57:
+ eax &= 0xffff;
+ edx &= 0xffff;
+ break;
+ case 58:
+ break;
+ case 59:
+ case 62:
+ edx &= 0xff;
+ break;
+ case 60:
+ case 61:
+ edx &= 0xffff;
+ break;
+ case 100:
+ eax &= 0xffff;
+ edx = (ll >> 16) & 0xffffffff;
+ break;
+ case 101:
+ edx = (eax >> 24) & 0xff;
+ eax &= 0xff;
+ break;
+ default:
+ abort ();
+ }
+ if (eax != 42 || edx != 43)
+ num_failed++;
+}
+
+void
+check_float_edx (void)
+{
+ union
+ {
+ unsigned long l;
+ float f;
+ } ueax;
+ switch (current_test)
+ {
+ case 300:
+ edx &= 0xff;
+ break;
+ case 301:
+ edx &= 0xffff;
+ break;
+ case 302:
+ edx &= 0xffff;
+ break;
+ default:
+ abort ();
+ }
+ ueax.l = eax;
+ if (ueax.f != 42 || edx != 43)
+ num_failed++;
+}
+
+void
+check_eax_float (void)
+{
+ union
+ {
+ unsigned long l;
+ float f;
+ } uedx;
+ switch (current_test)
+ {
+ case 400:
+ eax &= 0xff;
+ break;
+ case 401:
+ eax &= 0xffff;
+ break;
+ case 402:
+ eax &= 0xffff;
+ break;
+ default:
+ abort ();
+ }
+ uedx.l = edx;
+ if (eax != 42 || uedx.f != 43)
+ num_failed++;
+}
+
+void
+check_float_float (void)
+{
+ union
+ {
+ unsigned long l;
+ float f;
+ } ueax, uedx;
+ switch (current_test)
+ {
+ case 500:
+ case 501:
+ break;
+ default:
+ abort ();
+ }
+ ueax.l = eax;
+ uedx.l = edx;
+ if (ueax.f != 42 || uedx.f != 43)
+ num_failed++;
+}
+
+void
+check_all (Type class, unsigned long size)
+{
+ union
+ {
+ struct
+ {
+ unsigned long eax;
+ unsigned long edx;
+ } eax_edx;
+ unsigned long long ll;
+ float f;
+ double d;
+ } u;
+
+ switch (class)
+ {
+ case EAX:
+ check_eax ();
+ break;
+ case LONG_LONG:
+ if (0xadadbeefL != eax || 0xadadbeefL != edx)
+ num_failed++;
+ break;
+ case EAX_EDX:
+ check_eax_edx ();
+ break;
+ case FLOAT:
+ u.eax_edx.eax = eax;
+ if (u.f != 42)
+ num_failed++;
+ break;
+ case DOUBLE:
+ u.eax_edx.eax = eax;
+ u.eax_edx.edx = edx;
+ if (u.d != 42)
+ num_failed++;
+ break;
+ case FLOAT_EDX:
+ check_float_edx ();
+ break;
+ case FLOAT_FLOAT:
+ check_float_float ();
+ break;
+ case EAX_FLOAT:
+ check_eax_float ();
+ break;
+ case MEM:
+ /* sret_eax contains a slot whose address is given to the f_*
+ functions. The slot may be a temporary one on stack. When
+ this function is called, hopefully this slot hasn't be
+ overriden. */
+ if (sret_eax != eax)
+ num_failed++;
+ else if (current_test < 700)
+ {
+ if (*(unsigned char*)sret_eax != 42
+ || *(unsigned char*)struct_addr != 42)
+ num_failed++;
+ }
+ else
+ {
+ if (*(float *)sret_eax != 42
+ || *(float *)struct_addr != 42)
+ num_failed++;
+ }
+ break;
+ }
+}
+
+#undef D
+#define D(I) { static struct S_ ## I s; current_test = I; struct_addr = (void*)&s; \
+ clear_non_sret_int_registers; \
+ s = WRAP_RET(f_ ## I) (); \
+ check_all(class_ ## I, sizeof(s)); \
+}
+
+int
+main (void)
+{
+ D(1) D(2) D(3) D(4) D(5) D(6) D(7)
+
+ D(30)
+
+ D(50) D(51) D(52) D(53) D(54) D(55) D(56) D(57) D(58) D(59)
+ D(60) D(61) D(62)
+
+ D(100) D(101)
+
+ D(200) D(201)
+
+ D(300) D(301) D(302)
+
+ D(400) D(401) D(402)
+
+ D(500) D(501)
+
+ D(600) D(601) D(602) D(603) D(604) D(605) D(606) D(607) D(608) D(609)
+ D(610) D(611)
+
+ D(700)
+
+ if (num_failed)
+ abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/iamcu/test_varargs.c b/gcc/testsuite/gcc.target/i386/iamcu/test_varargs.c
new file mode 100644
index 0000000..124bef1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/iamcu/test_varargs.c
@@ -0,0 +1,101 @@
+/* Test variable number of arguments passed to functions. */
+
+#include <stdarg.h>
+#include "defines.h"
+
+
+#define ARG_INT 1
+#define ARG_DOUBLE 2
+#define ARG_POINTER 3
+
+union types
+{
+ int ivalue;
+ double dvalue;
+ void *pvalue;
+};
+
+struct arg
+{
+ int type;
+ union types value;
+};
+
+struct arg *arglist;
+
+/* This tests the argumentlist to see if it matches the format string which
+ is printf-like. Nothing will be printed of course. It can handle ints,
+ doubles and void pointers. The given value will be tested against the
+ values given in arglist.
+ This test only assures that the variable argument passing is working.
+ No attempt is made to see if argument passing is done the right way. */
+void
+__attribute__ ((noinline))
+noprintf (char *format, ...)
+{
+ va_list va_arglist;
+ char *c;
+
+ int ivalue;
+ double dvalue;
+ void *pvalue;
+ struct arg *argp = arglist;
+
+ va_start (va_arglist, format);
+ for (c = format; *c; c++)
+ if (*c == '%')
+ {
+ switch (*++c)
+ {
+ case 'd':
+ assert (argp->type == ARG_INT);
+ ivalue = va_arg (va_arglist, int);
+ assert (argp->value.ivalue == ivalue);
+ break;
+ case 'f':
+ assert (argp->type == ARG_DOUBLE);
+ dvalue = va_arg (va_arglist, double);
+ assert (argp->value.dvalue == dvalue);
+ break;
+ case 'p':
+ assert (argp->type == ARG_POINTER);
+ pvalue = va_arg (va_arglist, void *);
+ assert (argp->value.pvalue == pvalue);
+ break;
+ default:
+ abort ();
+ }
+
+ argp++;
+ }
+}
+
+extern void iamcu_noprintf (char *, ...);
+
+int
+main (void)
+{
+#ifdef CHECK_VARARGS
+ float f = 258.0;
+ struct arg al[5];
+
+ al[0].type = ARG_INT;
+ al[0].value.ivalue = 256;
+ al[1].type = ARG_DOUBLE;
+ al[1].value.dvalue = 257.0;
+ al[2].type = ARG_POINTER;
+ al[2].value.pvalue = al;
+ al[3].type = ARG_DOUBLE;
+ al[3].value.dvalue = f;
+ al[4].type = ARG_INT;
+ al[4].value.ivalue = 259;
+
+ arglist = al;
+ noprintf("%d%f%p%f%d", 256, 257.0, al, f, 259);
+
+ iamcu_noprintf ((char *) 0xabadbeef, 256, 257.0,
+ (void *) 0xbbadbeef, f, 259);
+#endif
+
+ return 0;
+}
diff --git a/libdecnumber/configure b/libdecnumber/configure
index 2720f46..964837d 100755
--- a/libdecnumber/configure
+++ b/libdecnumber/configure
@@ -4614,7 +4614,7 @@ else
case $target in
powerpc*-*-linux* | i?86*-*-linux* | x86_64*-*-linux* | s390*-*-linux* | \
- i?86*-*-gnu* | \
+ i?86*-*-elfiamcu | i?86*-*-gnu* | \
i?86*-*-mingw* | x86_64*-*-mingw* | \
i?86*-*-cygwin* | x86_64*-*-cygwin*)
enable_decimal_float=yes
diff --git a/libgcc/config.host b/libgcc/config.host
index 46666df..dd8e356 100644
--- a/libgcc/config.host
+++ b/libgcc/config.host
@@ -562,6 +562,9 @@ x86_64-*-darwin*)
tm_file="$tm_file i386/darwin-lib.h"
extra_parts="$extra_parts crtprec32.o crtprec64.o crtprec80.o crtfastmath.o"
;;
+i[34567]86-*-elfiamcu)
+ tmake_file="$tmake_file i386/t-crtstuff t-softfp-sfdf i386/32/t-softfp i386/32/t-iamcu i386/t-softfp t-softfp t-dfprules"
+ ;;
i[34567]86-*-elf*)
tmake_file="$tmake_file i386/t-crtstuff t-crtstuff-pic t-libgcc-pic"
;;
diff --git a/libgcc/config/i386/32/t-iamcu b/libgcc/config/i386/32/t-iamcu
new file mode 100644
index 0000000..0752bff
--- /dev/null
+++ b/libgcc/config/i386/32/t-iamcu
@@ -0,0 +1,6 @@
+softfp_float_modes += tf
+softfp_extensions += sftf dftf xftf
+softfp_truncations += tfsf tfdf tfxf
+softfp_exclude_libgcc2 := n
+
+HOST_LIBGCC2_CFLAGS += -mlong-double-80
diff --git a/libgcc/configure b/libgcc/configure
index ce66d1d..e22cbcb 100644
--- a/libgcc/configure
+++ b/libgcc/configure
@@ -4436,7 +4436,7 @@ else
case $host in
powerpc*-*-linux* | i?86*-*-linux* | x86_64*-*-linux* | s390*-*-linux* | \
- i?86*-*-gnu* | \
+ i?86*-*-elfiamcu | i?86*-*-gnu* | \
i?86*-*-mingw* | x86_64*-*-mingw* | \
i?86*-*-cygwin* | x86_64*-*-cygwin*)
enable_decimal_float=yes
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [i386, PATCH, 1/3] IA MCU psABI support: GCC changes.
2015-06-22 13:52 [i386, PATCH] Support new psABI for IA MCU Kirill Yukhin
@ 2015-06-22 14:38 ` Kirill Yukhin
2015-06-26 10:40 ` Uros Bizjak
2015-06-22 15:41 ` [i386, PATCH, 2/3] IA MCU psABI support: changes to libraries Kirill Yukhin
2015-06-23 9:46 ` [i386, PATCH, 3/3] IA MCU psABI support: testsuite Kirill Yukhin
2 siblings, 1 reply; 7+ messages in thread
From: Kirill Yukhin @ 2015-06-22 14:38 UTC (permalink / raw)
To: Uros Bizjak, Joseph S. Myers; +Cc: H.J. Lu, GCC Patches
Hello,
This patch introduces basic support into GCC.
Bootstrapped and regtested.
/
* configure.ac (ospace_frag): Enable for i?86*-*-elfiamcu
target.
* configure: Regenerate.
gcc/
* config.gcc: Support i[34567]86-*-elfiamcu target.
* config/i386/iamcu.h: New.
* config/i386/i386.opt: Add -miamcu.
* doc/invoke.texi: Document -miamcu.
* common/config/i386/i386-common.c (ix86_handle_option): Turn
off x87/MMX/SSE/AVX codegen for -miamcu.
* config/i386/i386-c.c (ix86_target_macros_internal): Define
__iamcu/__iamcu__ for -miamcu.
* config/i386/i386.h (PREFERRED_STACK_BOUNDARY_DEFAULT): Set
to MIN_STACK_BOUNDARY if TARGET_IAMCU is true.
(BIGGEST_ALIGNMENT): Set to 32 if TARGET_IAMCU is true.
* config/i386/i386.c (ix86_option_override_internal):
- Ignore and warn -mregparm for Intel MCU. Turn
on -mregparm=3 for Intel MCU by default.
- Default long double to 64-bit for Intel MCU.
- Turn on -freg-struct-return for Intel MCU.
- Issue an error when -miamcu is used in 64-bit or x32 mode,
or if x87, MMX, SSE or AVX is turned on.
(function_arg_advance_32): Pass value whose
size is no larger than 8 bytes in registers for Intel MCU.
(function_arg_32): Likewise.
(ix86_return_in_memory): Return value whose size is no larger
than 8 bytes in registers for Intel MCU.
(iamcu_alignment): New function.
(ix86_data_alignment): Call iamcu_alignment if TARGET_IAMCU is
true.
(ix86_local_alignment): Don't increase
alignment for Intel MCU.
(x86_field_alignment): Return iamcu_alignment if TARGET_IAMCU is
true.
Is it OK for trunk?
--
Thanks, K
diff --git a/configure b/configure
index bced9de..82e45f3 100755
--- a/configure
+++ b/configure
@@ -6914,7 +6914,7 @@ case "${enable_target_optspace}:${target}" in
:d30v-*)
ospace_frag="config/mt-d30v"
;;
- :m32r-* | :d10v-* | :fr30-*)
+ :m32r-* | :d10v-* | :fr30-* | :i?86*-*-elfiamcu)
ospace_frag="config/mt-ospace"
;;
no:* | :*)
diff --git a/configure.ac b/configure.ac
index 7c06e6b..dc77a1b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2560,7 +2560,7 @@ case "${enable_target_optspace}:${target}" in
:d30v-*)
ospace_frag="config/mt-d30v"
;;
- :m32r-* | :d10v-* | :fr30-*)
+ :m32r-* | :d10v-* | :fr30-* | :i?86*-*-elfiamcu)
ospace_frag="config/mt-ospace"
;;
no:* | :*)
diff --git a/gcc/common/config/i386/i386-common.c b/gcc/common/config/i386/i386-common.c
index 0f8c3e1..79b2472 100644
--- a/gcc/common/config/i386/i386-common.c
+++ b/gcc/common/config/i386/i386-common.c
@@ -223,7 +223,7 @@ along with GCC; see the file COPYING3. If not see
bool
ix86_handle_option (struct gcc_options *opts,
- struct gcc_options *opts_set ATTRIBUTE_UNUSED,
+ struct gcc_options *opts_set,
const struct cl_decoded_option *decoded,
location_t loc)
{
@@ -232,6 +232,20 @@ ix86_handle_option (struct gcc_options *opts,
switch (code)
{
+ case OPT_miamcu:
+ if (value)
+ {
+ /* Turn off x87/MMX/SSE/AVX codegen for -miamcu. */
+ opts->x_target_flags &= ~MASK_80387;
+ opts_set->x_target_flags |= MASK_80387;
+ opts->x_ix86_isa_flags &= ~(OPTION_MASK_ISA_MMX_UNSET
+ | OPTION_MASK_ISA_SSE_UNSET);
+ opts->x_ix86_isa_flags_explicit |= (OPTION_MASK_ISA_MMX_UNSET
+ | OPTION_MASK_ISA_SSE_UNSET);
+
+ }
+ return true;
+
case OPT_mmmx:
if (value)
{
diff --git a/gcc/config.gcc b/gcc/config.gcc
index 805638d..2b3af82 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -1389,6 +1389,9 @@ x86_64-*-darwin*)
tmake_file="${tmake_file} ${cpu_type}/t-darwin64 t-slibgcc"
tm_file="${tm_file} ${cpu_type}/darwin64.h"
;;
+i[34567]86-*-elfiamcu)
+ tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h newlib-stdint.h i386/iamcu.h"
+ ;;
i[34567]86-*-elf*)
tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h newlib-stdint.h i386/i386elf.h"
;;
diff --git a/gcc/config/i386/i386-c.c b/gcc/config/i386/i386-c.c
index 0228f4b..66f7e37 100644
--- a/gcc/config/i386/i386-c.c
+++ b/gcc/config/i386/i386-c.c
@@ -426,6 +426,11 @@ ix86_target_macros_internal (HOST_WIDE_INT isa_flag,
def_or_undef (parse_in, "__CLWB__");
if (isa_flag & OPTION_MASK_ISA_MWAITX)
def_or_undef (parse_in, "__MWAITX__");
+ if (TARGET_IAMCU)
+ {
+ def_or_undef (parse_in, "__iamcu");
+ def_or_undef (parse_in, "__iamcu__");
+ }
}
\f
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 24fccfc..26ffa67 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -3433,6 +3433,10 @@ ix86_option_override_internal (bool main_args_p,
|| TARGET_16BIT_P (opts->x_ix86_isa_flags))
opts->x_ix86_isa_flags &= ~OPTION_MASK_ABI_X32;
#endif
+ if (TARGET_64BIT_P (opts->x_ix86_isa_flags)
+ && TARGET_IAMCU_P (opts->x_target_flags))
+ sorry ("Intel MCU psABI isn%'t supported in %s mode",
+ TARGET_X32_P (opts->x_ix86_isa_flags) ? "x32" : "64-bit");
}
#endif
@@ -3817,6 +3821,20 @@ ix86_option_override_internal (bool main_args_p,
if (TARGET_X32 && (ix86_isa_flags & OPTION_MASK_ISA_MPX))
error ("Intel MPX does not support x32");
+ if (TARGET_IAMCU_P (opts->x_target_flags))
+ {
+ /* Verify that x87/MMX/SSE/AVX is off for -miamcu. */
+ if (TARGET_80387_P (opts->x_target_flags))
+ sorry ("X87 FPU isn%'t supported in Intel MCU psABI");
+ else if ((opts->x_ix86_isa_flags & (OPTION_MASK_ISA_MMX
+ | OPTION_MASK_ISA_SSE
+ | OPTION_MASK_ISA_AVX)))
+ sorry ("%s isn%'t supported in Intel MCU psABI",
+ TARGET_MMX_P (opts->x_ix86_isa_flags)
+ ? "MMX"
+ : TARGET_SSE_P (opts->x_ix86_isa_flags) ? "SSE" : "AVX");
+ }
+
if (!strcmp (opts->x_ix86_arch_string, "generic"))
error ("generic CPU can be used only for %stune=%s %s",
prefix, suffix, sw);
@@ -3904,7 +3922,16 @@ ix86_option_override_internal (bool main_args_p,
if (opts->x_flag_asynchronous_unwind_tables == 2)
opts->x_flag_asynchronous_unwind_tables = !USE_IX86_FRAME_POINTER;
if (opts->x_flag_pcc_struct_return == 2)
- opts->x_flag_pcc_struct_return = DEFAULT_PCC_STRUCT_RETURN;
+ {
+ /* Intel MCU psABI specifies that -freg-struct-return should
+ be on. Instead of setting DEFAULT_PCC_STRUCT_RETURN to 1,
+ we check -miamcu so that -freg-struct-return is always
+ turned on if -miamcu is used. */
+ if (TARGET_IAMCU_P (opts->x_target_flags))
+ opts->x_flag_pcc_struct_return = 0;
+ else
+ opts->x_flag_pcc_struct_return = DEFAULT_PCC_STRUCT_RETURN;
+ }
}
ix86_tune_cost = processor_target_table[ix86_tune].cost;
@@ -3923,6 +3950,8 @@ ix86_option_override_internal (bool main_args_p,
{
if (TARGET_64BIT_P (opts->x_ix86_isa_flags))
warning (0, "-mregparm is ignored in 64-bit mode");
+ else if (TARGET_IAMCU_P (opts->x_target_flags))
+ warning (0, "-mregparm is ignored for Intel MCU psABI");
if (opts->x_ix86_regparm > REGPARM_MAX)
{
error ("-mregparm=%d is not between 0 and %d",
@@ -3930,7 +3959,8 @@ ix86_option_override_internal (bool main_args_p,
opts->x_ix86_regparm = 0;
}
}
- if (TARGET_64BIT_P (opts->x_ix86_isa_flags))
+ if (TARGET_IAMCU_P (opts->x_target_flags)
+ || TARGET_64BIT_P (opts->x_ix86_isa_flags))
opts->x_ix86_regparm = REGPARM_MAX;
/* Default align_* from the processor table. */
@@ -4334,8 +4364,9 @@ ix86_option_override_internal (bool main_args_p,
opts->x_recip_mask &= ~(RECIP_MASK_ALL & ~opts->x_recip_mask_explicit);
/* Default long double to 64-bit for 32-bit Bionic and to __float128
- for 64-bit Bionic. */
- if (TARGET_HAS_BIONIC
+ for 64-bit Bionic. Also default long double to 64-bit for Intel
+ MCU psABI. */
+ if ((TARGET_HAS_BIONIC || TARGET_IAMCU)
&& !(opts_set->x_target_flags
& (MASK_LONG_DOUBLE_64 | MASK_LONG_DOUBLE_128)))
opts->x_target_flags |= (TARGET_64BIT
@@ -7455,6 +7486,15 @@ function_arg_advance_32 (CUMULATIVE_ARGS *cum, machine_mode mode,
int res = 0;
bool error_p = NULL;
+ if (TARGET_IAMCU)
+ {
+ /* Intel MCU psABI passes scalars and aggregates no larger than 8
+ bytes in registers. */
+ if (bytes <= 8)
+ goto pass_in_reg;
+ return res;
+ }
+
switch (mode)
{
default:
@@ -7469,6 +7509,7 @@ function_arg_advance_32 (CUMULATIVE_ARGS *cum, machine_mode mode,
case SImode:
case HImode:
case QImode:
+pass_in_reg:
cum->words += words;
cum->nregs -= words;
cum->regno += words;
@@ -7702,6 +7743,15 @@ function_arg_32 (CUMULATIVE_ARGS *cum, machine_mode mode,
if (mode == VOIDmode)
return constm1_rtx;
+ if (TARGET_IAMCU)
+ {
+ /* Intel MCU psABI passes scalars and aggregates no larger than 8
+ bytes in registers. */
+ if (bytes <= 8)
+ goto pass_in_reg;
+ return NULL_RTX;
+ }
+
switch (mode)
{
default:
@@ -7715,6 +7765,7 @@ function_arg_32 (CUMULATIVE_ARGS *cum, machine_mode mode,
case SImode:
case HImode:
case QImode:
+pass_in_reg:
if (words <= cum->nregs)
{
int regno = cum->regno;
@@ -8561,11 +8612,16 @@ ix86_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
}
else
{
+ size = int_size_in_bytes (type);
+
+ /* Intel MCU psABI returns scalars and aggregates no larger than 8
+ bytes in registers. */
+ if (TARGET_IAMCU)
+ return size > 8;
+
if (mode == BLKmode)
return true;
- size = int_size_in_bytes (type);
-
if (MS_AGGREGATE_RETURN && AGGREGATE_TYPE_P (type) && size <= 8)
return false;
@@ -27341,6 +27397,34 @@ ix86_constant_alignment (tree exp, int align)
return align;
}
+/* Compute the alignment for a variable for Intel MCU psABI. TYPE is
+ the data type, and ALIGN is the alignment that the object would
+ ordinarily have. */
+
+static int
+iamcu_alignment (tree type, int align)
+{
+ enum machine_mode mode;
+
+ if (align < 32 || TYPE_USER_ALIGN (type))
+ return align;
+
+ /* Intel MCU psABI specifies scalar types > 4 bytes aligned to 4
+ bytes. */
+ mode = TYPE_MODE (strip_array_types (type));
+ switch (GET_MODE_CLASS (mode))
+ {
+ case MODE_INT:
+ case MODE_COMPLEX_INT:
+ case MODE_COMPLEX_FLOAT:
+ case MODE_FLOAT:
+ case MODE_DECIMAL_FLOAT:
+ return 32;
+ default:
+ return align;
+ }
+}
+
/* Compute the alignment for a static variable.
TYPE is the data type, and ALIGN is the alignment that
the object would ordinarily have. The value of this function is used
@@ -27375,6 +27459,9 @@ ix86_data_alignment (tree type, int align, bool opt)
case ix86_align_data_type_cacheline: break;
}
+ if (TARGET_IAMCU)
+ align = iamcu_alignment (type, align);
+
if (opt
&& AGGREGATE_TYPE_P (type)
&& TYPE_SIZE (type)
@@ -27484,6 +27571,10 @@ ix86_local_alignment (tree exp, machine_mode mode,
return align;
}
+ /* Don't increase alignment for Intel MCU psABI. */
+ if (TARGET_IAMCU)
+ return align;
+
/* x86-64 ABI requires arrays greater than 16 bytes to be aligned
to 16byte boundary. Exact wording is:
@@ -43182,6 +43273,8 @@ x86_field_alignment (tree field, int computed)
if (TARGET_64BIT || TARGET_ALIGN_DOUBLE)
return computed;
+ if (TARGET_IAMCU)
+ return iamcu_alignment (type, computed);
mode = TYPE_MODE (strip_array_types (type));
if (mode == DFmode || mode == DCmode
|| GET_MODE_CLASS (mode) == MODE_INT
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index e0af36c..d710b3d 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -756,7 +756,8 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);
/* It should be MIN_STACK_BOUNDARY. But we set it to 128 bits for
both 32bit and 64bit, to support codes that need 128 bit stack
alignment for SSE instructions, but can't realign the stack. */
-#define PREFERRED_STACK_BOUNDARY_DEFAULT 128
+#define PREFERRED_STACK_BOUNDARY_DEFAULT \
+ (TARGET_IAMCU ? MIN_STACK_BOUNDARY : 128)
/* 1 if -mstackrealign should be turned on by default. It will
generate an alternate prologue and epilogue that realigns the
@@ -803,7 +804,7 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);
TARGET_ABSOLUTE_BIGGEST_ALIGNMENT. */
#define BIGGEST_ALIGNMENT \
- (TARGET_AVX512F ? 512 : (TARGET_AVX ? 256 : 128))
+ (TARGET_AVX512F ? 512 : (TARGET_AVX ? 256 : (TARGET_IAMCU ? 32 : 128)))
/* Maximum stack alignment. */
#define MAX_STACK_ALIGNMENT MAX_OFILE_ALIGNMENT
diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt
index dd46e26..042f3c1 100644
--- a/gcc/config/i386/i386.opt
+++ b/gcc/config/i386/i386.opt
@@ -514,6 +514,10 @@ Clear all tune features
mdump-tune-features
Target RejectNegative Var(ix86_dump_tunes) Init(0)
+miamcu
+Target Report Mask(IAMCU)
+Generate code that conforms to Intel MCU psABI
+
mabi=
Target RejectNegative Joined Var(ix86_abi) Enum(calling_abi) Init(SYSV_ABI)
Generate code that conforms to the given ABI
diff --git a/gcc/config/i386/iamcu.h b/gcc/config/i386/iamcu.h
new file mode 100644
index 0000000..a1c83f4
--- /dev/null
+++ b/gcc/config/i386/iamcu.h
@@ -0,0 +1,42 @@
+/* Definitions of target machine for Intel MCU psABI.
+ Copyright (C) 2015 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+<http://www.gnu.org/licenses/>. */
+
+/* Intel MCU has no 80387. Default to Intel MCU psABI. */
+#undef TARGET_SUBTARGET_DEFAULT
+#define TARGET_SUBTARGET_DEFAULT MASK_IAMCU
+
+#undef ASM_SPEC
+#define ASM_SPEC "--32 -march=iamcu"
+
+#undef LINK_SPEC
+#define LINK_SPEC "-m elf_iamcu"
+
+#undef ENDFILE_SPEC
+#define ENDFILE_SPEC ""
+
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC "crt0.o%s"
+
+#undef LIB_SPEC
+#define LIB_SPEC "--start-group -lc -lgloss --end-group"
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index b99ab1c..e4f816f 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -1096,7 +1096,7 @@ See RS/6000 and PowerPC Options.
-mpc32 -mpc64 -mpc80 -mstackrealign @gol
-momit-leaf-frame-pointer -mno-red-zone -mno-tls-direct-seg-refs @gol
-mcmodel=@var{code-model} -mabi=@var{name} -maddress-mode=@var{mode} @gol
--m32 -m64 -mx32 -m16 -mlarge-data-threshold=@var{num} @gol
+-m32 -m64 -mx32 -m16 -miamcu -mlarge-data-threshold=@var{num} @gol
-msse2avx -mfentry -mrecord-mcount -mnop-mcount -m8bit-idiv @gol
-mavx256-split-unaligned-load -mavx256-split-unaligned-store @gol
-malign-data=@var{type} -mstack-protector-guard=@var{guard}}
@@ -23267,10 +23267,12 @@ on x86-64 processors in 64-bit environments.
@itemx -m64
@itemx -mx32
@itemx -m16
+@itemx -miamcu
@opindex m32
@opindex m64
@opindex mx32
@opindex m16
+@opindex miamcu
Generate code for a 16-bit, 32-bit or 64-bit environment.
The @option{-m32} option sets @code{int}, @code{long}, and pointer types
to 32 bits, and
@@ -23289,6 +23291,9 @@ The @option{-m16} option is the same as @option{-m32}, except for that
it outputs the @code{.code16gcc} assembly directive at the beginning of
the assembly output so that the binary can run in 16-bit mode.
+The @option{-miamcu} option generates code which conforms to Intel MCU
+psABI. It requires the @option{-m32} option to be turned on.
+
@item -mno-red-zone
@opindex mno-red-zone
Do not use a so-called ``red zone'' for x86-64 code. The red zone is mandated
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [i386, PATCH, 2/3] IA MCU psABI support: changes to libraries.
2015-06-22 13:52 [i386, PATCH] Support new psABI for IA MCU Kirill Yukhin
2015-06-22 14:38 ` [i386, PATCH, 1/3] IA MCU psABI support: GCC changes Kirill Yukhin
@ 2015-06-22 15:41 ` Kirill Yukhin
2015-06-26 10:54 ` Uros Bizjak
2015-06-23 9:46 ` [i386, PATCH, 3/3] IA MCU psABI support: testsuite Kirill Yukhin
2 siblings, 1 reply; 7+ messages in thread
From: Kirill Yukhin @ 2015-06-22 15:41 UTC (permalink / raw)
To: Uros Bizjak, Joseph S. Myers; +Cc: H.J. Lu, GCC Patches
Hello,
Patch in the bottom adds support of IA MCU psABI to libgcc
(enables soft-fp) and libdecnumber (enables it for IA MCU).
Bootstrapped and regtested on top of [1/3] patch.
config/
* dfp.m4 (enable_decimal_float): Also set to yes for
i?86*-*-elfiamcu target.
gcc/
* configure: Regenerated.
libdecnumber/
* configure: Regenerated.
libgcc/
* config.host: Support i[34567]86-*-elfiamcu target.
* config/i386/32/t-iamcu: New file.
* configure: Regenerated.
Is it OK for trunk?
--
Thanks, K
diff --git a/config/dfp.m4 b/config/dfp.m4
index 48683f0..5b29089 100644
--- a/config/dfp.m4
+++ b/config/dfp.m4
@@ -21,7 +21,7 @@ Valid choices are 'yes', 'bid', 'dpd', and 'no'.]) ;;
[
case $1 in
powerpc*-*-linux* | i?86*-*-linux* | x86_64*-*-linux* | s390*-*-linux* | \
- i?86*-*-gnu* | \
+ i?86*-*-elfiamcu | i?86*-*-gnu* | \
i?86*-*-mingw* | x86_64*-*-mingw* | \
i?86*-*-cygwin* | x86_64*-*-cygwin*)
enable_decimal_float=yes
diff --git a/gcc/configure b/gcc/configure
index b26a86f..64eeac6 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -7317,7 +7317,7 @@ else
case $target in
powerpc*-*-linux* | i?86*-*-linux* | x86_64*-*-linux* | s390*-*-linux* | \
- i?86*-*-gnu* | \
+ i?86*-*-elfiamcu | i?86*-*-gnu* | \
i?86*-*-mingw* | x86_64*-*-mingw* | \
i?86*-*-cygwin* | x86_64*-*-cygwin*)
enable_decimal_float=yes
diff --git a/libdecnumber/configure b/libdecnumber/configure
index 2720f46..964837d 100755
--- a/libdecnumber/configure
+++ b/libdecnumber/configure
@@ -4614,7 +4614,7 @@ else
case $target in
powerpc*-*-linux* | i?86*-*-linux* | x86_64*-*-linux* | s390*-*-linux* | \
- i?86*-*-gnu* | \
+ i?86*-*-elfiamcu | i?86*-*-gnu* | \
i?86*-*-mingw* | x86_64*-*-mingw* | \
i?86*-*-cygwin* | x86_64*-*-cygwin*)
enable_decimal_float=yes
diff --git a/libgcc/config.host b/libgcc/config.host
index 46666df..dd8e356 100644
--- a/libgcc/config.host
+++ b/libgcc/config.host
@@ -562,6 +562,9 @@ x86_64-*-darwin*)
tm_file="$tm_file i386/darwin-lib.h"
extra_parts="$extra_parts crtprec32.o crtprec64.o crtprec80.o crtfastmath.o"
;;
+i[34567]86-*-elfiamcu)
+ tmake_file="$tmake_file i386/t-crtstuff t-softfp-sfdf i386/32/t-softfp i386/32/t-iamcu i386/t-softfp t-softfp t-dfprules"
+ ;;
i[34567]86-*-elf*)
tmake_file="$tmake_file i386/t-crtstuff t-crtstuff-pic t-libgcc-pic"
;;
diff --git a/libgcc/config/i386/32/t-iamcu b/libgcc/config/i386/32/t-iamcu
new file mode 100644
index 0000000..0752bff
--- /dev/null
+++ b/libgcc/config/i386/32/t-iamcu
@@ -0,0 +1,6 @@
+softfp_float_modes += tf
+softfp_extensions += sftf dftf xftf
+softfp_truncations += tfsf tfdf tfxf
+softfp_exclude_libgcc2 := n
+
+HOST_LIBGCC2_CFLAGS += -mlong-double-80
diff --git a/libgcc/configure b/libgcc/configure
index ce66d1d..e22cbcb 100644
--- a/libgcc/configure
+++ b/libgcc/configure
@@ -4436,7 +4436,7 @@ else
case $host in
powerpc*-*-linux* | i?86*-*-linux* | x86_64*-*-linux* | s390*-*-linux* | \
- i?86*-*-gnu* | \
+ i?86*-*-elfiamcu | i?86*-*-gnu* | \
i?86*-*-mingw* | x86_64*-*-mingw* | \
i?86*-*-cygwin* | x86_64*-*-cygwin*)
enable_decimal_float=yes
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [i386, PATCH, 3/3] IA MCU psABI support: testsuite.
2015-06-22 13:52 [i386, PATCH] Support new psABI for IA MCU Kirill Yukhin
2015-06-22 14:38 ` [i386, PATCH, 1/3] IA MCU psABI support: GCC changes Kirill Yukhin
2015-06-22 15:41 ` [i386, PATCH, 2/3] IA MCU psABI support: changes to libraries Kirill Yukhin
@ 2015-06-23 9:46 ` Kirill Yukhin
2015-06-26 11:03 ` Uros Bizjak
2 siblings, 1 reply; 7+ messages in thread
From: Kirill Yukhin @ 2015-06-23 9:46 UTC (permalink / raw)
To: Uros Bizjak, Joseph S. Myers; +Cc: H.J. Lu, GCC Patches
Hello,
This patch introduces tests for new psABI.
gcc/testsuite/
* gcc.target/i386/iamcu/abi-iamcu.exp: New file.
* gcc.target/i386/iamcu/args.h: Likewise.
* gcc.target/i386/iamcu/asm-support.S: Likewise.
* gcc.target/i386/iamcu/defines.h: Likewise.
* gcc.target/i386/iamcu/macros.h: Likewise.
* gcc.target/i386/iamcu/test_3_element_struct_and_unions.c: Likewise.
* gcc.target/i386/iamcu/test_basic_64bit_returning.c: Likewise.
* gcc.target/i386/iamcu/test_basic_alignment.c: Likewise.
* gcc.target/i386/iamcu/test_basic_array_size_and_align.c: Likewise.
* gcc.target/i386/iamcu/test_basic_returning.c: Likewise.
* gcc.target/i386/iamcu/test_basic_sizes.c: Likewise.
* gcc.target/i386/iamcu/test_basic_struct_size_and_align.c: Likewise.
* gcc.target/i386/iamcu/test_basic_union_size_and_align.c: Likewise.
* gcc.target/i386/iamcu/test_bitfields.c: Likewise.
* gcc.target/i386/iamcu/test_complex_returning.c: Likewise.
* gcc.target/i386/iamcu/test_passing_floats.c: Likewise.
* gcc.target/i386/iamcu/test_passing_integers.c: Likewise.
* gcc.target/i386/iamcu/test_passing_structs.c: Likewise.
* gcc.target/i386/iamcu/test_passing_structs_and_unions.c: Likewise.
* gcc.target/i386/iamcu/test_passing_unions.c: Likewise.
* gcc.target/i386/iamcu/test_struct_returning.c: Likewise.
* gcc.target/i386/iamcu/test_varargs.c: Likewise.
New tests pass, when run on for 32b target.
Is it ok for trunk?
--
Thanks, K
diff --git a/gcc/testsuite/gcc.target/i386/iamcu/abi-iamcu.exp b/gcc/testsuite/gcc.target/i386/iamcu/abi-iamcu.exp
new file mode 100644
index 0000000..b5b3261
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/iamcu/abi-iamcu.exp
@@ -0,0 +1,42 @@
+# Copyright (C) 2015 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
+# The Intel MCU psABI testsuite needs one additional assembler file for
+# most testcases. For simplicity we will just link it into each test.
+
+load_lib c-torture.exp
+load_lib target-supports.exp
+load_lib torture-options.exp
+
+if { (![istarget x86_64-*-linux*] && ![istarget i?86-*-linux*])
+ || ![is-effective-target ia32] } then {
+ return
+}
+
+
+torture-init
+set-torture-options $C_TORTURE_OPTIONS
+set additional_flags "-miamcu -W -Wall -Wno-abi"
+
+foreach src [lsort [glob -nocomplain $srcdir/$subdir/test_*.c]] {
+ if {[runtest_file_p $runtests $src]} {
+ c-torture-execute [list $src \
+ $srcdir/$subdir/asm-support.S] \
+ $additional_flags
+ }
+}
+
+torture-finish
diff --git a/gcc/testsuite/gcc.target/i386/iamcu/args.h b/gcc/testsuite/gcc.target/i386/iamcu/args.h
new file mode 100644
index 0000000..f8abde4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/iamcu/args.h
@@ -0,0 +1,77 @@
+#ifndef INCLUDED_ARGS_H
+#define INCLUDED_ARGS_H
+
+/* This defines the calling sequences for integers and floats. */
+#define I0 eax
+#define I1 edx
+#define I2 ecx
+
+typedef unsigned int size_t;
+
+extern void (*callthis)(void);
+extern unsigned long eax,ebx,ecx,edx,esi,edi,esp,ebp;
+extern unsigned long sret_eax;
+extern volatile unsigned long volatile_var;
+extern void snapshot (void);
+extern void snapshot_ret (void);
+extern void *iamcu_memset (void *, int, size_t);
+#define WRAP_CALL(N) \
+ (callthis = (void (*)()) (N), (typeof (&N)) snapshot)
+#define WRAP_RET(N) \
+ (callthis = (void (*)()) (N), (typeof (&N)) snapshot_ret)
+
+/* Clear all scratch integer registers. */
+#define clear_int_hardware_registers \
+ asm __volatile__ ("xor %%eax, %%eax\n\t" \
+ "xor %%edx, %%edx\n\t" \
+ "xor %%ecx, %%ecx\n\t" \
+ ::: "eax", "edx", "ecx");
+
+/* Clear all scratch integer registers, excluding the one used to return
+ aggregate. */
+#define clear_non_sret_int_hardware_registers \
+ asm __volatile__ ("xor %%edx, %%ebx\n\t" \
+ "xor %%ecx, %%ecx\n\t" \
+ ::: "edx", "ecx");
+
+/* This is the list of registers available for passing arguments. Not all of
+ these are used or even really available. */
+struct IntegerRegisters
+{
+ unsigned long eax, ebx, ecx, edx, esi, edi;
+};
+
+/* Implemented in scalarargs.c */
+extern struct IntegerRegisters iregs, iregbits;
+extern unsigned int num_iregs;
+
+#define check_int_arguments do { \
+ assert (num_iregs <= 0 || (iregs.I0 & iregbits.I0) == (I0 & iregbits.I0)); \
+ assert (num_iregs <= 1 || (iregs.I1 & iregbits.I1) == (I1 & iregbits.I1)); \
+ assert (num_iregs <= 2 || (iregs.I2 & iregbits.I2) == (I2 & iregbits.I2)); \
+ } while (0)
+
+#define check_char_arguments check_int_arguments
+#define check_short_arguments check_int_arguments
+#define check_long_arguments check_int_arguments
+#define check_float_arguments check_int_arguments
+#define check_double_arguments check_int_arguments
+#define check_ldouble_arguments check_int_arguments
+
+/* Clear register struct. */
+#define clear_struct_registers \
+ eax = edx = ecx = 0; \
+ iamcu_memset (&iregs, 0, sizeof iregs);
+
+/* Clear both hardware and register structs for integers. */
+#define clear_int_registers \
+ clear_struct_registers \
+ clear_int_hardware_registers
+
+/* Clear both hardware and register structs for integers, excluding the
+ one used to return aggregate. */
+#define clear_non_sret_int_registers \
+ clear_struct_registers \
+ clear_non_sret_int_hardware_registers
+
+#endif /* INCLUDED_ARGS_H */
diff --git a/gcc/testsuite/gcc.target/i386/iamcu/asm-support.S b/gcc/testsuite/gcc.target/i386/iamcu/asm-support.S
new file mode 100644
index 0000000..b4a4a14
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/iamcu/asm-support.S
@@ -0,0 +1,302 @@
+ .comm callthis,4,4
+ .comm eax,4,4
+ .comm ebx,4,4
+ .comm ecx,4,4
+ .comm edx,4,4
+ .comm esi,4,4
+ .comm edi,4,4
+ .comm esp,4,4
+ .comm ebp,4,4
+ .comm sret_eax,4,4
+ .comm volatile_var,4,4
+
+ .text
+ .p2align 4,,15
+.globl snapshot
+ .type snapshot, @function
+snapshot:
+ movl %eax, eax
+ movl %ebx, ebx
+ movl %ecx, ecx
+ movl %edx, edx
+ movl %edi, edi
+ movl %esi, esi
+ movl %ebp, ebp
+ movl %esp, esp
+ jmp *callthis
+ .size snapshot, .-snapshot
+
+ .p2align 4,,15
+.globl snapshot_ret
+ .type snapshot_ret, @function
+snapshot_ret:
+ movl %eax, sret_eax
+ call *callthis
+ movl %eax, eax
+ movl %edx, edx
+ ret
+ .size snapshot_ret, .-snapshot_ret
+
+ .p2align 4,,15
+ .globl __nesf2
+ .type __nesf2, @function
+__nesf2:
+ .cfi_startproc
+ subl $4, %esp
+ .cfi_def_cfa_offset 8
+ movl %eax, (%esp)
+ movl $1, %eax
+ fildl (%esp)
+ movl %edx, (%esp)
+ xorl %edx, %edx
+ fildl (%esp)
+ fucomip %st(1), %st
+ fstp %st(0)
+ setp %dl
+ cmove %edx, %eax
+ addl $4, %esp
+ .cfi_def_cfa_offset 4
+ ret
+ .cfi_endproc
+ .size __nesf2, .-__nesf2
+
+ .p2align 4,,15
+ .globl __nedf2
+ .type __nedf2, @function
+__nedf2:
+ .cfi_startproc
+ pushl %ebp
+ .cfi_def_cfa_offset 8
+ .cfi_offset 5, -8
+ movl %esp, %ebp
+ .cfi_def_cfa_register 5
+ andl $-8, %esp
+ subl $8, %esp
+ movl %eax, (%esp)
+ movl $1, %eax
+ movl %edx, 4(%esp)
+ xorl %edx, %edx
+ fildq (%esp)
+ fildq 8(%ebp)
+ fucomip %st(1), %st
+ fstp %st(0)
+ setp %dl
+ cmove %edx, %eax
+ leave
+ .cfi_restore 5
+ .cfi_def_cfa 4, 4
+ ret
+ .cfi_endproc
+ .size __nedf2, .-__nedf2
+
+ .p2align 4,,15
+ .globl __addsf3
+ .type __addsf3, @function
+__addsf3:
+ .cfi_startproc
+ subl $4, %esp
+ .cfi_def_cfa_offset 8
+ movl %eax, (%esp)
+ flds (%esp)
+ movl %edx, (%esp)
+ flds (%esp)
+ faddp %st, %st(1)
+ fstps (%esp)
+ movl (%esp), %eax
+ addl $4, %esp
+ .cfi_def_cfa_offset 4
+ ret
+ .cfi_endproc
+ .size __addsf3, .-__addsf3
+
+ .p2align 4,,15
+ .globl __adddf3
+ .type __adddf3, @function
+__adddf3:
+ .cfi_startproc
+ pushl %ebp
+ .cfi_def_cfa_offset 8
+ .cfi_offset 5, -8
+ movl %esp, %ebp
+ .cfi_def_cfa_register 5
+ andl $-8, %esp
+ subl $8, %esp
+ movl %eax, (%esp)
+ movl %edx, 4(%esp)
+ fldl (%esp)
+ faddl 8(%ebp)
+ fstpl (%esp)
+ movl (%esp), %eax
+ movl 4(%esp), %edx
+ leave
+ .cfi_restore 5
+ .cfi_def_cfa 4, 4
+ ret
+ .cfi_endproc
+ .size __adddf3, .-__adddf3
+
+ .p2align 4,,15
+ .globl __floatsisf
+ .type __floatsisf, @function
+__floatsisf:
+ .cfi_startproc
+ subl $4, %esp
+ .cfi_def_cfa_offset 8
+ movl %eax, (%esp)
+ fildl (%esp)
+ addl $4, %esp
+ .cfi_def_cfa_offset 4
+ ret
+ .cfi_endproc
+ .size __floatsisf, .-__floatsisf
+
+ .p2align 4,,15
+ .globl __floatunsisf
+ .type __floatunsisf, @function
+__floatunsisf:
+ .cfi_startproc
+ subl $8, %esp
+ .cfi_def_cfa_offset 12
+ xorl %edx, %edx
+ movl %eax, (%esp)
+ movl %edx, 4(%esp)
+ fildq (%esp)
+ addl $8, %esp
+ .cfi_def_cfa_offset 4
+ ret
+ .cfi_endproc
+ .size __floatunsisf, .-__floatunsisf
+
+ .globl __extendsfdf2
+ .type __extendsfdf2, @function
+__extendsfdf2:
+ .cfi_startproc
+ pushl %ebp
+ .cfi_def_cfa_offset 8
+ .cfi_offset 5, -8
+ movl %esp, %ebp
+ .cfi_def_cfa_register 5
+ andl $-8, %esp
+ subl $8, %esp
+ movl %eax, (%esp)
+ flds (%esp)
+ fstpl (%esp)
+ movl (%esp), %eax
+ movl 4(%esp), %edx
+ leave
+ .cfi_restore 5
+ .cfi_def_cfa 4, 4
+ ret
+ .cfi_endproc
+ .size __extendsfdf2, .-__extendsfdf2
+
+ .p2align 4,,15
+ .globl __truncdfsf2
+ .type __truncdfsf2, @function
+__truncdfsf2:
+ .cfi_startproc
+ pushl %ebp
+ .cfi_def_cfa_offset 8
+ .cfi_offset 5, -8
+ movl %esp, %ebp
+ .cfi_def_cfa_register 5
+ andl $-8, %esp
+ subl $12, %esp
+ movl %eax, (%esp)
+ movl %edx, 4(%esp)
+ fldl (%esp)
+ fstps (%esp)
+ movl (%esp), %eax
+ leave
+ .cfi_restore 5
+ .cfi_def_cfa 4, 4
+ ret
+ .cfi_endproc
+ .size __truncdfsf2, .-__truncdfsf2
+
+ .p2align 4,,15
+ .globl iamcu_memset
+ .type iamcu_memset, @function
+iamcu_memset:
+ .cfi_startproc
+ pushl %edi
+ .cfi_adjust_cfa_offset 4
+ .cfi_rel_offset %edi, 0
+ movl %eax, %edi
+ movzbl %dl, %eax
+ movl %edi, %edx
+ rep stosb
+ movl %edx, %eax
+ popl %edi
+ .cfi_adjust_cfa_offset -4
+ .cfi_restore %edi
+ ret
+ .cfi_endproc
+ .size iamcu_memset, .-iamcu_memset
+
+ .p2align 4,,15
+ .globl iamcu_noprintf
+ .type iamcu_noprintf, @function
+iamcu_noprintf:
+ .cfi_startproc
+ pushl %ebp
+ .cfi_def_cfa_offset 8
+ .cfi_offset 5, -8
+ movl %esp, %ebp
+ .cfi_def_cfa_register 5
+ cmpl $-1414676753, 8(%ebp)
+ fldl 16(%ebp)
+ fldl 28(%ebp)
+ jne 7f
+ cmpl $256, 12(%ebp)
+ jne 8f
+ flds .LCiamcu_noprintf0
+ movl $1, %eax
+ fucomip %st(2), %st
+ fstp %st(1)
+ setp %dl
+ cmovne %eax, %edx
+ testb %dl, %dl
+ jne 9f
+ cmpl $-1146241297, 24(%ebp)
+ jne 10f
+ flds .LCiamcu_noprintf1
+ fucomip %st(1), %st
+ fstp %st(0)
+ setp %dl
+ cmove %edx, %eax
+ testb %al, %al
+ jne 2f
+ cmpl $259, 36(%ebp)
+ jne 2f
+ popl %ebp
+ .cfi_remember_state
+ .cfi_restore 5
+ .cfi_def_cfa 4, 4
+ ret
+7:
+ .cfi_restore_state
+ fstp %st(0)
+ fstp %st(0)
+ jmp 2f
+8:
+ fstp %st(0)
+ fstp %st(0)
+ .p2align 4,,3
+ jmp 2f
+9:
+ fstp %st(0)
+ jmp 2f
+10:
+ fstp %st(0)
+2:
+ call abort
+ .cfi_endproc
+ .size iamcu_noprintf, .-iamcu_noprintf
+ .section .rodata.cst4,"aM",@progbits,4
+ .align 4
+.LCiamcu_noprintf0:
+ .long 1132494848
+ .align 4
+.LCiamcu_noprintf1:
+ .long 1132527616
diff --git a/gcc/testsuite/gcc.target/i386/iamcu/defines.h b/gcc/testsuite/gcc.target/i386/iamcu/defines.h
new file mode 100644
index 0000000..e715f42
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/iamcu/defines.h
@@ -0,0 +1,110 @@
+#ifndef DEFINED_DEFINES_H
+#define DEFINED_DEFINES_H
+
+typedef unsigned long long ulonglong;
+typedef long double ldouble;
+
+/* These defines determines what part of the test should be run. When
+ GCC implements these parts, the defines should be uncommented to
+ enable testing. */
+
+/* Scalar type long double. */
+#define CHECK_LONG_DOUBLE
+
+/* Scalar type __float128. */
+#define CHECK_FLOAT128
+
+/* Returning of complex type. */
+#define CHECK_COMPLEX
+
+/* Structs with size > 8. */
+#define CHECK_LARGER_STRUCTS
+
+/* Checks for passing floats and doubles. */
+#define CHECK_FLOAT_DOUBLE_PASSING
+
+/* Union passing with not-extremely-simple unions. */
+#define CHECK_LARGER_UNION_PASSING
+
+/* Variable args. */
+#define CHECK_VARARGS
+
+/* Check argument passing and returning for scalar types with sizeof > 8. */
+#define CHECK_LARGE_SCALAR_PASSING
+
+/* Defines for sizing and alignment. */
+
+#define TYPE_SIZE_CHAR 1
+#define TYPE_SIZE_SHORT 2
+#define TYPE_SIZE_INT 4
+#define TYPE_SIZE_LONG 4
+#define TYPE_SIZE_LONG_LONG 8
+#define TYPE_SIZE_FLOAT 4
+#define TYPE_SIZE_DOUBLE 8
+#define TYPE_SIZE_LONG_DOUBLE 8
+#define TYPE_SIZE_FLOAT128 16
+#define TYPE_SIZE_ENUM 4
+#define TYPE_SIZE_POINTER 4
+
+#define TYPE_ALIGN_CHAR 1
+#define TYPE_ALIGN_SHORT 2
+#define TYPE_ALIGN_INT 4
+#define TYPE_ALIGN_LONG 4
+#define TYPE_ALIGN_LONG_LONG 4
+#define TYPE_ALIGN_FLOAT 4
+#define TYPE_ALIGN_DOUBLE 4
+#define TYPE_ALIGN_LONG_DOUBLE 4
+#define TYPE_ALIGN_FLOAT128 4
+#define TYPE_ALIGN_ENUM 4
+#define TYPE_ALIGN_POINTER 4
+
+/* These defines control the building of the list of types to check. There
+ is a string identifying the type (with a comma after), a size of the type
+ (also with a comma and an integer for adding to the total amount of types)
+ and an alignment of the type (which is currently not really needed since
+ the abi specifies that alignof == sizeof for all scalar types). */
+#ifdef CHECK_LONG_DOUBLE
+#define CLD_STR "long double",
+#define CLD_SIZ TYPE_SIZE_LONG_DOUBLE,
+#define CLD_ALI TYPE_ALIGN_LONG_DOUBLE,
+#define CLD_RET "???",
+#else
+#define CLD_STR
+#define CLD_SIZ
+#define CLD_ALI
+#define CLD_RET
+#endif
+#ifdef CHECK_FLOAT128
+#define CF128_STR "__float128",
+#define CF128_SIZ TYPE_SIZE_FLOAT128,
+#define CF128_ALI TYPE_ALIGN_FLOAT128,
+#define CF128_RET "???",
+#else
+#define CF128_STR
+#define CF128_SIZ
+#define CF128_ALI
+#define CF128_RET
+#endif
+
+/* Used in size and alignment tests. */
+enum dummytype { enumtype };
+
+extern void abort (void);
+
+/* Assertion macro. */
+#define assert(test) if (!(test)) abort()
+
+#ifdef __GNUC__
+#define ATTRIBUTE_UNUSED __attribute__((__unused__))
+#else
+#define ATTRIBUTE_UNUSED
+#endif
+
+#ifdef __GNUC__
+#define PACKED __attribute__((__packed__))
+#else
+#warning Some tests will fail due to missing __packed__ support
+#define PACKED
+#endif
+
+#endif /* DEFINED_DEFINES_H */
diff --git a/gcc/testsuite/gcc.target/i386/iamcu/macros.h b/gcc/testsuite/gcc.target/i386/iamcu/macros.h
new file mode 100644
index 0000000..98fbc66
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/iamcu/macros.h
@@ -0,0 +1,53 @@
+#ifndef MACROS_H
+
+#define check_size(_t, _size) assert(sizeof(_t) == (_size))
+
+#define check_align(_t, _align) assert(__alignof__(_t) == (_align))
+
+#define check_align_lv(_t, _align) assert(__alignof__(_t) == (_align) \
+ && (((unsigned long)&(_t)) & ((_align) - 1) ) == 0)
+
+#define check_basic_struct_size_and_align(_type, _size, _align) { \
+ struct _str { _type dummy; } _t; \
+ check_size(_t, _size); \
+ check_align_lv(_t, _align); \
+}
+
+#define check_array_size_and_align(_type, _size, _align) { \
+ _type _a[1]; _type _b[2]; _type _c[16]; \
+ struct _str { _type _a[1]; } _s; \
+ check_align_lv(_a[0], _align); \
+ check_size(_a, _size); \
+ check_size(_b, (_size*2)); \
+ check_size(_c, (_size*16)); \
+ check_size(_s, _size); \
+ check_align_lv(_s._a[0], _align); \
+}
+
+#define check_basic_union_size_and_align(_type, _size, _align) { \
+ union _union { _type dummy; } _u; \
+ check_size(_u, _size); \
+ check_align_lv(_u, _align); \
+}
+
+#define run_signed_tests2(_function, _arg1, _arg2) \
+ _function(_arg1, _arg2); \
+ _function(signed _arg1, _arg2); \
+ _function(unsigned _arg1, _arg2);
+
+#define run_signed_tests3(_function, _arg1, _arg2, _arg3) \
+ _function(_arg1, _arg2, _arg3); \
+ _function(signed _arg1, _arg2, _arg3); \
+ _function(unsigned _arg1, _arg2, _arg3);
+
+/* Check size of a struct and a union of three types. */
+
+#define check_struct_and_union3(type1, type2, type3, struct_size, align_size) \
+{ \
+ struct _str { type1 t1; type2 t2; type3 t3; } _t; \
+ union _uni { type1 t1; type2 t2; type3 t3; } _u; \
+ check_size(_t, struct_size); \
+ check_size(_u, align_size); \
+}
+
+#endif // MACROS_H
diff --git a/gcc/testsuite/gcc.target/i386/iamcu/test_3_element_struct_and_unions.c b/gcc/testsuite/gcc.target/i386/iamcu/test_3_element_struct_and_unions.c
new file mode 100644
index 0000000..7bec211
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/iamcu/test_3_element_struct_and_unions.c
@@ -0,0 +1,521 @@
+#include "defines.h"
+#include "macros.h"
+
+/* Check structs and unions of all permutations of 3 basic types. */
+int
+main (void)
+{
+ check_struct_and_union3(char, char, char, 3, 1);
+ check_struct_and_union3(char, char, short, 4, 2);
+ check_struct_and_union3(char, char, int, 8, 4);
+ check_struct_and_union3(char, char, long, 8, 4);
+ check_struct_and_union3(char, char, long long, 12, 8);
+ check_struct_and_union3(char, char, float, 8, 4);
+ check_struct_and_union3(char, char, double, 12, 8);
+ check_struct_and_union3(char, char, long double, 12, 8);
+ check_struct_and_union3(char, short, char, 6, 2);
+ check_struct_and_union3(char, short, short, 6, 2);
+ check_struct_and_union3(char, short, int, 8, 4);
+ check_struct_and_union3(char, short, long, 8, 4);
+ check_struct_and_union3(char, short, long long, 12, 8);
+ check_struct_and_union3(char, short, float, 8, 4);
+ check_struct_and_union3(char, short, double, 12, 8);
+ check_struct_and_union3(char, short, long double, 12, 8);
+ check_struct_and_union3(char, int, char, 12, 4);
+ check_struct_and_union3(char, int, short, 12, 4);
+ check_struct_and_union3(char, int, int, 12, 4);
+ check_struct_and_union3(char, int, long, 12, 4);
+ check_struct_and_union3(char, int, long long, 16, 8);
+ check_struct_and_union3(char, int, float, 12, 4);
+ check_struct_and_union3(char, int, double, 16, 8);
+ check_struct_and_union3(char, int, long double, 16, 8);
+ check_struct_and_union3(char, long, char, 12, 4);
+ check_struct_and_union3(char, long, short, 12, 4);
+ check_struct_and_union3(char, long, int, 12, 4);
+ check_struct_and_union3(char, long, long, 12, 4);
+ check_struct_and_union3(char, long, long long, 16, 8);
+ check_struct_and_union3(char, long, float, 12, 4);
+ check_struct_and_union3(char, long, double, 16, 8);
+ check_struct_and_union3(char, long, long double, 16, 8);
+ check_struct_and_union3(char, long long, char, 16, 8);
+ check_struct_and_union3(char, long long, short, 16, 8);
+ check_struct_and_union3(char, long long, int, 16, 8);
+ check_struct_and_union3(char, long long, long, 16, 8);
+ check_struct_and_union3(char, long long, long long, 20, 8);
+ check_struct_and_union3(char, long long, float, 16, 8);
+ check_struct_and_union3(char, long long, double, 20, 8);
+ check_struct_and_union3(char, long long, long double, 20, 8);
+ check_struct_and_union3(char, float, char, 12, 4);
+ check_struct_and_union3(char, float, short, 12, 4);
+ check_struct_and_union3(char, float, int, 12, 4);
+ check_struct_and_union3(char, float, long, 12, 4);
+ check_struct_and_union3(char, float, long long, 16, 8);
+ check_struct_and_union3(char, float, float, 12, 4);
+ check_struct_and_union3(char, float, double, 16, 8);
+ check_struct_and_union3(char, float, long double, 16, 8);
+ check_struct_and_union3(char, double, char, 16, 8);
+ check_struct_and_union3(char, double, short, 16, 8);
+ check_struct_and_union3(char, double, int, 16, 8);
+ check_struct_and_union3(char, double, long, 16, 8);
+ check_struct_and_union3(char, double, long long, 20, 8);
+ check_struct_and_union3(char, double, float, 16, 8);
+ check_struct_and_union3(char, double, double, 20, 8);
+ check_struct_and_union3(char, double, long double, 20, 8);
+ check_struct_and_union3(char, long double, char, 16, 8);
+ check_struct_and_union3(char, long double, short, 16, 8);
+ check_struct_and_union3(char, long double, int, 16, 8);
+ check_struct_and_union3(char, long double, long, 16, 8);
+ check_struct_and_union3(char, long double, long long, 20, 8);
+ check_struct_and_union3(char, long double, float, 16, 8);
+ check_struct_and_union3(char, long double, double, 20, 8);
+ check_struct_and_union3(char, long double, long double, 20, 8);
+ check_struct_and_union3(short, char, char, 4, 2);
+ check_struct_and_union3(short, char, short, 6, 2);
+ check_struct_and_union3(short, char, int, 8, 4);
+ check_struct_and_union3(short, char, long, 8, 4);
+ check_struct_and_union3(short, char, long long, 12, 8);
+ check_struct_and_union3(short, char, float, 8, 4);
+ check_struct_and_union3(short, char, double, 12, 8);
+ check_struct_and_union3(short, char, long double, 12, 8);
+ check_struct_and_union3(short, short, char, 6, 2);
+ check_struct_and_union3(short, short, short, 6, 2);
+ check_struct_and_union3(short, short, int, 8, 4);
+ check_struct_and_union3(short, short, long, 8, 4);
+ check_struct_and_union3(short, short, long long, 12, 8);
+ check_struct_and_union3(short, short, float, 8, 4);
+ check_struct_and_union3(short, short, double, 12, 8);
+ check_struct_and_union3(short, short, long double, 12, 8);
+ check_struct_and_union3(short, int, char, 12, 4);
+ check_struct_and_union3(short, int, short, 12, 4);
+ check_struct_and_union3(short, int, int, 12, 4);
+ check_struct_and_union3(short, int, long, 12, 4);
+ check_struct_and_union3(short, int, long long, 16, 8);
+ check_struct_and_union3(short, int, float, 12, 4);
+ check_struct_and_union3(short, int, double, 16, 8);
+ check_struct_and_union3(short, int, long double, 16, 8);
+ check_struct_and_union3(short, long, char, 12, 4);
+ check_struct_and_union3(short, long, short, 12, 4);
+ check_struct_and_union3(short, long, int, 12, 4);
+ check_struct_and_union3(short, long, long, 12, 4);
+ check_struct_and_union3(short, long, long long, 16, 8);
+ check_struct_and_union3(short, long, float, 12, 4);
+ check_struct_and_union3(short, long, double, 16, 8);
+ check_struct_and_union3(short, long, long double, 16, 8);
+ check_struct_and_union3(short, long long, char, 16, 8);
+ check_struct_and_union3(short, long long, short, 16, 8);
+ check_struct_and_union3(short, long long, int, 16, 8);
+ check_struct_and_union3(short, long long, long, 16, 8);
+ check_struct_and_union3(short, long long, long long, 20, 8);
+ check_struct_and_union3(short, long long, float, 16, 8);
+ check_struct_and_union3(short, long long, double, 20, 8);
+ check_struct_and_union3(short, long long, long double, 20, 8);
+ check_struct_and_union3(short, float, char, 12, 4);
+ check_struct_and_union3(short, float, short, 12, 4);
+ check_struct_and_union3(short, float, int, 12, 4);
+ check_struct_and_union3(short, float, long, 12, 4);
+ check_struct_and_union3(short, float, long long, 16, 8);
+ check_struct_and_union3(short, float, float, 12, 4);
+ check_struct_and_union3(short, float, double, 16, 8);
+ check_struct_and_union3(short, float, long double, 16, 8);
+ check_struct_and_union3(short, double, char, 16, 8);
+ check_struct_and_union3(short, double, short, 16, 8);
+ check_struct_and_union3(short, double, int, 16, 8);
+ check_struct_and_union3(short, double, long, 16, 8);
+ check_struct_and_union3(short, double, long long, 20, 8);
+ check_struct_and_union3(short, double, float, 16, 8);
+ check_struct_and_union3(short, double, double, 20, 8);
+ check_struct_and_union3(short, double, long double, 20, 8);
+ check_struct_and_union3(short, long double, char, 16, 8);
+ check_struct_and_union3(short, long double, short, 16, 8);
+ check_struct_and_union3(short, long double, int, 16, 8);
+ check_struct_and_union3(short, long double, long, 16, 8);
+ check_struct_and_union3(short, long double, long long, 20, 8);
+ check_struct_and_union3(short, long double, float, 16, 8);
+ check_struct_and_union3(short, long double, double, 20, 8);
+ check_struct_and_union3(short, long double, long double, 20, 8);
+ check_struct_and_union3(int, char, char, 8, 4);
+ check_struct_and_union3(int, char, short, 8, 4);
+ check_struct_and_union3(int, char, int, 12, 4);
+ check_struct_and_union3(int, char, long, 12, 4);
+ check_struct_and_union3(int, char, long long, 16, 8);
+ check_struct_and_union3(int, char, float, 12, 4);
+ check_struct_and_union3(int, char, double, 16, 8);
+ check_struct_and_union3(int, char, long double, 16, 8);
+ check_struct_and_union3(int, short, char, 8, 4);
+ check_struct_and_union3(int, short, short, 8, 4);
+ check_struct_and_union3(int, short, int, 12, 4);
+ check_struct_and_union3(int, short, long, 12, 4);
+ check_struct_and_union3(int, short, long long, 16, 8);
+ check_struct_and_union3(int, short, float, 12, 4);
+ check_struct_and_union3(int, short, double, 16, 8);
+ check_struct_and_union3(int, short, long double, 16, 8);
+ check_struct_and_union3(int, int, char, 12, 4);
+ check_struct_and_union3(int, int, short, 12, 4);
+ check_struct_and_union3(int, int, int, 12, 4);
+ check_struct_and_union3(int, int, long, 12, 4);
+ check_struct_and_union3(int, int, long long, 16, 8);
+ check_struct_and_union3(int, int, float, 12, 4);
+ check_struct_and_union3(int, int, double, 16, 8);
+ check_struct_and_union3(int, int, long double, 16, 8);
+ check_struct_and_union3(int, long, char, 12, 4);
+ check_struct_and_union3(int, long, short, 12, 4);
+ check_struct_and_union3(int, long, int, 12, 4);
+ check_struct_and_union3(int, long, long, 12, 4);
+ check_struct_and_union3(int, long, long long, 16, 8);
+ check_struct_and_union3(int, long, float, 12, 4);
+ check_struct_and_union3(int, long, double, 16, 8);
+ check_struct_and_union3(int, long, long double, 16, 8);
+ check_struct_and_union3(int, long long, char, 16, 8);
+ check_struct_and_union3(int, long long, short, 16, 8);
+ check_struct_and_union3(int, long long, int, 16, 8);
+ check_struct_and_union3(int, long long, long, 16, 8);
+ check_struct_and_union3(int, long long, long long, 20, 8);
+ check_struct_and_union3(int, long long, float, 16, 8);
+ check_struct_and_union3(int, long long, double, 20, 8);
+ check_struct_and_union3(int, long long, long double, 20, 8);
+ check_struct_and_union3(int, float, char, 12, 4);
+ check_struct_and_union3(int, float, short, 12, 4);
+ check_struct_and_union3(int, float, int, 12, 4);
+ check_struct_and_union3(int, float, long, 12, 4);
+ check_struct_and_union3(int, float, long long, 16, 8);
+ check_struct_and_union3(int, float, float, 12, 4);
+ check_struct_and_union3(int, float, double, 16, 8);
+ check_struct_and_union3(int, float, long double, 16, 8);
+ check_struct_and_union3(int, double, char, 16, 8);
+ check_struct_and_union3(int, double, short, 16, 8);
+ check_struct_and_union3(int, double, int, 16, 8);
+ check_struct_and_union3(int, double, long, 16, 8);
+ check_struct_and_union3(int, double, long long, 20, 8);
+ check_struct_and_union3(int, double, float, 16, 8);
+ check_struct_and_union3(int, double, double, 20, 8);
+ check_struct_and_union3(int, double, long double, 20, 8);
+ check_struct_and_union3(int, long double, char, 16, 8);
+ check_struct_and_union3(int, long double, short, 16, 8);
+ check_struct_and_union3(int, long double, int, 16, 8);
+ check_struct_and_union3(int, long double, long, 16, 8);
+ check_struct_and_union3(int, long double, long long, 20, 8);
+ check_struct_and_union3(int, long double, float, 16, 8);
+ check_struct_and_union3(int, long double, double, 20, 8);
+ check_struct_and_union3(int, long double, long double, 20, 8);
+ check_struct_and_union3(long, char, char, 8, 4);
+ check_struct_and_union3(long, char, short, 8, 4);
+ check_struct_and_union3(long, char, int, 12, 4);
+ check_struct_and_union3(long, char, long, 12, 4);
+ check_struct_and_union3(long, char, long long, 16, 8);
+ check_struct_and_union3(long, char, float, 12, 4);
+ check_struct_and_union3(long, char, double, 16, 8);
+ check_struct_and_union3(long, char, long double, 16, 8);
+ check_struct_and_union3(long, short, char, 8, 4);
+ check_struct_and_union3(long, short, short, 8, 4);
+ check_struct_and_union3(long, short, int, 12, 4);
+ check_struct_and_union3(long, short, long, 12, 4);
+ check_struct_and_union3(long, short, long long, 16, 8);
+ check_struct_and_union3(long, short, float, 12, 4);
+ check_struct_and_union3(long, short, double, 16, 8);
+ check_struct_and_union3(long, short, long double, 16, 8);
+ check_struct_and_union3(long, int, char, 12, 4);
+ check_struct_and_union3(long, int, short, 12, 4);
+ check_struct_and_union3(long, int, int, 12, 4);
+ check_struct_and_union3(long, int, long, 12, 4);
+ check_struct_and_union3(long, int, long long, 16, 8);
+ check_struct_and_union3(long, int, float, 12, 4);
+ check_struct_and_union3(long, int, double, 16, 8);
+ check_struct_and_union3(long, int, long double, 16, 8);
+ check_struct_and_union3(long, long, char, 12, 4);
+ check_struct_and_union3(long, long, short, 12, 4);
+ check_struct_and_union3(long, long, int, 12, 4);
+ check_struct_and_union3(long, long, long, 12, 4);
+ check_struct_and_union3(long, long, long long, 16, 8);
+ check_struct_and_union3(long, long, float, 12, 4);
+ check_struct_and_union3(long, long, double, 16, 8);
+ check_struct_and_union3(long, long, long double, 16, 8);
+ check_struct_and_union3(long, long long, char, 16, 8);
+ check_struct_and_union3(long, long long, short, 16, 8);
+ check_struct_and_union3(long, long long, int, 16, 8);
+ check_struct_and_union3(long, long long, long, 16, 8);
+ check_struct_and_union3(long, long long, long long, 20, 8);
+ check_struct_and_union3(long, long long, float, 16, 8);
+ check_struct_and_union3(long, long long, double, 20, 8);
+ check_struct_and_union3(long, long long, long double, 20, 8);
+ check_struct_and_union3(long, float, char, 12, 4);
+ check_struct_and_union3(long, float, short, 12, 4);
+ check_struct_and_union3(long, float, int, 12, 4);
+ check_struct_and_union3(long, float, long, 12, 4);
+ check_struct_and_union3(long, float, long long, 16, 8);
+ check_struct_and_union3(long, float, float, 12, 4);
+ check_struct_and_union3(long, float, double, 16, 8);
+ check_struct_and_union3(long, float, long double, 16, 8);
+ check_struct_and_union3(long, double, char, 16, 8);
+ check_struct_and_union3(long, double, short, 16, 8);
+ check_struct_and_union3(long, double, int, 16, 8);
+ check_struct_and_union3(long, double, long, 16, 8);
+ check_struct_and_union3(long, double, long long, 20, 8);
+ check_struct_and_union3(long, double, float, 16, 8);
+ check_struct_and_union3(long, double, double, 20, 8);
+ check_struct_and_union3(long, double, long double, 20, 8);
+ check_struct_and_union3(long, long double, char, 16, 8);
+ check_struct_and_union3(long, long double, short, 16, 8);
+ check_struct_and_union3(long, long double, int, 16, 8);
+ check_struct_and_union3(long, long double, long, 16, 8);
+ check_struct_and_union3(long, long double, long long, 20, 8);
+ check_struct_and_union3(long, long double, float, 16, 8);
+ check_struct_and_union3(long, long double, double, 20, 8);
+ check_struct_and_union3(long, long double, long double, 20, 8);
+ check_struct_and_union3(long long, char, char, 12, 8);
+ check_struct_and_union3(long long, char, short, 12, 8);
+ check_struct_and_union3(long long, char, int, 16, 8);
+ check_struct_and_union3(long long, char, long, 16, 8);
+ check_struct_and_union3(long long, char, long long, 20, 8);
+ check_struct_and_union3(long long, char, float, 16, 8);
+ check_struct_and_union3(long long, char, double, 20, 8);
+ check_struct_and_union3(long long, char, long double, 20, 8);
+ check_struct_and_union3(long long, short, char, 12, 8);
+ check_struct_and_union3(long long, short, short, 12, 8);
+ check_struct_and_union3(long long, short, int, 16, 8);
+ check_struct_and_union3(long long, short, long, 16, 8);
+ check_struct_and_union3(long long, short, long long, 20, 8);
+ check_struct_and_union3(long long, short, float, 16, 8);
+ check_struct_and_union3(long long, short, double, 20, 8);
+ check_struct_and_union3(long long, short, long double, 20, 8);
+ check_struct_and_union3(long long, int, char, 16, 8);
+ check_struct_and_union3(long long, int, short, 16, 8);
+ check_struct_and_union3(long long, int, int, 16, 8);
+ check_struct_and_union3(long long, int, long, 16, 8);
+ check_struct_and_union3(long long, int, long long, 20, 8);
+ check_struct_and_union3(long long, int, float, 16, 8);
+ check_struct_and_union3(long long, int, double, 20, 8);
+ check_struct_and_union3(long long, int, long double, 20, 8);
+ check_struct_and_union3(long long, long, char, 16, 8);
+ check_struct_and_union3(long long, long, short, 16, 8);
+ check_struct_and_union3(long long, long, int, 16, 8);
+ check_struct_and_union3(long long, long, long, 16, 8);
+ check_struct_and_union3(long long, long, long long, 20, 8);
+ check_struct_and_union3(long long, long, float, 16, 8);
+ check_struct_and_union3(long long, long, double, 20, 8);
+ check_struct_and_union3(long long, long, long double, 20, 8);
+ check_struct_and_union3(long long, long long, char, 20, 8);
+ check_struct_and_union3(long long, long long, short, 20, 8);
+ check_struct_and_union3(long long, long long, int, 20, 8);
+ check_struct_and_union3(long long, long long, long, 20, 8);
+ check_struct_and_union3(long long, long long, long long, 24, 8);
+ check_struct_and_union3(long long, long long, float, 20, 8);
+ check_struct_and_union3(long long, long long, double, 24, 8);
+ check_struct_and_union3(long long, long long, long double, 24, 8);
+ check_struct_and_union3(long long, float, char, 16, 8);
+ check_struct_and_union3(long long, float, short, 16, 8);
+ check_struct_and_union3(long long, float, int, 16, 8);
+ check_struct_and_union3(long long, float, long, 16, 8);
+ check_struct_and_union3(long long, float, long long, 20, 8);
+ check_struct_and_union3(long long, float, float, 16, 8);
+ check_struct_and_union3(long long, float, double, 20, 8);
+ check_struct_and_union3(long long, float, long double, 20, 8);
+ check_struct_and_union3(long long, double, char, 20, 8);
+ check_struct_and_union3(long long, double, short, 20, 8);
+ check_struct_and_union3(long long, double, int, 20, 8);
+ check_struct_and_union3(long long, double, long, 20, 8);
+ check_struct_and_union3(long long, double, long long, 24, 8);
+ check_struct_and_union3(long long, double, float, 20, 8);
+ check_struct_and_union3(long long, double, double, 24, 8);
+ check_struct_and_union3(long long, double, long double, 24, 8);
+ check_struct_and_union3(long long, long double, char, 20, 8);
+ check_struct_and_union3(long long, long double, short, 20, 8);
+ check_struct_and_union3(long long, long double, int, 20, 8);
+ check_struct_and_union3(long long, long double, long, 20, 8);
+ check_struct_and_union3(long long, long double, long long, 24, 8);
+ check_struct_and_union3(long long, long double, float, 20, 8);
+ check_struct_and_union3(long long, long double, double, 24, 8);
+ check_struct_and_union3(long long, long double, long double, 24, 8);
+ check_struct_and_union3(float, char, char, 8, 4);
+ check_struct_and_union3(float, char, short, 8, 4);
+ check_struct_and_union3(float, char, int, 12, 4);
+ check_struct_and_union3(float, char, long, 12, 4);
+ check_struct_and_union3(float, char, long long, 16, 8);
+ check_struct_and_union3(float, char, float, 12, 4);
+ check_struct_and_union3(float, char, double, 16, 8);
+ check_struct_and_union3(float, char, long double, 16, 8);
+ check_struct_and_union3(float, short, char, 8, 4);
+ check_struct_and_union3(float, short, short, 8, 4);
+ check_struct_and_union3(float, short, int, 12, 4);
+ check_struct_and_union3(float, short, long, 12, 4);
+ check_struct_and_union3(float, short, long long, 16, 8);
+ check_struct_and_union3(float, short, float, 12, 4);
+ check_struct_and_union3(float, short, double, 16, 8);
+ check_struct_and_union3(float, short, long double, 16, 8);
+ check_struct_and_union3(float, int, char, 12, 4);
+ check_struct_and_union3(float, int, short, 12, 4);
+ check_struct_and_union3(float, int, int, 12, 4);
+ check_struct_and_union3(float, int, long, 12, 4);
+ check_struct_and_union3(float, int, long long, 16, 8);
+ check_struct_and_union3(float, int, float, 12, 4);
+ check_struct_and_union3(float, int, double, 16, 8);
+ check_struct_and_union3(float, int, long double, 16, 8);
+ check_struct_and_union3(float, long, char, 12, 4);
+ check_struct_and_union3(float, long, short, 12, 4);
+ check_struct_and_union3(float, long, int, 12, 4);
+ check_struct_and_union3(float, long, long, 12, 4);
+ check_struct_and_union3(float, long, long long, 16, 8);
+ check_struct_and_union3(float, long, float, 12, 4);
+ check_struct_and_union3(float, long, double, 16, 8);
+ check_struct_and_union3(float, long, long double, 16, 8);
+ check_struct_and_union3(float, long long, char, 16, 8);
+ check_struct_and_union3(float, long long, short, 16, 8);
+ check_struct_and_union3(float, long long, int, 16, 8);
+ check_struct_and_union3(float, long long, long, 16, 8);
+ check_struct_and_union3(float, long long, long long, 20, 8);
+ check_struct_and_union3(float, long long, float, 16, 8);
+ check_struct_and_union3(float, long long, double, 20, 8);
+ check_struct_and_union3(float, long long, long double, 20, 8);
+ check_struct_and_union3(float, float, char, 12, 4);
+ check_struct_and_union3(float, float, short, 12, 4);
+ check_struct_and_union3(float, float, int, 12, 4);
+ check_struct_and_union3(float, float, long, 12, 4);
+ check_struct_and_union3(float, float, long long, 16, 8);
+ check_struct_and_union3(float, float, float, 12, 4);
+ check_struct_and_union3(float, float, double, 16, 8);
+ check_struct_and_union3(float, float, long double, 16, 8);
+ check_struct_and_union3(float, double, char, 16, 8);
+ check_struct_and_union3(float, double, short, 16, 8);
+ check_struct_and_union3(float, double, int, 16, 8);
+ check_struct_and_union3(float, double, long, 16, 8);
+ check_struct_and_union3(float, double, long long, 20, 8);
+ check_struct_and_union3(float, double, float, 16, 8);
+ check_struct_and_union3(float, double, double, 20, 8);
+ check_struct_and_union3(float, double, long double, 20, 8);
+ check_struct_and_union3(float, long double, char, 16, 8);
+ check_struct_and_union3(float, long double, short, 16, 8);
+ check_struct_and_union3(float, long double, int, 16, 8);
+ check_struct_and_union3(float, long double, long, 16, 8);
+ check_struct_and_union3(float, long double, long long, 20, 8);
+ check_struct_and_union3(float, long double, float, 16, 8);
+ check_struct_and_union3(float, long double, double, 20, 8);
+ check_struct_and_union3(float, long double, long double, 20, 8);
+ check_struct_and_union3(double, char, char, 12, 8);
+ check_struct_and_union3(double, char, short, 12, 8);
+ check_struct_and_union3(double, char, int, 16, 8);
+ check_struct_and_union3(double, char, long, 16, 8);
+ check_struct_and_union3(double, char, long long, 20, 8);
+ check_struct_and_union3(double, char, float, 16, 8);
+ check_struct_and_union3(double, char, double, 20, 8);
+ check_struct_and_union3(double, char, long double, 20, 8);
+ check_struct_and_union3(double, short, char, 12, 8);
+ check_struct_and_union3(double, short, short, 12, 8);
+ check_struct_and_union3(double, short, int, 16, 8);
+ check_struct_and_union3(double, short, long, 16, 8);
+ check_struct_and_union3(double, short, long long, 20, 8);
+ check_struct_and_union3(double, short, float, 16, 8);
+ check_struct_and_union3(double, short, double, 20, 8);
+ check_struct_and_union3(double, short, long double, 20, 8);
+ check_struct_and_union3(double, int, char, 16, 8);
+ check_struct_and_union3(double, int, short, 16, 8);
+ check_struct_and_union3(double, int, int, 16, 8);
+ check_struct_and_union3(double, int, long, 16, 8);
+ check_struct_and_union3(double, int, long long, 20, 8);
+ check_struct_and_union3(double, int, float, 16, 8);
+ check_struct_and_union3(double, int, double, 20, 8);
+ check_struct_and_union3(double, int, long double, 20, 8);
+ check_struct_and_union3(double, long, char, 16, 8);
+ check_struct_and_union3(double, long, short, 16, 8);
+ check_struct_and_union3(double, long, int, 16, 8);
+ check_struct_and_union3(double, long, long, 16, 8);
+ check_struct_and_union3(double, long, long long, 20, 8);
+ check_struct_and_union3(double, long, float, 16, 8);
+ check_struct_and_union3(double, long, double, 20, 8);
+ check_struct_and_union3(double, long, long double, 20, 8);
+ check_struct_and_union3(double, long long, char, 20, 8);
+ check_struct_and_union3(double, long long, short, 20, 8);
+ check_struct_and_union3(double, long long, int, 20, 8);
+ check_struct_and_union3(double, long long, long, 20, 8);
+ check_struct_and_union3(double, long long, long long, 24, 8);
+ check_struct_and_union3(double, long long, float, 20, 8);
+ check_struct_and_union3(double, long long, double, 24, 8);
+ check_struct_and_union3(double, long long, long double, 24, 8);
+ check_struct_and_union3(double, float, char, 16, 8);
+ check_struct_and_union3(double, float, short, 16, 8);
+ check_struct_and_union3(double, float, int, 16, 8);
+ check_struct_and_union3(double, float, long, 16, 8);
+ check_struct_and_union3(double, float, long long, 20, 8);
+ check_struct_and_union3(double, float, float, 16, 8);
+ check_struct_and_union3(double, float, double, 20, 8);
+ check_struct_and_union3(double, float, long double, 20, 8);
+ check_struct_and_union3(double, double, char, 20, 8);
+ check_struct_and_union3(double, double, short, 20, 8);
+ check_struct_and_union3(double, double, int, 20, 8);
+ check_struct_and_union3(double, double, long, 20, 8);
+ check_struct_and_union3(double, double, long long, 24, 8);
+ check_struct_and_union3(double, double, float, 20, 8);
+ check_struct_and_union3(double, double, double, 24, 8);
+ check_struct_and_union3(double, double, long double, 24, 8);
+ check_struct_and_union3(double, long double, char, 20, 8);
+ check_struct_and_union3(double, long double, short, 20, 8);
+ check_struct_and_union3(double, long double, int, 20, 8);
+ check_struct_and_union3(double, long double, long, 20, 8);
+ check_struct_and_union3(double, long double, long long, 24, 8);
+ check_struct_and_union3(double, long double, float, 20, 8);
+ check_struct_and_union3(double, long double, double, 24, 8);
+ check_struct_and_union3(double, long double, long double, 24, 8);
+ check_struct_and_union3(long double, char, char, 12, 8);
+ check_struct_and_union3(long double, char, short, 12, 8);
+ check_struct_and_union3(long double, char, int, 16, 8);
+ check_struct_and_union3(long double, char, long, 16, 8);
+ check_struct_and_union3(long double, char, long long, 20, 8);
+ check_struct_and_union3(long double, char, float, 16, 8);
+ check_struct_and_union3(long double, char, double, 20, 8);
+ check_struct_and_union3(long double, char, long double, 20, 8);
+ check_struct_and_union3(long double, short, char, 12, 8);
+ check_struct_and_union3(long double, short, short, 12, 8);
+ check_struct_and_union3(long double, short, int, 16, 8);
+ check_struct_and_union3(long double, short, long, 16, 8);
+ check_struct_and_union3(long double, short, long long, 20, 8);
+ check_struct_and_union3(long double, short, float, 16, 8);
+ check_struct_and_union3(long double, short, double, 20, 8);
+ check_struct_and_union3(long double, short, long double, 20, 8);
+ check_struct_and_union3(long double, int, char, 16, 8);
+ check_struct_and_union3(long double, int, short, 16, 8);
+ check_struct_and_union3(long double, int, int, 16, 8);
+ check_struct_and_union3(long double, int, long, 16, 8);
+ check_struct_and_union3(long double, int, long long, 20, 8);
+ check_struct_and_union3(long double, int, float, 16, 8);
+ check_struct_and_union3(long double, int, double, 20, 8);
+ check_struct_and_union3(long double, int, long double, 20, 8);
+ check_struct_and_union3(long double, long, char, 16, 8);
+ check_struct_and_union3(long double, long, short, 16, 8);
+ check_struct_and_union3(long double, long, int, 16, 8);
+ check_struct_and_union3(long double, long, long, 16, 8);
+ check_struct_and_union3(long double, long, long long, 20, 8);
+ check_struct_and_union3(long double, long, float, 16, 8);
+ check_struct_and_union3(long double, long, double, 20, 8);
+ check_struct_and_union3(long double, long, long double, 20, 8);
+ check_struct_and_union3(long double, long long, char, 20, 8);
+ check_struct_and_union3(long double, long long, short, 20, 8);
+ check_struct_and_union3(long double, long long, int, 20, 8);
+ check_struct_and_union3(long double, long long, long, 20, 8);
+ check_struct_and_union3(long double, long long, long long, 24, 8);
+ check_struct_and_union3(long double, long long, float, 20, 8);
+ check_struct_and_union3(long double, long long, double, 24, 8);
+ check_struct_and_union3(long double, long long, long double, 24, 8);
+ check_struct_and_union3(long double, float, char, 16, 8);
+ check_struct_and_union3(long double, float, short, 16, 8);
+ check_struct_and_union3(long double, float, int, 16, 8);
+ check_struct_and_union3(long double, float, long, 16, 8);
+ check_struct_and_union3(long double, float, long long, 20, 8);
+ check_struct_and_union3(long double, float, float, 16, 8);
+ check_struct_and_union3(long double, float, double, 20, 8);
+ check_struct_and_union3(long double, float, long double, 20, 8);
+ check_struct_and_union3(long double, double, char, 20, 8);
+ check_struct_and_union3(long double, double, short, 20, 8);
+ check_struct_and_union3(long double, double, int, 20, 8);
+ check_struct_and_union3(long double, double, long, 20, 8);
+ check_struct_and_union3(long double, double, long long, 24, 8);
+ check_struct_and_union3(long double, double, float, 20, 8);
+ check_struct_and_union3(long double, double, double, 24, 8);
+ check_struct_and_union3(long double, double, long double, 24, 8);
+ check_struct_and_union3(long double, long double, char, 20, 8);
+ check_struct_and_union3(long double, long double, short, 20, 8);
+ check_struct_and_union3(long double, long double, int, 20, 8);
+ check_struct_and_union3(long double, long double, long, 20, 8);
+ check_struct_and_union3(long double, long double, long long, 24, 8);
+ check_struct_and_union3(long double, long double, float, 20, 8);
+ check_struct_and_union3(long double, long double, double, 24, 8);
+ check_struct_and_union3(long double, long double, long double, 24, 8);
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/iamcu/test_basic_64bit_returning.c b/gcc/testsuite/gcc.target/i386/iamcu/test_basic_64bit_returning.c
new file mode 100644
index 0000000..ecece94
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/iamcu/test_basic_64bit_returning.c
@@ -0,0 +1,57 @@
+#include "defines.h"
+#include "macros.h"
+#include "args.h"
+
+struct IntegerRegisters iregbits = { ~0, ~0, ~0, ~0, ~0, ~0 };
+struct IntegerRegisters iregs;
+unsigned int num_iregs;
+
+long long
+fun_test_returning_long_long (void)
+{
+ volatile_var++;
+ return (long long) 0xabadbeefabadbeefLL;
+}
+
+double
+fun_test_returning_double (void)
+{
+ volatile_var++;
+ return (double) 12345678.0;
+}
+
+union
+{
+ long long ll;
+ double d;
+} test_64;
+
+int
+main (void)
+{
+ unsigned failed = 0;
+ long long ll;
+ double d;
+
+ clear_struct_registers;
+ test_64.ll = 0xabadbeefabadbeefLL;
+
+ ll = WRAP_RET (fun_test_returning_long_long)();
+ if (ll != test_64.ll
+ || (test_64.ll & 0xffffffff) != eax
+ || ((test_64.ll >> 32) & 0xffffffff) != edx)
+ failed++;
+
+ clear_struct_registers;
+ test_64.d = 12345678.0;
+
+ d = WRAP_RET (fun_test_returning_double)();
+ if (d != test_64.d
+ || (test_64.ll & 0xffffffff) != eax
+ || ((test_64.ll >> 32) & 0xffffffff) != edx)
+ printf ("fail double\n"), failed++;
+
+ if (failed)
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/iamcu/test_basic_alignment.c b/gcc/testsuite/gcc.target/i386/iamcu/test_basic_alignment.c
new file mode 100644
index 0000000..f14cf17
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/iamcu/test_basic_alignment.c
@@ -0,0 +1,33 @@
+/* This checks alignment of basic types. */
+
+#include "defines.h"
+#include "macros.h"
+
+
+int
+main (void)
+{
+ /* Integral types. */
+ run_signed_tests2(check_align, char, TYPE_ALIGN_CHAR);
+ run_signed_tests2(check_align, short, TYPE_ALIGN_SHORT);
+ run_signed_tests2(check_align, int, TYPE_ALIGN_INT);
+ run_signed_tests2(check_align, long, TYPE_ALIGN_LONG);
+ run_signed_tests2(check_align, long long, TYPE_ALIGN_LONG_LONG);
+ check_align(enumtype, TYPE_ALIGN_ENUM);
+
+ /* Floating point types. */
+ check_align(float, TYPE_ALIGN_FLOAT);
+ check_align(double, TYPE_ALIGN_DOUBLE);
+#ifdef CHECK_LONG_DOUBLE
+ check_align(long double, TYPE_ALIGN_LONG_DOUBLE);
+#endif
+#ifdef CHECK_FLOAT128
+ check_align(__float128, TYPE_ALIGN_FLOAT128);
+#endif
+
+ /* Pointer types. */
+ check_align(void *, TYPE_ALIGN_POINTER);
+ check_align(void (*)(), TYPE_ALIGN_POINTER);
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/iamcu/test_basic_array_size_and_align.c b/gcc/testsuite/gcc.target/i386/iamcu/test_basic_array_size_and_align.c
new file mode 100644
index 0000000..e4b6369
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/iamcu/test_basic_array_size_and_align.c
@@ -0,0 +1,32 @@
+/* Test of simple arrays, size and alignment. */
+
+#include "defines.h"
+#include "macros.h"
+
+
+int
+main (void)
+{
+ /* Integral types. */
+ run_signed_tests3(check_array_size_and_align, char, TYPE_SIZE_CHAR, TYPE_ALIGN_CHAR);
+ run_signed_tests3(check_array_size_and_align, short, TYPE_SIZE_SHORT, TYPE_ALIGN_SHORT);
+ run_signed_tests3(check_array_size_and_align, int, TYPE_SIZE_INT, TYPE_ALIGN_INT);
+ run_signed_tests3(check_array_size_and_align, long, TYPE_SIZE_LONG, TYPE_ALIGN_LONG);
+ run_signed_tests3(check_array_size_and_align, long long, TYPE_SIZE_LONG_LONG, TYPE_ALIGN_LONG_LONG);
+ check_array_size_and_align(enum dummytype, TYPE_SIZE_ENUM, TYPE_ALIGN_ENUM);
+
+ /* Floating point types. */
+ check_array_size_and_align(float, TYPE_SIZE_FLOAT, TYPE_ALIGN_FLOAT);
+ check_array_size_and_align(double, TYPE_SIZE_DOUBLE, TYPE_ALIGN_DOUBLE);
+#ifdef CHECK_LONG_DOUBLE
+ check_array_size_and_align(long double, TYPE_SIZE_LONG_DOUBLE, TYPE_ALIGN_LONG_DOUBLE);
+#endif
+#ifdef CHECK_FLOAT128
+ check_array_size_and_align(__float128, TYPE_SIZE_FLOAT128, TYPE_ALIGN_FLOAT128);
+#endif
+
+ /* Pointer types. The function pointer doesn't work with these macros. */
+ check_array_size_and_align(void *, TYPE_SIZE_POINTER, TYPE_ALIGN_POINTER);
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/iamcu/test_basic_returning.c b/gcc/testsuite/gcc.target/i386/iamcu/test_basic_returning.c
new file mode 100644
index 0000000..23efa6e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/iamcu/test_basic_returning.c
@@ -0,0 +1,52 @@
+#include "defines.h"
+#include "macros.h"
+#include "args.h"
+
+char
+fun_test_returning_char (void)
+{
+ volatile_var++;
+ return 64;
+}
+
+short
+fun_test_returning_short (void)
+{
+ volatile_var++;
+ return 65;
+}
+
+int
+fun_test_returning_int (void)
+{
+ volatile_var++;
+ return 66;
+}
+
+long
+fun_test_returning_long (void)
+{
+ volatile_var++;
+ return 67;
+}
+
+float
+fun_test_returning_float (void)
+{
+ volatile_var++;
+ return 68;
+}
+
+#define def_test_returning_type(fun, type, ret, reg) \
+ { type var = WRAP_RET (fun) (); \
+ assert (ret == (type) reg && ret == var); }
+int
+main (void)
+{
+ def_test_returning_type(fun_test_returning_char, char, 64, eax);
+ def_test_returning_type(fun_test_returning_short, short, 65, eax);
+ def_test_returning_type(fun_test_returning_int, int, 66, eax);
+ def_test_returning_type(fun_test_returning_long, long, 67, eax);
+ def_test_returning_type(fun_test_returning_float, float, 68, eax);
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/iamcu/test_basic_sizes.c b/gcc/testsuite/gcc.target/i386/iamcu/test_basic_sizes.c
new file mode 100644
index 0000000..6582fc6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/iamcu/test_basic_sizes.c
@@ -0,0 +1,36 @@
+/* This checks sizes of basic types. */
+
+#include "defines.h"
+#include "macros.h"
+
+
+int
+main (void)
+{
+ /* Integral types. */
+ run_signed_tests2(check_size, char, TYPE_SIZE_CHAR);
+ run_signed_tests2(check_size, short, TYPE_SIZE_SHORT);
+ run_signed_tests2(check_size, int, TYPE_SIZE_INT);
+ run_signed_tests2(check_size, long, TYPE_SIZE_LONG);
+ run_signed_tests2(check_size, long long, TYPE_SIZE_LONG_LONG);
+#ifdef CHECK_INT128
+ run_signed_tests2(check_size, __int128, TYPE_SIZE_INT128);
+#endif
+ check_size(enumtype, TYPE_SIZE_ENUM);
+
+ /* Floating point types. */
+ check_size(float, TYPE_SIZE_FLOAT);
+ check_size(double, TYPE_SIZE_DOUBLE);
+#ifdef CHECK_LONG_DOUBLE
+ check_size(long double, TYPE_SIZE_LONG_DOUBLE);
+#endif
+#ifdef CHECK_FLOAT128
+ check_size(__float128, TYPE_SIZE_FLOAT128);
+#endif
+
+ /* Pointer types. */
+ check_size(void *, TYPE_SIZE_POINTER);
+ check_size(void (*)(), TYPE_SIZE_POINTER);
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/iamcu/test_basic_struct_size_and_align.c b/gcc/testsuite/gcc.target/i386/iamcu/test_basic_struct_size_and_align.c
new file mode 100644
index 0000000..3b5027f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/iamcu/test_basic_struct_size_and_align.c
@@ -0,0 +1,33 @@
+/* This checks size and alignment of structs with a single basic type
+ element. All basic types are checked. */
+
+#include "defines.h"
+#include "macros.h"
+
+
+int
+main (void)
+{
+ /* Integral types. */
+ run_signed_tests3(check_basic_struct_size_and_align, char, TYPE_SIZE_CHAR, TYPE_ALIGN_CHAR);
+ run_signed_tests3(check_basic_struct_size_and_align, short, TYPE_SIZE_SHORT, TYPE_ALIGN_SHORT);
+ run_signed_tests3(check_basic_struct_size_and_align, int, TYPE_SIZE_INT, TYPE_ALIGN_INT);
+ run_signed_tests3(check_basic_struct_size_and_align, long, TYPE_SIZE_LONG, TYPE_ALIGN_LONG);
+ run_signed_tests3(check_basic_struct_size_and_align, long long, TYPE_SIZE_LONG_LONG, TYPE_ALIGN_LONG_LONG);
+ check_basic_struct_size_and_align(enum dummytype, TYPE_SIZE_ENUM, TYPE_ALIGN_ENUM);
+
+ /* Floating point types. */
+ check_basic_struct_size_and_align(float, TYPE_SIZE_FLOAT, TYPE_ALIGN_FLOAT);
+ check_basic_struct_size_and_align(double, TYPE_SIZE_DOUBLE, TYPE_ALIGN_DOUBLE);
+#ifdef CHECK_LONG_DOUBLE
+ check_basic_struct_size_and_align(long double, TYPE_SIZE_LONG_DOUBLE, TYPE_ALIGN_LONG_DOUBLE);
+#endif
+#ifdef CHECK_FLOAT128
+ check_basic_struct_size_and_align(__float128, TYPE_SIZE_FLOAT128, TYPE_ALIGN_FLOAT128);
+#endif
+
+ /* Pointer types. The function pointer doesn't work with these macros. */
+ check_basic_struct_size_and_align(void *, TYPE_SIZE_POINTER, TYPE_ALIGN_POINTER);
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/iamcu/test_basic_union_size_and_align.c b/gcc/testsuite/gcc.target/i386/iamcu/test_basic_union_size_and_align.c
new file mode 100644
index 0000000..93ba5ff
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/iamcu/test_basic_union_size_and_align.c
@@ -0,0 +1,32 @@
+/* Test of simple unions, size and alignment. */
+
+#include "defines.h"
+#include "macros.h"
+
+
+int
+main (void)
+{
+ /* Integral types. */
+ run_signed_tests3(check_basic_union_size_and_align, char, TYPE_SIZE_CHAR, TYPE_ALIGN_CHAR);
+ run_signed_tests3(check_basic_union_size_and_align, short, TYPE_SIZE_SHORT, TYPE_ALIGN_SHORT);
+ run_signed_tests3(check_basic_union_size_and_align, int, TYPE_SIZE_INT, TYPE_ALIGN_INT);
+ run_signed_tests3(check_basic_union_size_and_align, long, TYPE_SIZE_LONG, TYPE_ALIGN_LONG);
+ run_signed_tests3(check_basic_union_size_and_align, long long, TYPE_SIZE_LONG_LONG, TYPE_ALIGN_LONG_LONG);
+ check_basic_union_size_and_align(enum dummytype, TYPE_SIZE_ENUM, TYPE_ALIGN_ENUM);
+
+ /* Floating point types. */
+ check_basic_union_size_and_align(float, TYPE_SIZE_FLOAT, TYPE_ALIGN_FLOAT);
+ check_basic_union_size_and_align(double, TYPE_SIZE_DOUBLE, TYPE_ALIGN_DOUBLE);
+#ifdef CHECK_LONG_DOUBLE
+ check_basic_union_size_and_align(long double, TYPE_SIZE_LONG_DOUBLE, TYPE_ALIGN_LONG_DOUBLE);
+#endif
+#ifdef CHECK_FLOAT128
+ check_basic_union_size_and_align(__float128, TYPE_SIZE_FLOAT128, TYPE_ALIGN_FLOAT128);
+#endif
+
+ /* Pointer types. The function pointer doesn't work with these macros. */
+ check_basic_union_size_and_align(void *, TYPE_SIZE_POINTER, TYPE_ALIGN_POINTER);
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/iamcu/test_bitfields.c b/gcc/testsuite/gcc.target/i386/iamcu/test_bitfields.c
new file mode 100644
index 0000000..0b1c293
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/iamcu/test_bitfields.c
@@ -0,0 +1,162 @@
+/* This is a small test to see if bitfields are working. It is only a
+ few structs and a union and a test to see if they have the correct
+ size, if values can be read and written and a couple of argument
+ passing tests. No alignment testing is done. */
+
+#include "defines.h"
+#include "macros.h"
+
+
+/* These five bitfields are taken from the System V ABI, Intel 386
+ architecture supplement. */
+
+/* Word aligned, sizeof is 4. */
+struct RightToLeft
+{
+ int j:5;
+ int k:6;
+ int m:7;
+};
+
+/* Word aligned, sizeof is 12. */
+struct BoundaryAlignment
+{
+ short s:9;
+ int j:9;
+ char c;
+ short t:9;
+ short u:9;
+ char d;
+};
+
+/* Halfword aligned, sizeof is 2. */
+struct StorageUnitSharing
+{
+ char c;
+ short s:8;
+};
+
+/* Halfword aligned, sizeof is 2. */
+union Allocation
+{
+ char c;
+ short s:8;
+};
+
+/* Byte aligned, sizeof is 9. */
+struct Unnamed
+{
+ char c;
+ int :0;
+ char d;
+ short :9;
+ char e;
+ char :0;
+};
+
+/* Extra struct testing bitfields in larger types.
+ Doubleword aligned, sizeof is 8. */
+struct LargerTypes
+{
+ long long l:33;
+ int i:31;
+};
+
+
+void
+passing1 (struct RightToLeft str, int j, int k, int m)
+{
+ assert (str.j == j);
+ assert (str.k == k);
+ assert (str.m == m);
+}
+
+void
+passing2 (struct BoundaryAlignment str, short s, int j, char c, short t,
+ short u, char d)
+{
+ assert (str.s == s);
+ assert (str.j == j);
+ assert (str.c == c);
+ assert (str.t == t);
+ assert (str.u == u);
+ assert (str.d == d);
+}
+
+void
+passing3 (struct StorageUnitSharing str, char c, short s)
+{
+ assert (str.c == c);
+ assert (str.s == s);
+}
+
+void
+passing4 (struct Unnamed str, char c, char d, char e)
+{
+ assert (str.c == c);
+ assert (str.d == d);
+ assert (str.e == e);
+}
+
+void
+passing5 (struct LargerTypes str, long long l, int i)
+{
+ assert (str.l == l);
+ assert (str.i == i);
+}
+
+
+void
+passingU (union Allocation u, char c)
+{
+ assert (u.c == c);
+ assert (u.s == c);
+}
+
+
+int
+main (void)
+{
+ struct RightToLeft str1;
+ struct BoundaryAlignment str2;
+ struct StorageUnitSharing str3;
+ struct Unnamed str4;
+ struct LargerTypes str5;
+ union Allocation u;
+
+ /* Check sizeof's. */
+ check_size(str1, 4);
+ check_size(str2, 12);
+ check_size(str3, 2);
+ check_size(str4, 9);
+ check_size(str5, 8);
+ check_size(u, 2);
+
+ /* Check alignof's. */
+ check_align_lv(str1, 4);
+ check_align_lv(str2, 4);
+ check_align_lv(str3, 2);
+ check_align_lv(str4, 1);
+ check_align_lv(str5, 4);
+ check_align_lv(u, 2);
+
+ /* Check passing. */
+ str1.j = str2.s = str3.c = str4.c = str5.l = 4;
+ str1.k = str2.j = str3.s = str4.d = str5.i = 5;
+ str1.m = str2.c = str4.e = 6;
+ str2.t = 7;
+ str2.u = 8;
+ str2.d = 9;
+ passing1 (str1, 4, 5, 6);
+ passing2 (str2, 4, 5, 6, 7, 8, 9);
+ passing3 (str3, 4, 5);
+ passing4 (str4, 4, 5, 6);
+ passing5 (str5, 4, 5);
+
+ u.c = 5;
+ passingU (u, 5);
+ u.s = 6;
+ passingU (u, 6);
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/iamcu/test_complex_returning.c b/gcc/testsuite/gcc.target/i386/iamcu/test_complex_returning.c
new file mode 100644
index 0000000..9e9678d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/iamcu/test_complex_returning.c
@@ -0,0 +1,83 @@
+/* This is a small test case for returning a complex number. Written by
+ Andreas Jaeger. */
+
+#include "defines.h"
+
+
+#define BUILD_F_COMPLEX(real, imag) \
+ ({ __complex__ float __retval; \
+ __real__ __retval = (real); \
+ __imag__ __retval = (imag); \
+ __retval; })
+
+#define BUILD_D_COMPLEX(real, imag) \
+ ({ __complex__ double __retval; \
+ __real__ __retval = (real); \
+ __imag__ __retval = (imag); \
+ __retval; })
+
+#define BUILD_LD_COMPLEX(real, imag) \
+ ({ __complex__ long double __retval; \
+ __real__ __retval = (real); \
+ __imag__ __retval = (imag); \
+ __retval; })
+
+__complex__ float
+aj_f_times2 (__complex__ float x)
+{
+ __complex__ float res;
+
+ __real__ res = (2.0 * __real__ x);
+ __imag__ res = (2.0 * __imag__ x);
+
+ return res;
+}
+
+__complex__ double
+aj_d_times2 (__complex__ double x)
+{
+ __complex__ double res;
+
+ __real__ res = (2.0 * __real__ x);
+ __imag__ res = (2.0 * __imag__ x);
+
+ return res;
+}
+
+__complex__ long double
+aj_ld_times2 (__complex__ long double x)
+{
+ __complex__ long double res;
+
+ __real__ res = (2.0 * __real__ x);
+ __imag__ res = (2.0 * __imag__ x);
+
+ return res;
+}
+
+int
+main (void)
+{
+#ifdef CHECK_COMPLEX
+ _Complex float fc, fd;
+ _Complex double dc, dd;
+ _Complex long double ldc, ldd;
+
+ fc = BUILD_LD_COMPLEX (2.0f, 3.0f);
+ fd = aj_f_times2 (fc);
+
+ assert (__real__ fd == 4.0f && __imag__ fd == 6.0f);
+
+ dc = BUILD_LD_COMPLEX (2.0, 3.0);
+ dd = aj_ld_times2 (dc);
+
+ assert (__real__ dd == 4.0 && __imag__ dd == 6.0);
+
+ ldc = BUILD_LD_COMPLEX (2.0L, 3.0L);
+ ldd = aj_ld_times2 (ldc);
+
+ assert (__real__ ldd == 4.0L && __imag__ ldd == 6.0L);
+#endif
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/iamcu/test_passing_floats.c b/gcc/testsuite/gcc.target/i386/iamcu/test_passing_floats.c
new file mode 100644
index 0000000..6bb24cc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/iamcu/test_passing_floats.c
@@ -0,0 +1,608 @@
+#include "defines.h"
+#include "macros.h"
+#include "args.h"
+
+struct IntegerRegisters iregbits = { ~0, ~0, ~0, ~0, ~0, ~0 };
+struct IntegerRegisters iregs;
+unsigned int num_iregs;
+
+/* This struct holds values for argument checking. */
+struct
+{
+ float f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17, f18, f19, f20, f21, f22, f23;
+} values_float;
+
+struct
+{
+ double f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17, f18, f19, f20, f21, f22, f23;
+} values_double;
+
+struct
+{
+ ldouble f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17, f18, f19, f20, f21, f22, f23;
+} values_ldouble;
+
+void
+fun_check_float_passing_float8_values (float f0 ATTRIBUTE_UNUSED, float f1 ATTRIBUTE_UNUSED, float f2 ATTRIBUTE_UNUSED, float f3 ATTRIBUTE_UNUSED, float f4 ATTRIBUTE_UNUSED, float f5 ATTRIBUTE_UNUSED, float f6 ATTRIBUTE_UNUSED, float f7 ATTRIBUTE_UNUSED)
+{
+ /* Check argument values. */
+ assert (values_float.f0 == f0);
+ assert (values_float.f1 == f1);
+ assert (values_float.f2 == f2);
+ assert (values_float.f3 == f3);
+ assert (values_float.f4 == f4);
+ assert (values_float.f5 == f5);
+ assert (values_float.f6 == f6);
+ assert (values_float.f7 == f7);
+
+}
+
+void
+fun_check_float_passing_float8_regs (float f0 ATTRIBUTE_UNUSED, float f1 ATTRIBUTE_UNUSED, float f2 ATTRIBUTE_UNUSED, float f3 ATTRIBUTE_UNUSED, float f4 ATTRIBUTE_UNUSED, float f5 ATTRIBUTE_UNUSED, float f6 ATTRIBUTE_UNUSED, float f7 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_float_arguments;
+}
+
+void
+fun_check_float_passing_float16_values (float f0 ATTRIBUTE_UNUSED, float f1 ATTRIBUTE_UNUSED, float f2 ATTRIBUTE_UNUSED, float f3 ATTRIBUTE_UNUSED, float f4 ATTRIBUTE_UNUSED, float f5 ATTRIBUTE_UNUSED, float f6 ATTRIBUTE_UNUSED, float f7 ATTRIBUTE_UNUSED, float f8 ATTRIBUTE_UNUSED, float f9 ATTRIBUTE_UNUSED, float f10 ATTRIBUTE_UNUSED, float f11 ATTRIBUTE_UNUSED, float f12 ATTRIBUTE_UNUSED, float f13 ATTRIBUTE_UNUSED, float f14 ATTRIBUTE_UNUSED, float f15 ATTRIBUTE_UNUSED)
+{
+ /* Check argument values. */
+ assert (values_float.f0 == f0);
+ assert (values_float.f1 == f1);
+ assert (values_float.f2 == f2);
+ assert (values_float.f3 == f3);
+ assert (values_float.f4 == f4);
+ assert (values_float.f5 == f5);
+ assert (values_float.f6 == f6);
+ assert (values_float.f7 == f7);
+ assert (values_float.f8 == f8);
+ assert (values_float.f9 == f9);
+ assert (values_float.f10 == f10);
+ assert (values_float.f11 == f11);
+ assert (values_float.f12 == f12);
+ assert (values_float.f13 == f13);
+ assert (values_float.f14 == f14);
+ assert (values_float.f15 == f15);
+
+}
+
+void
+fun_check_float_passing_float16_regs (float f0 ATTRIBUTE_UNUSED, float f1 ATTRIBUTE_UNUSED, float f2 ATTRIBUTE_UNUSED, float f3 ATTRIBUTE_UNUSED, float f4 ATTRIBUTE_UNUSED, float f5 ATTRIBUTE_UNUSED, float f6 ATTRIBUTE_UNUSED, float f7 ATTRIBUTE_UNUSED, float f8 ATTRIBUTE_UNUSED, float f9 ATTRIBUTE_UNUSED, float f10 ATTRIBUTE_UNUSED, float f11 ATTRIBUTE_UNUSED, float f12 ATTRIBUTE_UNUSED, float f13 ATTRIBUTE_UNUSED, float f14 ATTRIBUTE_UNUSED, float f15 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_float_arguments;
+}
+
+void
+fun_check_float_passing_float20_values (float f0 ATTRIBUTE_UNUSED, float f1 ATTRIBUTE_UNUSED, float f2 ATTRIBUTE_UNUSED, float f3 ATTRIBUTE_UNUSED, float f4 ATTRIBUTE_UNUSED, float f5 ATTRIBUTE_UNUSED, float f6 ATTRIBUTE_UNUSED, float f7 ATTRIBUTE_UNUSED, float f8 ATTRIBUTE_UNUSED, float f9 ATTRIBUTE_UNUSED, float f10 ATTRIBUTE_UNUSED, float f11 ATTRIBUTE_UNUSED, float f12 ATTRIBUTE_UNUSED, float f13 ATTRIBUTE_UNUSED, float f14 ATTRIBUTE_UNUSED, float f15 ATTRIBUTE_UNUSED, float f16 ATTRIBUTE_UNUSED, float f17 ATTRIBUTE_UNUSED, float f18 ATTRIBUTE_UNUSED, float f19 ATTRIBUTE_UNUSED)
+{
+ /* Check argument values. */
+ assert (values_float.f0 == f0);
+ assert (values_float.f1 == f1);
+ assert (values_float.f2 == f2);
+ assert (values_float.f3 == f3);
+ assert (values_float.f4 == f4);
+ assert (values_float.f5 == f5);
+ assert (values_float.f6 == f6);
+ assert (values_float.f7 == f7);
+ assert (values_float.f8 == f8);
+ assert (values_float.f9 == f9);
+ assert (values_float.f10 == f10);
+ assert (values_float.f11 == f11);
+ assert (values_float.f12 == f12);
+ assert (values_float.f13 == f13);
+ assert (values_float.f14 == f14);
+ assert (values_float.f15 == f15);
+ assert (values_float.f16 == f16);
+ assert (values_float.f17 == f17);
+ assert (values_float.f18 == f18);
+ assert (values_float.f19 == f19);
+
+}
+
+void
+fun_check_float_passing_float20_regs (float f0 ATTRIBUTE_UNUSED, float f1 ATTRIBUTE_UNUSED, float f2 ATTRIBUTE_UNUSED, float f3 ATTRIBUTE_UNUSED, float f4 ATTRIBUTE_UNUSED, float f5 ATTRIBUTE_UNUSED, float f6 ATTRIBUTE_UNUSED, float f7 ATTRIBUTE_UNUSED, float f8 ATTRIBUTE_UNUSED, float f9 ATTRIBUTE_UNUSED, float f10 ATTRIBUTE_UNUSED, float f11 ATTRIBUTE_UNUSED, float f12 ATTRIBUTE_UNUSED, float f13 ATTRIBUTE_UNUSED, float f14 ATTRIBUTE_UNUSED, float f15 ATTRIBUTE_UNUSED, float f16 ATTRIBUTE_UNUSED, float f17 ATTRIBUTE_UNUSED, float f18 ATTRIBUTE_UNUSED, float f19 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_float_arguments;
+}
+
+void
+fun_check_float_passing_double8_values (double f0 ATTRIBUTE_UNUSED, double f1 ATTRIBUTE_UNUSED, double f2 ATTRIBUTE_UNUSED, double f3 ATTRIBUTE_UNUSED, double f4 ATTRIBUTE_UNUSED, double f5 ATTRIBUTE_UNUSED, double f6 ATTRIBUTE_UNUSED, double f7 ATTRIBUTE_UNUSED)
+{
+ /* Check argument values. */
+ assert (values_double.f0 == f0);
+ assert (values_double.f1 == f1);
+ assert (values_double.f2 == f2);
+ assert (values_double.f3 == f3);
+ assert (values_double.f4 == f4);
+ assert (values_double.f5 == f5);
+ assert (values_double.f6 == f6);
+ assert (values_double.f7 == f7);
+
+}
+
+void
+fun_check_float_passing_double8_regs (double f0 ATTRIBUTE_UNUSED, double f1 ATTRIBUTE_UNUSED, double f2 ATTRIBUTE_UNUSED, double f3 ATTRIBUTE_UNUSED, double f4 ATTRIBUTE_UNUSED, double f5 ATTRIBUTE_UNUSED, double f6 ATTRIBUTE_UNUSED, double f7 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_double_arguments;
+}
+
+void
+fun_check_float_passing_double16_values (double f0 ATTRIBUTE_UNUSED, double f1 ATTRIBUTE_UNUSED, double f2 ATTRIBUTE_UNUSED, double f3 ATTRIBUTE_UNUSED, double f4 ATTRIBUTE_UNUSED, double f5 ATTRIBUTE_UNUSED, double f6 ATTRIBUTE_UNUSED, double f7 ATTRIBUTE_UNUSED, double f8 ATTRIBUTE_UNUSED, double f9 ATTRIBUTE_UNUSED, double f10 ATTRIBUTE_UNUSED, double f11 ATTRIBUTE_UNUSED, double f12 ATTRIBUTE_UNUSED, double f13 ATTRIBUTE_UNUSED, double f14 ATTRIBUTE_UNUSED, double f15 ATTRIBUTE_UNUSED)
+{
+ /* Check argument values. */
+ assert (values_double.f0 == f0);
+ assert (values_double.f1 == f1);
+ assert (values_double.f2 == f2);
+ assert (values_double.f3 == f3);
+ assert (values_double.f4 == f4);
+ assert (values_double.f5 == f5);
+ assert (values_double.f6 == f6);
+ assert (values_double.f7 == f7);
+ assert (values_double.f8 == f8);
+ assert (values_double.f9 == f9);
+ assert (values_double.f10 == f10);
+ assert (values_double.f11 == f11);
+ assert (values_double.f12 == f12);
+ assert (values_double.f13 == f13);
+ assert (values_double.f14 == f14);
+ assert (values_double.f15 == f15);
+
+}
+
+void
+fun_check_float_passing_double16_regs (double f0 ATTRIBUTE_UNUSED, double f1 ATTRIBUTE_UNUSED, double f2 ATTRIBUTE_UNUSED, double f3 ATTRIBUTE_UNUSED, double f4 ATTRIBUTE_UNUSED, double f5 ATTRIBUTE_UNUSED, double f6 ATTRIBUTE_UNUSED, double f7 ATTRIBUTE_UNUSED, double f8 ATTRIBUTE_UNUSED, double f9 ATTRIBUTE_UNUSED, double f10 ATTRIBUTE_UNUSED, double f11 ATTRIBUTE_UNUSED, double f12 ATTRIBUTE_UNUSED, double f13 ATTRIBUTE_UNUSED, double f14 ATTRIBUTE_UNUSED, double f15 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_double_arguments;
+}
+
+void
+fun_check_float_passing_double20_values (double f0 ATTRIBUTE_UNUSED, double f1 ATTRIBUTE_UNUSED, double f2 ATTRIBUTE_UNUSED, double f3 ATTRIBUTE_UNUSED, double f4 ATTRIBUTE_UNUSED, double f5 ATTRIBUTE_UNUSED, double f6 ATTRIBUTE_UNUSED, double f7 ATTRIBUTE_UNUSED, double f8 ATTRIBUTE_UNUSED, double f9 ATTRIBUTE_UNUSED, double f10 ATTRIBUTE_UNUSED, double f11 ATTRIBUTE_UNUSED, double f12 ATTRIBUTE_UNUSED, double f13 ATTRIBUTE_UNUSED, double f14 ATTRIBUTE_UNUSED, double f15 ATTRIBUTE_UNUSED, double f16 ATTRIBUTE_UNUSED, double f17 ATTRIBUTE_UNUSED, double f18 ATTRIBUTE_UNUSED, double f19 ATTRIBUTE_UNUSED)
+{
+ /* Check argument values. */
+ assert (values_double.f0 == f0);
+ assert (values_double.f1 == f1);
+ assert (values_double.f2 == f2);
+ assert (values_double.f3 == f3);
+ assert (values_double.f4 == f4);
+ assert (values_double.f5 == f5);
+ assert (values_double.f6 == f6);
+ assert (values_double.f7 == f7);
+ assert (values_double.f8 == f8);
+ assert (values_double.f9 == f9);
+ assert (values_double.f10 == f10);
+ assert (values_double.f11 == f11);
+ assert (values_double.f12 == f12);
+ assert (values_double.f13 == f13);
+ assert (values_double.f14 == f14);
+ assert (values_double.f15 == f15);
+ assert (values_double.f16 == f16);
+ assert (values_double.f17 == f17);
+ assert (values_double.f18 == f18);
+ assert (values_double.f19 == f19);
+
+}
+
+void
+fun_check_float_passing_double20_regs (double f0 ATTRIBUTE_UNUSED, double f1 ATTRIBUTE_UNUSED, double f2 ATTRIBUTE_UNUSED, double f3 ATTRIBUTE_UNUSED, double f4 ATTRIBUTE_UNUSED, double f5 ATTRIBUTE_UNUSED, double f6 ATTRIBUTE_UNUSED, double f7 ATTRIBUTE_UNUSED, double f8 ATTRIBUTE_UNUSED, double f9 ATTRIBUTE_UNUSED, double f10 ATTRIBUTE_UNUSED, double f11 ATTRIBUTE_UNUSED, double f12 ATTRIBUTE_UNUSED, double f13 ATTRIBUTE_UNUSED, double f14 ATTRIBUTE_UNUSED, double f15 ATTRIBUTE_UNUSED, double f16 ATTRIBUTE_UNUSED, double f17 ATTRIBUTE_UNUSED, double f18 ATTRIBUTE_UNUSED, double f19 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_double_arguments;
+}
+
+void
+fun_check_x87_passing_ldouble8_values (ldouble f0 ATTRIBUTE_UNUSED, ldouble f1 ATTRIBUTE_UNUSED, ldouble f2 ATTRIBUTE_UNUSED, ldouble f3 ATTRIBUTE_UNUSED, ldouble f4 ATTRIBUTE_UNUSED, ldouble f5 ATTRIBUTE_UNUSED, ldouble f6 ATTRIBUTE_UNUSED, ldouble f7 ATTRIBUTE_UNUSED)
+{
+ /* Check argument values. */
+ assert (values_ldouble.f0 == f0);
+ assert (values_ldouble.f1 == f1);
+ assert (values_ldouble.f2 == f2);
+ assert (values_ldouble.f3 == f3);
+ assert (values_ldouble.f4 == f4);
+ assert (values_ldouble.f5 == f5);
+ assert (values_ldouble.f6 == f6);
+ assert (values_ldouble.f7 == f7);
+
+}
+
+void
+fun_check_x87_passing_ldouble8_regs (ldouble f0 ATTRIBUTE_UNUSED, ldouble f1 ATTRIBUTE_UNUSED, ldouble f2 ATTRIBUTE_UNUSED, ldouble f3 ATTRIBUTE_UNUSED, ldouble f4 ATTRIBUTE_UNUSED, ldouble f5 ATTRIBUTE_UNUSED, ldouble f6 ATTRIBUTE_UNUSED, ldouble f7 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_ldouble_arguments;
+}
+
+void
+fun_check_x87_passing_ldouble16_values (ldouble f0 ATTRIBUTE_UNUSED, ldouble f1 ATTRIBUTE_UNUSED, ldouble f2 ATTRIBUTE_UNUSED, ldouble f3 ATTRIBUTE_UNUSED, ldouble f4 ATTRIBUTE_UNUSED, ldouble f5 ATTRIBUTE_UNUSED, ldouble f6 ATTRIBUTE_UNUSED, ldouble f7 ATTRIBUTE_UNUSED, ldouble f8 ATTRIBUTE_UNUSED, ldouble f9 ATTRIBUTE_UNUSED, ldouble f10 ATTRIBUTE_UNUSED, ldouble f11 ATTRIBUTE_UNUSED, ldouble f12 ATTRIBUTE_UNUSED, ldouble f13 ATTRIBUTE_UNUSED, ldouble f14 ATTRIBUTE_UNUSED, ldouble f15 ATTRIBUTE_UNUSED)
+{
+ /* Check argument values. */
+ assert (values_ldouble.f0 == f0);
+ assert (values_ldouble.f1 == f1);
+ assert (values_ldouble.f2 == f2);
+ assert (values_ldouble.f3 == f3);
+ assert (values_ldouble.f4 == f4);
+ assert (values_ldouble.f5 == f5);
+ assert (values_ldouble.f6 == f6);
+ assert (values_ldouble.f7 == f7);
+ assert (values_ldouble.f8 == f8);
+ assert (values_ldouble.f9 == f9);
+ assert (values_ldouble.f10 == f10);
+ assert (values_ldouble.f11 == f11);
+ assert (values_ldouble.f12 == f12);
+ assert (values_ldouble.f13 == f13);
+ assert (values_ldouble.f14 == f14);
+ assert (values_ldouble.f15 == f15);
+
+}
+
+void
+fun_check_x87_passing_ldouble16_regs (ldouble f0 ATTRIBUTE_UNUSED, ldouble f1 ATTRIBUTE_UNUSED, ldouble f2 ATTRIBUTE_UNUSED, ldouble f3 ATTRIBUTE_UNUSED, ldouble f4 ATTRIBUTE_UNUSED, ldouble f5 ATTRIBUTE_UNUSED, ldouble f6 ATTRIBUTE_UNUSED, ldouble f7 ATTRIBUTE_UNUSED, ldouble f8 ATTRIBUTE_UNUSED, ldouble f9 ATTRIBUTE_UNUSED, ldouble f10 ATTRIBUTE_UNUSED, ldouble f11 ATTRIBUTE_UNUSED, ldouble f12 ATTRIBUTE_UNUSED, ldouble f13 ATTRIBUTE_UNUSED, ldouble f14 ATTRIBUTE_UNUSED, ldouble f15 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_ldouble_arguments;
+}
+
+void
+fun_check_x87_passing_ldouble20_values (ldouble f0 ATTRIBUTE_UNUSED, ldouble f1 ATTRIBUTE_UNUSED, ldouble f2 ATTRIBUTE_UNUSED, ldouble f3 ATTRIBUTE_UNUSED, ldouble f4 ATTRIBUTE_UNUSED, ldouble f5 ATTRIBUTE_UNUSED, ldouble f6 ATTRIBUTE_UNUSED, ldouble f7 ATTRIBUTE_UNUSED, ldouble f8 ATTRIBUTE_UNUSED, ldouble f9 ATTRIBUTE_UNUSED, ldouble f10 ATTRIBUTE_UNUSED, ldouble f11 ATTRIBUTE_UNUSED, ldouble f12 ATTRIBUTE_UNUSED, ldouble f13 ATTRIBUTE_UNUSED, ldouble f14 ATTRIBUTE_UNUSED, ldouble f15 ATTRIBUTE_UNUSED, ldouble f16 ATTRIBUTE_UNUSED, ldouble f17 ATTRIBUTE_UNUSED, ldouble f18 ATTRIBUTE_UNUSED, ldouble f19 ATTRIBUTE_UNUSED)
+{
+ /* Check argument values. */
+ assert (values_ldouble.f0 == f0);
+ assert (values_ldouble.f1 == f1);
+ assert (values_ldouble.f2 == f2);
+ assert (values_ldouble.f3 == f3);
+ assert (values_ldouble.f4 == f4);
+ assert (values_ldouble.f5 == f5);
+ assert (values_ldouble.f6 == f6);
+ assert (values_ldouble.f7 == f7);
+ assert (values_ldouble.f8 == f8);
+ assert (values_ldouble.f9 == f9);
+ assert (values_ldouble.f10 == f10);
+ assert (values_ldouble.f11 == f11);
+ assert (values_ldouble.f12 == f12);
+ assert (values_ldouble.f13 == f13);
+ assert (values_ldouble.f14 == f14);
+ assert (values_ldouble.f15 == f15);
+ assert (values_ldouble.f16 == f16);
+ assert (values_ldouble.f17 == f17);
+ assert (values_ldouble.f18 == f18);
+ assert (values_ldouble.f19 == f19);
+
+}
+
+void
+fun_check_x87_passing_ldouble20_regs (ldouble f0 ATTRIBUTE_UNUSED, ldouble f1 ATTRIBUTE_UNUSED, ldouble f2 ATTRIBUTE_UNUSED, ldouble f3 ATTRIBUTE_UNUSED, ldouble f4 ATTRIBUTE_UNUSED, ldouble f5 ATTRIBUTE_UNUSED, ldouble f6 ATTRIBUTE_UNUSED, ldouble f7 ATTRIBUTE_UNUSED, ldouble f8 ATTRIBUTE_UNUSED, ldouble f9 ATTRIBUTE_UNUSED, ldouble f10 ATTRIBUTE_UNUSED, ldouble f11 ATTRIBUTE_UNUSED, ldouble f12 ATTRIBUTE_UNUSED, ldouble f13 ATTRIBUTE_UNUSED, ldouble f14 ATTRIBUTE_UNUSED, ldouble f15 ATTRIBUTE_UNUSED, ldouble f16 ATTRIBUTE_UNUSED, ldouble f17 ATTRIBUTE_UNUSED, ldouble f18 ATTRIBUTE_UNUSED, ldouble f19 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_ldouble_arguments;
+}
+
+#define def_check_float_passing8(_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _func1, _func2, TYPE) \
+ values_ ## TYPE .f0 = _f0; \
+ values_ ## TYPE .f1 = _f1; \
+ values_ ## TYPE .f2 = _f2; \
+ values_ ## TYPE .f3 = _f3; \
+ values_ ## TYPE .f4 = _f4; \
+ values_ ## TYPE .f5 = _f5; \
+ values_ ## TYPE .f6 = _f6; \
+ values_ ## TYPE .f7 = _f7; \
+ WRAP_CALL(_func1) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7); \
+ \
+ clear_int_registers; \
+ if (sizeof (TYPE) == 4) \
+ { \
+ u.f = _f0; \
+ iregs.I0 = u.i[0]; \
+ u.f = _f1; \
+ iregs.I1 = u.i[0]; \
+ u.f = _f2; \
+ iregs.I2 = u.i[0]; \
+ num_iregs = 3; \
+ } \
+ else \
+ { \
+ u.d = _f0; \
+ iregs.I0 = u.i[0]; \
+ iregs.I1 = u.i[1]; \
+ num_iregs = 2; \
+ } \
+ WRAP_CALL(_func2) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7);
+
+#define def_check_float_passing16(_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15, _func1, _func2, TYPE) \
+ values_ ## TYPE .f0 = _f0; \
+ values_ ## TYPE .f1 = _f1; \
+ values_ ## TYPE .f2 = _f2; \
+ values_ ## TYPE .f3 = _f3; \
+ values_ ## TYPE .f4 = _f4; \
+ values_ ## TYPE .f5 = _f5; \
+ values_ ## TYPE .f6 = _f6; \
+ values_ ## TYPE .f7 = _f7; \
+ values_ ## TYPE .f8 = _f8; \
+ values_ ## TYPE .f9 = _f9; \
+ values_ ## TYPE .f10 = _f10; \
+ values_ ## TYPE .f11 = _f11; \
+ values_ ## TYPE .f12 = _f12; \
+ values_ ## TYPE .f13 = _f13; \
+ values_ ## TYPE .f14 = _f14; \
+ values_ ## TYPE .f15 = _f15; \
+ WRAP_CALL(_func1) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15); \
+ \
+ clear_int_registers; \
+ if (sizeof (TYPE) == 4) \
+ { \
+ u.f = _f0; \
+ iregs.I0 = u.i[0]; \
+ u.f = _f1; \
+ iregs.I1 = u.i[0]; \
+ u.f = _f2; \
+ iregs.I2 = u.i[0]; \
+ num_iregs = 3; \
+ } \
+ else \
+ { \
+ u.d = _f0; \
+ iregs.I0 = u.i[0]; \
+ iregs.I1 = u.i[1]; \
+ num_iregs = 2; \
+ } \
+ WRAP_CALL(_func2) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15);
+
+#define def_check_float_passing20(_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15, _f16, _f17, _f18, _f19, _func1, _func2, TYPE) \
+ values_ ## TYPE .f0 = _f0; \
+ values_ ## TYPE .f1 = _f1; \
+ values_ ## TYPE .f2 = _f2; \
+ values_ ## TYPE .f3 = _f3; \
+ values_ ## TYPE .f4 = _f4; \
+ values_ ## TYPE .f5 = _f5; \
+ values_ ## TYPE .f6 = _f6; \
+ values_ ## TYPE .f7 = _f7; \
+ values_ ## TYPE .f8 = _f8; \
+ values_ ## TYPE .f9 = _f9; \
+ values_ ## TYPE .f10 = _f10; \
+ values_ ## TYPE .f11 = _f11; \
+ values_ ## TYPE .f12 = _f12; \
+ values_ ## TYPE .f13 = _f13; \
+ values_ ## TYPE .f14 = _f14; \
+ values_ ## TYPE .f15 = _f15; \
+ values_ ## TYPE .f16 = _f16; \
+ values_ ## TYPE .f17 = _f17; \
+ values_ ## TYPE .f18 = _f18; \
+ values_ ## TYPE .f19 = _f19; \
+ WRAP_CALL(_func1) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15, _f16, _f17, _f18, _f19); \
+ \
+ clear_int_registers; \
+ if (sizeof (TYPE) == 4) \
+ { \
+ u.f = _f0; \
+ iregs.I0 = u.i[0]; \
+ u.f = _f1; \
+ iregs.I1 = u.i[0]; \
+ u.f = _f2; \
+ iregs.I2 = u.i[0]; \
+ num_iregs = 3; \
+ } \
+ else \
+ { \
+ u.d = _f0; \
+ iregs.I0 = u.i[0]; \
+ iregs.I1 = u.i[1]; \
+ num_iregs = 2; \
+ } \
+ WRAP_CALL(_func2) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15, _f16, _f17, _f18, _f19);
+
+#define def_check_x87_passing8(_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _func1, _func2, TYPE) \
+ values_ ## TYPE .f0 = _f0; \
+ values_ ## TYPE .f1 = _f1; \
+ values_ ## TYPE .f2 = _f2; \
+ values_ ## TYPE .f3 = _f3; \
+ values_ ## TYPE .f4 = _f4; \
+ values_ ## TYPE .f5 = _f5; \
+ values_ ## TYPE .f6 = _f6; \
+ values_ ## TYPE .f7 = _f7; \
+ WRAP_CALL(_func1) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7); \
+ \
+ clear_int_registers; \
+ if (sizeof (TYPE) == 4) \
+ { \
+ u.f = _f0; \
+ iregs.I0 = u.i[0]; \
+ u.f = _f1; \
+ iregs.I1 = u.i[0]; \
+ u.f = _f2; \
+ iregs.I2 = u.i[0]; \
+ num_iregs = 3; \
+ } \
+ else \
+ { \
+ u.d = _f0; \
+ iregs.I0 = u.i[0]; \
+ iregs.I1 = u.i[1]; \
+ num_iregs = 2; \
+ } \
+ WRAP_CALL(_func2) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7);
+
+#define def_check_x87_passing16(_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15, _func1, _func2, TYPE) \
+ values_ ## TYPE .f0 = _f0; \
+ values_ ## TYPE .f1 = _f1; \
+ values_ ## TYPE .f2 = _f2; \
+ values_ ## TYPE .f3 = _f3; \
+ values_ ## TYPE .f4 = _f4; \
+ values_ ## TYPE .f5 = _f5; \
+ values_ ## TYPE .f6 = _f6; \
+ values_ ## TYPE .f7 = _f7; \
+ values_ ## TYPE .f8 = _f8; \
+ values_ ## TYPE .f9 = _f9; \
+ values_ ## TYPE .f10 = _f10; \
+ values_ ## TYPE .f11 = _f11; \
+ values_ ## TYPE .f12 = _f12; \
+ values_ ## TYPE .f13 = _f13; \
+ values_ ## TYPE .f14 = _f14; \
+ values_ ## TYPE .f15 = _f15; \
+ WRAP_CALL(_func1) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15); \
+ \
+ clear_int_registers; \
+ if (sizeof (TYPE) == 4) \
+ { \
+ u.f = _f0; \
+ iregs.I0 = u.i[0]; \
+ u.f = _f1; \
+ iregs.I1 = u.i[0]; \
+ u.f = _f2; \
+ iregs.I2 = u.i[0]; \
+ num_iregs = 3; \
+ } \
+ else \
+ { \
+ u.d = _f0; \
+ iregs.I0 = u.i[0]; \
+ iregs.I1 = u.i[1]; \
+ num_iregs = 2; \
+ } \
+ WRAP_CALL(_func2) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15);
+
+#define def_check_x87_passing20(_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15, _f16, _f17, _f18, _f19, _func1, _func2, TYPE) \
+ values_ ## TYPE .f0 = _f0; \
+ values_ ## TYPE .f1 = _f1; \
+ values_ ## TYPE .f2 = _f2; \
+ values_ ## TYPE .f3 = _f3; \
+ values_ ## TYPE .f4 = _f4; \
+ values_ ## TYPE .f5 = _f5; \
+ values_ ## TYPE .f6 = _f6; \
+ values_ ## TYPE .f7 = _f7; \
+ values_ ## TYPE .f8 = _f8; \
+ values_ ## TYPE .f9 = _f9; \
+ values_ ## TYPE .f10 = _f10; \
+ values_ ## TYPE .f11 = _f11; \
+ values_ ## TYPE .f12 = _f12; \
+ values_ ## TYPE .f13 = _f13; \
+ values_ ## TYPE .f14 = _f14; \
+ values_ ## TYPE .f15 = _f15; \
+ values_ ## TYPE .f16 = _f16; \
+ values_ ## TYPE .f17 = _f17; \
+ values_ ## TYPE .f18 = _f18; \
+ values_ ## TYPE .f19 = _f19; \
+ WRAP_CALL(_func1) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15, _f16, _f17, _f18, _f19); \
+ \
+ clear_int_registers; \
+ if (sizeof (TYPE) == 4) \
+ { \
+ u.f = _f0; \
+ iregs.I0 = u.i[0]; \
+ u.f = _f1; \
+ iregs.I1 = u.i[0]; \
+ u.f = _f2; \
+ iregs.I2 = u.i[0]; \
+ num_iregs = 3; \
+ } \
+ else \
+ { \
+ u.d = _f0; \
+ iregs.I0 = u.i[0]; \
+ iregs.I1 = u.i[1]; \
+ num_iregs = 2; \
+ } \
+ WRAP_CALL(_func2) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15, _f16, _f17, _f18, _f19);
+
+void
+test_floats_on_stack ()
+{
+ union
+ {
+ float f;
+ double d;
+ int i[2];
+ } u;
+ def_check_float_passing8(32, 33, 34, 35, 36, 37, 38, 39, fun_check_float_passing_float8_values, fun_check_float_passing_float8_regs, float);
+
+ def_check_float_passing16(32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, fun_check_float_passing_float16_values, fun_check_float_passing_float16_regs, float);
+}
+
+void
+test_too_many_floats ()
+{
+ union
+ {
+ float f;
+ double d;
+ int i[2];
+ } u;
+ def_check_float_passing20(32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, fun_check_float_passing_float20_values, fun_check_float_passing_float20_regs, float);
+}
+
+void
+test_doubles_on_stack ()
+{
+ union
+ {
+ float f;
+ double d;
+ int i[2];
+ } u;
+ def_check_float_passing8(32, 33, 34, 35, 36, 37, 38, 39, fun_check_float_passing_double8_values, fun_check_float_passing_double8_regs, double);
+
+ def_check_float_passing16(32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, fun_check_float_passing_double16_values, fun_check_float_passing_double16_regs, double);
+}
+
+void
+test_too_many_doubles ()
+{
+ union
+ {
+ float f;
+ double d;
+ int i[2];
+ } u;
+ def_check_float_passing20(32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, fun_check_float_passing_double20_values, fun_check_float_passing_double20_regs, double);
+}
+
+void
+test_long_doubles_on_stack ()
+{
+ union
+ {
+ float f;
+ double d;
+ int i[2];
+ } u;
+ def_check_x87_passing8(32, 33, 34, 35, 36, 37, 38, 39, fun_check_x87_passing_ldouble8_values, fun_check_x87_passing_ldouble8_regs, ldouble);
+}
+
+void
+test_too_many_long_doubles ()
+{
+ union
+ {
+ float f;
+ double d;
+ int i[2];
+ } u;
+ def_check_x87_passing20(32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, fun_check_x87_passing_ldouble20_values, fun_check_x87_passing_ldouble20_regs, ldouble);
+}
+
+void
+test_float128s_on_stack ()
+{
+}
+
+void
+test_too_many_float128s ()
+{
+}
+
+
+int
+main (void)
+{
+ test_floats_on_stack ();
+ test_too_many_floats ();
+ test_doubles_on_stack ();
+ test_too_many_doubles ();
+ test_long_doubles_on_stack ();
+ test_too_many_long_doubles ();
+ test_float128s_on_stack ();
+ test_too_many_float128s ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/iamcu/test_passing_integers.c b/gcc/testsuite/gcc.target/i386/iamcu/test_passing_integers.c
new file mode 100644
index 0000000..046e140
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/iamcu/test_passing_integers.c
@@ -0,0 +1,182 @@
+#include "defines.h"
+#include "macros.h"
+#include "args.h"
+
+struct IntegerRegisters iregbits = { ~0, ~0, ~0, ~0, ~0, ~0 };
+struct IntegerRegisters iregs;
+unsigned int num_iregs;
+
+/* This struct holds values for argument checking. */
+struct
+{
+ int i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14, i15, i16, i17, i18, i19, i20, i21, i22, i23;
+} values_int;
+
+struct
+{
+ long i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14, i15, i16, i17, i18, i19, i20, i21, i22, i23;
+} values_long;
+
+void
+fun_check_int_passing_int6_values (int i0 ATTRIBUTE_UNUSED, int i1 ATTRIBUTE_UNUSED, int i2 ATTRIBUTE_UNUSED, int i3 ATTRIBUTE_UNUSED, int i4 ATTRIBUTE_UNUSED, int i5 ATTRIBUTE_UNUSED)
+{
+ /* Check argument values. */
+ assert (values_int.i0 == i0);
+ assert (values_int.i1 == i1);
+ assert (values_int.i2 == i2);
+ assert (values_int.i3 == i3);
+ assert (values_int.i4 == i4);
+ assert (values_int.i5 == i5);
+
+}
+
+void
+fun_check_int_passing_int6_regs (int i0 ATTRIBUTE_UNUSED, int i1 ATTRIBUTE_UNUSED, int i2 ATTRIBUTE_UNUSED, int i3 ATTRIBUTE_UNUSED, int i4 ATTRIBUTE_UNUSED, int i5 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_int_arguments;
+}
+
+void
+fun_check_int_passing_int12_values (int i0 ATTRIBUTE_UNUSED, int i1 ATTRIBUTE_UNUSED, int i2 ATTRIBUTE_UNUSED, int i3 ATTRIBUTE_UNUSED, int i4 ATTRIBUTE_UNUSED, int i5 ATTRIBUTE_UNUSED, int i6 ATTRIBUTE_UNUSED, int i7 ATTRIBUTE_UNUSED, int i8 ATTRIBUTE_UNUSED, int i9 ATTRIBUTE_UNUSED, int i10 ATTRIBUTE_UNUSED, int i11 ATTRIBUTE_UNUSED)
+{
+ /* Check argument values. */
+ assert (values_int.i0 == i0);
+ assert (values_int.i1 == i1);
+ assert (values_int.i2 == i2);
+ assert (values_int.i3 == i3);
+ assert (values_int.i4 == i4);
+ assert (values_int.i5 == i5);
+ assert (values_int.i6 == i6);
+ assert (values_int.i7 == i7);
+ assert (values_int.i8 == i8);
+ assert (values_int.i9 == i9);
+ assert (values_int.i10 == i10);
+ assert (values_int.i11 == i11);
+
+}
+
+void
+fun_check_int_passing_int12_regs (int i0 ATTRIBUTE_UNUSED, int i1 ATTRIBUTE_UNUSED, int i2 ATTRIBUTE_UNUSED, int i3 ATTRIBUTE_UNUSED, int i4 ATTRIBUTE_UNUSED, int i5 ATTRIBUTE_UNUSED, int i6 ATTRIBUTE_UNUSED, int i7 ATTRIBUTE_UNUSED, int i8 ATTRIBUTE_UNUSED, int i9 ATTRIBUTE_UNUSED, int i10 ATTRIBUTE_UNUSED, int i11 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_int_arguments;
+}
+
+void
+fun_check_int_passing_long6_values (long i0 ATTRIBUTE_UNUSED, long i1 ATTRIBUTE_UNUSED, long i2 ATTRIBUTE_UNUSED, long i3 ATTRIBUTE_UNUSED, long i4 ATTRIBUTE_UNUSED, long i5 ATTRIBUTE_UNUSED)
+{
+ /* Check argument values. */
+ assert (values_long.i0 == i0);
+ assert (values_long.i1 == i1);
+ assert (values_long.i2 == i2);
+ assert (values_long.i3 == i3);
+ assert (values_long.i4 == i4);
+ assert (values_long.i5 == i5);
+
+}
+
+void
+fun_check_int_passing_long6_regs (long i0 ATTRIBUTE_UNUSED, long i1 ATTRIBUTE_UNUSED, long i2 ATTRIBUTE_UNUSED, long i3 ATTRIBUTE_UNUSED, long i4 ATTRIBUTE_UNUSED, long i5 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_long_arguments;
+}
+
+void
+fun_check_int_passing_long12_values (long i0 ATTRIBUTE_UNUSED, long i1 ATTRIBUTE_UNUSED, long i2 ATTRIBUTE_UNUSED, long i3 ATTRIBUTE_UNUSED, long i4 ATTRIBUTE_UNUSED, long i5 ATTRIBUTE_UNUSED, long i6 ATTRIBUTE_UNUSED, long i7 ATTRIBUTE_UNUSED, long i8 ATTRIBUTE_UNUSED, long i9 ATTRIBUTE_UNUSED, long i10 ATTRIBUTE_UNUSED, long i11 ATTRIBUTE_UNUSED)
+{
+ /* Check argument values. */
+ assert (values_long.i0 == i0);
+ assert (values_long.i1 == i1);
+ assert (values_long.i2 == i2);
+ assert (values_long.i3 == i3);
+ assert (values_long.i4 == i4);
+ assert (values_long.i5 == i5);
+ assert (values_long.i6 == i6);
+ assert (values_long.i7 == i7);
+ assert (values_long.i8 == i8);
+ assert (values_long.i9 == i9);
+ assert (values_long.i10 == i10);
+ assert (values_long.i11 == i11);
+
+}
+
+void
+fun_check_int_passing_long12_regs (long i0 ATTRIBUTE_UNUSED, long i1 ATTRIBUTE_UNUSED, long i2 ATTRIBUTE_UNUSED, long i3 ATTRIBUTE_UNUSED, long i4 ATTRIBUTE_UNUSED, long i5 ATTRIBUTE_UNUSED, long i6 ATTRIBUTE_UNUSED, long i7 ATTRIBUTE_UNUSED, long i8 ATTRIBUTE_UNUSED, long i9 ATTRIBUTE_UNUSED, long i10 ATTRIBUTE_UNUSED, long i11 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_long_arguments;
+}
+
+#define def_check_int_passing6(_i0, _i1, _i2, _i3, _i4, _i5, _func1, _func2, TYPE) \
+ values_ ## TYPE .i0 = _i0; \
+ values_ ## TYPE .i1 = _i1; \
+ values_ ## TYPE .i2 = _i2; \
+ values_ ## TYPE .i3 = _i3; \
+ values_ ## TYPE .i4 = _i4; \
+ values_ ## TYPE .i5 = _i5; \
+ WRAP_CALL(_func1) (_i0, _i1, _i2, _i3, _i4, _i5); \
+ \
+ clear_int_registers; \
+ iregs.I0 = _i0; \
+ iregs.I1 = _i1; \
+ iregs.I2 = _i2; \
+ num_iregs = 3; \
+ WRAP_CALL(_func2) (_i0, _i1, _i2, _i3, _i4, _i5);
+
+#define def_check_int_passing12(_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, _i9, _i10, _i11, _func1, _func2, TYPE) \
+ values_ ## TYPE .i0 = _i0; \
+ values_ ## TYPE .i1 = _i1; \
+ values_ ## TYPE .i2 = _i2; \
+ values_ ## TYPE .i3 = _i3; \
+ values_ ## TYPE .i4 = _i4; \
+ values_ ## TYPE .i5 = _i5; \
+ values_ ## TYPE .i6 = _i6; \
+ values_ ## TYPE .i7 = _i7; \
+ values_ ## TYPE .i8 = _i8; \
+ values_ ## TYPE .i9 = _i9; \
+ values_ ## TYPE .i10 = _i10; \
+ values_ ## TYPE .i11 = _i11; \
+ WRAP_CALL(_func1) (_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, _i9, _i10, _i11); \
+ \
+ clear_int_registers; \
+ iregs.I0 = _i0; \
+ iregs.I1 = _i1; \
+ iregs.I2 = _i2; \
+ num_iregs = 3; \
+ WRAP_CALL(_func2) (_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, _i9, _i10, _i11);
+
+void
+test_ints_on_stack ()
+{
+ def_check_int_passing6(32, 33, 34, 35, 36, 37, fun_check_int_passing_int6_values, fun_check_int_passing_int6_regs, int);
+}
+
+void
+test_too_many_ints ()
+{
+ def_check_int_passing12(32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, fun_check_int_passing_int12_values, fun_check_int_passing_int12_regs, int);
+}
+
+void
+test_longs_on_stack ()
+{
+ def_check_int_passing6(32, 33, 34, 35, 36, 37, fun_check_int_passing_long6_values, fun_check_int_passing_long6_regs, long);
+}
+
+void
+test_too_many_longs ()
+{
+ def_check_int_passing12(32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, fun_check_int_passing_long12_values, fun_check_int_passing_long12_regs, long);
+}
+
+int
+main (void)
+{
+ test_ints_on_stack ();
+ test_too_many_ints ();
+ test_longs_on_stack ();
+ test_too_many_longs ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/iamcu/test_passing_structs.c b/gcc/testsuite/gcc.target/i386/iamcu/test_passing_structs.c
new file mode 100644
index 0000000..1660a4d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/iamcu/test_passing_structs.c
@@ -0,0 +1,237 @@
+/* This tests passing of structs. */
+
+#include "defines.h"
+#include "args.h"
+#include <complex.h>
+
+struct IntegerRegisters iregbits = { ~0, ~0, ~0, ~0, ~0, ~0 };
+struct IntegerRegisters iregs;
+unsigned int num_iregs;
+
+struct int_struct
+{
+ int i;
+};
+
+struct long_struct
+{
+ long l;
+};
+
+struct longlong2_struct
+{
+ long long ll1, ll2;
+};
+
+struct longlong3_struct
+{
+ long long ll1, ll2, ll3;
+};
+
+/* Check that the struct is passed as the individual members in iregs. */
+void
+check_struct_passing1 (struct int_struct is ATTRIBUTE_UNUSED)
+{
+ check_int_arguments;
+}
+
+void
+check_struct_passing2 (struct long_struct ls ATTRIBUTE_UNUSED)
+{
+ check_int_arguments;
+}
+
+void
+check_struct_passing3 (struct longlong2_struct ls ATTRIBUTE_UNUSED)
+{
+ check_int_arguments;
+}
+
+void
+check_struct_passing4 (struct longlong3_struct ls ATTRIBUTE_UNUSED)
+{
+ /* Check the passing on the stack by comparing the address of the
+ stack elements to the expected place on the stack. */
+ assert ((unsigned long)&ls.ll1 == esp+4);
+ assert ((unsigned long)&ls.ll2 == esp+12);
+ assert ((unsigned long)&ls.ll3 == esp+20);
+}
+
+struct flex1_struct
+{
+ long i;
+ long flex[];
+};
+
+struct flex2_struct
+{
+ long i;
+ long flex[0];
+};
+
+void
+check_struct_passing7 (struct flex1_struct is ATTRIBUTE_UNUSED)
+{
+ check_int_arguments;
+}
+
+void
+check_struct_passing8 (struct flex2_struct is ATTRIBUTE_UNUSED)
+{
+ check_int_arguments;
+}
+
+struct complex1_struct
+{
+ __complex__ float x;
+};
+
+struct complex1a_struct
+{
+ long l;
+ union
+ {
+ float f;
+ int i;
+ } u;
+};
+
+void
+check_struct_passing9 (struct complex1_struct is ATTRIBUTE_UNUSED)
+{
+ check_int_arguments;
+}
+
+struct long3_struct
+{
+ long l1, l2, l3;
+};
+
+void
+check_struct_passing10 (struct long3_struct ls ATTRIBUTE_UNUSED)
+{
+ /* Check the passing on the stack by comparing the address of the
+ stack elements to the expected place on the stack. */
+ assert ((unsigned long)&ls.l1 == esp+4);
+ assert ((unsigned long)&ls.l2 == esp+8);
+ assert ((unsigned long)&ls.l3 == esp+12);
+}
+
+struct char3_struct
+{
+ char c1, c2, c3;
+};
+
+void
+check_struct_passing11 (struct char3_struct is ATTRIBUTE_UNUSED)
+{
+ check_int_arguments;
+}
+
+struct char7_struct
+{
+ char c1, c2, c3, c4, c5, c6, c7;
+};
+
+void
+check_struct_passing12 (struct char7_struct is ATTRIBUTE_UNUSED)
+{
+ check_int_arguments;
+}
+
+static struct flex1_struct f1s = { 60, { } };
+static struct flex2_struct f2s = { 61, { } };
+
+int
+main (void)
+{
+ struct int_struct is = { 48 };
+ struct long_struct ls = { 49 };
+#ifdef CHECK_LARGER_STRUCTS
+ struct longlong2_struct ll2s = { 50, 51 };
+ struct longlong3_struct ll3s = { 52, 53, 54 };
+ struct long3_struct l3s = { 60, 61, 62 };
+#endif
+ struct complex1_struct c1s = { ( -13.4 + 3.5*I ) };
+ union
+ {
+ struct complex1_struct c;
+ struct complex1a_struct u;
+ } c1u;
+ struct char3_struct c3 = { 0x12, 0x34, 0x56 };
+ union
+ {
+ struct char3_struct c;
+ int i;
+ } c3u;
+ struct char7_struct c7 = { 0x12, 0x34, 0x56, 0x78, 0x12, 0x34, 0x56 };
+ union
+ {
+ struct char7_struct c;
+ struct
+ {
+ int i0, i1;
+ } i;
+ } c7u;
+
+ clear_struct_registers;
+ iregs.I0 = is.i;
+ num_iregs = 1;
+ clear_int_hardware_registers;
+ WRAP_CALL (check_struct_passing1)(is);
+
+ clear_struct_registers;
+ iregs.I0 = ls.l;
+ num_iregs = 1;
+ clear_int_hardware_registers;
+ WRAP_CALL (check_struct_passing2)(ls);
+
+#ifdef CHECK_LARGER_STRUCTS
+ clear_struct_registers;
+ num_iregs = 0;
+ clear_int_hardware_registers;
+ WRAP_CALL (check_struct_passing3)(ll2s);
+ WRAP_CALL (check_struct_passing4)(ll3s);
+ WRAP_CALL (check_struct_passing10)(l3s);
+#endif
+
+ clear_struct_registers;
+ iregs.I0 = f1s.i;
+ num_iregs = 1;
+ clear_int_hardware_registers;
+ WRAP_CALL (check_struct_passing7)(f1s);
+
+ clear_struct_registers;
+ iregs.I0 = f2s.i;
+ num_iregs = 1;
+ clear_int_hardware_registers;
+ WRAP_CALL (check_struct_passing8)(f2s);
+
+ clear_struct_registers;
+ c1u.c = c1s;
+ iregs.I0 = c1u.u.l;
+ iregs.I1 = c1u.u.u.i;
+ num_iregs = 2;
+ clear_int_hardware_registers;
+ WRAP_CALL (check_struct_passing9)(c1s);
+
+ clear_struct_registers;
+ c3u.c = c3;
+ iregs.I0 = c3u.i;
+ iregbits.I0 = 0xffffff;
+ num_iregs = 1;
+ clear_int_hardware_registers;
+ WRAP_CALL (check_struct_passing11)(c3);
+
+ clear_struct_registers;
+ c7u.c = c7;
+ iregs.I0 = c7u.i.i0;
+ iregs.I1 = c7u.i.i1;
+ iregbits.I0 = 0xffffffff;
+ iregbits.I1 = 0xffffff;
+ num_iregs = 2;
+ clear_int_hardware_registers;
+ WRAP_CALL (check_struct_passing12)(c7);
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/iamcu/test_passing_structs_and_unions.c b/gcc/testsuite/gcc.target/i386/iamcu/test_passing_structs_and_unions.c
new file mode 100644
index 0000000..ff6354c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/iamcu/test_passing_structs_and_unions.c
@@ -0,0 +1,97 @@
+/* This tests passing of structs. Only integers are tested. */
+
+#include "defines.h"
+#include "args.h"
+
+struct IntegerRegisters iregbits = { ~0, ~0, ~0, ~0, ~0, ~0 };
+struct IntegerRegisters iregs;
+unsigned int num_iregs;
+
+struct int_struct
+{
+ int i;
+};
+
+struct longlong_struct
+{
+ long long ll;
+};
+
+struct long2_struct
+{
+ long long ll1, ll2;
+};
+
+struct long3_struct
+{
+ long l1, l2, l3;
+};
+
+union un1
+{
+ char c;
+ int i;
+};
+
+union un2
+{
+ char c1;
+ long l;
+ char c2;
+};
+
+union un3
+{
+ struct int_struct is;
+ struct longlong_struct ls;
+ union un1 un;
+};
+
+
+void
+check_mixed_passing1 (char c1 ATTRIBUTE_UNUSED, struct int_struct is ATTRIBUTE_UNUSED, char c2 ATTRIBUTE_UNUSED)
+{
+ check_int_arguments;
+}
+
+void
+check_mixed_passing2 (char c1 ATTRIBUTE_UNUSED, struct long3_struct ls ATTRIBUTE_UNUSED, char c2 ATTRIBUTE_UNUSED)
+{
+ check_int_arguments;
+
+ /* Check the passing on the stack by comparing the address of the
+ stack elements to the expected place on the stack. */
+ assert ((unsigned long)&ls.l1 == esp+4);
+ assert ((unsigned long)&ls.l2 == esp+8);
+ assert ((unsigned long)&ls.l3 == esp+12);
+}
+
+int
+main (void)
+{
+ struct int_struct is = { 64 };
+#ifdef CHECK_LARGER_STRUCTS
+ struct long3_struct l3s = { 65, 66, 67 };
+#endif
+
+ clear_struct_registers;
+ iregs.I0 = 8;
+ iregs.I1 = 64;
+ iregs.I2 = 9;
+ num_iregs = 3;
+ clear_int_hardware_registers;
+ WRAP_CALL (check_mixed_passing1)(8, is, 9);
+
+#ifdef CHECK_LARGER_STRUCTS
+ clear_struct_registers;
+ iregs.I0 = 10;
+ iregbits.I0 = 0xff;
+ iregs.I1 = 11;
+ iregbits.I1 = 0xff;
+ num_iregs = 2;
+ clear_int_hardware_registers;
+ WRAP_CALL (check_mixed_passing2)(10, l3s, 11);
+#endif
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/iamcu/test_passing_unions.c b/gcc/testsuite/gcc.target/i386/iamcu/test_passing_unions.c
new file mode 100644
index 0000000..534fc85
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/iamcu/test_passing_unions.c
@@ -0,0 +1,221 @@
+/* This tests passing of structs. */
+
+#include "defines.h"
+#include "args.h"
+
+struct IntegerRegisters iregbits = { ~0, ~0, ~0, ~0, ~0, ~0 };
+struct IntegerRegisters iregs;
+unsigned int num_iregs;
+
+struct int_struct
+{
+ int i;
+};
+
+struct long_struct
+{
+ long l;
+};
+
+union un1
+{
+ char c;
+ int i;
+};
+
+union un2
+{
+ char c1;
+ long l;
+ char c2;
+};
+
+union un3
+{
+ struct int_struct is;
+ struct long_struct ls;
+ union un1 un;
+};
+
+
+void
+check_union_passing1(union un1 u ATTRIBUTE_UNUSED)
+{
+ check_int_arguments;
+}
+
+void
+check_union_passing2(union un2 u1 ATTRIBUTE_UNUSED)
+{
+ check_int_arguments;
+}
+
+void
+check_union_passing3(union un3 u ATTRIBUTE_UNUSED)
+{
+ check_int_arguments;
+}
+
+#define check_union_passing1 WRAP_CALL(check_union_passing1)
+#define check_union_passing2 WRAP_CALL(check_union_passing2)
+#define check_union_passing3 WRAP_CALL(check_union_passing3)
+
+union un4
+{
+ int i;
+ float f;
+};
+
+union un5
+{
+ long long ll;
+ double d;
+};
+
+void
+check_union_passing4(union un4 u1 ATTRIBUTE_UNUSED,
+ union un4 u2 ATTRIBUTE_UNUSED,
+ union un4 u3 ATTRIBUTE_UNUSED,
+ union un4 u4 ATTRIBUTE_UNUSED,
+ union un4 u5 ATTRIBUTE_UNUSED,
+ union un4 u6 ATTRIBUTE_UNUSED,
+ union un4 u7 ATTRIBUTE_UNUSED,
+ union un4 u8 ATTRIBUTE_UNUSED)
+{
+ check_int_arguments;
+}
+
+void
+check_union_passing5(union un5 u ATTRIBUTE_UNUSED)
+{
+ check_int_arguments;
+}
+
+#define check_union_passing4 WRAP_CALL(check_union_passing4)
+#define check_union_passing5 WRAP_CALL(check_union_passing5)
+
+union un6
+{
+ __float128 f128;
+ int i;
+};
+
+
+void
+check_union_passing6(union un6 u ATTRIBUTE_UNUSED)
+{
+ /* Check the passing on the stack by comparing the address of the
+ stack elements to the expected place on the stack. */
+ assert ((unsigned long)&u.f128 == esp+4);
+ assert ((unsigned long)&u.i == esp+4);
+}
+
+#define check_union_passing6 WRAP_CALL(check_union_passing6)
+
+int
+main (void)
+{
+ union un1 u1;
+#ifdef CHECK_LARGER_UNION_PASSING
+ union un2 u2;
+ union un3 u3;
+ struct int_struct is;
+ struct long_struct ls;
+#endif /* CHECK_LARGER_UNION_PASSING */
+ union un4 u4[8];
+ union un5 u5 = { { 48.394, 39.3, -397.9, 3484.9 } };
+ int i;
+ union un6 u6;
+
+ /* Check a union with char, int. */
+ clear_struct_registers;
+ u1.i = 0; /* clear the struct to not have high bits left */
+ u1.c = 32;
+ iregs.I0 = 32;
+ num_iregs = 1;
+ clear_int_hardware_registers;
+ check_union_passing1(u1);
+ u1.i = 0; /* clear the struct to not have high bits left */
+ u1.i = 33;
+ iregs.I0 = 33;
+ num_iregs = 1;
+ clear_int_hardware_registers;
+ check_union_passing1(u1);
+
+ /* Check a union with char, long, char. */
+#ifdef CHECK_LARGER_UNION_PASSING
+ clear_struct_registers;
+ u2.l = 0; /* clear the struct to not have high bits left */
+ u2.c1 = 34;
+ iregs.I0 = 34;
+ num_iregs = 1;
+ clear_int_hardware_registers;
+ check_union_passing2(u2);
+ u2.l = 0; /* clear the struct to not have high bits left */
+ u2.l = 35;
+ iregs.I0 = 35;
+ num_iregs = 1;
+ clear_int_hardware_registers;
+ check_union_passing2(u2);
+ u2.l = 0; /* clear the struct to not have high bits left */
+ u2.c2 = 36;
+ iregs.I0 = 36;
+ num_iregs = 1;
+ clear_int_hardware_registers;
+ check_union_passing2(u2);
+
+ /* check a union containing two structs and a union. */
+ clear_struct_registers;
+ is.i = 37;
+ u3.ls.l = 0; /* clear the struct to not have high bits left */
+ u3.is = is;
+ iregs.I0 = 37;
+ num_iregs = 1;
+ clear_int_hardware_registers;
+ check_union_passing3(u3);
+ ls.l = 38;
+ u3.ls.l = 0; /* clear the struct to not have high bits left */
+ u3.ls = ls;
+ iregs.I0 = 38;
+ num_iregs = 1;
+ clear_int_hardware_registers;
+ check_union_passing3(u3);
+ u1.c = 39;
+ u3.ls.l = 0; /* clear the struct to not have high bits left */
+ u3.un = u1;
+ iregs.I0 = 39;
+ num_iregs = 1;
+ clear_int_hardware_registers;
+ check_union_passing3(u3);
+ u1.i = 40;
+ u3.ls.l = 0; /* clear the struct to not have high bits left */
+ u3.un = u1;
+ iregs.I0 = 40;
+ num_iregs = 1;
+ clear_int_hardware_registers;
+ check_union_passing3(u3);
+#endif /* CHECK_LARGER_UNION_PASSING */
+
+ clear_struct_registers;
+ for (i = 0; i < 8; i++)
+ u4[i].f = 32 + i;
+ iregs.I0 = u4[0].i;
+ iregs.I1 = u4[1].i;
+ iregs.I2 = u4[2].i;
+ num_iregs = 3;
+ clear_int_hardware_registers;
+ check_union_passing4(u4[0], u4[1], u4[2], u4[3],
+ u4[4], u4[5], u4[6], u4[7]);
+
+ clear_struct_registers;
+ iregs.I0 = u5.ll & 0xffffffff;
+ iregs.I1 = (u5.ll >> 32) & 0xffffffff;
+ num_iregs = 2;
+ clear_int_hardware_registers;
+ check_union_passing5(u5);
+
+ u6.i = 2;
+ check_union_passing6(u6);
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/iamcu/test_struct_returning.c b/gcc/testsuite/gcc.target/i386/iamcu/test_struct_returning.c
new file mode 100644
index 0000000..49a6b1f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/iamcu/test_struct_returning.c
@@ -0,0 +1,362 @@
+/* This tests returning of structures. */
+
+#include "defines.h"
+#include "macros.h"
+#include "args.h"
+
+struct IntegerRegisters iregbits = { ~0, ~0, ~0, ~0, ~0, ~0 };
+struct IntegerRegisters iregs;
+unsigned int num_iregs;
+
+int current_test;
+int num_failed = 0;
+
+typedef enum {
+ EAX = 0,
+ EAX_EDX,
+ LONG_LONG,
+ FLOAT,
+ DOUBLE,
+ FLOAT_FLOAT,
+ EAX_FLOAT,
+ FLOAT_EDX,
+ MEM
+} Type;
+
+/* Structures which should be returned in EAX/LONG_LONG/EAX_EDX. */
+#define D(I,MEMBERS,C,B) struct S_ ## I { MEMBERS ; }; Type class_ ## I = C; \
+struct S_ ## I f_ ## I (void) { struct S_ ## I s; iamcu_memset (&s, 0, sizeof(s)); B; return s; }
+
+D(1,char m1, EAX, s.m1=42)
+D(2,short m1, EAX, s.m1=42)
+D(3,int m1, EAX, s.m1=42)
+D(4,char m1[3], EAX, s.m1[0]=42)
+D(5,char m1[4], EAX, s.m1[0]=42)
+D(6,char m1;char m2; char m3, EAX, s.m1=42)
+D(7,char m1;short m2, EAX, s.m1=42)
+
+D(30,long long m1, LONG_LONG, s.m1=0xadadbeefadadbeefLL)
+
+D(50,short m1;int m2, EAX_EDX, s.m1=42; s.m2=43)
+D(51,char m1;int m2, EAX_EDX, s.m1=42; s.m2=43)
+D(52,char m1[5], EAX_EDX, s.m1[0]=42; s.m1[4]=43)
+D(53,char m1[6], EAX_EDX, s.m1[0]=42; s.m1[4]=43)
+D(54,char m1[7], EAX_EDX, s.m1[0]=42; s.m1[4]=43)
+D(55,char m1[8], EAX_EDX, s.m1[0]=42; s.m1[4]=43)
+D(56,char m1;short m2[2], EAX_EDX, s.m1=42; s.m2[1]=43)
+D(57,short m1[4], EAX_EDX, s.m1[0]=42; s.m1[2]=43)
+D(58,int m1[2], EAX_EDX, s.m1[0]=42; s.m1[1]=43)
+D(59,int m1;char m2, EAX_EDX, s.m1=42; s.m2=43)
+D(60,int m1;short m2, EAX_EDX, s.m1=42; s.m2=43)
+D(61,int m1;short m2; char m3, EAX_EDX, s.m1=42; s.m2=43)
+D(62,int m1;char m2; short m3, EAX_EDX, s.m1=42; s.m2=43)
+
+/* Packed members. */
+D(100,short m1[1];int m2 PACKED, EAX_EDX, s.m1[0]=42; s.m2=43)
+D(101,char m1; short m2 PACKED; char m3, EAX_EDX, s.m1=42; s.m3=43)
+
+/* Structures which should be returned in FLOAT/DOUBLE. */
+#undef D
+#define D(I,MEMBERS,C,B) struct S_ ## I { MEMBERS ; }; Type class_ ## I = C; \
+struct S_ ## I f_ ## I (void) { struct S_ ## I s; iamcu_memset (&s, 0, sizeof(s)); B; return s; }
+
+D(200,float f, FLOAT, s.f=42)
+D(201,double d, DOUBLE, s.d=42)
+
+D(300,float m;char m2, FLOAT_EDX, s.m=42; s.m2=43)
+D(301,float m;short m2, FLOAT_EDX, s.m=42; s.m2=43)
+D(302,float m;int m2, FLOAT_EDX, s.m=42; s.m2=43)
+
+D(400,char m1; float m2, EAX_FLOAT, s.m1=42; s.m2=43)
+D(401,short m1; float m2, EAX_FLOAT, s.m1=42; s.m2=43)
+D(402,int m1; float m2, EAX_FLOAT, s.m1=42; s.m2=43)
+
+D(500,float m;float m2, FLOAT_FLOAT, s.m=42; s.m2=43)
+D(501,float f[2], FLOAT, s.f[0]=42; s.f[1]=43)
+
+/* Structures which should be returned in MEM. */
+void *struct_addr;
+#undef D
+#define D(I,MEMBERS) struct S_ ## I { MEMBERS ; }; Type class_ ## I = MEM; \
+struct S_ ## I f_ ## I (void) { union {unsigned char c; struct S_ ## I s;} u; iamcu_memset (&u.s, 0, sizeof(u.s)); u.c = 42; return u.s; }
+
+/* Too large. */
+D(600,char m1[17])
+D(601,short m1[9])
+D(602,int m1[5])
+D(603,long m1[3])
+D(604,short m1[8];char c)
+D(605,char m1[1];int i[4])
+D(606,float m1[5])
+D(607,double m1[3])
+D(608,char m1[1];float f[4])
+D(609,char m1[1];double d[2])
+D(610,__complex long double m1[1])
+
+/* Too large due to padding. */
+D(611,char m1[1]; int i; char c2)
+
+/* Special tests. */
+#undef D
+#define D(I,MEMBERS,B) struct S_ ## I { MEMBERS ; }; Type class_ ## I = MEM; \
+struct S_ ## I f_ ## I (void) { struct S_ ## I s; B; return s; }
+D(700,float f[4], s.f[0] = s.f[1] = s.f[2] = s.f[3] = 42)
+
+void
+check_eax (void)
+{
+ switch (current_test)
+ {
+ case 1:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ eax &= 0xff;
+ break;
+ case 2:
+ eax &= 0xffff;
+ break;
+ case 3:
+ eax &= 0xffff;
+ break;
+ default:
+ abort ();
+ }
+ if (eax != 42)
+ num_failed++;
+}
+
+void
+check_eax_edx (void)
+{
+ unsigned long long ll = eax | ((unsigned long long) edx) << 32;
+ switch (current_test)
+ {
+ case 50:
+ eax &= 0xffff;
+ break;
+ case 52:
+ case 53:
+ case 54:
+ case 55:
+ edx &= 0xff;
+ case 51:
+ eax &= 0xff;
+ break;
+ case 56:
+ eax &= 0xff;
+ edx &= 0xffff;
+ break;
+ case 57:
+ eax &= 0xffff;
+ edx &= 0xffff;
+ break;
+ case 58:
+ break;
+ case 59:
+ case 62:
+ edx &= 0xff;
+ break;
+ case 60:
+ case 61:
+ edx &= 0xffff;
+ break;
+ case 100:
+ eax &= 0xffff;
+ edx = (ll >> 16) & 0xffffffff;
+ break;
+ case 101:
+ edx = (eax >> 24) & 0xff;
+ eax &= 0xff;
+ break;
+ default:
+ abort ();
+ }
+ if (eax != 42 || edx != 43)
+ num_failed++;
+}
+
+void
+check_float_edx (void)
+{
+ union
+ {
+ unsigned long l;
+ float f;
+ } ueax;
+ switch (current_test)
+ {
+ case 300:
+ edx &= 0xff;
+ break;
+ case 301:
+ edx &= 0xffff;
+ break;
+ case 302:
+ edx &= 0xffff;
+ break;
+ default:
+ abort ();
+ }
+ ueax.l = eax;
+ if (ueax.f != 42 || edx != 43)
+ num_failed++;
+}
+
+void
+check_eax_float (void)
+{
+ union
+ {
+ unsigned long l;
+ float f;
+ } uedx;
+ switch (current_test)
+ {
+ case 400:
+ eax &= 0xff;
+ break;
+ case 401:
+ eax &= 0xffff;
+ break;
+ case 402:
+ eax &= 0xffff;
+ break;
+ default:
+ abort ();
+ }
+ uedx.l = edx;
+ if (eax != 42 || uedx.f != 43)
+ num_failed++;
+}
+
+void
+check_float_float (void)
+{
+ union
+ {
+ unsigned long l;
+ float f;
+ } ueax, uedx;
+ switch (current_test)
+ {
+ case 500:
+ case 501:
+ break;
+ default:
+ abort ();
+ }
+ ueax.l = eax;
+ uedx.l = edx;
+ if (ueax.f != 42 || uedx.f != 43)
+ num_failed++;
+}
+
+void
+check_all (Type class, unsigned long size)
+{
+ union
+ {
+ struct
+ {
+ unsigned long eax;
+ unsigned long edx;
+ } eax_edx;
+ unsigned long long ll;
+ float f;
+ double d;
+ } u;
+
+ switch (class)
+ {
+ case EAX:
+ check_eax ();
+ break;
+ case LONG_LONG:
+ if (0xadadbeefL != eax || 0xadadbeefL != edx)
+ num_failed++;
+ break;
+ case EAX_EDX:
+ check_eax_edx ();
+ break;
+ case FLOAT:
+ u.eax_edx.eax = eax;
+ if (u.f != 42)
+ num_failed++;
+ break;
+ case DOUBLE:
+ u.eax_edx.eax = eax;
+ u.eax_edx.edx = edx;
+ if (u.d != 42)
+ num_failed++;
+ break;
+ case FLOAT_EDX:
+ check_float_edx ();
+ break;
+ case FLOAT_FLOAT:
+ check_float_float ();
+ break;
+ case EAX_FLOAT:
+ check_eax_float ();
+ break;
+ case MEM:
+ /* sret_eax contains a slot whose address is given to the f_*
+ functions. The slot may be a temporary one on stack. When
+ this function is called, hopefully this slot hasn't be
+ overriden. */
+ if (sret_eax != eax)
+ num_failed++;
+ else if (current_test < 700)
+ {
+ if (*(unsigned char*)sret_eax != 42
+ || *(unsigned char*)struct_addr != 42)
+ num_failed++;
+ }
+ else
+ {
+ if (*(float *)sret_eax != 42
+ || *(float *)struct_addr != 42)
+ num_failed++;
+ }
+ break;
+ }
+}
+
+#undef D
+#define D(I) { static struct S_ ## I s; current_test = I; struct_addr = (void*)&s; \
+ clear_non_sret_int_registers; \
+ s = WRAP_RET(f_ ## I) (); \
+ check_all(class_ ## I, sizeof(s)); \
+}
+
+int
+main (void)
+{
+ D(1) D(2) D(3) D(4) D(5) D(6) D(7)
+
+ D(30)
+
+ D(50) D(51) D(52) D(53) D(54) D(55) D(56) D(57) D(58) D(59)
+ D(60) D(61) D(62)
+
+ D(100) D(101)
+
+ D(200) D(201)
+
+ D(300) D(301) D(302)
+
+ D(400) D(401) D(402)
+
+ D(500) D(501)
+
+ D(600) D(601) D(602) D(603) D(604) D(605) D(606) D(607) D(608) D(609)
+ D(610) D(611)
+
+ D(700)
+
+ if (num_failed)
+ abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/iamcu/test_varargs.c b/gcc/testsuite/gcc.target/i386/iamcu/test_varargs.c
new file mode 100644
index 0000000..124bef1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/iamcu/test_varargs.c
@@ -0,0 +1,101 @@
+/* Test variable number of arguments passed to functions. */
+
+#include <stdarg.h>
+#include "defines.h"
+
+
+#define ARG_INT 1
+#define ARG_DOUBLE 2
+#define ARG_POINTER 3
+
+union types
+{
+ int ivalue;
+ double dvalue;
+ void *pvalue;
+};
+
+struct arg
+{
+ int type;
+ union types value;
+};
+
+struct arg *arglist;
+
+/* This tests the argumentlist to see if it matches the format string which
+ is printf-like. Nothing will be printed of course. It can handle ints,
+ doubles and void pointers. The given value will be tested against the
+ values given in arglist.
+ This test only assures that the variable argument passing is working.
+ No attempt is made to see if argument passing is done the right way. */
+void
+__attribute__ ((noinline))
+noprintf (char *format, ...)
+{
+ va_list va_arglist;
+ char *c;
+
+ int ivalue;
+ double dvalue;
+ void *pvalue;
+ struct arg *argp = arglist;
+
+ va_start (va_arglist, format);
+ for (c = format; *c; c++)
+ if (*c == '%')
+ {
+ switch (*++c)
+ {
+ case 'd':
+ assert (argp->type == ARG_INT);
+ ivalue = va_arg (va_arglist, int);
+ assert (argp->value.ivalue == ivalue);
+ break;
+ case 'f':
+ assert (argp->type == ARG_DOUBLE);
+ dvalue = va_arg (va_arglist, double);
+ assert (argp->value.dvalue == dvalue);
+ break;
+ case 'p':
+ assert (argp->type == ARG_POINTER);
+ pvalue = va_arg (va_arglist, void *);
+ assert (argp->value.pvalue == pvalue);
+ break;
+ default:
+ abort ();
+ }
+
+ argp++;
+ }
+}
+
+extern void iamcu_noprintf (char *, ...);
+
+int
+main (void)
+{
+#ifdef CHECK_VARARGS
+ float f = 258.0;
+ struct arg al[5];
+
+ al[0].type = ARG_INT;
+ al[0].value.ivalue = 256;
+ al[1].type = ARG_DOUBLE;
+ al[1].value.dvalue = 257.0;
+ al[2].type = ARG_POINTER;
+ al[2].value.pvalue = al;
+ al[3].type = ARG_DOUBLE;
+ al[3].value.dvalue = f;
+ al[4].type = ARG_INT;
+ al[4].value.ivalue = 259;
+
+ arglist = al;
+ noprintf("%d%f%p%f%d", 256, 257.0, al, f, 259);
+
+ iamcu_noprintf ((char *) 0xabadbeef, 256, 257.0,
+ (void *) 0xbbadbeef, f, 259);
+#endif
+
+ return 0;
+}
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [i386, PATCH, 1/3] IA MCU psABI support: GCC changes.
2015-06-22 14:38 ` [i386, PATCH, 1/3] IA MCU psABI support: GCC changes Kirill Yukhin
@ 2015-06-26 10:40 ` Uros Bizjak
0 siblings, 0 replies; 7+ messages in thread
From: Uros Bizjak @ 2015-06-26 10:40 UTC (permalink / raw)
To: Kirill Yukhin; +Cc: Joseph S. Myers, H.J. Lu, GCC Patches
On Mon, Jun 22, 2015 at 4:36 PM, Kirill Yukhin <kirill.yukhin@gmail.com> wrote:
> Hello,
> This patch introduces basic support into GCC.
>
> Bootstrapped and regtested.
>
> /
> * configure.ac (ospace_frag): Enable for i?86*-*-elfiamcu
> target.
> * configure: Regenerate.
> gcc/
> * config.gcc: Support i[34567]86-*-elfiamcu target.
> * config/i386/iamcu.h: New.
> * config/i386/i386.opt: Add -miamcu.
> * doc/invoke.texi: Document -miamcu.
> * common/config/i386/i386-common.c (ix86_handle_option): Turn
> off x87/MMX/SSE/AVX codegen for -miamcu.
> * config/i386/i386-c.c (ix86_target_macros_internal): Define
> __iamcu/__iamcu__ for -miamcu.
> * config/i386/i386.h (PREFERRED_STACK_BOUNDARY_DEFAULT): Set
> to MIN_STACK_BOUNDARY if TARGET_IAMCU is true.
> (BIGGEST_ALIGNMENT): Set to 32 if TARGET_IAMCU is true.
> * config/i386/i386.c (ix86_option_override_internal):
> - Ignore and warn -mregparm for Intel MCU. Turn
> on -mregparm=3 for Intel MCU by default.
> - Default long double to 64-bit for Intel MCU.
> - Turn on -freg-struct-return for Intel MCU.
> - Issue an error when -miamcu is used in 64-bit or x32 mode,
> or if x87, MMX, SSE or AVX is turned on.
Please avoid lines here. Just go with the sentences one after another,
separated with two spaces.
> (function_arg_advance_32): Pass value whose
> size is no larger than 8 bytes in registers for Intel MCU.
> (function_arg_32): Likewise.
> (ix86_return_in_memory): Return value whose size is no larger
> than 8 bytes in registers for Intel MCU.
> (iamcu_alignment): New function.
> (ix86_data_alignment): Call iamcu_alignment if TARGET_IAMCU is
> true.
> (ix86_local_alignment): Don't increase
> alignment for Intel MCU.
> (x86_field_alignment): Return iamcu_alignment if TARGET_IAMCU is
> true.
>
> Is it OK for trunk?
OK.
Thanks,
Uros.
>
> --
> Thanks, K
>
> diff --git a/configure b/configure
> index bced9de..82e45f3 100755
> --- a/configure
> +++ b/configure
> @@ -6914,7 +6914,7 @@ case "${enable_target_optspace}:${target}" in
> :d30v-*)
> ospace_frag="config/mt-d30v"
> ;;
> - :m32r-* | :d10v-* | :fr30-*)
> + :m32r-* | :d10v-* | :fr30-* | :i?86*-*-elfiamcu)
> ospace_frag="config/mt-ospace"
> ;;
> no:* | :*)
> diff --git a/configure.ac b/configure.ac
> index 7c06e6b..dc77a1b 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -2560,7 +2560,7 @@ case "${enable_target_optspace}:${target}" in
> :d30v-*)
> ospace_frag="config/mt-d30v"
> ;;
> - :m32r-* | :d10v-* | :fr30-*)
> + :m32r-* | :d10v-* | :fr30-* | :i?86*-*-elfiamcu)
> ospace_frag="config/mt-ospace"
> ;;
> no:* | :*)
> diff --git a/gcc/common/config/i386/i386-common.c b/gcc/common/config/i386/i386-common.c
> index 0f8c3e1..79b2472 100644
> --- a/gcc/common/config/i386/i386-common.c
> +++ b/gcc/common/config/i386/i386-common.c
> @@ -223,7 +223,7 @@ along with GCC; see the file COPYING3. If not see
>
> bool
> ix86_handle_option (struct gcc_options *opts,
> - struct gcc_options *opts_set ATTRIBUTE_UNUSED,
> + struct gcc_options *opts_set,
> const struct cl_decoded_option *decoded,
> location_t loc)
> {
> @@ -232,6 +232,20 @@ ix86_handle_option (struct gcc_options *opts,
>
> switch (code)
> {
> + case OPT_miamcu:
> + if (value)
> + {
> + /* Turn off x87/MMX/SSE/AVX codegen for -miamcu. */
> + opts->x_target_flags &= ~MASK_80387;
> + opts_set->x_target_flags |= MASK_80387;
> + opts->x_ix86_isa_flags &= ~(OPTION_MASK_ISA_MMX_UNSET
> + | OPTION_MASK_ISA_SSE_UNSET);
> + opts->x_ix86_isa_flags_explicit |= (OPTION_MASK_ISA_MMX_UNSET
> + | OPTION_MASK_ISA_SSE_UNSET);
> +
> + }
> + return true;
> +
> case OPT_mmmx:
> if (value)
> {
> diff --git a/gcc/config.gcc b/gcc/config.gcc
> index 805638d..2b3af82 100644
> --- a/gcc/config.gcc
> +++ b/gcc/config.gcc
> @@ -1389,6 +1389,9 @@ x86_64-*-darwin*)
> tmake_file="${tmake_file} ${cpu_type}/t-darwin64 t-slibgcc"
> tm_file="${tm_file} ${cpu_type}/darwin64.h"
> ;;
> +i[34567]86-*-elfiamcu)
> + tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h newlib-stdint.h i386/iamcu.h"
> + ;;
> i[34567]86-*-elf*)
> tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h newlib-stdint.h i386/i386elf.h"
> ;;
> diff --git a/gcc/config/i386/i386-c.c b/gcc/config/i386/i386-c.c
> index 0228f4b..66f7e37 100644
> --- a/gcc/config/i386/i386-c.c
> +++ b/gcc/config/i386/i386-c.c
> @@ -426,6 +426,11 @@ ix86_target_macros_internal (HOST_WIDE_INT isa_flag,
> def_or_undef (parse_in, "__CLWB__");
> if (isa_flag & OPTION_MASK_ISA_MWAITX)
> def_or_undef (parse_in, "__MWAITX__");
> + if (TARGET_IAMCU)
> + {
> + def_or_undef (parse_in, "__iamcu");
> + def_or_undef (parse_in, "__iamcu__");
> + }
> }
>
>
> diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
> index 24fccfc..26ffa67 100644
> --- a/gcc/config/i386/i386.c
> +++ b/gcc/config/i386/i386.c
> @@ -3433,6 +3433,10 @@ ix86_option_override_internal (bool main_args_p,
> || TARGET_16BIT_P (opts->x_ix86_isa_flags))
> opts->x_ix86_isa_flags &= ~OPTION_MASK_ABI_X32;
> #endif
> + if (TARGET_64BIT_P (opts->x_ix86_isa_flags)
> + && TARGET_IAMCU_P (opts->x_target_flags))
> + sorry ("Intel MCU psABI isn%'t supported in %s mode",
> + TARGET_X32_P (opts->x_ix86_isa_flags) ? "x32" : "64-bit");
> }
> #endif
>
> @@ -3817,6 +3821,20 @@ ix86_option_override_internal (bool main_args_p,
> if (TARGET_X32 && (ix86_isa_flags & OPTION_MASK_ISA_MPX))
> error ("Intel MPX does not support x32");
>
> + if (TARGET_IAMCU_P (opts->x_target_flags))
> + {
> + /* Verify that x87/MMX/SSE/AVX is off for -miamcu. */
> + if (TARGET_80387_P (opts->x_target_flags))
> + sorry ("X87 FPU isn%'t supported in Intel MCU psABI");
> + else if ((opts->x_ix86_isa_flags & (OPTION_MASK_ISA_MMX
> + | OPTION_MASK_ISA_SSE
> + | OPTION_MASK_ISA_AVX)))
> + sorry ("%s isn%'t supported in Intel MCU psABI",
> + TARGET_MMX_P (opts->x_ix86_isa_flags)
> + ? "MMX"
> + : TARGET_SSE_P (opts->x_ix86_isa_flags) ? "SSE" : "AVX");
> + }
> +
> if (!strcmp (opts->x_ix86_arch_string, "generic"))
> error ("generic CPU can be used only for %stune=%s %s",
> prefix, suffix, sw);
> @@ -3904,7 +3922,16 @@ ix86_option_override_internal (bool main_args_p,
> if (opts->x_flag_asynchronous_unwind_tables == 2)
> opts->x_flag_asynchronous_unwind_tables = !USE_IX86_FRAME_POINTER;
> if (opts->x_flag_pcc_struct_return == 2)
> - opts->x_flag_pcc_struct_return = DEFAULT_PCC_STRUCT_RETURN;
> + {
> + /* Intel MCU psABI specifies that -freg-struct-return should
> + be on. Instead of setting DEFAULT_PCC_STRUCT_RETURN to 1,
> + we check -miamcu so that -freg-struct-return is always
> + turned on if -miamcu is used. */
> + if (TARGET_IAMCU_P (opts->x_target_flags))
> + opts->x_flag_pcc_struct_return = 0;
> + else
> + opts->x_flag_pcc_struct_return = DEFAULT_PCC_STRUCT_RETURN;
> + }
> }
>
> ix86_tune_cost = processor_target_table[ix86_tune].cost;
> @@ -3923,6 +3950,8 @@ ix86_option_override_internal (bool main_args_p,
> {
> if (TARGET_64BIT_P (opts->x_ix86_isa_flags))
> warning (0, "-mregparm is ignored in 64-bit mode");
> + else if (TARGET_IAMCU_P (opts->x_target_flags))
> + warning (0, "-mregparm is ignored for Intel MCU psABI");
> if (opts->x_ix86_regparm > REGPARM_MAX)
> {
> error ("-mregparm=%d is not between 0 and %d",
> @@ -3930,7 +3959,8 @@ ix86_option_override_internal (bool main_args_p,
> opts->x_ix86_regparm = 0;
> }
> }
> - if (TARGET_64BIT_P (opts->x_ix86_isa_flags))
> + if (TARGET_IAMCU_P (opts->x_target_flags)
> + || TARGET_64BIT_P (opts->x_ix86_isa_flags))
> opts->x_ix86_regparm = REGPARM_MAX;
>
> /* Default align_* from the processor table. */
> @@ -4334,8 +4364,9 @@ ix86_option_override_internal (bool main_args_p,
> opts->x_recip_mask &= ~(RECIP_MASK_ALL & ~opts->x_recip_mask_explicit);
>
> /* Default long double to 64-bit for 32-bit Bionic and to __float128
> - for 64-bit Bionic. */
> - if (TARGET_HAS_BIONIC
> + for 64-bit Bionic. Also default long double to 64-bit for Intel
> + MCU psABI. */
> + if ((TARGET_HAS_BIONIC || TARGET_IAMCU)
> && !(opts_set->x_target_flags
> & (MASK_LONG_DOUBLE_64 | MASK_LONG_DOUBLE_128)))
> opts->x_target_flags |= (TARGET_64BIT
> @@ -7455,6 +7486,15 @@ function_arg_advance_32 (CUMULATIVE_ARGS *cum, machine_mode mode,
> int res = 0;
> bool error_p = NULL;
>
> + if (TARGET_IAMCU)
> + {
> + /* Intel MCU psABI passes scalars and aggregates no larger than 8
> + bytes in registers. */
> + if (bytes <= 8)
> + goto pass_in_reg;
> + return res;
> + }
> +
> switch (mode)
> {
> default:
> @@ -7469,6 +7509,7 @@ function_arg_advance_32 (CUMULATIVE_ARGS *cum, machine_mode mode,
> case SImode:
> case HImode:
> case QImode:
> +pass_in_reg:
> cum->words += words;
> cum->nregs -= words;
> cum->regno += words;
> @@ -7702,6 +7743,15 @@ function_arg_32 (CUMULATIVE_ARGS *cum, machine_mode mode,
> if (mode == VOIDmode)
> return constm1_rtx;
>
> + if (TARGET_IAMCU)
> + {
> + /* Intel MCU psABI passes scalars and aggregates no larger than 8
> + bytes in registers. */
> + if (bytes <= 8)
> + goto pass_in_reg;
> + return NULL_RTX;
> + }
> +
> switch (mode)
> {
> default:
> @@ -7715,6 +7765,7 @@ function_arg_32 (CUMULATIVE_ARGS *cum, machine_mode mode,
> case SImode:
> case HImode:
> case QImode:
> +pass_in_reg:
> if (words <= cum->nregs)
> {
> int regno = cum->regno;
> @@ -8561,11 +8612,16 @@ ix86_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
> }
> else
> {
> + size = int_size_in_bytes (type);
> +
> + /* Intel MCU psABI returns scalars and aggregates no larger than 8
> + bytes in registers. */
> + if (TARGET_IAMCU)
> + return size > 8;
> +
> if (mode == BLKmode)
> return true;
>
> - size = int_size_in_bytes (type);
> -
> if (MS_AGGREGATE_RETURN && AGGREGATE_TYPE_P (type) && size <= 8)
> return false;
>
> @@ -27341,6 +27397,34 @@ ix86_constant_alignment (tree exp, int align)
> return align;
> }
>
> +/* Compute the alignment for a variable for Intel MCU psABI. TYPE is
> + the data type, and ALIGN is the alignment that the object would
> + ordinarily have. */
> +
> +static int
> +iamcu_alignment (tree type, int align)
> +{
> + enum machine_mode mode;
> +
> + if (align < 32 || TYPE_USER_ALIGN (type))
> + return align;
> +
> + /* Intel MCU psABI specifies scalar types > 4 bytes aligned to 4
> + bytes. */
> + mode = TYPE_MODE (strip_array_types (type));
> + switch (GET_MODE_CLASS (mode))
> + {
> + case MODE_INT:
> + case MODE_COMPLEX_INT:
> + case MODE_COMPLEX_FLOAT:
> + case MODE_FLOAT:
> + case MODE_DECIMAL_FLOAT:
> + return 32;
> + default:
> + return align;
> + }
> +}
> +
> /* Compute the alignment for a static variable.
> TYPE is the data type, and ALIGN is the alignment that
> the object would ordinarily have. The value of this function is used
> @@ -27375,6 +27459,9 @@ ix86_data_alignment (tree type, int align, bool opt)
> case ix86_align_data_type_cacheline: break;
> }
>
> + if (TARGET_IAMCU)
> + align = iamcu_alignment (type, align);
> +
> if (opt
> && AGGREGATE_TYPE_P (type)
> && TYPE_SIZE (type)
> @@ -27484,6 +27571,10 @@ ix86_local_alignment (tree exp, machine_mode mode,
> return align;
> }
>
> + /* Don't increase alignment for Intel MCU psABI. */
> + if (TARGET_IAMCU)
> + return align;
> +
> /* x86-64 ABI requires arrays greater than 16 bytes to be aligned
> to 16byte boundary. Exact wording is:
>
> @@ -43182,6 +43273,8 @@ x86_field_alignment (tree field, int computed)
>
> if (TARGET_64BIT || TARGET_ALIGN_DOUBLE)
> return computed;
> + if (TARGET_IAMCU)
> + return iamcu_alignment (type, computed);
> mode = TYPE_MODE (strip_array_types (type));
> if (mode == DFmode || mode == DCmode
> || GET_MODE_CLASS (mode) == MODE_INT
> diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
> index e0af36c..d710b3d 100644
> --- a/gcc/config/i386/i386.h
> +++ b/gcc/config/i386/i386.h
> @@ -756,7 +756,8 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);
> /* It should be MIN_STACK_BOUNDARY. But we set it to 128 bits for
> both 32bit and 64bit, to support codes that need 128 bit stack
> alignment for SSE instructions, but can't realign the stack. */
> -#define PREFERRED_STACK_BOUNDARY_DEFAULT 128
> +#define PREFERRED_STACK_BOUNDARY_DEFAULT \
> + (TARGET_IAMCU ? MIN_STACK_BOUNDARY : 128)
>
> /* 1 if -mstackrealign should be turned on by default. It will
> generate an alternate prologue and epilogue that realigns the
> @@ -803,7 +804,7 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);
> TARGET_ABSOLUTE_BIGGEST_ALIGNMENT. */
>
> #define BIGGEST_ALIGNMENT \
> - (TARGET_AVX512F ? 512 : (TARGET_AVX ? 256 : 128))
> + (TARGET_AVX512F ? 512 : (TARGET_AVX ? 256 : (TARGET_IAMCU ? 32 : 128)))
>
> /* Maximum stack alignment. */
> #define MAX_STACK_ALIGNMENT MAX_OFILE_ALIGNMENT
> diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt
> index dd46e26..042f3c1 100644
> --- a/gcc/config/i386/i386.opt
> +++ b/gcc/config/i386/i386.opt
> @@ -514,6 +514,10 @@ Clear all tune features
> mdump-tune-features
> Target RejectNegative Var(ix86_dump_tunes) Init(0)
>
> +miamcu
> +Target Report Mask(IAMCU)
> +Generate code that conforms to Intel MCU psABI
> +
> mabi=
> Target RejectNegative Joined Var(ix86_abi) Enum(calling_abi) Init(SYSV_ABI)
> Generate code that conforms to the given ABI
> diff --git a/gcc/config/i386/iamcu.h b/gcc/config/i386/iamcu.h
> new file mode 100644
> index 0000000..a1c83f4
> --- /dev/null
> +++ b/gcc/config/i386/iamcu.h
> @@ -0,0 +1,42 @@
> +/* Definitions of target machine for Intel MCU psABI.
> + Copyright (C) 2015 Free Software Foundation, Inc.
> +
> +This file is part of GCC.
> +
> +GCC is free software; you can redistribute it and/or modify
> +it under the terms of the GNU General Public License as published by
> +the Free Software Foundation; either version 3, or (at your option)
> +any later version.
> +
> +GCC is distributed in the hope that it will be useful,
> +but WITHOUT ANY WARRANTY; without even the implied warranty of
> +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> +GNU General Public License for more details.
> +
> +Under Section 7 of GPL version 3, you are granted additional
> +permissions described in the GCC Runtime Library Exception, version
> +3.1, as published by the Free Software Foundation.
> +
> +You should have received a copy of the GNU General Public License and
> +a copy of the GCC Runtime Library Exception along with this program;
> +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
> +<http://www.gnu.org/licenses/>. */
> +
> +/* Intel MCU has no 80387. Default to Intel MCU psABI. */
> +#undef TARGET_SUBTARGET_DEFAULT
> +#define TARGET_SUBTARGET_DEFAULT MASK_IAMCU
> +
> +#undef ASM_SPEC
> +#define ASM_SPEC "--32 -march=iamcu"
> +
> +#undef LINK_SPEC
> +#define LINK_SPEC "-m elf_iamcu"
> +
> +#undef ENDFILE_SPEC
> +#define ENDFILE_SPEC ""
> +
> +#undef STARTFILE_SPEC
> +#define STARTFILE_SPEC "crt0.o%s"
> +
> +#undef LIB_SPEC
> +#define LIB_SPEC "--start-group -lc -lgloss --end-group"
> diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
> index b99ab1c..e4f816f 100644
> --- a/gcc/doc/invoke.texi
> +++ b/gcc/doc/invoke.texi
> @@ -1096,7 +1096,7 @@ See RS/6000 and PowerPC Options.
> -mpc32 -mpc64 -mpc80 -mstackrealign @gol
> -momit-leaf-frame-pointer -mno-red-zone -mno-tls-direct-seg-refs @gol
> -mcmodel=@var{code-model} -mabi=@var{name} -maddress-mode=@var{mode} @gol
> --m32 -m64 -mx32 -m16 -mlarge-data-threshold=@var{num} @gol
> +-m32 -m64 -mx32 -m16 -miamcu -mlarge-data-threshold=@var{num} @gol
> -msse2avx -mfentry -mrecord-mcount -mnop-mcount -m8bit-idiv @gol
> -mavx256-split-unaligned-load -mavx256-split-unaligned-store @gol
> -malign-data=@var{type} -mstack-protector-guard=@var{guard}}
> @@ -23267,10 +23267,12 @@ on x86-64 processors in 64-bit environments.
> @itemx -m64
> @itemx -mx32
> @itemx -m16
> +@itemx -miamcu
> @opindex m32
> @opindex m64
> @opindex mx32
> @opindex m16
> +@opindex miamcu
> Generate code for a 16-bit, 32-bit or 64-bit environment.
> The @option{-m32} option sets @code{int}, @code{long}, and pointer types
> to 32 bits, and
> @@ -23289,6 +23291,9 @@ The @option{-m16} option is the same as @option{-m32}, except for that
> it outputs the @code{.code16gcc} assembly directive at the beginning of
> the assembly output so that the binary can run in 16-bit mode.
>
> +The @option{-miamcu} option generates code which conforms to Intel MCU
> +psABI. It requires the @option{-m32} option to be turned on.
> +
> @item -mno-red-zone
> @opindex mno-red-zone
> Do not use a so-called ``red zone'' for x86-64 code. The red zone is mandated
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [i386, PATCH, 2/3] IA MCU psABI support: changes to libraries.
2015-06-22 15:41 ` [i386, PATCH, 2/3] IA MCU psABI support: changes to libraries Kirill Yukhin
@ 2015-06-26 10:54 ` Uros Bizjak
0 siblings, 0 replies; 7+ messages in thread
From: Uros Bizjak @ 2015-06-26 10:54 UTC (permalink / raw)
To: Kirill Yukhin; +Cc: Joseph S. Myers, H.J. Lu, GCC Patches
On Mon, Jun 22, 2015 at 5:39 PM, Kirill Yukhin <kirill.yukhin@gmail.com> wrote:
> Hello,
> Patch in the bottom adds support of IA MCU psABI to libgcc
> (enables soft-fp) and libdecnumber (enables it for IA MCU).
>
> Bootstrapped and regtested on top of [1/3] patch.
>
> config/
> * dfp.m4 (enable_decimal_float): Also set to yes for
> i?86*-*-elfiamcu target.
> gcc/
> * configure: Regenerated.
> libdecnumber/
> * configure: Regenerated.
> libgcc/
> * config.host: Support i[34567]86-*-elfiamcu target.
> * config/i386/32/t-iamcu: New file.
> * configure: Regenerated.
>
> Is it OK for trunk?
Please introduce config/t-softfp-sfdftf as an union of t-softfp-sfdf
and t-softfp-tf and use it instead of config/t-softfp-sfdf. You will
be able to remove all softfp stuff from t-iamcu then.
OK with the above improvement.
Thanks,
Uros.
> --
> Thanks, K
>
> diff --git a/config/dfp.m4 b/config/dfp.m4
> index 48683f0..5b29089 100644
> --- a/config/dfp.m4
> +++ b/config/dfp.m4
> @@ -21,7 +21,7 @@ Valid choices are 'yes', 'bid', 'dpd', and 'no'.]) ;;
> [
> case $1 in
> powerpc*-*-linux* | i?86*-*-linux* | x86_64*-*-linux* | s390*-*-linux* | \
> - i?86*-*-gnu* | \
> + i?86*-*-elfiamcu | i?86*-*-gnu* | \
> i?86*-*-mingw* | x86_64*-*-mingw* | \
> i?86*-*-cygwin* | x86_64*-*-cygwin*)
> enable_decimal_float=yes
> diff --git a/gcc/configure b/gcc/configure
> index b26a86f..64eeac6 100755
> --- a/gcc/configure
> +++ b/gcc/configure
> @@ -7317,7 +7317,7 @@ else
>
> case $target in
> powerpc*-*-linux* | i?86*-*-linux* | x86_64*-*-linux* | s390*-*-linux* | \
> - i?86*-*-gnu* | \
> + i?86*-*-elfiamcu | i?86*-*-gnu* | \
> i?86*-*-mingw* | x86_64*-*-mingw* | \
> i?86*-*-cygwin* | x86_64*-*-cygwin*)
> enable_decimal_float=yes
> diff --git a/libdecnumber/configure b/libdecnumber/configure
> index 2720f46..964837d 100755
> --- a/libdecnumber/configure
> +++ b/libdecnumber/configure
> @@ -4614,7 +4614,7 @@ else
>
> case $target in
> powerpc*-*-linux* | i?86*-*-linux* | x86_64*-*-linux* | s390*-*-linux* | \
> - i?86*-*-gnu* | \
> + i?86*-*-elfiamcu | i?86*-*-gnu* | \
> i?86*-*-mingw* | x86_64*-*-mingw* | \
> i?86*-*-cygwin* | x86_64*-*-cygwin*)
> enable_decimal_float=yes
> diff --git a/libgcc/config.host b/libgcc/config.host
> index 46666df..dd8e356 100644
> --- a/libgcc/config.host
> +++ b/libgcc/config.host
> @@ -562,6 +562,9 @@ x86_64-*-darwin*)
> tm_file="$tm_file i386/darwin-lib.h"
> extra_parts="$extra_parts crtprec32.o crtprec64.o crtprec80.o crtfastmath.o"
> ;;
> +i[34567]86-*-elfiamcu)
> + tmake_file="$tmake_file i386/t-crtstuff t-softfp-sfdf i386/32/t-softfp i386/32/t-iamcu i386/t-softfp t-softfp t-dfprules"
> + ;;
> i[34567]86-*-elf*)
> tmake_file="$tmake_file i386/t-crtstuff t-crtstuff-pic t-libgcc-pic"
> ;;
> diff --git a/libgcc/config/i386/32/t-iamcu b/libgcc/config/i386/32/t-iamcu
> new file mode 100644
> index 0000000..0752bff
> --- /dev/null
> +++ b/libgcc/config/i386/32/t-iamcu
> @@ -0,0 +1,6 @@
> +softfp_float_modes += tf
> +softfp_extensions += sftf dftf xftf
> +softfp_truncations += tfsf tfdf tfxf
> +softfp_exclude_libgcc2 := n
> +
> +HOST_LIBGCC2_CFLAGS += -mlong-double-80
> diff --git a/libgcc/configure b/libgcc/configure
> index ce66d1d..e22cbcb 100644
> --- a/libgcc/configure
> +++ b/libgcc/configure
> @@ -4436,7 +4436,7 @@ else
>
> case $host in
> powerpc*-*-linux* | i?86*-*-linux* | x86_64*-*-linux* | s390*-*-linux* | \
> - i?86*-*-gnu* | \
> + i?86*-*-elfiamcu | i?86*-*-gnu* | \
> i?86*-*-mingw* | x86_64*-*-mingw* | \
> i?86*-*-cygwin* | x86_64*-*-cygwin*)
> enable_decimal_float=yes
>
>
>
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [i386, PATCH, 3/3] IA MCU psABI support: testsuite.
2015-06-23 9:46 ` [i386, PATCH, 3/3] IA MCU psABI support: testsuite Kirill Yukhin
@ 2015-06-26 11:03 ` Uros Bizjak
0 siblings, 0 replies; 7+ messages in thread
From: Uros Bizjak @ 2015-06-26 11:03 UTC (permalink / raw)
To: Kirill Yukhin; +Cc: Joseph S. Myers, H.J. Lu, GCC Patches
On Tue, Jun 23, 2015 at 11:38 AM, Kirill Yukhin <kirill.yukhin@gmail.com> wrote:
> Hello,
> This patch introduces tests for new psABI.
>
> gcc/testsuite/
> * gcc.target/i386/iamcu/abi-iamcu.exp: New file.
> * gcc.target/i386/iamcu/args.h: Likewise.
> * gcc.target/i386/iamcu/asm-support.S: Likewise.
> * gcc.target/i386/iamcu/defines.h: Likewise.
> * gcc.target/i386/iamcu/macros.h: Likewise.
> * gcc.target/i386/iamcu/test_3_element_struct_and_unions.c: Likewise.
> * gcc.target/i386/iamcu/test_basic_64bit_returning.c: Likewise.
> * gcc.target/i386/iamcu/test_basic_alignment.c: Likewise.
> * gcc.target/i386/iamcu/test_basic_array_size_and_align.c: Likewise.
> * gcc.target/i386/iamcu/test_basic_returning.c: Likewise.
> * gcc.target/i386/iamcu/test_basic_sizes.c: Likewise.
> * gcc.target/i386/iamcu/test_basic_struct_size_and_align.c: Likewise.
> * gcc.target/i386/iamcu/test_basic_union_size_and_align.c: Likewise.
> * gcc.target/i386/iamcu/test_bitfields.c: Likewise.
> * gcc.target/i386/iamcu/test_complex_returning.c: Likewise.
> * gcc.target/i386/iamcu/test_passing_floats.c: Likewise.
> * gcc.target/i386/iamcu/test_passing_integers.c: Likewise.
> * gcc.target/i386/iamcu/test_passing_structs.c: Likewise.
> * gcc.target/i386/iamcu/test_passing_structs_and_unions.c: Likewise.
> * gcc.target/i386/iamcu/test_passing_unions.c: Likewise.
> * gcc.target/i386/iamcu/test_struct_returning.c: Likewise.
> * gcc.target/i386/iamcu/test_varargs.c: Likewise.
>
> New tests pass, when run on for 32b target.
> Is it ok for trunk?
I didn't look in all the details, but the patch LGTM.
So, OK.
Thanks,
Uros.
> --
> Thanks, K
>
> diff --git a/gcc/testsuite/gcc.target/i386/iamcu/abi-iamcu.exp b/gcc/testsuite/gcc.target/i386/iamcu/abi-iamcu.exp
> new file mode 100644
> index 0000000..b5b3261
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/iamcu/abi-iamcu.exp
> @@ -0,0 +1,42 @@
> +# Copyright (C) 2015 Free Software Foundation, Inc.
> +
> +# This program is free software; you can redistribute it and/or modify
> +# it under the terms of the GNU General Public License as published by
> +# the Free Software Foundation; either version 3 of the License, or
> +# (at your option) any later version.
> +#
> +# This program is distributed in the hope that it will be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> +# GNU General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License
> +# along with GCC; see the file COPYING3. If not see
> +# <http://www.gnu.org/licenses/>.
> +
> +# The Intel MCU psABI testsuite needs one additional assembler file for
> +# most testcases. For simplicity we will just link it into each test.
> +
> +load_lib c-torture.exp
> +load_lib target-supports.exp
> +load_lib torture-options.exp
> +
> +if { (![istarget x86_64-*-linux*] && ![istarget i?86-*-linux*])
> + || ![is-effective-target ia32] } then {
> + return
> +}
> +
> +
> +torture-init
> +set-torture-options $C_TORTURE_OPTIONS
> +set additional_flags "-miamcu -W -Wall -Wno-abi"
> +
> +foreach src [lsort [glob -nocomplain $srcdir/$subdir/test_*.c]] {
> + if {[runtest_file_p $runtests $src]} {
> + c-torture-execute [list $src \
> + $srcdir/$subdir/asm-support.S] \
> + $additional_flags
> + }
> +}
> +
> +torture-finish
> diff --git a/gcc/testsuite/gcc.target/i386/iamcu/args.h b/gcc/testsuite/gcc.target/i386/iamcu/args.h
> new file mode 100644
> index 0000000..f8abde4
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/iamcu/args.h
> @@ -0,0 +1,77 @@
> +#ifndef INCLUDED_ARGS_H
> +#define INCLUDED_ARGS_H
> +
> +/* This defines the calling sequences for integers and floats. */
> +#define I0 eax
> +#define I1 edx
> +#define I2 ecx
> +
> +typedef unsigned int size_t;
> +
> +extern void (*callthis)(void);
> +extern unsigned long eax,ebx,ecx,edx,esi,edi,esp,ebp;
> +extern unsigned long sret_eax;
> +extern volatile unsigned long volatile_var;
> +extern void snapshot (void);
> +extern void snapshot_ret (void);
> +extern void *iamcu_memset (void *, int, size_t);
> +#define WRAP_CALL(N) \
> + (callthis = (void (*)()) (N), (typeof (&N)) snapshot)
> +#define WRAP_RET(N) \
> + (callthis = (void (*)()) (N), (typeof (&N)) snapshot_ret)
> +
> +/* Clear all scratch integer registers. */
> +#define clear_int_hardware_registers \
> + asm __volatile__ ("xor %%eax, %%eax\n\t" \
> + "xor %%edx, %%edx\n\t" \
> + "xor %%ecx, %%ecx\n\t" \
> + ::: "eax", "edx", "ecx");
> +
> +/* Clear all scratch integer registers, excluding the one used to return
> + aggregate. */
> +#define clear_non_sret_int_hardware_registers \
> + asm __volatile__ ("xor %%edx, %%ebx\n\t" \
> + "xor %%ecx, %%ecx\n\t" \
> + ::: "edx", "ecx");
> +
> +/* This is the list of registers available for passing arguments. Not all of
> + these are used or even really available. */
> +struct IntegerRegisters
> +{
> + unsigned long eax, ebx, ecx, edx, esi, edi;
> +};
> +
> +/* Implemented in scalarargs.c */
> +extern struct IntegerRegisters iregs, iregbits;
> +extern unsigned int num_iregs;
> +
> +#define check_int_arguments do { \
> + assert (num_iregs <= 0 || (iregs.I0 & iregbits.I0) == (I0 & iregbits.I0)); \
> + assert (num_iregs <= 1 || (iregs.I1 & iregbits.I1) == (I1 & iregbits.I1)); \
> + assert (num_iregs <= 2 || (iregs.I2 & iregbits.I2) == (I2 & iregbits.I2)); \
> + } while (0)
> +
> +#define check_char_arguments check_int_arguments
> +#define check_short_arguments check_int_arguments
> +#define check_long_arguments check_int_arguments
> +#define check_float_arguments check_int_arguments
> +#define check_double_arguments check_int_arguments
> +#define check_ldouble_arguments check_int_arguments
> +
> +/* Clear register struct. */
> +#define clear_struct_registers \
> + eax = edx = ecx = 0; \
> + iamcu_memset (&iregs, 0, sizeof iregs);
> +
> +/* Clear both hardware and register structs for integers. */
> +#define clear_int_registers \
> + clear_struct_registers \
> + clear_int_hardware_registers
> +
> +/* Clear both hardware and register structs for integers, excluding the
> + one used to return aggregate. */
> +#define clear_non_sret_int_registers \
> + clear_struct_registers \
> + clear_non_sret_int_hardware_registers
> +
> +#endif /* INCLUDED_ARGS_H */
> diff --git a/gcc/testsuite/gcc.target/i386/iamcu/asm-support.S b/gcc/testsuite/gcc.target/i386/iamcu/asm-support.S
> new file mode 100644
> index 0000000..b4a4a14
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/iamcu/asm-support.S
> @@ -0,0 +1,302 @@
> + .comm callthis,4,4
> + .comm eax,4,4
> + .comm ebx,4,4
> + .comm ecx,4,4
> + .comm edx,4,4
> + .comm esi,4,4
> + .comm edi,4,4
> + .comm esp,4,4
> + .comm ebp,4,4
> + .comm sret_eax,4,4
> + .comm volatile_var,4,4
> +
> + .text
> + .p2align 4,,15
> +.globl snapshot
> + .type snapshot, @function
> +snapshot:
> + movl %eax, eax
> + movl %ebx, ebx
> + movl %ecx, ecx
> + movl %edx, edx
> + movl %edi, edi
> + movl %esi, esi
> + movl %ebp, ebp
> + movl %esp, esp
> + jmp *callthis
> + .size snapshot, .-snapshot
> +
> + .p2align 4,,15
> +.globl snapshot_ret
> + .type snapshot_ret, @function
> +snapshot_ret:
> + movl %eax, sret_eax
> + call *callthis
> + movl %eax, eax
> + movl %edx, edx
> + ret
> + .size snapshot_ret, .-snapshot_ret
> +
> + .p2align 4,,15
> + .globl __nesf2
> + .type __nesf2, @function
> +__nesf2:
> + .cfi_startproc
> + subl $4, %esp
> + .cfi_def_cfa_offset 8
> + movl %eax, (%esp)
> + movl $1, %eax
> + fildl (%esp)
> + movl %edx, (%esp)
> + xorl %edx, %edx
> + fildl (%esp)
> + fucomip %st(1), %st
> + fstp %st(0)
> + setp %dl
> + cmove %edx, %eax
> + addl $4, %esp
> + .cfi_def_cfa_offset 4
> + ret
> + .cfi_endproc
> + .size __nesf2, .-__nesf2
> +
> + .p2align 4,,15
> + .globl __nedf2
> + .type __nedf2, @function
> +__nedf2:
> + .cfi_startproc
> + pushl %ebp
> + .cfi_def_cfa_offset 8
> + .cfi_offset 5, -8
> + movl %esp, %ebp
> + .cfi_def_cfa_register 5
> + andl $-8, %esp
> + subl $8, %esp
> + movl %eax, (%esp)
> + movl $1, %eax
> + movl %edx, 4(%esp)
> + xorl %edx, %edx
> + fildq (%esp)
> + fildq 8(%ebp)
> + fucomip %st(1), %st
> + fstp %st(0)
> + setp %dl
> + cmove %edx, %eax
> + leave
> + .cfi_restore 5
> + .cfi_def_cfa 4, 4
> + ret
> + .cfi_endproc
> + .size __nedf2, .-__nedf2
> +
> + .p2align 4,,15
> + .globl __addsf3
> + .type __addsf3, @function
> +__addsf3:
> + .cfi_startproc
> + subl $4, %esp
> + .cfi_def_cfa_offset 8
> + movl %eax, (%esp)
> + flds (%esp)
> + movl %edx, (%esp)
> + flds (%esp)
> + faddp %st, %st(1)
> + fstps (%esp)
> + movl (%esp), %eax
> + addl $4, %esp
> + .cfi_def_cfa_offset 4
> + ret
> + .cfi_endproc
> + .size __addsf3, .-__addsf3
> +
> + .p2align 4,,15
> + .globl __adddf3
> + .type __adddf3, @function
> +__adddf3:
> + .cfi_startproc
> + pushl %ebp
> + .cfi_def_cfa_offset 8
> + .cfi_offset 5, -8
> + movl %esp, %ebp
> + .cfi_def_cfa_register 5
> + andl $-8, %esp
> + subl $8, %esp
> + movl %eax, (%esp)
> + movl %edx, 4(%esp)
> + fldl (%esp)
> + faddl 8(%ebp)
> + fstpl (%esp)
> + movl (%esp), %eax
> + movl 4(%esp), %edx
> + leave
> + .cfi_restore 5
> + .cfi_def_cfa 4, 4
> + ret
> + .cfi_endproc
> + .size __adddf3, .-__adddf3
> +
> + .p2align 4,,15
> + .globl __floatsisf
> + .type __floatsisf, @function
> +__floatsisf:
> + .cfi_startproc
> + subl $4, %esp
> + .cfi_def_cfa_offset 8
> + movl %eax, (%esp)
> + fildl (%esp)
> + addl $4, %esp
> + .cfi_def_cfa_offset 4
> + ret
> + .cfi_endproc
> + .size __floatsisf, .-__floatsisf
> +
> + .p2align 4,,15
> + .globl __floatunsisf
> + .type __floatunsisf, @function
> +__floatunsisf:
> + .cfi_startproc
> + subl $8, %esp
> + .cfi_def_cfa_offset 12
> + xorl %edx, %edx
> + movl %eax, (%esp)
> + movl %edx, 4(%esp)
> + fildq (%esp)
> + addl $8, %esp
> + .cfi_def_cfa_offset 4
> + ret
> + .cfi_endproc
> + .size __floatunsisf, .-__floatunsisf
> +
> + .globl __extendsfdf2
> + .type __extendsfdf2, @function
> +__extendsfdf2:
> + .cfi_startproc
> + pushl %ebp
> + .cfi_def_cfa_offset 8
> + .cfi_offset 5, -8
> + movl %esp, %ebp
> + .cfi_def_cfa_register 5
> + andl $-8, %esp
> + subl $8, %esp
> + movl %eax, (%esp)
> + flds (%esp)
> + fstpl (%esp)
> + movl (%esp), %eax
> + movl 4(%esp), %edx
> + leave
> + .cfi_restore 5
> + .cfi_def_cfa 4, 4
> + ret
> + .cfi_endproc
> + .size __extendsfdf2, .-__extendsfdf2
> +
> + .p2align 4,,15
> + .globl __truncdfsf2
> + .type __truncdfsf2, @function
> +__truncdfsf2:
> + .cfi_startproc
> + pushl %ebp
> + .cfi_def_cfa_offset 8
> + .cfi_offset 5, -8
> + movl %esp, %ebp
> + .cfi_def_cfa_register 5
> + andl $-8, %esp
> + subl $12, %esp
> + movl %eax, (%esp)
> + movl %edx, 4(%esp)
> + fldl (%esp)
> + fstps (%esp)
> + movl (%esp), %eax
> + leave
> + .cfi_restore 5
> + .cfi_def_cfa 4, 4
> + ret
> + .cfi_endproc
> + .size __truncdfsf2, .-__truncdfsf2
> +
> + .p2align 4,,15
> + .globl iamcu_memset
> + .type iamcu_memset, @function
> +iamcu_memset:
> + .cfi_startproc
> + pushl %edi
> + .cfi_adjust_cfa_offset 4
> + .cfi_rel_offset %edi, 0
> + movl %eax, %edi
> + movzbl %dl, %eax
> + movl %edi, %edx
> + rep stosb
> + movl %edx, %eax
> + popl %edi
> + .cfi_adjust_cfa_offset -4
> + .cfi_restore %edi
> + ret
> + .cfi_endproc
> + .size iamcu_memset, .-iamcu_memset
> +
> + .p2align 4,,15
> + .globl iamcu_noprintf
> + .type iamcu_noprintf, @function
> +iamcu_noprintf:
> + .cfi_startproc
> + pushl %ebp
> + .cfi_def_cfa_offset 8
> + .cfi_offset 5, -8
> + movl %esp, %ebp
> + .cfi_def_cfa_register 5
> + cmpl $-1414676753, 8(%ebp)
> + fldl 16(%ebp)
> + fldl 28(%ebp)
> + jne 7f
> + cmpl $256, 12(%ebp)
> + jne 8f
> + flds .LCiamcu_noprintf0
> + movl $1, %eax
> + fucomip %st(2), %st
> + fstp %st(1)
> + setp %dl
> + cmovne %eax, %edx
> + testb %dl, %dl
> + jne 9f
> + cmpl $-1146241297, 24(%ebp)
> + jne 10f
> + flds .LCiamcu_noprintf1
> + fucomip %st(1), %st
> + fstp %st(0)
> + setp %dl
> + cmove %edx, %eax
> + testb %al, %al
> + jne 2f
> + cmpl $259, 36(%ebp)
> + jne 2f
> + popl %ebp
> + .cfi_remember_state
> + .cfi_restore 5
> + .cfi_def_cfa 4, 4
> + ret
> +7:
> + .cfi_restore_state
> + fstp %st(0)
> + fstp %st(0)
> + jmp 2f
> +8:
> + fstp %st(0)
> + fstp %st(0)
> + .p2align 4,,3
> + jmp 2f
> +9:
> + fstp %st(0)
> + jmp 2f
> +10:
> + fstp %st(0)
> +2:
> + call abort
> + .cfi_endproc
> + .size iamcu_noprintf, .-iamcu_noprintf
> + .section .rodata.cst4,"aM",@progbits,4
> + .align 4
> +.LCiamcu_noprintf0:
> + .long 1132494848
> + .align 4
> +.LCiamcu_noprintf1:
> + .long 1132527616
> diff --git a/gcc/testsuite/gcc.target/i386/iamcu/defines.h b/gcc/testsuite/gcc.target/i386/iamcu/defines.h
> new file mode 100644
> index 0000000..e715f42
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/iamcu/defines.h
> @@ -0,0 +1,110 @@
> +#ifndef DEFINED_DEFINES_H
> +#define DEFINED_DEFINES_H
> +
> +typedef unsigned long long ulonglong;
> +typedef long double ldouble;
> +
> +/* These defines determines what part of the test should be run. When
> + GCC implements these parts, the defines should be uncommented to
> + enable testing. */
> +
> +/* Scalar type long double. */
> +#define CHECK_LONG_DOUBLE
> +
> +/* Scalar type __float128. */
> +#define CHECK_FLOAT128
> +
> +/* Returning of complex type. */
> +#define CHECK_COMPLEX
> +
> +/* Structs with size > 8. */
> +#define CHECK_LARGER_STRUCTS
> +
> +/* Checks for passing floats and doubles. */
> +#define CHECK_FLOAT_DOUBLE_PASSING
> +
> +/* Union passing with not-extremely-simple unions. */
> +#define CHECK_LARGER_UNION_PASSING
> +
> +/* Variable args. */
> +#define CHECK_VARARGS
> +
> +/* Check argument passing and returning for scalar types with sizeof > 8. */
> +#define CHECK_LARGE_SCALAR_PASSING
> +
> +/* Defines for sizing and alignment. */
> +
> +#define TYPE_SIZE_CHAR 1
> +#define TYPE_SIZE_SHORT 2
> +#define TYPE_SIZE_INT 4
> +#define TYPE_SIZE_LONG 4
> +#define TYPE_SIZE_LONG_LONG 8
> +#define TYPE_SIZE_FLOAT 4
> +#define TYPE_SIZE_DOUBLE 8
> +#define TYPE_SIZE_LONG_DOUBLE 8
> +#define TYPE_SIZE_FLOAT128 16
> +#define TYPE_SIZE_ENUM 4
> +#define TYPE_SIZE_POINTER 4
> +
> +#define TYPE_ALIGN_CHAR 1
> +#define TYPE_ALIGN_SHORT 2
> +#define TYPE_ALIGN_INT 4
> +#define TYPE_ALIGN_LONG 4
> +#define TYPE_ALIGN_LONG_LONG 4
> +#define TYPE_ALIGN_FLOAT 4
> +#define TYPE_ALIGN_DOUBLE 4
> +#define TYPE_ALIGN_LONG_DOUBLE 4
> +#define TYPE_ALIGN_FLOAT128 4
> +#define TYPE_ALIGN_ENUM 4
> +#define TYPE_ALIGN_POINTER 4
> +
> +/* These defines control the building of the list of types to check. There
> + is a string identifying the type (with a comma after), a size of the type
> + (also with a comma and an integer for adding to the total amount of types)
> + and an alignment of the type (which is currently not really needed since
> + the abi specifies that alignof == sizeof for all scalar types). */
> +#ifdef CHECK_LONG_DOUBLE
> +#define CLD_STR "long double",
> +#define CLD_SIZ TYPE_SIZE_LONG_DOUBLE,
> +#define CLD_ALI TYPE_ALIGN_LONG_DOUBLE,
> +#define CLD_RET "???",
> +#else
> +#define CLD_STR
> +#define CLD_SIZ
> +#define CLD_ALI
> +#define CLD_RET
> +#endif
> +#ifdef CHECK_FLOAT128
> +#define CF128_STR "__float128",
> +#define CF128_SIZ TYPE_SIZE_FLOAT128,
> +#define CF128_ALI TYPE_ALIGN_FLOAT128,
> +#define CF128_RET "???",
> +#else
> +#define CF128_STR
> +#define CF128_SIZ
> +#define CF128_ALI
> +#define CF128_RET
> +#endif
> +
> +/* Used in size and alignment tests. */
> +enum dummytype { enumtype };
> +
> +extern void abort (void);
> +
> +/* Assertion macro. */
> +#define assert(test) if (!(test)) abort()
> +
> +#ifdef __GNUC__
> +#define ATTRIBUTE_UNUSED __attribute__((__unused__))
> +#else
> +#define ATTRIBUTE_UNUSED
> +#endif
> +
> +#ifdef __GNUC__
> +#define PACKED __attribute__((__packed__))
> +#else
> +#warning Some tests will fail due to missing __packed__ support
> +#define PACKED
> +#endif
> +
> +#endif /* DEFINED_DEFINES_H */
> diff --git a/gcc/testsuite/gcc.target/i386/iamcu/macros.h b/gcc/testsuite/gcc.target/i386/iamcu/macros.h
> new file mode 100644
> index 0000000..98fbc66
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/iamcu/macros.h
> @@ -0,0 +1,53 @@
> +#ifndef MACROS_H
> +
> +#define check_size(_t, _size) assert(sizeof(_t) == (_size))
> +
> +#define check_align(_t, _align) assert(__alignof__(_t) == (_align))
> +
> +#define check_align_lv(_t, _align) assert(__alignof__(_t) == (_align) \
> + && (((unsigned long)&(_t)) & ((_align) - 1) ) == 0)
> +
> +#define check_basic_struct_size_and_align(_type, _size, _align) { \
> + struct _str { _type dummy; } _t; \
> + check_size(_t, _size); \
> + check_align_lv(_t, _align); \
> +}
> +
> +#define check_array_size_and_align(_type, _size, _align) { \
> + _type _a[1]; _type _b[2]; _type _c[16]; \
> + struct _str { _type _a[1]; } _s; \
> + check_align_lv(_a[0], _align); \
> + check_size(_a, _size); \
> + check_size(_b, (_size*2)); \
> + check_size(_c, (_size*16)); \
> + check_size(_s, _size); \
> + check_align_lv(_s._a[0], _align); \
> +}
> +
> +#define check_basic_union_size_and_align(_type, _size, _align) { \
> + union _union { _type dummy; } _u; \
> + check_size(_u, _size); \
> + check_align_lv(_u, _align); \
> +}
> +
> +#define run_signed_tests2(_function, _arg1, _arg2) \
> + _function(_arg1, _arg2); \
> + _function(signed _arg1, _arg2); \
> + _function(unsigned _arg1, _arg2);
> +
> +#define run_signed_tests3(_function, _arg1, _arg2, _arg3) \
> + _function(_arg1, _arg2, _arg3); \
> + _function(signed _arg1, _arg2, _arg3); \
> + _function(unsigned _arg1, _arg2, _arg3);
> +
> +/* Check size of a struct and a union of three types. */
> +
> +#define check_struct_and_union3(type1, type2, type3, struct_size, align_size) \
> +{ \
> + struct _str { type1 t1; type2 t2; type3 t3; } _t; \
> + union _uni { type1 t1; type2 t2; type3 t3; } _u; \
> + check_size(_t, struct_size); \
> + check_size(_u, align_size); \
> +}
> +
> +#endif // MACROS_H
> diff --git a/gcc/testsuite/gcc.target/i386/iamcu/test_3_element_struct_and_unions.c b/gcc/testsuite/gcc.target/i386/iamcu/test_3_element_struct_and_unions.c
> new file mode 100644
> index 0000000..7bec211
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/iamcu/test_3_element_struct_and_unions.c
> @@ -0,0 +1,521 @@
> +#include "defines.h"
> +#include "macros.h"
> +
> +/* Check structs and unions of all permutations of 3 basic types. */
> +int
> +main (void)
> +{
> + check_struct_and_union3(char, char, char, 3, 1);
> + check_struct_and_union3(char, char, short, 4, 2);
> + check_struct_and_union3(char, char, int, 8, 4);
> + check_struct_and_union3(char, char, long, 8, 4);
> + check_struct_and_union3(char, char, long long, 12, 8);
> + check_struct_and_union3(char, char, float, 8, 4);
> + check_struct_and_union3(char, char, double, 12, 8);
> + check_struct_and_union3(char, char, long double, 12, 8);
> + check_struct_and_union3(char, short, char, 6, 2);
> + check_struct_and_union3(char, short, short, 6, 2);
> + check_struct_and_union3(char, short, int, 8, 4);
> + check_struct_and_union3(char, short, long, 8, 4);
> + check_struct_and_union3(char, short, long long, 12, 8);
> + check_struct_and_union3(char, short, float, 8, 4);
> + check_struct_and_union3(char, short, double, 12, 8);
> + check_struct_and_union3(char, short, long double, 12, 8);
> + check_struct_and_union3(char, int, char, 12, 4);
> + check_struct_and_union3(char, int, short, 12, 4);
> + check_struct_and_union3(char, int, int, 12, 4);
> + check_struct_and_union3(char, int, long, 12, 4);
> + check_struct_and_union3(char, int, long long, 16, 8);
> + check_struct_and_union3(char, int, float, 12, 4);
> + check_struct_and_union3(char, int, double, 16, 8);
> + check_struct_and_union3(char, int, long double, 16, 8);
> + check_struct_and_union3(char, long, char, 12, 4);
> + check_struct_and_union3(char, long, short, 12, 4);
> + check_struct_and_union3(char, long, int, 12, 4);
> + check_struct_and_union3(char, long, long, 12, 4);
> + check_struct_and_union3(char, long, long long, 16, 8);
> + check_struct_and_union3(char, long, float, 12, 4);
> + check_struct_and_union3(char, long, double, 16, 8);
> + check_struct_and_union3(char, long, long double, 16, 8);
> + check_struct_and_union3(char, long long, char, 16, 8);
> + check_struct_and_union3(char, long long, short, 16, 8);
> + check_struct_and_union3(char, long long, int, 16, 8);
> + check_struct_and_union3(char, long long, long, 16, 8);
> + check_struct_and_union3(char, long long, long long, 20, 8);
> + check_struct_and_union3(char, long long, float, 16, 8);
> + check_struct_and_union3(char, long long, double, 20, 8);
> + check_struct_and_union3(char, long long, long double, 20, 8);
> + check_struct_and_union3(char, float, char, 12, 4);
> + check_struct_and_union3(char, float, short, 12, 4);
> + check_struct_and_union3(char, float, int, 12, 4);
> + check_struct_and_union3(char, float, long, 12, 4);
> + check_struct_and_union3(char, float, long long, 16, 8);
> + check_struct_and_union3(char, float, float, 12, 4);
> + check_struct_and_union3(char, float, double, 16, 8);
> + check_struct_and_union3(char, float, long double, 16, 8);
> + check_struct_and_union3(char, double, char, 16, 8);
> + check_struct_and_union3(char, double, short, 16, 8);
> + check_struct_and_union3(char, double, int, 16, 8);
> + check_struct_and_union3(char, double, long, 16, 8);
> + check_struct_and_union3(char, double, long long, 20, 8);
> + check_struct_and_union3(char, double, float, 16, 8);
> + check_struct_and_union3(char, double, double, 20, 8);
> + check_struct_and_union3(char, double, long double, 20, 8);
> + check_struct_and_union3(char, long double, char, 16, 8);
> + check_struct_and_union3(char, long double, short, 16, 8);
> + check_struct_and_union3(char, long double, int, 16, 8);
> + check_struct_and_union3(char, long double, long, 16, 8);
> + check_struct_and_union3(char, long double, long long, 20, 8);
> + check_struct_and_union3(char, long double, float, 16, 8);
> + check_struct_and_union3(char, long double, double, 20, 8);
> + check_struct_and_union3(char, long double, long double, 20, 8);
> + check_struct_and_union3(short, char, char, 4, 2);
> + check_struct_and_union3(short, char, short, 6, 2);
> + check_struct_and_union3(short, char, int, 8, 4);
> + check_struct_and_union3(short, char, long, 8, 4);
> + check_struct_and_union3(short, char, long long, 12, 8);
> + check_struct_and_union3(short, char, float, 8, 4);
> + check_struct_and_union3(short, char, double, 12, 8);
> + check_struct_and_union3(short, char, long double, 12, 8);
> + check_struct_and_union3(short, short, char, 6, 2);
> + check_struct_and_union3(short, short, short, 6, 2);
> + check_struct_and_union3(short, short, int, 8, 4);
> + check_struct_and_union3(short, short, long, 8, 4);
> + check_struct_and_union3(short, short, long long, 12, 8);
> + check_struct_and_union3(short, short, float, 8, 4);
> + check_struct_and_union3(short, short, double, 12, 8);
> + check_struct_and_union3(short, short, long double, 12, 8);
> + check_struct_and_union3(short, int, char, 12, 4);
> + check_struct_and_union3(short, int, short, 12, 4);
> + check_struct_and_union3(short, int, int, 12, 4);
> + check_struct_and_union3(short, int, long, 12, 4);
> + check_struct_and_union3(short, int, long long, 16, 8);
> + check_struct_and_union3(short, int, float, 12, 4);
> + check_struct_and_union3(short, int, double, 16, 8);
> + check_struct_and_union3(short, int, long double, 16, 8);
> + check_struct_and_union3(short, long, char, 12, 4);
> + check_struct_and_union3(short, long, short, 12, 4);
> + check_struct_and_union3(short, long, int, 12, 4);
> + check_struct_and_union3(short, long, long, 12, 4);
> + check_struct_and_union3(short, long, long long, 16, 8);
> + check_struct_and_union3(short, long, float, 12, 4);
> + check_struct_and_union3(short, long, double, 16, 8);
> + check_struct_and_union3(short, long, long double, 16, 8);
> + check_struct_and_union3(short, long long, char, 16, 8);
> + check_struct_and_union3(short, long long, short, 16, 8);
> + check_struct_and_union3(short, long long, int, 16, 8);
> + check_struct_and_union3(short, long long, long, 16, 8);
> + check_struct_and_union3(short, long long, long long, 20, 8);
> + check_struct_and_union3(short, long long, float, 16, 8);
> + check_struct_and_union3(short, long long, double, 20, 8);
> + check_struct_and_union3(short, long long, long double, 20, 8);
> + check_struct_and_union3(short, float, char, 12, 4);
> + check_struct_and_union3(short, float, short, 12, 4);
> + check_struct_and_union3(short, float, int, 12, 4);
> + check_struct_and_union3(short, float, long, 12, 4);
> + check_struct_and_union3(short, float, long long, 16, 8);
> + check_struct_and_union3(short, float, float, 12, 4);
> + check_struct_and_union3(short, float, double, 16, 8);
> + check_struct_and_union3(short, float, long double, 16, 8);
> + check_struct_and_union3(short, double, char, 16, 8);
> + check_struct_and_union3(short, double, short, 16, 8);
> + check_struct_and_union3(short, double, int, 16, 8);
> + check_struct_and_union3(short, double, long, 16, 8);
> + check_struct_and_union3(short, double, long long, 20, 8);
> + check_struct_and_union3(short, double, float, 16, 8);
> + check_struct_and_union3(short, double, double, 20, 8);
> + check_struct_and_union3(short, double, long double, 20, 8);
> + check_struct_and_union3(short, long double, char, 16, 8);
> + check_struct_and_union3(short, long double, short, 16, 8);
> + check_struct_and_union3(short, long double, int, 16, 8);
> + check_struct_and_union3(short, long double, long, 16, 8);
> + check_struct_and_union3(short, long double, long long, 20, 8);
> + check_struct_and_union3(short, long double, float, 16, 8);
> + check_struct_and_union3(short, long double, double, 20, 8);
> + check_struct_and_union3(short, long double, long double, 20, 8);
> + check_struct_and_union3(int, char, char, 8, 4);
> + check_struct_and_union3(int, char, short, 8, 4);
> + check_struct_and_union3(int, char, int, 12, 4);
> + check_struct_and_union3(int, char, long, 12, 4);
> + check_struct_and_union3(int, char, long long, 16, 8);
> + check_struct_and_union3(int, char, float, 12, 4);
> + check_struct_and_union3(int, char, double, 16, 8);
> + check_struct_and_union3(int, char, long double, 16, 8);
> + check_struct_and_union3(int, short, char, 8, 4);
> + check_struct_and_union3(int, short, short, 8, 4);
> + check_struct_and_union3(int, short, int, 12, 4);
> + check_struct_and_union3(int, short, long, 12, 4);
> + check_struct_and_union3(int, short, long long, 16, 8);
> + check_struct_and_union3(int, short, float, 12, 4);
> + check_struct_and_union3(int, short, double, 16, 8);
> + check_struct_and_union3(int, short, long double, 16, 8);
> + check_struct_and_union3(int, int, char, 12, 4);
> + check_struct_and_union3(int, int, short, 12, 4);
> + check_struct_and_union3(int, int, int, 12, 4);
> + check_struct_and_union3(int, int, long, 12, 4);
> + check_struct_and_union3(int, int, long long, 16, 8);
> + check_struct_and_union3(int, int, float, 12, 4);
> + check_struct_and_union3(int, int, double, 16, 8);
> + check_struct_and_union3(int, int, long double, 16, 8);
> + check_struct_and_union3(int, long, char, 12, 4);
> + check_struct_and_union3(int, long, short, 12, 4);
> + check_struct_and_union3(int, long, int, 12, 4);
> + check_struct_and_union3(int, long, long, 12, 4);
> + check_struct_and_union3(int, long, long long, 16, 8);
> + check_struct_and_union3(int, long, float, 12, 4);
> + check_struct_and_union3(int, long, double, 16, 8);
> + check_struct_and_union3(int, long, long double, 16, 8);
> + check_struct_and_union3(int, long long, char, 16, 8);
> + check_struct_and_union3(int, long long, short, 16, 8);
> + check_struct_and_union3(int, long long, int, 16, 8);
> + check_struct_and_union3(int, long long, long, 16, 8);
> + check_struct_and_union3(int, long long, long long, 20, 8);
> + check_struct_and_union3(int, long long, float, 16, 8);
> + check_struct_and_union3(int, long long, double, 20, 8);
> + check_struct_and_union3(int, long long, long double, 20, 8);
> + check_struct_and_union3(int, float, char, 12, 4);
> + check_struct_and_union3(int, float, short, 12, 4);
> + check_struct_and_union3(int, float, int, 12, 4);
> + check_struct_and_union3(int, float, long, 12, 4);
> + check_struct_and_union3(int, float, long long, 16, 8);
> + check_struct_and_union3(int, float, float, 12, 4);
> + check_struct_and_union3(int, float, double, 16, 8);
> + check_struct_and_union3(int, float, long double, 16, 8);
> + check_struct_and_union3(int, double, char, 16, 8);
> + check_struct_and_union3(int, double, short, 16, 8);
> + check_struct_and_union3(int, double, int, 16, 8);
> + check_struct_and_union3(int, double, long, 16, 8);
> + check_struct_and_union3(int, double, long long, 20, 8);
> + check_struct_and_union3(int, double, float, 16, 8);
> + check_struct_and_union3(int, double, double, 20, 8);
> + check_struct_and_union3(int, double, long double, 20, 8);
> + check_struct_and_union3(int, long double, char, 16, 8);
> + check_struct_and_union3(int, long double, short, 16, 8);
> + check_struct_and_union3(int, long double, int, 16, 8);
> + check_struct_and_union3(int, long double, long, 16, 8);
> + check_struct_and_union3(int, long double, long long, 20, 8);
> + check_struct_and_union3(int, long double, float, 16, 8);
> + check_struct_and_union3(int, long double, double, 20, 8);
> + check_struct_and_union3(int, long double, long double, 20, 8);
> + check_struct_and_union3(long, char, char, 8, 4);
> + check_struct_and_union3(long, char, short, 8, 4);
> + check_struct_and_union3(long, char, int, 12, 4);
> + check_struct_and_union3(long, char, long, 12, 4);
> + check_struct_and_union3(long, char, long long, 16, 8);
> + check_struct_and_union3(long, char, float, 12, 4);
> + check_struct_and_union3(long, char, double, 16, 8);
> + check_struct_and_union3(long, char, long double, 16, 8);
> + check_struct_and_union3(long, short, char, 8, 4);
> + check_struct_and_union3(long, short, short, 8, 4);
> + check_struct_and_union3(long, short, int, 12, 4);
> + check_struct_and_union3(long, short, long, 12, 4);
> + check_struct_and_union3(long, short, long long, 16, 8);
> + check_struct_and_union3(long, short, float, 12, 4);
> + check_struct_and_union3(long, short, double, 16, 8);
> + check_struct_and_union3(long, short, long double, 16, 8);
> + check_struct_and_union3(long, int, char, 12, 4);
> + check_struct_and_union3(long, int, short, 12, 4);
> + check_struct_and_union3(long, int, int, 12, 4);
> + check_struct_and_union3(long, int, long, 12, 4);
> + check_struct_and_union3(long, int, long long, 16, 8);
> + check_struct_and_union3(long, int, float, 12, 4);
> + check_struct_and_union3(long, int, double, 16, 8);
> + check_struct_and_union3(long, int, long double, 16, 8);
> + check_struct_and_union3(long, long, char, 12, 4);
> + check_struct_and_union3(long, long, short, 12, 4);
> + check_struct_and_union3(long, long, int, 12, 4);
> + check_struct_and_union3(long, long, long, 12, 4);
> + check_struct_and_union3(long, long, long long, 16, 8);
> + check_struct_and_union3(long, long, float, 12, 4);
> + check_struct_and_union3(long, long, double, 16, 8);
> + check_struct_and_union3(long, long, long double, 16, 8);
> + check_struct_and_union3(long, long long, char, 16, 8);
> + check_struct_and_union3(long, long long, short, 16, 8);
> + check_struct_and_union3(long, long long, int, 16, 8);
> + check_struct_and_union3(long, long long, long, 16, 8);
> + check_struct_and_union3(long, long long, long long, 20, 8);
> + check_struct_and_union3(long, long long, float, 16, 8);
> + check_struct_and_union3(long, long long, double, 20, 8);
> + check_struct_and_union3(long, long long, long double, 20, 8);
> + check_struct_and_union3(long, float, char, 12, 4);
> + check_struct_and_union3(long, float, short, 12, 4);
> + check_struct_and_union3(long, float, int, 12, 4);
> + check_struct_and_union3(long, float, long, 12, 4);
> + check_struct_and_union3(long, float, long long, 16, 8);
> + check_struct_and_union3(long, float, float, 12, 4);
> + check_struct_and_union3(long, float, double, 16, 8);
> + check_struct_and_union3(long, float, long double, 16, 8);
> + check_struct_and_union3(long, double, char, 16, 8);
> + check_struct_and_union3(long, double, short, 16, 8);
> + check_struct_and_union3(long, double, int, 16, 8);
> + check_struct_and_union3(long, double, long, 16, 8);
> + check_struct_and_union3(long, double, long long, 20, 8);
> + check_struct_and_union3(long, double, float, 16, 8);
> + check_struct_and_union3(long, double, double, 20, 8);
> + check_struct_and_union3(long, double, long double, 20, 8);
> + check_struct_and_union3(long, long double, char, 16, 8);
> + check_struct_and_union3(long, long double, short, 16, 8);
> + check_struct_and_union3(long, long double, int, 16, 8);
> + check_struct_and_union3(long, long double, long, 16, 8);
> + check_struct_and_union3(long, long double, long long, 20, 8);
> + check_struct_and_union3(long, long double, float, 16, 8);
> + check_struct_and_union3(long, long double, double, 20, 8);
> + check_struct_and_union3(long, long double, long double, 20, 8);
> + check_struct_and_union3(long long, char, char, 12, 8);
> + check_struct_and_union3(long long, char, short, 12, 8);
> + check_struct_and_union3(long long, char, int, 16, 8);
> + check_struct_and_union3(long long, char, long, 16, 8);
> + check_struct_and_union3(long long, char, long long, 20, 8);
> + check_struct_and_union3(long long, char, float, 16, 8);
> + check_struct_and_union3(long long, char, double, 20, 8);
> + check_struct_and_union3(long long, char, long double, 20, 8);
> + check_struct_and_union3(long long, short, char, 12, 8);
> + check_struct_and_union3(long long, short, short, 12, 8);
> + check_struct_and_union3(long long, short, int, 16, 8);
> + check_struct_and_union3(long long, short, long, 16, 8);
> + check_struct_and_union3(long long, short, long long, 20, 8);
> + check_struct_and_union3(long long, short, float, 16, 8);
> + check_struct_and_union3(long long, short, double, 20, 8);
> + check_struct_and_union3(long long, short, long double, 20, 8);
> + check_struct_and_union3(long long, int, char, 16, 8);
> + check_struct_and_union3(long long, int, short, 16, 8);
> + check_struct_and_union3(long long, int, int, 16, 8);
> + check_struct_and_union3(long long, int, long, 16, 8);
> + check_struct_and_union3(long long, int, long long, 20, 8);
> + check_struct_and_union3(long long, int, float, 16, 8);
> + check_struct_and_union3(long long, int, double, 20, 8);
> + check_struct_and_union3(long long, int, long double, 20, 8);
> + check_struct_and_union3(long long, long, char, 16, 8);
> + check_struct_and_union3(long long, long, short, 16, 8);
> + check_struct_and_union3(long long, long, int, 16, 8);
> + check_struct_and_union3(long long, long, long, 16, 8);
> + check_struct_and_union3(long long, long, long long, 20, 8);
> + check_struct_and_union3(long long, long, float, 16, 8);
> + check_struct_and_union3(long long, long, double, 20, 8);
> + check_struct_and_union3(long long, long, long double, 20, 8);
> + check_struct_and_union3(long long, long long, char, 20, 8);
> + check_struct_and_union3(long long, long long, short, 20, 8);
> + check_struct_and_union3(long long, long long, int, 20, 8);
> + check_struct_and_union3(long long, long long, long, 20, 8);
> + check_struct_and_union3(long long, long long, long long, 24, 8);
> + check_struct_and_union3(long long, long long, float, 20, 8);
> + check_struct_and_union3(long long, long long, double, 24, 8);
> + check_struct_and_union3(long long, long long, long double, 24, 8);
> + check_struct_and_union3(long long, float, char, 16, 8);
> + check_struct_and_union3(long long, float, short, 16, 8);
> + check_struct_and_union3(long long, float, int, 16, 8);
> + check_struct_and_union3(long long, float, long, 16, 8);
> + check_struct_and_union3(long long, float, long long, 20, 8);
> + check_struct_and_union3(long long, float, float, 16, 8);
> + check_struct_and_union3(long long, float, double, 20, 8);
> + check_struct_and_union3(long long, float, long double, 20, 8);
> + check_struct_and_union3(long long, double, char, 20, 8);
> + check_struct_and_union3(long long, double, short, 20, 8);
> + check_struct_and_union3(long long, double, int, 20, 8);
> + check_struct_and_union3(long long, double, long, 20, 8);
> + check_struct_and_union3(long long, double, long long, 24, 8);
> + check_struct_and_union3(long long, double, float, 20, 8);
> + check_struct_and_union3(long long, double, double, 24, 8);
> + check_struct_and_union3(long long, double, long double, 24, 8);
> + check_struct_and_union3(long long, long double, char, 20, 8);
> + check_struct_and_union3(long long, long double, short, 20, 8);
> + check_struct_and_union3(long long, long double, int, 20, 8);
> + check_struct_and_union3(long long, long double, long, 20, 8);
> + check_struct_and_union3(long long, long double, long long, 24, 8);
> + check_struct_and_union3(long long, long double, float, 20, 8);
> + check_struct_and_union3(long long, long double, double, 24, 8);
> + check_struct_and_union3(long long, long double, long double, 24, 8);
> + check_struct_and_union3(float, char, char, 8, 4);
> + check_struct_and_union3(float, char, short, 8, 4);
> + check_struct_and_union3(float, char, int, 12, 4);
> + check_struct_and_union3(float, char, long, 12, 4);
> + check_struct_and_union3(float, char, long long, 16, 8);
> + check_struct_and_union3(float, char, float, 12, 4);
> + check_struct_and_union3(float, char, double, 16, 8);
> + check_struct_and_union3(float, char, long double, 16, 8);
> + check_struct_and_union3(float, short, char, 8, 4);
> + check_struct_and_union3(float, short, short, 8, 4);
> + check_struct_and_union3(float, short, int, 12, 4);
> + check_struct_and_union3(float, short, long, 12, 4);
> + check_struct_and_union3(float, short, long long, 16, 8);
> + check_struct_and_union3(float, short, float, 12, 4);
> + check_struct_and_union3(float, short, double, 16, 8);
> + check_struct_and_union3(float, short, long double, 16, 8);
> + check_struct_and_union3(float, int, char, 12, 4);
> + check_struct_and_union3(float, int, short, 12, 4);
> + check_struct_and_union3(float, int, int, 12, 4);
> + check_struct_and_union3(float, int, long, 12, 4);
> + check_struct_and_union3(float, int, long long, 16, 8);
> + check_struct_and_union3(float, int, float, 12, 4);
> + check_struct_and_union3(float, int, double, 16, 8);
> + check_struct_and_union3(float, int, long double, 16, 8);
> + check_struct_and_union3(float, long, char, 12, 4);
> + check_struct_and_union3(float, long, short, 12, 4);
> + check_struct_and_union3(float, long, int, 12, 4);
> + check_struct_and_union3(float, long, long, 12, 4);
> + check_struct_and_union3(float, long, long long, 16, 8);
> + check_struct_and_union3(float, long, float, 12, 4);
> + check_struct_and_union3(float, long, double, 16, 8);
> + check_struct_and_union3(float, long, long double, 16, 8);
> + check_struct_and_union3(float, long long, char, 16, 8);
> + check_struct_and_union3(float, long long, short, 16, 8);
> + check_struct_and_union3(float, long long, int, 16, 8);
> + check_struct_and_union3(float, long long, long, 16, 8);
> + check_struct_and_union3(float, long long, long long, 20, 8);
> + check_struct_and_union3(float, long long, float, 16, 8);
> + check_struct_and_union3(float, long long, double, 20, 8);
> + check_struct_and_union3(float, long long, long double, 20, 8);
> + check_struct_and_union3(float, float, char, 12, 4);
> + check_struct_and_union3(float, float, short, 12, 4);
> + check_struct_and_union3(float, float, int, 12, 4);
> + check_struct_and_union3(float, float, long, 12, 4);
> + check_struct_and_union3(float, float, long long, 16, 8);
> + check_struct_and_union3(float, float, float, 12, 4);
> + check_struct_and_union3(float, float, double, 16, 8);
> + check_struct_and_union3(float, float, long double, 16, 8);
> + check_struct_and_union3(float, double, char, 16, 8);
> + check_struct_and_union3(float, double, short, 16, 8);
> + check_struct_and_union3(float, double, int, 16, 8);
> + check_struct_and_union3(float, double, long, 16, 8);
> + check_struct_and_union3(float, double, long long, 20, 8);
> + check_struct_and_union3(float, double, float, 16, 8);
> + check_struct_and_union3(float, double, double, 20, 8);
> + check_struct_and_union3(float, double, long double, 20, 8);
> + check_struct_and_union3(float, long double, char, 16, 8);
> + check_struct_and_union3(float, long double, short, 16, 8);
> + check_struct_and_union3(float, long double, int, 16, 8);
> + check_struct_and_union3(float, long double, long, 16, 8);
> + check_struct_and_union3(float, long double, long long, 20, 8);
> + check_struct_and_union3(float, long double, float, 16, 8);
> + check_struct_and_union3(float, long double, double, 20, 8);
> + check_struct_and_union3(float, long double, long double, 20, 8);
> + check_struct_and_union3(double, char, char, 12, 8);
> + check_struct_and_union3(double, char, short, 12, 8);
> + check_struct_and_union3(double, char, int, 16, 8);
> + check_struct_and_union3(double, char, long, 16, 8);
> + check_struct_and_union3(double, char, long long, 20, 8);
> + check_struct_and_union3(double, char, float, 16, 8);
> + check_struct_and_union3(double, char, double, 20, 8);
> + check_struct_and_union3(double, char, long double, 20, 8);
> + check_struct_and_union3(double, short, char, 12, 8);
> + check_struct_and_union3(double, short, short, 12, 8);
> + check_struct_and_union3(double, short, int, 16, 8);
> + check_struct_and_union3(double, short, long, 16, 8);
> + check_struct_and_union3(double, short, long long, 20, 8);
> + check_struct_and_union3(double, short, float, 16, 8);
> + check_struct_and_union3(double, short, double, 20, 8);
> + check_struct_and_union3(double, short, long double, 20, 8);
> + check_struct_and_union3(double, int, char, 16, 8);
> + check_struct_and_union3(double, int, short, 16, 8);
> + check_struct_and_union3(double, int, int, 16, 8);
> + check_struct_and_union3(double, int, long, 16, 8);
> + check_struct_and_union3(double, int, long long, 20, 8);
> + check_struct_and_union3(double, int, float, 16, 8);
> + check_struct_and_union3(double, int, double, 20, 8);
> + check_struct_and_union3(double, int, long double, 20, 8);
> + check_struct_and_union3(double, long, char, 16, 8);
> + check_struct_and_union3(double, long, short, 16, 8);
> + check_struct_and_union3(double, long, int, 16, 8);
> + check_struct_and_union3(double, long, long, 16, 8);
> + check_struct_and_union3(double, long, long long, 20, 8);
> + check_struct_and_union3(double, long, float, 16, 8);
> + check_struct_and_union3(double, long, double, 20, 8);
> + check_struct_and_union3(double, long, long double, 20, 8);
> + check_struct_and_union3(double, long long, char, 20, 8);
> + check_struct_and_union3(double, long long, short, 20, 8);
> + check_struct_and_union3(double, long long, int, 20, 8);
> + check_struct_and_union3(double, long long, long, 20, 8);
> + check_struct_and_union3(double, long long, long long, 24, 8);
> + check_struct_and_union3(double, long long, float, 20, 8);
> + check_struct_and_union3(double, long long, double, 24, 8);
> + check_struct_and_union3(double, long long, long double, 24, 8);
> + check_struct_and_union3(double, float, char, 16, 8);
> + check_struct_and_union3(double, float, short, 16, 8);
> + check_struct_and_union3(double, float, int, 16, 8);
> + check_struct_and_union3(double, float, long, 16, 8);
> + check_struct_and_union3(double, float, long long, 20, 8);
> + check_struct_and_union3(double, float, float, 16, 8);
> + check_struct_and_union3(double, float, double, 20, 8);
> + check_struct_and_union3(double, float, long double, 20, 8);
> + check_struct_and_union3(double, double, char, 20, 8);
> + check_struct_and_union3(double, double, short, 20, 8);
> + check_struct_and_union3(double, double, int, 20, 8);
> + check_struct_and_union3(double, double, long, 20, 8);
> + check_struct_and_union3(double, double, long long, 24, 8);
> + check_struct_and_union3(double, double, float, 20, 8);
> + check_struct_and_union3(double, double, double, 24, 8);
> + check_struct_and_union3(double, double, long double, 24, 8);
> + check_struct_and_union3(double, long double, char, 20, 8);
> + check_struct_and_union3(double, long double, short, 20, 8);
> + check_struct_and_union3(double, long double, int, 20, 8);
> + check_struct_and_union3(double, long double, long, 20, 8);
> + check_struct_and_union3(double, long double, long long, 24, 8);
> + check_struct_and_union3(double, long double, float, 20, 8);
> + check_struct_and_union3(double, long double, double, 24, 8);
> + check_struct_and_union3(double, long double, long double, 24, 8);
> + check_struct_and_union3(long double, char, char, 12, 8);
> + check_struct_and_union3(long double, char, short, 12, 8);
> + check_struct_and_union3(long double, char, int, 16, 8);
> + check_struct_and_union3(long double, char, long, 16, 8);
> + check_struct_and_union3(long double, char, long long, 20, 8);
> + check_struct_and_union3(long double, char, float, 16, 8);
> + check_struct_and_union3(long double, char, double, 20, 8);
> + check_struct_and_union3(long double, char, long double, 20, 8);
> + check_struct_and_union3(long double, short, char, 12, 8);
> + check_struct_and_union3(long double, short, short, 12, 8);
> + check_struct_and_union3(long double, short, int, 16, 8);
> + check_struct_and_union3(long double, short, long, 16, 8);
> + check_struct_and_union3(long double, short, long long, 20, 8);
> + check_struct_and_union3(long double, short, float, 16, 8);
> + check_struct_and_union3(long double, short, double, 20, 8);
> + check_struct_and_union3(long double, short, long double, 20, 8);
> + check_struct_and_union3(long double, int, char, 16, 8);
> + check_struct_and_union3(long double, int, short, 16, 8);
> + check_struct_and_union3(long double, int, int, 16, 8);
> + check_struct_and_union3(long double, int, long, 16, 8);
> + check_struct_and_union3(long double, int, long long, 20, 8);
> + check_struct_and_union3(long double, int, float, 16, 8);
> + check_struct_and_union3(long double, int, double, 20, 8);
> + check_struct_and_union3(long double, int, long double, 20, 8);
> + check_struct_and_union3(long double, long, char, 16, 8);
> + check_struct_and_union3(long double, long, short, 16, 8);
> + check_struct_and_union3(long double, long, int, 16, 8);
> + check_struct_and_union3(long double, long, long, 16, 8);
> + check_struct_and_union3(long double, long, long long, 20, 8);
> + check_struct_and_union3(long double, long, float, 16, 8);
> + check_struct_and_union3(long double, long, double, 20, 8);
> + check_struct_and_union3(long double, long, long double, 20, 8);
> + check_struct_and_union3(long double, long long, char, 20, 8);
> + check_struct_and_union3(long double, long long, short, 20, 8);
> + check_struct_and_union3(long double, long long, int, 20, 8);
> + check_struct_and_union3(long double, long long, long, 20, 8);
> + check_struct_and_union3(long double, long long, long long, 24, 8);
> + check_struct_and_union3(long double, long long, float, 20, 8);
> + check_struct_and_union3(long double, long long, double, 24, 8);
> + check_struct_and_union3(long double, long long, long double, 24, 8);
> + check_struct_and_union3(long double, float, char, 16, 8);
> + check_struct_and_union3(long double, float, short, 16, 8);
> + check_struct_and_union3(long double, float, int, 16, 8);
> + check_struct_and_union3(long double, float, long, 16, 8);
> + check_struct_and_union3(long double, float, long long, 20, 8);
> + check_struct_and_union3(long double, float, float, 16, 8);
> + check_struct_and_union3(long double, float, double, 20, 8);
> + check_struct_and_union3(long double, float, long double, 20, 8);
> + check_struct_and_union3(long double, double, char, 20, 8);
> + check_struct_and_union3(long double, double, short, 20, 8);
> + check_struct_and_union3(long double, double, int, 20, 8);
> + check_struct_and_union3(long double, double, long, 20, 8);
> + check_struct_and_union3(long double, double, long long, 24, 8);
> + check_struct_and_union3(long double, double, float, 20, 8);
> + check_struct_and_union3(long double, double, double, 24, 8);
> + check_struct_and_union3(long double, double, long double, 24, 8);
> + check_struct_and_union3(long double, long double, char, 20, 8);
> + check_struct_and_union3(long double, long double, short, 20, 8);
> + check_struct_and_union3(long double, long double, int, 20, 8);
> + check_struct_and_union3(long double, long double, long, 20, 8);
> + check_struct_and_union3(long double, long double, long long, 24, 8);
> + check_struct_and_union3(long double, long double, float, 20, 8);
> + check_struct_and_union3(long double, long double, double, 24, 8);
> + check_struct_and_union3(long double, long double, long double, 24, 8);
> + return 0;
> +}
> diff --git a/gcc/testsuite/gcc.target/i386/iamcu/test_basic_64bit_returning.c b/gcc/testsuite/gcc.target/i386/iamcu/test_basic_64bit_returning.c
> new file mode 100644
> index 0000000..ecece94
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/iamcu/test_basic_64bit_returning.c
> @@ -0,0 +1,57 @@
> +#include "defines.h"
> +#include "macros.h"
> +#include "args.h"
> +
> +struct IntegerRegisters iregbits = { ~0, ~0, ~0, ~0, ~0, ~0 };
> +struct IntegerRegisters iregs;
> +unsigned int num_iregs;
> +
> +long long
> +fun_test_returning_long_long (void)
> +{
> + volatile_var++;
> + return (long long) 0xabadbeefabadbeefLL;
> +}
> +
> +double
> +fun_test_returning_double (void)
> +{
> + volatile_var++;
> + return (double) 12345678.0;
> +}
> +
> +union
> +{
> + long long ll;
> + double d;
> +} test_64;
> +
> +int
> +main (void)
> +{
> + unsigned failed = 0;
> + long long ll;
> + double d;
> +
> + clear_struct_registers;
> + test_64.ll = 0xabadbeefabadbeefLL;
> +
> + ll = WRAP_RET (fun_test_returning_long_long)();
> + if (ll != test_64.ll
> + || (test_64.ll & 0xffffffff) != eax
> + || ((test_64.ll >> 32) & 0xffffffff) != edx)
> + failed++;
> +
> + clear_struct_registers;
> + test_64.d = 12345678.0;
> +
> + d = WRAP_RET (fun_test_returning_double)();
> + if (d != test_64.d
> + || (test_64.ll & 0xffffffff) != eax
> + || ((test_64.ll >> 32) & 0xffffffff) != edx)
> + printf ("fail double\n"), failed++;
> +
> + if (failed)
> + abort ();
> + return 0;
> +}
> diff --git a/gcc/testsuite/gcc.target/i386/iamcu/test_basic_alignment.c b/gcc/testsuite/gcc.target/i386/iamcu/test_basic_alignment.c
> new file mode 100644
> index 0000000..f14cf17
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/iamcu/test_basic_alignment.c
> @@ -0,0 +1,33 @@
> +/* This checks alignment of basic types. */
> +
> +#include "defines.h"
> +#include "macros.h"
> +
> +
> +int
> +main (void)
> +{
> + /* Integral types. */
> + run_signed_tests2(check_align, char, TYPE_ALIGN_CHAR);
> + run_signed_tests2(check_align, short, TYPE_ALIGN_SHORT);
> + run_signed_tests2(check_align, int, TYPE_ALIGN_INT);
> + run_signed_tests2(check_align, long, TYPE_ALIGN_LONG);
> + run_signed_tests2(check_align, long long, TYPE_ALIGN_LONG_LONG);
> + check_align(enumtype, TYPE_ALIGN_ENUM);
> +
> + /* Floating point types. */
> + check_align(float, TYPE_ALIGN_FLOAT);
> + check_align(double, TYPE_ALIGN_DOUBLE);
> +#ifdef CHECK_LONG_DOUBLE
> + check_align(long double, TYPE_ALIGN_LONG_DOUBLE);
> +#endif
> +#ifdef CHECK_FLOAT128
> + check_align(__float128, TYPE_ALIGN_FLOAT128);
> +#endif
> +
> + /* Pointer types. */
> + check_align(void *, TYPE_ALIGN_POINTER);
> + check_align(void (*)(), TYPE_ALIGN_POINTER);
> +
> + return 0;
> +}
> diff --git a/gcc/testsuite/gcc.target/i386/iamcu/test_basic_array_size_and_align.c b/gcc/testsuite/gcc.target/i386/iamcu/test_basic_array_size_and_align.c
> new file mode 100644
> index 0000000..e4b6369
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/iamcu/test_basic_array_size_and_align.c
> @@ -0,0 +1,32 @@
> +/* Test of simple arrays, size and alignment. */
> +
> +#include "defines.h"
> +#include "macros.h"
> +
> +
> +int
> +main (void)
> +{
> + /* Integral types. */
> + run_signed_tests3(check_array_size_and_align, char, TYPE_SIZE_CHAR, TYPE_ALIGN_CHAR);
> + run_signed_tests3(check_array_size_and_align, short, TYPE_SIZE_SHORT, TYPE_ALIGN_SHORT);
> + run_signed_tests3(check_array_size_and_align, int, TYPE_SIZE_INT, TYPE_ALIGN_INT);
> + run_signed_tests3(check_array_size_and_align, long, TYPE_SIZE_LONG, TYPE_ALIGN_LONG);
> + run_signed_tests3(check_array_size_and_align, long long, TYPE_SIZE_LONG_LONG, TYPE_ALIGN_LONG_LONG);
> + check_array_size_and_align(enum dummytype, TYPE_SIZE_ENUM, TYPE_ALIGN_ENUM);
> +
> + /* Floating point types. */
> + check_array_size_and_align(float, TYPE_SIZE_FLOAT, TYPE_ALIGN_FLOAT);
> + check_array_size_and_align(double, TYPE_SIZE_DOUBLE, TYPE_ALIGN_DOUBLE);
> +#ifdef CHECK_LONG_DOUBLE
> + check_array_size_and_align(long double, TYPE_SIZE_LONG_DOUBLE, TYPE_ALIGN_LONG_DOUBLE);
> +#endif
> +#ifdef CHECK_FLOAT128
> + check_array_size_and_align(__float128, TYPE_SIZE_FLOAT128, TYPE_ALIGN_FLOAT128);
> +#endif
> +
> + /* Pointer types. The function pointer doesn't work with these macros. */
> + check_array_size_and_align(void *, TYPE_SIZE_POINTER, TYPE_ALIGN_POINTER);
> +
> + return 0;
> +}
> diff --git a/gcc/testsuite/gcc.target/i386/iamcu/test_basic_returning.c b/gcc/testsuite/gcc.target/i386/iamcu/test_basic_returning.c
> new file mode 100644
> index 0000000..23efa6e
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/iamcu/test_basic_returning.c
> @@ -0,0 +1,52 @@
> +#include "defines.h"
> +#include "macros.h"
> +#include "args.h"
> +
> +char
> +fun_test_returning_char (void)
> +{
> + volatile_var++;
> + return 64;
> +}
> +
> +short
> +fun_test_returning_short (void)
> +{
> + volatile_var++;
> + return 65;
> +}
> +
> +int
> +fun_test_returning_int (void)
> +{
> + volatile_var++;
> + return 66;
> +}
> +
> +long
> +fun_test_returning_long (void)
> +{
> + volatile_var++;
> + return 67;
> +}
> +
> +float
> +fun_test_returning_float (void)
> +{
> + volatile_var++;
> + return 68;
> +}
> +
> +#define def_test_returning_type(fun, type, ret, reg) \
> + { type var = WRAP_RET (fun) (); \
> + assert (ret == (type) reg && ret == var); }
> +int
> +main (void)
> +{
> + def_test_returning_type(fun_test_returning_char, char, 64, eax);
> + def_test_returning_type(fun_test_returning_short, short, 65, eax);
> + def_test_returning_type(fun_test_returning_int, int, 66, eax);
> + def_test_returning_type(fun_test_returning_long, long, 67, eax);
> + def_test_returning_type(fun_test_returning_float, float, 68, eax);
> + return 0;
> +}
> diff --git a/gcc/testsuite/gcc.target/i386/iamcu/test_basic_sizes.c b/gcc/testsuite/gcc.target/i386/iamcu/test_basic_sizes.c
> new file mode 100644
> index 0000000..6582fc6
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/iamcu/test_basic_sizes.c
> @@ -0,0 +1,36 @@
> +/* This checks sizes of basic types. */
> +
> +#include "defines.h"
> +#include "macros.h"
> +
> +
> +int
> +main (void)
> +{
> + /* Integral types. */
> + run_signed_tests2(check_size, char, TYPE_SIZE_CHAR);
> + run_signed_tests2(check_size, short, TYPE_SIZE_SHORT);
> + run_signed_tests2(check_size, int, TYPE_SIZE_INT);
> + run_signed_tests2(check_size, long, TYPE_SIZE_LONG);
> + run_signed_tests2(check_size, long long, TYPE_SIZE_LONG_LONG);
> +#ifdef CHECK_INT128
> + run_signed_tests2(check_size, __int128, TYPE_SIZE_INT128);
> +#endif
> + check_size(enumtype, TYPE_SIZE_ENUM);
> +
> + /* Floating point types. */
> + check_size(float, TYPE_SIZE_FLOAT);
> + check_size(double, TYPE_SIZE_DOUBLE);
> +#ifdef CHECK_LONG_DOUBLE
> + check_size(long double, TYPE_SIZE_LONG_DOUBLE);
> +#endif
> +#ifdef CHECK_FLOAT128
> + check_size(__float128, TYPE_SIZE_FLOAT128);
> +#endif
> +
> + /* Pointer types. */
> + check_size(void *, TYPE_SIZE_POINTER);
> + check_size(void (*)(), TYPE_SIZE_POINTER);
> +
> + return 0;
> +}
> diff --git a/gcc/testsuite/gcc.target/i386/iamcu/test_basic_struct_size_and_align.c b/gcc/testsuite/gcc.target/i386/iamcu/test_basic_struct_size_and_align.c
> new file mode 100644
> index 0000000..3b5027f
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/iamcu/test_basic_struct_size_and_align.c
> @@ -0,0 +1,33 @@
> +/* This checks size and alignment of structs with a single basic type
> + element. All basic types are checked. */
> +
> +#include "defines.h"
> +#include "macros.h"
> +
> +
> +int
> +main (void)
> +{
> + /* Integral types. */
> + run_signed_tests3(check_basic_struct_size_and_align, char, TYPE_SIZE_CHAR, TYPE_ALIGN_CHAR);
> + run_signed_tests3(check_basic_struct_size_and_align, short, TYPE_SIZE_SHORT, TYPE_ALIGN_SHORT);
> + run_signed_tests3(check_basic_struct_size_and_align, int, TYPE_SIZE_INT, TYPE_ALIGN_INT);
> + run_signed_tests3(check_basic_struct_size_and_align, long, TYPE_SIZE_LONG, TYPE_ALIGN_LONG);
> + run_signed_tests3(check_basic_struct_size_and_align, long long, TYPE_SIZE_LONG_LONG, TYPE_ALIGN_LONG_LONG);
> + check_basic_struct_size_and_align(enum dummytype, TYPE_SIZE_ENUM, TYPE_ALIGN_ENUM);
> +
> + /* Floating point types. */
> + check_basic_struct_size_and_align(float, TYPE_SIZE_FLOAT, TYPE_ALIGN_FLOAT);
> + check_basic_struct_size_and_align(double, TYPE_SIZE_DOUBLE, TYPE_ALIGN_DOUBLE);
> +#ifdef CHECK_LONG_DOUBLE
> + check_basic_struct_size_and_align(long double, TYPE_SIZE_LONG_DOUBLE, TYPE_ALIGN_LONG_DOUBLE);
> +#endif
> +#ifdef CHECK_FLOAT128
> + check_basic_struct_size_and_align(__float128, TYPE_SIZE_FLOAT128, TYPE_ALIGN_FLOAT128);
> +#endif
> +
> + /* Pointer types. The function pointer doesn't work with these macros. */
> + check_basic_struct_size_and_align(void *, TYPE_SIZE_POINTER, TYPE_ALIGN_POINTER);
> +
> + return 0;
> +}
> diff --git a/gcc/testsuite/gcc.target/i386/iamcu/test_basic_union_size_and_align.c b/gcc/testsuite/gcc.target/i386/iamcu/test_basic_union_size_and_align.c
> new file mode 100644
> index 0000000..93ba5ff
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/iamcu/test_basic_union_size_and_align.c
> @@ -0,0 +1,32 @@
> +/* Test of simple unions, size and alignment. */
> +
> +#include "defines.h"
> +#include "macros.h"
> +
> +
> +int
> +main (void)
> +{
> + /* Integral types. */
> + run_signed_tests3(check_basic_union_size_and_align, char, TYPE_SIZE_CHAR, TYPE_ALIGN_CHAR);
> + run_signed_tests3(check_basic_union_size_and_align, short, TYPE_SIZE_SHORT, TYPE_ALIGN_SHORT);
> + run_signed_tests3(check_basic_union_size_and_align, int, TYPE_SIZE_INT, TYPE_ALIGN_INT);
> + run_signed_tests3(check_basic_union_size_and_align, long, TYPE_SIZE_LONG, TYPE_ALIGN_LONG);
> + run_signed_tests3(check_basic_union_size_and_align, long long, TYPE_SIZE_LONG_LONG, TYPE_ALIGN_LONG_LONG);
> + check_basic_union_size_and_align(enum dummytype, TYPE_SIZE_ENUM, TYPE_ALIGN_ENUM);
> +
> + /* Floating point types. */
> + check_basic_union_size_and_align(float, TYPE_SIZE_FLOAT, TYPE_ALIGN_FLOAT);
> + check_basic_union_size_and_align(double, TYPE_SIZE_DOUBLE, TYPE_ALIGN_DOUBLE);
> +#ifdef CHECK_LONG_DOUBLE
> + check_basic_union_size_and_align(long double, TYPE_SIZE_LONG_DOUBLE, TYPE_ALIGN_LONG_DOUBLE);
> +#endif
> +#ifdef CHECK_FLOAT128
> + check_basic_union_size_and_align(__float128, TYPE_SIZE_FLOAT128, TYPE_ALIGN_FLOAT128);
> +#endif
> +
> + /* Pointer types. The function pointer doesn't work with these macros. */
> + check_basic_union_size_and_align(void *, TYPE_SIZE_POINTER, TYPE_ALIGN_POINTER);
> +
> + return 0;
> +}
> diff --git a/gcc/testsuite/gcc.target/i386/iamcu/test_bitfields.c b/gcc/testsuite/gcc.target/i386/iamcu/test_bitfields.c
> new file mode 100644
> index 0000000..0b1c293
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/iamcu/test_bitfields.c
> @@ -0,0 +1,162 @@
> +/* This is a small test to see if bitfields are working. It is only a
> + few structs and a union and a test to see if they have the correct
> + size, if values can be read and written and a couple of argument
> + passing tests. No alignment testing is done. */
> +
> +#include "defines.h"
> +#include "macros.h"
> +
> +
> +/* These five bitfields are taken from the System V ABI, Intel 386
> + architecture supplement. */
> +
> +/* Word aligned, sizeof is 4. */
> +struct RightToLeft
> +{
> + int j:5;
> + int k:6;
> + int m:7;
> +};
> +
> +/* Word aligned, sizeof is 12. */
> +struct BoundaryAlignment
> +{
> + short s:9;
> + int j:9;
> + char c;
> + short t:9;
> + short u:9;
> + char d;
> +};
> +
> +/* Halfword aligned, sizeof is 2. */
> +struct StorageUnitSharing
> +{
> + char c;
> + short s:8;
> +};
> +
> +/* Halfword aligned, sizeof is 2. */
> +union Allocation
> +{
> + char c;
> + short s:8;
> +};
> +
> +/* Byte aligned, sizeof is 9. */
> +struct Unnamed
> +{
> + char c;
> + int :0;
> + char d;
> + short :9;
> + char e;
> + char :0;
> +};
> +
> +/* Extra struct testing bitfields in larger types.
> + Doubleword aligned, sizeof is 8. */
> +struct LargerTypes
> +{
> + long long l:33;
> + int i:31;
> +};
> +
> +
> +void
> +passing1 (struct RightToLeft str, int j, int k, int m)
> +{
> + assert (str.j == j);
> + assert (str.k == k);
> + assert (str.m == m);
> +}
> +
> +void
> +passing2 (struct BoundaryAlignment str, short s, int j, char c, short t,
> + short u, char d)
> +{
> + assert (str.s == s);
> + assert (str.j == j);
> + assert (str.c == c);
> + assert (str.t == t);
> + assert (str.u == u);
> + assert (str.d == d);
> +}
> +
> +void
> +passing3 (struct StorageUnitSharing str, char c, short s)
> +{
> + assert (str.c == c);
> + assert (str.s == s);
> +}
> +
> +void
> +passing4 (struct Unnamed str, char c, char d, char e)
> +{
> + assert (str.c == c);
> + assert (str.d == d);
> + assert (str.e == e);
> +}
> +
> +void
> +passing5 (struct LargerTypes str, long long l, int i)
> +{
> + assert (str.l == l);
> + assert (str.i == i);
> +}
> +
> +
> +void
> +passingU (union Allocation u, char c)
> +{
> + assert (u.c == c);
> + assert (u.s == c);
> +}
> +
> +
> +int
> +main (void)
> +{
> + struct RightToLeft str1;
> + struct BoundaryAlignment str2;
> + struct StorageUnitSharing str3;
> + struct Unnamed str4;
> + struct LargerTypes str5;
> + union Allocation u;
> +
> + /* Check sizeof's. */
> + check_size(str1, 4);
> + check_size(str2, 12);
> + check_size(str3, 2);
> + check_size(str4, 9);
> + check_size(str5, 8);
> + check_size(u, 2);
> +
> + /* Check alignof's. */
> + check_align_lv(str1, 4);
> + check_align_lv(str2, 4);
> + check_align_lv(str3, 2);
> + check_align_lv(str4, 1);
> + check_align_lv(str5, 4);
> + check_align_lv(u, 2);
> +
> + /* Check passing. */
> + str1.j = str2.s = str3.c = str4.c = str5.l = 4;
> + str1.k = str2.j = str3.s = str4.d = str5.i = 5;
> + str1.m = str2.c = str4.e = 6;
> + str2.t = 7;
> + str2.u = 8;
> + str2.d = 9;
> + passing1 (str1, 4, 5, 6);
> + passing2 (str2, 4, 5, 6, 7, 8, 9);
> + passing3 (str3, 4, 5);
> + passing4 (str4, 4, 5, 6);
> + passing5 (str5, 4, 5);
> +
> + u.c = 5;
> + passingU (u, 5);
> + u.s = 6;
> + passingU (u, 6);
> +
> + return 0;
> +}
> diff --git a/gcc/testsuite/gcc.target/i386/iamcu/test_complex_returning.c b/gcc/testsuite/gcc.target/i386/iamcu/test_complex_returning.c
> new file mode 100644
> index 0000000..9e9678d
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/iamcu/test_complex_returning.c
> @@ -0,0 +1,83 @@
> +/* This is a small test case for returning a complex number. Written by
> + Andreas Jaeger. */
> +
> +#include "defines.h"
> +
> +
> +#define BUILD_F_COMPLEX(real, imag) \
> + ({ __complex__ float __retval; \
> + __real__ __retval = (real); \
> + __imag__ __retval = (imag); \
> + __retval; })
> +
> +#define BUILD_D_COMPLEX(real, imag) \
> + ({ __complex__ double __retval; \
> + __real__ __retval = (real); \
> + __imag__ __retval = (imag); \
> + __retval; })
> +
> +#define BUILD_LD_COMPLEX(real, imag) \
> + ({ __complex__ long double __retval; \
> + __real__ __retval = (real); \
> + __imag__ __retval = (imag); \
> + __retval; })
> +
> +__complex__ float
> +aj_f_times2 (__complex__ float x)
> +{
> + __complex__ float res;
> +
> + __real__ res = (2.0 * __real__ x);
> + __imag__ res = (2.0 * __imag__ x);
> +
> + return res;
> +}
> +
> +__complex__ double
> +aj_d_times2 (__complex__ double x)
> +{
> + __complex__ double res;
> +
> + __real__ res = (2.0 * __real__ x);
> + __imag__ res = (2.0 * __imag__ x);
> +
> + return res;
> +}
> +
> +__complex__ long double
> +aj_ld_times2 (__complex__ long double x)
> +{
> + __complex__ long double res;
> +
> + __real__ res = (2.0 * __real__ x);
> + __imag__ res = (2.0 * __imag__ x);
> +
> + return res;
> +}
> +
> +int
> +main (void)
> +{
> +#ifdef CHECK_COMPLEX
> + _Complex float fc, fd;
> + _Complex double dc, dd;
> + _Complex long double ldc, ldd;
> +
> + fc = BUILD_LD_COMPLEX (2.0f, 3.0f);
> + fd = aj_f_times2 (fc);
> +
> + assert (__real__ fd == 4.0f && __imag__ fd == 6.0f);
> +
> + dc = BUILD_LD_COMPLEX (2.0, 3.0);
> + dd = aj_ld_times2 (dc);
> +
> + assert (__real__ dd == 4.0 && __imag__ dd == 6.0);
> +
> + ldc = BUILD_LD_COMPLEX (2.0L, 3.0L);
> + ldd = aj_ld_times2 (ldc);
> +
> + assert (__real__ ldd == 4.0L && __imag__ ldd == 6.0L);
> +#endif
> +
> + return 0;
> +}
> diff --git a/gcc/testsuite/gcc.target/i386/iamcu/test_passing_floats.c b/gcc/testsuite/gcc.target/i386/iamcu/test_passing_floats.c
> new file mode 100644
> index 0000000..6bb24cc
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/iamcu/test_passing_floats.c
> @@ -0,0 +1,608 @@
> +#include "defines.h"
> +#include "macros.h"
> +#include "args.h"
> +
> +struct IntegerRegisters iregbits = { ~0, ~0, ~0, ~0, ~0, ~0 };
> +struct IntegerRegisters iregs;
> +unsigned int num_iregs;
> +
> +/* This struct holds values for argument checking. */
> +struct
> +{
> + float f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17, f18, f19, f20, f21, f22, f23;
> +} values_float;
> +
> +struct
> +{
> + double f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17, f18, f19, f20, f21, f22, f23;
> +} values_double;
> +
> +struct
> +{
> + ldouble f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17, f18, f19, f20, f21, f22, f23;
> +} values_ldouble;
> +
> +void
> +fun_check_float_passing_float8_values (float f0 ATTRIBUTE_UNUSED, float f1 ATTRIBUTE_UNUSED, float f2 ATTRIBUTE_UNUSED, float f3 ATTRIBUTE_UNUSED, float f4 ATTRIBUTE_UNUSED, float f5 ATTRIBUTE_UNUSED, float f6 ATTRIBUTE_UNUSED, float f7 ATTRIBUTE_UNUSED)
> +{
> + /* Check argument values. */
> + assert (values_float.f0 == f0);
> + assert (values_float.f1 == f1);
> + assert (values_float.f2 == f2);
> + assert (values_float.f3 == f3);
> + assert (values_float.f4 == f4);
> + assert (values_float.f5 == f5);
> + assert (values_float.f6 == f6);
> + assert (values_float.f7 == f7);
> +
> +}
> +
> +void
> +fun_check_float_passing_float8_regs (float f0 ATTRIBUTE_UNUSED, float f1 ATTRIBUTE_UNUSED, float f2 ATTRIBUTE_UNUSED, float f3 ATTRIBUTE_UNUSED, float f4 ATTRIBUTE_UNUSED, float f5 ATTRIBUTE_UNUSED, float f6 ATTRIBUTE_UNUSED, float f7 ATTRIBUTE_UNUSED)
> +{
> + /* Check register contents. */
> + check_float_arguments;
> +}
> +
> +void
> +fun_check_float_passing_float16_values (float f0 ATTRIBUTE_UNUSED, float f1 ATTRIBUTE_UNUSED, float f2 ATTRIBUTE_UNUSED, float f3 ATTRIBUTE_UNUSED, float f4 ATTRIBUTE_UNUSED, float f5 ATTRIBUTE_UNUSED, float f6 ATTRIBUTE_UNUSED, float f7 ATTRIBUTE_UNUSED, float f8 ATTRIBUTE_UNUSED, float f9 ATTRIBUTE_UNUSED, float f10 ATTRIBUTE_UNUSED, float f11 ATTRIBUTE_UNUSED, float f12 ATTRIBUTE_UNUSED, float f13 ATTRIBUTE_UNUSED, float f14 ATTRIBUTE_UNUSED, float f15 ATTRIBUTE_UNUSED)
> +{
> + /* Check argument values. */
> + assert (values_float.f0 == f0);
> + assert (values_float.f1 == f1);
> + assert (values_float.f2 == f2);
> + assert (values_float.f3 == f3);
> + assert (values_float.f4 == f4);
> + assert (values_float.f5 == f5);
> + assert (values_float.f6 == f6);
> + assert (values_float.f7 == f7);
> + assert (values_float.f8 == f8);
> + assert (values_float.f9 == f9);
> + assert (values_float.f10 == f10);
> + assert (values_float.f11 == f11);
> + assert (values_float.f12 == f12);
> + assert (values_float.f13 == f13);
> + assert (values_float.f14 == f14);
> + assert (values_float.f15 == f15);
> +
> +}
> +
> +void
> +fun_check_float_passing_float16_regs (float f0 ATTRIBUTE_UNUSED, float f1 ATTRIBUTE_UNUSED, float f2 ATTRIBUTE_UNUSED, float f3 ATTRIBUTE_UNUSED, float f4 ATTRIBUTE_UNUSED, float f5 ATTRIBUTE_UNUSED, float f6 ATTRIBUTE_UNUSED, float f7 ATTRIBUTE_UNUSED, float f8 ATTRIBUTE_UNUSED, float f9 ATTRIBUTE_UNUSED, float f10 ATTRIBUTE_UNUSED, float f11 ATTRIBUTE_UNUSED, float f12 ATTRIBUTE_UNUSED, float f13 ATTRIBUTE_UNUSED, float f14 ATTRIBUTE_UNUSED, float f15 ATTRIBUTE_UNUSED)
> +{
> + /* Check register contents. */
> + check_float_arguments;
> +}
> +
> +void
> +fun_check_float_passing_float20_values (float f0 ATTRIBUTE_UNUSED, float f1 ATTRIBUTE_UNUSED, float f2 ATTRIBUTE_UNUSED, float f3 ATTRIBUTE_UNUSED, float f4 ATTRIBUTE_UNUSED, float f5 ATTRIBUTE_UNUSED, float f6 ATTRIBUTE_UNUSED, float f7 ATTRIBUTE_UNUSED, float f8 ATTRIBUTE_UNUSED, float f9 ATTRIBUTE_UNUSED, float f10 ATTRIBUTE_UNUSED, float f11 ATTRIBUTE_UNUSED, float f12 ATTRIBUTE_UNUSED, float f13 ATTRIBUTE_UNUSED, float f14 ATTRIBUTE_UNUSED, float f15 ATTRIBUTE_UNUSED, float f16 ATTRIBUTE_UNUSED, float f17 ATTRIBUTE_UNUSED, float f18 ATTRIBUTE_UNUSED, float f19 ATTRIBUTE_UNUSED)
> +{
> + /* Check argument values. */
> + assert (values_float.f0 == f0);
> + assert (values_float.f1 == f1);
> + assert (values_float.f2 == f2);
> + assert (values_float.f3 == f3);
> + assert (values_float.f4 == f4);
> + assert (values_float.f5 == f5);
> + assert (values_float.f6 == f6);
> + assert (values_float.f7 == f7);
> + assert (values_float.f8 == f8);
> + assert (values_float.f9 == f9);
> + assert (values_float.f10 == f10);
> + assert (values_float.f11 == f11);
> + assert (values_float.f12 == f12);
> + assert (values_float.f13 == f13);
> + assert (values_float.f14 == f14);
> + assert (values_float.f15 == f15);
> + assert (values_float.f16 == f16);
> + assert (values_float.f17 == f17);
> + assert (values_float.f18 == f18);
> + assert (values_float.f19 == f19);
> +
> +}
> +
> +void
> +fun_check_float_passing_float20_regs (float f0 ATTRIBUTE_UNUSED, float f1 ATTRIBUTE_UNUSED, float f2 ATTRIBUTE_UNUSED, float f3 ATTRIBUTE_UNUSED, float f4 ATTRIBUTE_UNUSED, float f5 ATTRIBUTE_UNUSED, float f6 ATTRIBUTE_UNUSED, float f7 ATTRIBUTE_UNUSED, float f8 ATTRIBUTE_UNUSED, float f9 ATTRIBUTE_UNUSED, float f10 ATTRIBUTE_UNUSED, float f11 ATTRIBUTE_UNUSED, float f12 ATTRIBUTE_UNUSED, float f13 ATTRIBUTE_UNUSED, float f14 ATTRIBUTE_UNUSED, float f15 ATTRIBUTE_UNUSED, float f16 ATTRIBUTE_UNUSED, float f17 ATTRIBUTE_UNUSED, float f18 ATTRIBUTE_UNUSED, float f19 ATTRIBUTE_UNUSED)
> +{
> + /* Check register contents. */
> + check_float_arguments;
> +}
> +
> +void
> +fun_check_float_passing_double8_values (double f0 ATTRIBUTE_UNUSED, double f1 ATTRIBUTE_UNUSED, double f2 ATTRIBUTE_UNUSED, double f3 ATTRIBUTE_UNUSED, double f4 ATTRIBUTE_UNUSED, double f5 ATTRIBUTE_UNUSED, double f6 ATTRIBUTE_UNUSED, double f7 ATTRIBUTE_UNUSED)
> +{
> + /* Check argument values. */
> + assert (values_double.f0 == f0);
> + assert (values_double.f1 == f1);
> + assert (values_double.f2 == f2);
> + assert (values_double.f3 == f3);
> + assert (values_double.f4 == f4);
> + assert (values_double.f5 == f5);
> + assert (values_double.f6 == f6);
> + assert (values_double.f7 == f7);
> +
> +}
> +
> +void
> +fun_check_float_passing_double8_regs (double f0 ATTRIBUTE_UNUSED, double f1 ATTRIBUTE_UNUSED, double f2 ATTRIBUTE_UNUSED, double f3 ATTRIBUTE_UNUSED, double f4 ATTRIBUTE_UNUSED, double f5 ATTRIBUTE_UNUSED, double f6 ATTRIBUTE_UNUSED, double f7 ATTRIBUTE_UNUSED)
> +{
> + /* Check register contents. */
> + check_double_arguments;
> +}
> +
> +void
> +fun_check_float_passing_double16_values (double f0 ATTRIBUTE_UNUSED, double f1 ATTRIBUTE_UNUSED, double f2 ATTRIBUTE_UNUSED, double f3 ATTRIBUTE_UNUSED, double f4 ATTRIBUTE_UNUSED, double f5 ATTRIBUTE_UNUSED, double f6 ATTRIBUTE_UNUSED, double f7 ATTRIBUTE_UNUSED, double f8 ATTRIBUTE_UNUSED, double f9 ATTRIBUTE_UNUSED, double f10 ATTRIBUTE_UNUSED, double f11 ATTRIBUTE_UNUSED, double f12 ATTRIBUTE_UNUSED, double f13 ATTRIBUTE_UNUSED, double f14 ATTRIBUTE_UNUSED, double f15 ATTRIBUTE_UNUSED)
> +{
> + /* Check argument values. */
> + assert (values_double.f0 == f0);
> + assert (values_double.f1 == f1);
> + assert (values_double.f2 == f2);
> + assert (values_double.f3 == f3);
> + assert (values_double.f4 == f4);
> + assert (values_double.f5 == f5);
> + assert (values_double.f6 == f6);
> + assert (values_double.f7 == f7);
> + assert (values_double.f8 == f8);
> + assert (values_double.f9 == f9);
> + assert (values_double.f10 == f10);
> + assert (values_double.f11 == f11);
> + assert (values_double.f12 == f12);
> + assert (values_double.f13 == f13);
> + assert (values_double.f14 == f14);
> + assert (values_double.f15 == f15);
> +
> +}
> +
> +void
> +fun_check_float_passing_double16_regs (double f0 ATTRIBUTE_UNUSED, double f1 ATTRIBUTE_UNUSED, double f2 ATTRIBUTE_UNUSED, double f3 ATTRIBUTE_UNUSED, double f4 ATTRIBUTE_UNUSED, double f5 ATTRIBUTE_UNUSED, double f6 ATTRIBUTE_UNUSED, double f7 ATTRIBUTE_UNUSED, double f8 ATTRIBUTE_UNUSED, double f9 ATTRIBUTE_UNUSED, double f10 ATTRIBUTE_UNUSED, double f11 ATTRIBUTE_UNUSED, double f12 ATTRIBUTE_UNUSED, double f13 ATTRIBUTE_UNUSED, double f14 ATTRIBUTE_UNUSED, double f15 ATTRIBUTE_UNUSED)
> +{
> + /* Check register contents. */
> + check_double_arguments;
> +}
> +
> +void
> +fun_check_float_passing_double20_values (double f0 ATTRIBUTE_UNUSED, double f1 ATTRIBUTE_UNUSED, double f2 ATTRIBUTE_UNUSED, double f3 ATTRIBUTE_UNUSED, double f4 ATTRIBUTE_UNUSED, double f5 ATTRIBUTE_UNUSED, double f6 ATTRIBUTE_UNUSED, double f7 ATTRIBUTE_UNUSED, double f8 ATTRIBUTE_UNUSED, double f9 ATTRIBUTE_UNUSED, double f10 ATTRIBUTE_UNUSED, double f11 ATTRIBUTE_UNUSED, double f12 ATTRIBUTE_UNUSED, double f13 ATTRIBUTE_UNUSED, double f14 ATTRIBUTE_UNUSED, double f15 ATTRIBUTE_UNUSED, double f16 ATTRIBUTE_UNUSED, double f17 ATTRIBUTE_UNUSED, double f18 ATTRIBUTE_UNUSED, double f19 ATTRIBUTE_UNUSED)
> +{
> + /* Check argument values. */
> + assert (values_double.f0 == f0);
> + assert (values_double.f1 == f1);
> + assert (values_double.f2 == f2);
> + assert (values_double.f3 == f3);
> + assert (values_double.f4 == f4);
> + assert (values_double.f5 == f5);
> + assert (values_double.f6 == f6);
> + assert (values_double.f7 == f7);
> + assert (values_double.f8 == f8);
> + assert (values_double.f9 == f9);
> + assert (values_double.f10 == f10);
> + assert (values_double.f11 == f11);
> + assert (values_double.f12 == f12);
> + assert (values_double.f13 == f13);
> + assert (values_double.f14 == f14);
> + assert (values_double.f15 == f15);
> + assert (values_double.f16 == f16);
> + assert (values_double.f17 == f17);
> + assert (values_double.f18 == f18);
> + assert (values_double.f19 == f19);
> +
> +}
> +
> +void
> +fun_check_float_passing_double20_regs (double f0 ATTRIBUTE_UNUSED, double f1 ATTRIBUTE_UNUSED, double f2 ATTRIBUTE_UNUSED, double f3 ATTRIBUTE_UNUSED, double f4 ATTRIBUTE_UNUSED, double f5 ATTRIBUTE_UNUSED, double f6 ATTRIBUTE_UNUSED, double f7 ATTRIBUTE_UNUSED, double f8 ATTRIBUTE_UNUSED, double f9 ATTRIBUTE_UNUSED, double f10 ATTRIBUTE_UNUSED, double f11 ATTRIBUTE_UNUSED, double f12 ATTRIBUTE_UNUSED, double f13 ATTRIBUTE_UNUSED, double f14 ATTRIBUTE_UNUSED, double f15 ATTRIBUTE_UNUSED, double f16 ATTRIBUTE_UNUSED, double f17 ATTRIBUTE_UNUSED, double f18 ATTRIBUTE_UNUSED, double f19 ATTRIBUTE_UNUSED)
> +{
> + /* Check register contents. */
> + check_double_arguments;
> +}
> +
> +void
> +fun_check_x87_passing_ldouble8_values (ldouble f0 ATTRIBUTE_UNUSED, ldouble f1 ATTRIBUTE_UNUSED, ldouble f2 ATTRIBUTE_UNUSED, ldouble f3 ATTRIBUTE_UNUSED, ldouble f4 ATTRIBUTE_UNUSED, ldouble f5 ATTRIBUTE_UNUSED, ldouble f6 ATTRIBUTE_UNUSED, ldouble f7 ATTRIBUTE_UNUSED)
> +{
> + /* Check argument values. */
> + assert (values_ldouble.f0 == f0);
> + assert (values_ldouble.f1 == f1);
> + assert (values_ldouble.f2 == f2);
> + assert (values_ldouble.f3 == f3);
> + assert (values_ldouble.f4 == f4);
> + assert (values_ldouble.f5 == f5);
> + assert (values_ldouble.f6 == f6);
> + assert (values_ldouble.f7 == f7);
> +
> +}
> +
> +void
> +fun_check_x87_passing_ldouble8_regs (ldouble f0 ATTRIBUTE_UNUSED, ldouble f1 ATTRIBUTE_UNUSED, ldouble f2 ATTRIBUTE_UNUSED, ldouble f3 ATTRIBUTE_UNUSED, ldouble f4 ATTRIBUTE_UNUSED, ldouble f5 ATTRIBUTE_UNUSED, ldouble f6 ATTRIBUTE_UNUSED, ldouble f7 ATTRIBUTE_UNUSED)
> +{
> + /* Check register contents. */
> + check_ldouble_arguments;
> +}
> +
> +void
> +fun_check_x87_passing_ldouble16_values (ldouble f0 ATTRIBUTE_UNUSED, ldouble f1 ATTRIBUTE_UNUSED, ldouble f2 ATTRIBUTE_UNUSED, ldouble f3 ATTRIBUTE_UNUSED, ldouble f4 ATTRIBUTE_UNUSED, ldouble f5 ATTRIBUTE_UNUSED, ldouble f6 ATTRIBUTE_UNUSED, ldouble f7 ATTRIBUTE_UNUSED, ldouble f8 ATTRIBUTE_UNUSED, ldouble f9 ATTRIBUTE_UNUSED, ldouble f10 ATTRIBUTE_UNUSED, ldouble f11 ATTRIBUTE_UNUSED, ldouble f12 ATTRIBUTE_UNUSED, ldouble f13 ATTRIBUTE_UNUSED, ldouble f14 ATTRIBUTE_UNUSED, ldouble f15 ATTRIBUTE_UNUSED)
> +{
> + /* Check argument values. */
> + assert (values_ldouble.f0 == f0);
> + assert (values_ldouble.f1 == f1);
> + assert (values_ldouble.f2 == f2);
> + assert (values_ldouble.f3 == f3);
> + assert (values_ldouble.f4 == f4);
> + assert (values_ldouble.f5 == f5);
> + assert (values_ldouble.f6 == f6);
> + assert (values_ldouble.f7 == f7);
> + assert (values_ldouble.f8 == f8);
> + assert (values_ldouble.f9 == f9);
> + assert (values_ldouble.f10 == f10);
> + assert (values_ldouble.f11 == f11);
> + assert (values_ldouble.f12 == f12);
> + assert (values_ldouble.f13 == f13);
> + assert (values_ldouble.f14 == f14);
> + assert (values_ldouble.f15 == f15);
> +
> +}
> +
> +void
> +fun_check_x87_passing_ldouble16_regs (ldouble f0 ATTRIBUTE_UNUSED, ldouble f1 ATTRIBUTE_UNUSED, ldouble f2 ATTRIBUTE_UNUSED, ldouble f3 ATTRIBUTE_UNUSED, ldouble f4 ATTRIBUTE_UNUSED, ldouble f5 ATTRIBUTE_UNUSED, ldouble f6 ATTRIBUTE_UNUSED, ldouble f7 ATTRIBUTE_UNUSED, ldouble f8 ATTRIBUTE_UNUSED, ldouble f9 ATTRIBUTE_UNUSED, ldouble f10 ATTRIBUTE_UNUSED, ldouble f11 ATTRIBUTE_UNUSED, ldouble f12 ATTRIBUTE_UNUSED, ldouble f13 ATTRIBUTE_UNUSED, ldouble f14 ATTRIBUTE_UNUSED, ldouble f15 ATTRIBUTE_UNUSED)
> +{
> + /* Check register contents. */
> + check_ldouble_arguments;
> +}
> +
> +void
> +fun_check_x87_passing_ldouble20_values (ldouble f0 ATTRIBUTE_UNUSED, ldouble f1 ATTRIBUTE_UNUSED, ldouble f2 ATTRIBUTE_UNUSED, ldouble f3 ATTRIBUTE_UNUSED, ldouble f4 ATTRIBUTE_UNUSED, ldouble f5 ATTRIBUTE_UNUSED, ldouble f6 ATTRIBUTE_UNUSED, ldouble f7 ATTRIBUTE_UNUSED, ldouble f8 ATTRIBUTE_UNUSED, ldouble f9 ATTRIBUTE_UNUSED, ldouble f10 ATTRIBUTE_UNUSED, ldouble f11 ATTRIBUTE_UNUSED, ldouble f12 ATTRIBUTE_UNUSED, ldouble f13 ATTRIBUTE_UNUSED, ldouble f14 ATTRIBUTE_UNUSED, ldouble f15 ATTRIBUTE_UNUSED, ldouble f16 ATTRIBUTE_UNUSED, ldouble f17 ATTRIBUTE_UNUSED, ldouble f18 ATTRIBUTE_UNUSED, ldouble f19 ATTRIBUTE_UNUSED)
> +{
> + /* Check argument values. */
> + assert (values_ldouble.f0 == f0);
> + assert (values_ldouble.f1 == f1);
> + assert (values_ldouble.f2 == f2);
> + assert (values_ldouble.f3 == f3);
> + assert (values_ldouble.f4 == f4);
> + assert (values_ldouble.f5 == f5);
> + assert (values_ldouble.f6 == f6);
> + assert (values_ldouble.f7 == f7);
> + assert (values_ldouble.f8 == f8);
> + assert (values_ldouble.f9 == f9);
> + assert (values_ldouble.f10 == f10);
> + assert (values_ldouble.f11 == f11);
> + assert (values_ldouble.f12 == f12);
> + assert (values_ldouble.f13 == f13);
> + assert (values_ldouble.f14 == f14);
> + assert (values_ldouble.f15 == f15);
> + assert (values_ldouble.f16 == f16);
> + assert (values_ldouble.f17 == f17);
> + assert (values_ldouble.f18 == f18);
> + assert (values_ldouble.f19 == f19);
> +
> +}
> +
> +void
> +fun_check_x87_passing_ldouble20_regs (ldouble f0 ATTRIBUTE_UNUSED, ldouble f1 ATTRIBUTE_UNUSED, ldouble f2 ATTRIBUTE_UNUSED, ldouble f3 ATTRIBUTE_UNUSED, ldouble f4 ATTRIBUTE_UNUSED, ldouble f5 ATTRIBUTE_UNUSED, ldouble f6 ATTRIBUTE_UNUSED, ldouble f7 ATTRIBUTE_UNUSED, ldouble f8 ATTRIBUTE_UNUSED, ldouble f9 ATTRIBUTE_UNUSED, ldouble f10 ATTRIBUTE_UNUSED, ldouble f11 ATTRIBUTE_UNUSED, ldouble f12 ATTRIBUTE_UNUSED, ldouble f13 ATTRIBUTE_UNUSED, ldouble f14 ATTRIBUTE_UNUSED, ldouble f15 ATTRIBUTE_UNUSED, ldouble f16 ATTRIBUTE_UNUSED, ldouble f17 ATTRIBUTE_UNUSED, ldouble f18 ATTRIBUTE_UNUSED, ldouble f19 ATTRIBUTE_UNUSED)
> +{
> + /* Check register contents. */
> + check_ldouble_arguments;
> +}
> +
> +#define def_check_float_passing8(_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _func1, _func2, TYPE) \
> + values_ ## TYPE .f0 = _f0; \
> + values_ ## TYPE .f1 = _f1; \
> + values_ ## TYPE .f2 = _f2; \
> + values_ ## TYPE .f3 = _f3; \
> + values_ ## TYPE .f4 = _f4; \
> + values_ ## TYPE .f5 = _f5; \
> + values_ ## TYPE .f6 = _f6; \
> + values_ ## TYPE .f7 = _f7; \
> + WRAP_CALL(_func1) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7); \
> + \
> + clear_int_registers; \
> + if (sizeof (TYPE) == 4) \
> + { \
> + u.f = _f0; \
> + iregs.I0 = u.i[0]; \
> + u.f = _f1; \
> + iregs.I1 = u.i[0]; \
> + u.f = _f2; \
> + iregs.I2 = u.i[0]; \
> + num_iregs = 3; \
> + } \
> + else \
> + { \
> + u.d = _f0; \
> + iregs.I0 = u.i[0]; \
> + iregs.I1 = u.i[1]; \
> + num_iregs = 2; \
> + } \
> + WRAP_CALL(_func2) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7);
> +
> +#define def_check_float_passing16(_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15, _func1, _func2, TYPE) \
> + values_ ## TYPE .f0 = _f0; \
> + values_ ## TYPE .f1 = _f1; \
> + values_ ## TYPE .f2 = _f2; \
> + values_ ## TYPE .f3 = _f3; \
> + values_ ## TYPE .f4 = _f4; \
> + values_ ## TYPE .f5 = _f5; \
> + values_ ## TYPE .f6 = _f6; \
> + values_ ## TYPE .f7 = _f7; \
> + values_ ## TYPE .f8 = _f8; \
> + values_ ## TYPE .f9 = _f9; \
> + values_ ## TYPE .f10 = _f10; \
> + values_ ## TYPE .f11 = _f11; \
> + values_ ## TYPE .f12 = _f12; \
> + values_ ## TYPE .f13 = _f13; \
> + values_ ## TYPE .f14 = _f14; \
> + values_ ## TYPE .f15 = _f15; \
> + WRAP_CALL(_func1) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15); \
> + \
> + clear_int_registers; \
> + if (sizeof (TYPE) == 4) \
> + { \
> + u.f = _f0; \
> + iregs.I0 = u.i[0]; \
> + u.f = _f1; \
> + iregs.I1 = u.i[0]; \
> + u.f = _f2; \
> + iregs.I2 = u.i[0]; \
> + num_iregs = 3; \
> + } \
> + else \
> + { \
> + u.d = _f0; \
> + iregs.I0 = u.i[0]; \
> + iregs.I1 = u.i[1]; \
> + num_iregs = 2; \
> + } \
> + WRAP_CALL(_func2) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15);
> +
> +#define def_check_float_passing20(_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15, _f16, _f17, _f18, _f19, _func1, _func2, TYPE) \
> + values_ ## TYPE .f0 = _f0; \
> + values_ ## TYPE .f1 = _f1; \
> + values_ ## TYPE .f2 = _f2; \
> + values_ ## TYPE .f3 = _f3; \
> + values_ ## TYPE .f4 = _f4; \
> + values_ ## TYPE .f5 = _f5; \
> + values_ ## TYPE .f6 = _f6; \
> + values_ ## TYPE .f7 = _f7; \
> + values_ ## TYPE .f8 = _f8; \
> + values_ ## TYPE .f9 = _f9; \
> + values_ ## TYPE .f10 = _f10; \
> + values_ ## TYPE .f11 = _f11; \
> + values_ ## TYPE .f12 = _f12; \
> + values_ ## TYPE .f13 = _f13; \
> + values_ ## TYPE .f14 = _f14; \
> + values_ ## TYPE .f15 = _f15; \
> + values_ ## TYPE .f16 = _f16; \
> + values_ ## TYPE .f17 = _f17; \
> + values_ ## TYPE .f18 = _f18; \
> + values_ ## TYPE .f19 = _f19; \
> + WRAP_CALL(_func1) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15, _f16, _f17, _f18, _f19); \
> + \
> + clear_int_registers; \
> + if (sizeof (TYPE) == 4) \
> + { \
> + u.f = _f0; \
> + iregs.I0 = u.i[0]; \
> + u.f = _f1; \
> + iregs.I1 = u.i[0]; \
> + u.f = _f2; \
> + iregs.I2 = u.i[0]; \
> + num_iregs = 3; \
> + } \
> + else \
> + { \
> + u.d = _f0; \
> + iregs.I0 = u.i[0]; \
> + iregs.I1 = u.i[1]; \
> + num_iregs = 2; \
> + } \
> + WRAP_CALL(_func2) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15, _f16, _f17, _f18, _f19);
> +
> +#define def_check_x87_passing8(_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _func1, _func2, TYPE) \
> + values_ ## TYPE .f0 = _f0; \
> + values_ ## TYPE .f1 = _f1; \
> + values_ ## TYPE .f2 = _f2; \
> + values_ ## TYPE .f3 = _f3; \
> + values_ ## TYPE .f4 = _f4; \
> + values_ ## TYPE .f5 = _f5; \
> + values_ ## TYPE .f6 = _f6; \
> + values_ ## TYPE .f7 = _f7; \
> + WRAP_CALL(_func1) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7); \
> + \
> + clear_int_registers; \
> + if (sizeof (TYPE) == 4) \
> + { \
> + u.f = _f0; \
> + iregs.I0 = u.i[0]; \
> + u.f = _f1; \
> + iregs.I1 = u.i[0]; \
> + u.f = _f2; \
> + iregs.I2 = u.i[0]; \
> + num_iregs = 3; \
> + } \
> + else \
> + { \
> + u.d = _f0; \
> + iregs.I0 = u.i[0]; \
> + iregs.I1 = u.i[1]; \
> + num_iregs = 2; \
> + } \
> + WRAP_CALL(_func2) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7);
> +
> +#define def_check_x87_passing16(_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15, _func1, _func2, TYPE) \
> + values_ ## TYPE .f0 = _f0; \
> + values_ ## TYPE .f1 = _f1; \
> + values_ ## TYPE .f2 = _f2; \
> + values_ ## TYPE .f3 = _f3; \
> + values_ ## TYPE .f4 = _f4; \
> + values_ ## TYPE .f5 = _f5; \
> + values_ ## TYPE .f6 = _f6; \
> + values_ ## TYPE .f7 = _f7; \
> + values_ ## TYPE .f8 = _f8; \
> + values_ ## TYPE .f9 = _f9; \
> + values_ ## TYPE .f10 = _f10; \
> + values_ ## TYPE .f11 = _f11; \
> + values_ ## TYPE .f12 = _f12; \
> + values_ ## TYPE .f13 = _f13; \
> + values_ ## TYPE .f14 = _f14; \
> + values_ ## TYPE .f15 = _f15; \
> + WRAP_CALL(_func1) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15); \
> + \
> + clear_int_registers; \
> + if (sizeof (TYPE) == 4) \
> + { \
> + u.f = _f0; \
> + iregs.I0 = u.i[0]; \
> + u.f = _f1; \
> + iregs.I1 = u.i[0]; \
> + u.f = _f2; \
> + iregs.I2 = u.i[0]; \
> + num_iregs = 3; \
> + } \
> + else \
> + { \
> + u.d = _f0; \
> + iregs.I0 = u.i[0]; \
> + iregs.I1 = u.i[1]; \
> + num_iregs = 2; \
> + } \
> + WRAP_CALL(_func2) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15);
> +
> +#define def_check_x87_passing20(_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15, _f16, _f17, _f18, _f19, _func1, _func2, TYPE) \
> + values_ ## TYPE .f0 = _f0; \
> + values_ ## TYPE .f1 = _f1; \
> + values_ ## TYPE .f2 = _f2; \
> + values_ ## TYPE .f3 = _f3; \
> + values_ ## TYPE .f4 = _f4; \
> + values_ ## TYPE .f5 = _f5; \
> + values_ ## TYPE .f6 = _f6; \
> + values_ ## TYPE .f7 = _f7; \
> + values_ ## TYPE .f8 = _f8; \
> + values_ ## TYPE .f9 = _f9; \
> + values_ ## TYPE .f10 = _f10; \
> + values_ ## TYPE .f11 = _f11; \
> + values_ ## TYPE .f12 = _f12; \
> + values_ ## TYPE .f13 = _f13; \
> + values_ ## TYPE .f14 = _f14; \
> + values_ ## TYPE .f15 = _f15; \
> + values_ ## TYPE .f16 = _f16; \
> + values_ ## TYPE .f17 = _f17; \
> + values_ ## TYPE .f18 = _f18; \
> + values_ ## TYPE .f19 = _f19; \
> + WRAP_CALL(_func1) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15, _f16, _f17, _f18, _f19); \
> + \
> + clear_int_registers; \
> + if (sizeof (TYPE) == 4) \
> + { \
> + u.f = _f0; \
> + iregs.I0 = u.i[0]; \
> + u.f = _f1; \
> + iregs.I1 = u.i[0]; \
> + u.f = _f2; \
> + iregs.I2 = u.i[0]; \
> + num_iregs = 3; \
> + } \
> + else \
> + { \
> + u.d = _f0; \
> + iregs.I0 = u.i[0]; \
> + iregs.I1 = u.i[1]; \
> + num_iregs = 2; \
> + } \
> + WRAP_CALL(_func2) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15, _f16, _f17, _f18, _f19);
> +
> +void
> +test_floats_on_stack ()
> +{
> + union
> + {
> + float f;
> + double d;
> + int i[2];
> + } u;
> + def_check_float_passing8(32, 33, 34, 35, 36, 37, 38, 39, fun_check_float_passing_float8_values, fun_check_float_passing_float8_regs, float);
> +
> + def_check_float_passing16(32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, fun_check_float_passing_float16_values, fun_check_float_passing_float16_regs, float);
> +}
> +
> +void
> +test_too_many_floats ()
> +{
> + union
> + {
> + float f;
> + double d;
> + int i[2];
> + } u;
> + def_check_float_passing20(32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, fun_check_float_passing_float20_values, fun_check_float_passing_float20_regs, float);
> +}
> +
> +void
> +test_doubles_on_stack ()
> +{
> + union
> + {
> + float f;
> + double d;
> + int i[2];
> + } u;
> + def_check_float_passing8(32, 33, 34, 35, 36, 37, 38, 39, fun_check_float_passing_double8_values, fun_check_float_passing_double8_regs, double);
> +
> + def_check_float_passing16(32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, fun_check_float_passing_double16_values, fun_check_float_passing_double16_regs, double);
> +}
> +
> +void
> +test_too_many_doubles ()
> +{
> + union
> + {
> + float f;
> + double d;
> + int i[2];
> + } u;
> + def_check_float_passing20(32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, fun_check_float_passing_double20_values, fun_check_float_passing_double20_regs, double);
> +}
> +
> +void
> +test_long_doubles_on_stack ()
> +{
> + union
> + {
> + float f;
> + double d;
> + int i[2];
> + } u;
> + def_check_x87_passing8(32, 33, 34, 35, 36, 37, 38, 39, fun_check_x87_passing_ldouble8_values, fun_check_x87_passing_ldouble8_regs, ldouble);
> +}
> +
> +void
> +test_too_many_long_doubles ()
> +{
> + union
> + {
> + float f;
> + double d;
> + int i[2];
> + } u;
> + def_check_x87_passing20(32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, fun_check_x87_passing_ldouble20_values, fun_check_x87_passing_ldouble20_regs, ldouble);
> +}
> +
> +void
> +test_float128s_on_stack ()
> +{
> +}
> +
> +void
> +test_too_many_float128s ()
> +{
> +}
> +
> +
> +int
> +main (void)
> +{
> + test_floats_on_stack ();
> + test_too_many_floats ();
> + test_doubles_on_stack ();
> + test_too_many_doubles ();
> + test_long_doubles_on_stack ();
> + test_too_many_long_doubles ();
> + test_float128s_on_stack ();
> + test_too_many_float128s ();
> + return 0;
> +}
> diff --git a/gcc/testsuite/gcc.target/i386/iamcu/test_passing_integers.c b/gcc/testsuite/gcc.target/i386/iamcu/test_passing_integers.c
> new file mode 100644
> index 0000000..046e140
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/iamcu/test_passing_integers.c
> @@ -0,0 +1,182 @@
> +#include "defines.h"
> +#include "macros.h"
> +#include "args.h"
> +
> +struct IntegerRegisters iregbits = { ~0, ~0, ~0, ~0, ~0, ~0 };
> +struct IntegerRegisters iregs;
> +unsigned int num_iregs;
> +
> +/* This struct holds values for argument checking. */
> +struct
> +{
> + int i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14, i15, i16, i17, i18, i19, i20, i21, i22, i23;
> +} values_int;
> +
> +struct
> +{
> + long i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14, i15, i16, i17, i18, i19, i20, i21, i22, i23;
> +} values_long;
> +
> +void
> +fun_check_int_passing_int6_values (int i0 ATTRIBUTE_UNUSED, int i1 ATTRIBUTE_UNUSED, int i2 ATTRIBUTE_UNUSED, int i3 ATTRIBUTE_UNUSED, int i4 ATTRIBUTE_UNUSED, int i5 ATTRIBUTE_UNUSED)
> +{
> + /* Check argument values. */
> + assert (values_int.i0 == i0);
> + assert (values_int.i1 == i1);
> + assert (values_int.i2 == i2);
> + assert (values_int.i3 == i3);
> + assert (values_int.i4 == i4);
> + assert (values_int.i5 == i5);
> +
> +}
> +
> +void
> +fun_check_int_passing_int6_regs (int i0 ATTRIBUTE_UNUSED, int i1 ATTRIBUTE_UNUSED, int i2 ATTRIBUTE_UNUSED, int i3 ATTRIBUTE_UNUSED, int i4 ATTRIBUTE_UNUSED, int i5 ATTRIBUTE_UNUSED)
> +{
> + /* Check register contents. */
> + check_int_arguments;
> +}
> +
> +void
> +fun_check_int_passing_int12_values (int i0 ATTRIBUTE_UNUSED, int i1 ATTRIBUTE_UNUSED, int i2 ATTRIBUTE_UNUSED, int i3 ATTRIBUTE_UNUSED, int i4 ATTRIBUTE_UNUSED, int i5 ATTRIBUTE_UNUSED, int i6 ATTRIBUTE_UNUSED, int i7 ATTRIBUTE_UNUSED, int i8 ATTRIBUTE_UNUSED, int i9 ATTRIBUTE_UNUSED, int i10 ATTRIBUTE_UNUSED, int i11 ATTRIBUTE_UNUSED)
> +{
> + /* Check argument values. */
> + assert (values_int.i0 == i0);
> + assert (values_int.i1 == i1);
> + assert (values_int.i2 == i2);
> + assert (values_int.i3 == i3);
> + assert (values_int.i4 == i4);
> + assert (values_int.i5 == i5);
> + assert (values_int.i6 == i6);
> + assert (values_int.i7 == i7);
> + assert (values_int.i8 == i8);
> + assert (values_int.i9 == i9);
> + assert (values_int.i10 == i10);
> + assert (values_int.i11 == i11);
> +
> +}
> +
> +void
> +fun_check_int_passing_int12_regs (int i0 ATTRIBUTE_UNUSED, int i1 ATTRIBUTE_UNUSED, int i2 ATTRIBUTE_UNUSED, int i3 ATTRIBUTE_UNUSED, int i4 ATTRIBUTE_UNUSED, int i5 ATTRIBUTE_UNUSED, int i6 ATTRIBUTE_UNUSED, int i7 ATTRIBUTE_UNUSED, int i8 ATTRIBUTE_UNUSED, int i9 ATTRIBUTE_UNUSED, int i10 ATTRIBUTE_UNUSED, int i11 ATTRIBUTE_UNUSED)
> +{
> + /* Check register contents. */
> + check_int_arguments;
> +}
> +
> +void
> +fun_check_int_passing_long6_values (long i0 ATTRIBUTE_UNUSED, long i1 ATTRIBUTE_UNUSED, long i2 ATTRIBUTE_UNUSED, long i3 ATTRIBUTE_UNUSED, long i4 ATTRIBUTE_UNUSED, long i5 ATTRIBUTE_UNUSED)
> +{
> + /* Check argument values. */
> + assert (values_long.i0 == i0);
> + assert (values_long.i1 == i1);
> + assert (values_long.i2 == i2);
> + assert (values_long.i3 == i3);
> + assert (values_long.i4 == i4);
> + assert (values_long.i5 == i5);
> +
> +}
> +
> +void
> +fun_check_int_passing_long6_regs (long i0 ATTRIBUTE_UNUSED, long i1 ATTRIBUTE_UNUSED, long i2 ATTRIBUTE_UNUSED, long i3 ATTRIBUTE_UNUSED, long i4 ATTRIBUTE_UNUSED, long i5 ATTRIBUTE_UNUSED)
> +{
> + /* Check register contents. */
> + check_long_arguments;
> +}
> +
> +void
> +fun_check_int_passing_long12_values (long i0 ATTRIBUTE_UNUSED, long i1 ATTRIBUTE_UNUSED, long i2 ATTRIBUTE_UNUSED, long i3 ATTRIBUTE_UNUSED, long i4 ATTRIBUTE_UNUSED, long i5 ATTRIBUTE_UNUSED, long i6 ATTRIBUTE_UNUSED, long i7 ATTRIBUTE_UNUSED, long i8 ATTRIBUTE_UNUSED, long i9 ATTRIBUTE_UNUSED, long i10 ATTRIBUTE_UNUSED, long i11 ATTRIBUTE_UNUSED)
> +{
> + /* Check argument values. */
> + assert (values_long.i0 == i0);
> + assert (values_long.i1 == i1);
> + assert (values_long.i2 == i2);
> + assert (values_long.i3 == i3);
> + assert (values_long.i4 == i4);
> + assert (values_long.i5 == i5);
> + assert (values_long.i6 == i6);
> + assert (values_long.i7 == i7);
> + assert (values_long.i8 == i8);
> + assert (values_long.i9 == i9);
> + assert (values_long.i10 == i10);
> + assert (values_long.i11 == i11);
> +
> +}
> +
> +void
> +fun_check_int_passing_long12_regs (long i0 ATTRIBUTE_UNUSED, long i1 ATTRIBUTE_UNUSED, long i2 ATTRIBUTE_UNUSED, long i3 ATTRIBUTE_UNUSED, long i4 ATTRIBUTE_UNUSED, long i5 ATTRIBUTE_UNUSED, long i6 ATTRIBUTE_UNUSED, long i7 ATTRIBUTE_UNUSED, long i8 ATTRIBUTE_UNUSED, long i9 ATTRIBUTE_UNUSED, long i10 ATTRIBUTE_UNUSED, long i11 ATTRIBUTE_UNUSED)
> +{
> + /* Check register contents. */
> + check_long_arguments;
> +}
> +
> +#define def_check_int_passing6(_i0, _i1, _i2, _i3, _i4, _i5, _func1, _func2, TYPE) \
> + values_ ## TYPE .i0 = _i0; \
> + values_ ## TYPE .i1 = _i1; \
> + values_ ## TYPE .i2 = _i2; \
> + values_ ## TYPE .i3 = _i3; \
> + values_ ## TYPE .i4 = _i4; \
> + values_ ## TYPE .i5 = _i5; \
> + WRAP_CALL(_func1) (_i0, _i1, _i2, _i3, _i4, _i5); \
> + \
> + clear_int_registers; \
> + iregs.I0 = _i0; \
> + iregs.I1 = _i1; \
> + iregs.I2 = _i2; \
> + num_iregs = 3; \
> + WRAP_CALL(_func2) (_i0, _i1, _i2, _i3, _i4, _i5);
> +
> +#define def_check_int_passing12(_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, _i9, _i10, _i11, _func1, _func2, TYPE) \
> + values_ ## TYPE .i0 = _i0; \
> + values_ ## TYPE .i1 = _i1; \
> + values_ ## TYPE .i2 = _i2; \
> + values_ ## TYPE .i3 = _i3; \
> + values_ ## TYPE .i4 = _i4; \
> + values_ ## TYPE .i5 = _i5; \
> + values_ ## TYPE .i6 = _i6; \
> + values_ ## TYPE .i7 = _i7; \
> + values_ ## TYPE .i8 = _i8; \
> + values_ ## TYPE .i9 = _i9; \
> + values_ ## TYPE .i10 = _i10; \
> + values_ ## TYPE .i11 = _i11; \
> + WRAP_CALL(_func1) (_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, _i9, _i10, _i11); \
> + \
> + clear_int_registers; \
> + iregs.I0 = _i0; \
> + iregs.I1 = _i1; \
> + iregs.I2 = _i2; \
> + num_iregs = 3; \
> + WRAP_CALL(_func2) (_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, _i9, _i10, _i11);
> +
> +void
> +test_ints_on_stack ()
> +{
> + def_check_int_passing6(32, 33, 34, 35, 36, 37, fun_check_int_passing_int6_values, fun_check_int_passing_int6_regs, int);
> +}
> +
> +void
> +test_too_many_ints ()
> +{
> + def_check_int_passing12(32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, fun_check_int_passing_int12_values, fun_check_int_passing_int12_regs, int);
> +}
> +
> +void
> +test_longs_on_stack ()
> +{
> + def_check_int_passing6(32, 33, 34, 35, 36, 37, fun_check_int_passing_long6_values, fun_check_int_passing_long6_regs, long);
> +}
> +
> +void
> +test_too_many_longs ()
> +{
> + def_check_int_passing12(32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, fun_check_int_passing_long12_values, fun_check_int_passing_long12_regs, long);
> +}
> +
> +int
> +main (void)
> +{
> + test_ints_on_stack ();
> + test_too_many_ints ();
> + test_longs_on_stack ();
> + test_too_many_longs ();
> + return 0;
> +}
> diff --git a/gcc/testsuite/gcc.target/i386/iamcu/test_passing_structs.c b/gcc/testsuite/gcc.target/i386/iamcu/test_passing_structs.c
> new file mode 100644
> index 0000000..1660a4d
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/iamcu/test_passing_structs.c
> @@ -0,0 +1,237 @@
> +/* This tests passing of structs. */
> +
> +#include "defines.h"
> +#include "args.h"
> +#include <complex.h>
> +
> +struct IntegerRegisters iregbits = { ~0, ~0, ~0, ~0, ~0, ~0 };
> +struct IntegerRegisters iregs;
> +unsigned int num_iregs;
> +
> +struct int_struct
> +{
> + int i;
> +};
> +
> +struct long_struct
> +{
> + long l;
> +};
> +
> +struct longlong2_struct
> +{
> + long long ll1, ll2;
> +};
> +
> +struct longlong3_struct
> +{
> + long long ll1, ll2, ll3;
> +};
> +
> +/* Check that the struct is passed as the individual members in iregs. */
> +void
> +check_struct_passing1 (struct int_struct is ATTRIBUTE_UNUSED)
> +{
> + check_int_arguments;
> +}
> +
> +void
> +check_struct_passing2 (struct long_struct ls ATTRIBUTE_UNUSED)
> +{
> + check_int_arguments;
> +}
> +
> +void
> +check_struct_passing3 (struct longlong2_struct ls ATTRIBUTE_UNUSED)
> +{
> + check_int_arguments;
> +}
> +
> +void
> +check_struct_passing4 (struct longlong3_struct ls ATTRIBUTE_UNUSED)
> +{
> + /* Check the passing on the stack by comparing the address of the
> + stack elements to the expected place on the stack. */
> + assert ((unsigned long)&ls.ll1 == esp+4);
> + assert ((unsigned long)&ls.ll2 == esp+12);
> + assert ((unsigned long)&ls.ll3 == esp+20);
> +}
> +
> +struct flex1_struct
> +{
> + long i;
> + long flex[];
> +};
> +
> +struct flex2_struct
> +{
> + long i;
> + long flex[0];
> +};
> +
> +void
> +check_struct_passing7 (struct flex1_struct is ATTRIBUTE_UNUSED)
> +{
> + check_int_arguments;
> +}
> +
> +void
> +check_struct_passing8 (struct flex2_struct is ATTRIBUTE_UNUSED)
> +{
> + check_int_arguments;
> +}
> +
> +struct complex1_struct
> +{
> + __complex__ float x;
> +};
> +
> +struct complex1a_struct
> +{
> + long l;
> + union
> + {
> + float f;
> + int i;
> + } u;
> +};
> +
> +void
> +check_struct_passing9 (struct complex1_struct is ATTRIBUTE_UNUSED)
> +{
> + check_int_arguments;
> +}
> +
> +struct long3_struct
> +{
> + long l1, l2, l3;
> +};
> +
> +void
> +check_struct_passing10 (struct long3_struct ls ATTRIBUTE_UNUSED)
> +{
> + /* Check the passing on the stack by comparing the address of the
> + stack elements to the expected place on the stack. */
> + assert ((unsigned long)&ls.l1 == esp+4);
> + assert ((unsigned long)&ls.l2 == esp+8);
> + assert ((unsigned long)&ls.l3 == esp+12);
> +}
> +
> +struct char3_struct
> +{
> + char c1, c2, c3;
> +};
> +
> +void
> +check_struct_passing11 (struct char3_struct is ATTRIBUTE_UNUSED)
> +{
> + check_int_arguments;
> +}
> +
> +struct char7_struct
> +{
> + char c1, c2, c3, c4, c5, c6, c7;
> +};
> +
> +void
> +check_struct_passing12 (struct char7_struct is ATTRIBUTE_UNUSED)
> +{
> + check_int_arguments;
> +}
> +
> +static struct flex1_struct f1s = { 60, { } };
> +static struct flex2_struct f2s = { 61, { } };
> +
> +int
> +main (void)
> +{
> + struct int_struct is = { 48 };
> + struct long_struct ls = { 49 };
> +#ifdef CHECK_LARGER_STRUCTS
> + struct longlong2_struct ll2s = { 50, 51 };
> + struct longlong3_struct ll3s = { 52, 53, 54 };
> + struct long3_struct l3s = { 60, 61, 62 };
> +#endif
> + struct complex1_struct c1s = { ( -13.4 + 3.5*I ) };
> + union
> + {
> + struct complex1_struct c;
> + struct complex1a_struct u;
> + } c1u;
> + struct char3_struct c3 = { 0x12, 0x34, 0x56 };
> + union
> + {
> + struct char3_struct c;
> + int i;
> + } c3u;
> + struct char7_struct c7 = { 0x12, 0x34, 0x56, 0x78, 0x12, 0x34, 0x56 };
> + union
> + {
> + struct char7_struct c;
> + struct
> + {
> + int i0, i1;
> + } i;
> + } c7u;
> +
> + clear_struct_registers;
> + iregs.I0 = is.i;
> + num_iregs = 1;
> + clear_int_hardware_registers;
> + WRAP_CALL (check_struct_passing1)(is);
> +
> + clear_struct_registers;
> + iregs.I0 = ls.l;
> + num_iregs = 1;
> + clear_int_hardware_registers;
> + WRAP_CALL (check_struct_passing2)(ls);
> +
> +#ifdef CHECK_LARGER_STRUCTS
> + clear_struct_registers;
> + num_iregs = 0;
> + clear_int_hardware_registers;
> + WRAP_CALL (check_struct_passing3)(ll2s);
> + WRAP_CALL (check_struct_passing4)(ll3s);
> + WRAP_CALL (check_struct_passing10)(l3s);
> +#endif
> +
> + clear_struct_registers;
> + iregs.I0 = f1s.i;
> + num_iregs = 1;
> + clear_int_hardware_registers;
> + WRAP_CALL (check_struct_passing7)(f1s);
> +
> + clear_struct_registers;
> + iregs.I0 = f2s.i;
> + num_iregs = 1;
> + clear_int_hardware_registers;
> + WRAP_CALL (check_struct_passing8)(f2s);
> +
> + clear_struct_registers;
> + c1u.c = c1s;
> + iregs.I0 = c1u.u.l;
> + iregs.I1 = c1u.u.u.i;
> + num_iregs = 2;
> + clear_int_hardware_registers;
> + WRAP_CALL (check_struct_passing9)(c1s);
> +
> + clear_struct_registers;
> + c3u.c = c3;
> + iregs.I0 = c3u.i;
> + iregbits.I0 = 0xffffff;
> + num_iregs = 1;
> + clear_int_hardware_registers;
> + WRAP_CALL (check_struct_passing11)(c3);
> +
> + clear_struct_registers;
> + c7u.c = c7;
> + iregs.I0 = c7u.i.i0;
> + iregs.I1 = c7u.i.i1;
> + iregbits.I0 = 0xffffffff;
> + iregbits.I1 = 0xffffff;
> + num_iregs = 2;
> + clear_int_hardware_registers;
> + WRAP_CALL (check_struct_passing12)(c7);
> +
> + return 0;
> +}
> diff --git a/gcc/testsuite/gcc.target/i386/iamcu/test_passing_structs_and_unions.c b/gcc/testsuite/gcc.target/i386/iamcu/test_passing_structs_and_unions.c
> new file mode 100644
> index 0000000..ff6354c
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/iamcu/test_passing_structs_and_unions.c
> @@ -0,0 +1,97 @@
> +/* This tests passing of structs. Only integers are tested. */
> +
> +#include "defines.h"
> +#include "args.h"
> +
> +struct IntegerRegisters iregbits = { ~0, ~0, ~0, ~0, ~0, ~0 };
> +struct IntegerRegisters iregs;
> +unsigned int num_iregs;
> +
> +struct int_struct
> +{
> + int i;
> +};
> +
> +struct longlong_struct
> +{
> + long long ll;
> +};
> +
> +struct long2_struct
> +{
> + long long ll1, ll2;
> +};
> +
> +struct long3_struct
> +{
> + long l1, l2, l3;
> +};
> +
> +union un1
> +{
> + char c;
> + int i;
> +};
> +
> +union un2
> +{
> + char c1;
> + long l;
> + char c2;
> +};
> +
> +union un3
> +{
> + struct int_struct is;
> + struct longlong_struct ls;
> + union un1 un;
> +};
> +
> +
> +void
> +check_mixed_passing1 (char c1 ATTRIBUTE_UNUSED, struct int_struct is ATTRIBUTE_UNUSED, char c2 ATTRIBUTE_UNUSED)
> +{
> + check_int_arguments;
> +}
> +
> +void
> +check_mixed_passing2 (char c1 ATTRIBUTE_UNUSED, struct long3_struct ls ATTRIBUTE_UNUSED, char c2 ATTRIBUTE_UNUSED)
> +{
> + check_int_arguments;
> +
> + /* Check the passing on the stack by comparing the address of the
> + stack elements to the expected place on the stack. */
> + assert ((unsigned long)&ls.l1 == esp+4);
> + assert ((unsigned long)&ls.l2 == esp+8);
> + assert ((unsigned long)&ls.l3 == esp+12);
> +}
> +
> +int
> +main (void)
> +{
> + struct int_struct is = { 64 };
> +#ifdef CHECK_LARGER_STRUCTS
> + struct long3_struct l3s = { 65, 66, 67 };
> +#endif
> +
> + clear_struct_registers;
> + iregs.I0 = 8;
> + iregs.I1 = 64;
> + iregs.I2 = 9;
> + num_iregs = 3;
> + clear_int_hardware_registers;
> + WRAP_CALL (check_mixed_passing1)(8, is, 9);
> +
> +#ifdef CHECK_LARGER_STRUCTS
> + clear_struct_registers;
> + iregs.I0 = 10;
> + iregbits.I0 = 0xff;
> + iregs.I1 = 11;
> + iregbits.I1 = 0xff;
> + num_iregs = 2;
> + clear_int_hardware_registers;
> + WRAP_CALL (check_mixed_passing2)(10, l3s, 11);
> +#endif
> +
> + return 0;
> +}
> diff --git a/gcc/testsuite/gcc.target/i386/iamcu/test_passing_unions.c b/gcc/testsuite/gcc.target/i386/iamcu/test_passing_unions.c
> new file mode 100644
> index 0000000..534fc85
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/iamcu/test_passing_unions.c
> @@ -0,0 +1,221 @@
> +/* This tests passing of structs. */
> +
> +#include "defines.h"
> +#include "args.h"
> +
> +struct IntegerRegisters iregbits = { ~0, ~0, ~0, ~0, ~0, ~0 };
> +struct IntegerRegisters iregs;
> +unsigned int num_iregs;
> +
> +struct int_struct
> +{
> + int i;
> +};
> +
> +struct long_struct
> +{
> + long l;
> +};
> +
> +union un1
> +{
> + char c;
> + int i;
> +};
> +
> +union un2
> +{
> + char c1;
> + long l;
> + char c2;
> +};
> +
> +union un3
> +{
> + struct int_struct is;
> + struct long_struct ls;
> + union un1 un;
> +};
> +
> +
> +void
> +check_union_passing1(union un1 u ATTRIBUTE_UNUSED)
> +{
> + check_int_arguments;
> +}
> +
> +void
> +check_union_passing2(union un2 u1 ATTRIBUTE_UNUSED)
> +{
> + check_int_arguments;
> +}
> +
> +void
> +check_union_passing3(union un3 u ATTRIBUTE_UNUSED)
> +{
> + check_int_arguments;
> +}
> +
> +#define check_union_passing1 WRAP_CALL(check_union_passing1)
> +#define check_union_passing2 WRAP_CALL(check_union_passing2)
> +#define check_union_passing3 WRAP_CALL(check_union_passing3)
> +
> +union un4
> +{
> + int i;
> + float f;
> +};
> +
> +union un5
> +{
> + long long ll;
> + double d;
> +};
> +
> +void
> +check_union_passing4(union un4 u1 ATTRIBUTE_UNUSED,
> + union un4 u2 ATTRIBUTE_UNUSED,
> + union un4 u3 ATTRIBUTE_UNUSED,
> + union un4 u4 ATTRIBUTE_UNUSED,
> + union un4 u5 ATTRIBUTE_UNUSED,
> + union un4 u6 ATTRIBUTE_UNUSED,
> + union un4 u7 ATTRIBUTE_UNUSED,
> + union un4 u8 ATTRIBUTE_UNUSED)
> +{
> + check_int_arguments;
> +}
> +
> +void
> +check_union_passing5(union un5 u ATTRIBUTE_UNUSED)
> +{
> + check_int_arguments;
> +}
> +
> +#define check_union_passing4 WRAP_CALL(check_union_passing4)
> +#define check_union_passing5 WRAP_CALL(check_union_passing5)
> +
> +union un6
> +{
> + __float128 f128;
> + int i;
> +};
> +
> +
> +void
> +check_union_passing6(union un6 u ATTRIBUTE_UNUSED)
> +{
> + /* Check the passing on the stack by comparing the address of the
> + stack elements to the expected place on the stack. */
> + assert ((unsigned long)&u.f128 == esp+4);
> + assert ((unsigned long)&u.i == esp+4);
> +}
> +
> +#define check_union_passing6 WRAP_CALL(check_union_passing6)
> +
> +int
> +main (void)
> +{
> + union un1 u1;
> +#ifdef CHECK_LARGER_UNION_PASSING
> + union un2 u2;
> + union un3 u3;
> + struct int_struct is;
> + struct long_struct ls;
> +#endif /* CHECK_LARGER_UNION_PASSING */
> + union un4 u4[8];
> + union un5 u5 = { { 48.394, 39.3, -397.9, 3484.9 } };
> + int i;
> + union un6 u6;
> +
> + /* Check a union with char, int. */
> + clear_struct_registers;
> + u1.i = 0; /* clear the struct to not have high bits left */
> + u1.c = 32;
> + iregs.I0 = 32;
> + num_iregs = 1;
> + clear_int_hardware_registers;
> + check_union_passing1(u1);
> + u1.i = 0; /* clear the struct to not have high bits left */
> + u1.i = 33;
> + iregs.I0 = 33;
> + num_iregs = 1;
> + clear_int_hardware_registers;
> + check_union_passing1(u1);
> +
> + /* Check a union with char, long, char. */
> +#ifdef CHECK_LARGER_UNION_PASSING
> + clear_struct_registers;
> + u2.l = 0; /* clear the struct to not have high bits left */
> + u2.c1 = 34;
> + iregs.I0 = 34;
> + num_iregs = 1;
> + clear_int_hardware_registers;
> + check_union_passing2(u2);
> + u2.l = 0; /* clear the struct to not have high bits left */
> + u2.l = 35;
> + iregs.I0 = 35;
> + num_iregs = 1;
> + clear_int_hardware_registers;
> + check_union_passing2(u2);
> + u2.l = 0; /* clear the struct to not have high bits left */
> + u2.c2 = 36;
> + iregs.I0 = 36;
> + num_iregs = 1;
> + clear_int_hardware_registers;
> + check_union_passing2(u2);
> +
> + /* check a union containing two structs and a union. */
> + clear_struct_registers;
> + is.i = 37;
> + u3.ls.l = 0; /* clear the struct to not have high bits left */
> + u3.is = is;
> + iregs.I0 = 37;
> + num_iregs = 1;
> + clear_int_hardware_registers;
> + check_union_passing3(u3);
> + ls.l = 38;
> + u3.ls.l = 0; /* clear the struct to not have high bits left */
> + u3.ls = ls;
> + iregs.I0 = 38;
> + num_iregs = 1;
> + clear_int_hardware_registers;
> + check_union_passing3(u3);
> + u1.c = 39;
> + u3.ls.l = 0; /* clear the struct to not have high bits left */
> + u3.un = u1;
> + iregs.I0 = 39;
> + num_iregs = 1;
> + clear_int_hardware_registers;
> + check_union_passing3(u3);
> + u1.i = 40;
> + u3.ls.l = 0; /* clear the struct to not have high bits left */
> + u3.un = u1;
> + iregs.I0 = 40;
> + num_iregs = 1;
> + clear_int_hardware_registers;
> + check_union_passing3(u3);
> +#endif /* CHECK_LARGER_UNION_PASSING */
> +
> + clear_struct_registers;
> + for (i = 0; i < 8; i++)
> + u4[i].f = 32 + i;
> + iregs.I0 = u4[0].i;
> + iregs.I1 = u4[1].i;
> + iregs.I2 = u4[2].i;
> + num_iregs = 3;
> + clear_int_hardware_registers;
> + check_union_passing4(u4[0], u4[1], u4[2], u4[3],
> + u4[4], u4[5], u4[6], u4[7]);
> +
> + clear_struct_registers;
> + iregs.I0 = u5.ll & 0xffffffff;
> + iregs.I1 = (u5.ll >> 32) & 0xffffffff;
> + num_iregs = 2;
> + clear_int_hardware_registers;
> + check_union_passing5(u5);
> +
> + u6.i = 2;
> + check_union_passing6(u6);
> +
> + return 0;
> +}
> diff --git a/gcc/testsuite/gcc.target/i386/iamcu/test_struct_returning.c b/gcc/testsuite/gcc.target/i386/iamcu/test_struct_returning.c
> new file mode 100644
> index 0000000..49a6b1f
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/iamcu/test_struct_returning.c
> @@ -0,0 +1,362 @@
> +/* This tests returning of structures. */
> +
> +#include "defines.h"
> +#include "macros.h"
> +#include "args.h"
> +
> +struct IntegerRegisters iregbits = { ~0, ~0, ~0, ~0, ~0, ~0 };
> +struct IntegerRegisters iregs;
> +unsigned int num_iregs;
> +
> +int current_test;
> +int num_failed = 0;
> +
> +typedef enum {
> + EAX = 0,
> + EAX_EDX,
> + LONG_LONG,
> + FLOAT,
> + DOUBLE,
> + FLOAT_FLOAT,
> + EAX_FLOAT,
> + FLOAT_EDX,
> + MEM
> +} Type;
> +
> +/* Structures which should be returned in EAX/LONG_LONG/EAX_EDX. */
> +#define D(I,MEMBERS,C,B) struct S_ ## I { MEMBERS ; }; Type class_ ## I = C; \
> +struct S_ ## I f_ ## I (void) { struct S_ ## I s; iamcu_memset (&s, 0, sizeof(s)); B; return s; }
> +
> +D(1,char m1, EAX, s.m1=42)
> +D(2,short m1, EAX, s.m1=42)
> +D(3,int m1, EAX, s.m1=42)
> +D(4,char m1[3], EAX, s.m1[0]=42)
> +D(5,char m1[4], EAX, s.m1[0]=42)
> +D(6,char m1;char m2; char m3, EAX, s.m1=42)
> +D(7,char m1;short m2, EAX, s.m1=42)
> +
> +D(30,long long m1, LONG_LONG, s.m1=0xadadbeefadadbeefLL)
> +
> +D(50,short m1;int m2, EAX_EDX, s.m1=42; s.m2=43)
> +D(51,char m1;int m2, EAX_EDX, s.m1=42; s.m2=43)
> +D(52,char m1[5], EAX_EDX, s.m1[0]=42; s.m1[4]=43)
> +D(53,char m1[6], EAX_EDX, s.m1[0]=42; s.m1[4]=43)
> +D(54,char m1[7], EAX_EDX, s.m1[0]=42; s.m1[4]=43)
> +D(55,char m1[8], EAX_EDX, s.m1[0]=42; s.m1[4]=43)
> +D(56,char m1;short m2[2], EAX_EDX, s.m1=42; s.m2[1]=43)
> +D(57,short m1[4], EAX_EDX, s.m1[0]=42; s.m1[2]=43)
> +D(58,int m1[2], EAX_EDX, s.m1[0]=42; s.m1[1]=43)
> +D(59,int m1;char m2, EAX_EDX, s.m1=42; s.m2=43)
> +D(60,int m1;short m2, EAX_EDX, s.m1=42; s.m2=43)
> +D(61,int m1;short m2; char m3, EAX_EDX, s.m1=42; s.m2=43)
> +D(62,int m1;char m2; short m3, EAX_EDX, s.m1=42; s.m2=43)
> +
> +/* Packed members. */
> +D(100,short m1[1];int m2 PACKED, EAX_EDX, s.m1[0]=42; s.m2=43)
> +D(101,char m1; short m2 PACKED; char m3, EAX_EDX, s.m1=42; s.m3=43)
> +
> +/* Structures which should be returned in FLOAT/DOUBLE. */
> +#undef D
> +#define D(I,MEMBERS,C,B) struct S_ ## I { MEMBERS ; }; Type class_ ## I = C; \
> +struct S_ ## I f_ ## I (void) { struct S_ ## I s; iamcu_memset (&s, 0, sizeof(s)); B; return s; }
> +
> +D(200,float f, FLOAT, s.f=42)
> +D(201,double d, DOUBLE, s.d=42)
> +
> +D(300,float m;char m2, FLOAT_EDX, s.m=42; s.m2=43)
> +D(301,float m;short m2, FLOAT_EDX, s.m=42; s.m2=43)
> +D(302,float m;int m2, FLOAT_EDX, s.m=42; s.m2=43)
> +
> +D(400,char m1; float m2, EAX_FLOAT, s.m1=42; s.m2=43)
> +D(401,short m1; float m2, EAX_FLOAT, s.m1=42; s.m2=43)
> +D(402,int m1; float m2, EAX_FLOAT, s.m1=42; s.m2=43)
> +
> +D(500,float m;float m2, FLOAT_FLOAT, s.m=42; s.m2=43)
> +D(501,float f[2], FLOAT, s.f[0]=42; s.f[1]=43)
> +
> +/* Structures which should be returned in MEM. */
> +void *struct_addr;
> +#undef D
> +#define D(I,MEMBERS) struct S_ ## I { MEMBERS ; }; Type class_ ## I = MEM; \
> +struct S_ ## I f_ ## I (void) { union {unsigned char c; struct S_ ## I s;} u; iamcu_memset (&u.s, 0, sizeof(u.s)); u.c = 42; return u.s; }
> +
> +/* Too large. */
> +D(600,char m1[17])
> +D(601,short m1[9])
> +D(602,int m1[5])
> +D(603,long m1[3])
> +D(604,short m1[8];char c)
> +D(605,char m1[1];int i[4])
> +D(606,float m1[5])
> +D(607,double m1[3])
> +D(608,char m1[1];float f[4])
> +D(609,char m1[1];double d[2])
> +D(610,__complex long double m1[1])
> +
> +/* Too large due to padding. */
> +D(611,char m1[1]; int i; char c2)
> +
> +/* Special tests. */
> +#undef D
> +#define D(I,MEMBERS,B) struct S_ ## I { MEMBERS ; }; Type class_ ## I = MEM; \
> +struct S_ ## I f_ ## I (void) { struct S_ ## I s; B; return s; }
> +D(700,float f[4], s.f[0] = s.f[1] = s.f[2] = s.f[3] = 42)
> +
> +void
> +check_eax (void)
> +{
> + switch (current_test)
> + {
> + case 1:
> + case 4:
> + case 5:
> + case 6:
> + case 7:
> + eax &= 0xff;
> + break;
> + case 2:
> + eax &= 0xffff;
> + break;
> + case 3:
> + eax &= 0xffff;
> + break;
> + default:
> + abort ();
> + }
> + if (eax != 42)
> + num_failed++;
> +}
> +
> +void
> +check_eax_edx (void)
> +{
> + unsigned long long ll = eax | ((unsigned long long) edx) << 32;
> + switch (current_test)
> + {
> + case 50:
> + eax &= 0xffff;
> + break;
> + case 52:
> + case 53:
> + case 54:
> + case 55:
> + edx &= 0xff;
> + case 51:
> + eax &= 0xff;
> + break;
> + case 56:
> + eax &= 0xff;
> + edx &= 0xffff;
> + break;
> + case 57:
> + eax &= 0xffff;
> + edx &= 0xffff;
> + break;
> + case 58:
> + break;
> + case 59:
> + case 62:
> + edx &= 0xff;
> + break;
> + case 60:
> + case 61:
> + edx &= 0xffff;
> + break;
> + case 100:
> + eax &= 0xffff;
> + edx = (ll >> 16) & 0xffffffff;
> + break;
> + case 101:
> + edx = (eax >> 24) & 0xff;
> + eax &= 0xff;
> + break;
> + default:
> + abort ();
> + }
> + if (eax != 42 || edx != 43)
> + num_failed++;
> +}
> +
> +void
> +check_float_edx (void)
> +{
> + union
> + {
> + unsigned long l;
> + float f;
> + } ueax;
> + switch (current_test)
> + {
> + case 300:
> + edx &= 0xff;
> + break;
> + case 301:
> + edx &= 0xffff;
> + break;
> + case 302:
> + edx &= 0xffff;
> + break;
> + default:
> + abort ();
> + }
> + ueax.l = eax;
> + if (ueax.f != 42 || edx != 43)
> + num_failed++;
> +}
> +
> +void
> +check_eax_float (void)
> +{
> + union
> + {
> + unsigned long l;
> + float f;
> + } uedx;
> + switch (current_test)
> + {
> + case 400:
> + eax &= 0xff;
> + break;
> + case 401:
> + eax &= 0xffff;
> + break;
> + case 402:
> + eax &= 0xffff;
> + break;
> + default:
> + abort ();
> + }
> + uedx.l = edx;
> + if (eax != 42 || uedx.f != 43)
> + num_failed++;
> +}
> +
> +void
> +check_float_float (void)
> +{
> + union
> + {
> + unsigned long l;
> + float f;
> + } ueax, uedx;
> + switch (current_test)
> + {
> + case 500:
> + case 501:
> + break;
> + default:
> + abort ();
> + }
> + ueax.l = eax;
> + uedx.l = edx;
> + if (ueax.f != 42 || uedx.f != 43)
> + num_failed++;
> +}
> +
> +void
> +check_all (Type class, unsigned long size)
> +{
> + union
> + {
> + struct
> + {
> + unsigned long eax;
> + unsigned long edx;
> + } eax_edx;
> + unsigned long long ll;
> + float f;
> + double d;
> + } u;
> +
> + switch (class)
> + {
> + case EAX:
> + check_eax ();
> + break;
> + case LONG_LONG:
> + if (0xadadbeefL != eax || 0xadadbeefL != edx)
> + num_failed++;
> + break;
> + case EAX_EDX:
> + check_eax_edx ();
> + break;
> + case FLOAT:
> + u.eax_edx.eax = eax;
> + if (u.f != 42)
> + num_failed++;
> + break;
> + case DOUBLE:
> + u.eax_edx.eax = eax;
> + u.eax_edx.edx = edx;
> + if (u.d != 42)
> + num_failed++;
> + break;
> + case FLOAT_EDX:
> + check_float_edx ();
> + break;
> + case FLOAT_FLOAT:
> + check_float_float ();
> + break;
> + case EAX_FLOAT:
> + check_eax_float ();
> + break;
> + case MEM:
> + /* sret_eax contains a slot whose address is given to the f_*
> + functions. The slot may be a temporary one on stack. When
> + this function is called, hopefully this slot hasn't be
> + overriden. */
> + if (sret_eax != eax)
> + num_failed++;
> + else if (current_test < 700)
> + {
> + if (*(unsigned char*)sret_eax != 42
> + || *(unsigned char*)struct_addr != 42)
> + num_failed++;
> + }
> + else
> + {
> + if (*(float *)sret_eax != 42
> + || *(float *)struct_addr != 42)
> + num_failed++;
> + }
> + break;
> + }
> +}
> +
> +#undef D
> +#define D(I) { static struct S_ ## I s; current_test = I; struct_addr = (void*)&s; \
> + clear_non_sret_int_registers; \
> + s = WRAP_RET(f_ ## I) (); \
> + check_all(class_ ## I, sizeof(s)); \
> +}
> +
> +int
> +main (void)
> +{
> + D(1) D(2) D(3) D(4) D(5) D(6) D(7)
> +
> + D(30)
> +
> + D(50) D(51) D(52) D(53) D(54) D(55) D(56) D(57) D(58) D(59)
> + D(60) D(61) D(62)
> +
> + D(100) D(101)
> +
> + D(200) D(201)
> +
> + D(300) D(301) D(302)
> +
> + D(400) D(401) D(402)
> +
> + D(500) D(501)
> +
> + D(600) D(601) D(602) D(603) D(604) D(605) D(606) D(607) D(608) D(609)
> + D(610) D(611)
> +
> + D(700)
> +
> + if (num_failed)
> + abort ();
> +
> + return 0;
> +}
> diff --git a/gcc/testsuite/gcc.target/i386/iamcu/test_varargs.c b/gcc/testsuite/gcc.target/i386/iamcu/test_varargs.c
> new file mode 100644
> index 0000000..124bef1
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/iamcu/test_varargs.c
> @@ -0,0 +1,101 @@
> +/* Test variable number of arguments passed to functions. */
> +
> +#include <stdarg.h>
> +#include "defines.h"
> +
> +
> +#define ARG_INT 1
> +#define ARG_DOUBLE 2
> +#define ARG_POINTER 3
> +
> +union types
> +{
> + int ivalue;
> + double dvalue;
> + void *pvalue;
> +};
> +
> +struct arg
> +{
> + int type;
> + union types value;
> +};
> +
> +struct arg *arglist;
> +
> +/* This tests the argumentlist to see if it matches the format string which
> + is printf-like. Nothing will be printed of course. It can handle ints,
> + doubles and void pointers. The given value will be tested against the
> + values given in arglist.
> + This test only assures that the variable argument passing is working.
> + No attempt is made to see if argument passing is done the right way. */
> +void
> +__attribute__ ((noinline))
> +noprintf (char *format, ...)
> +{
> + va_list va_arglist;
> + char *c;
> +
> + int ivalue;
> + double dvalue;
> + void *pvalue;
> + struct arg *argp = arglist;
> +
> + va_start (va_arglist, format);
> + for (c = format; *c; c++)
> + if (*c == '%')
> + {
> + switch (*++c)
> + {
> + case 'd':
> + assert (argp->type == ARG_INT);
> + ivalue = va_arg (va_arglist, int);
> + assert (argp->value.ivalue == ivalue);
> + break;
> + case 'f':
> + assert (argp->type == ARG_DOUBLE);
> + dvalue = va_arg (va_arglist, double);
> + assert (argp->value.dvalue == dvalue);
> + break;
> + case 'p':
> + assert (argp->type == ARG_POINTER);
> + pvalue = va_arg (va_arglist, void *);
> + assert (argp->value.pvalue == pvalue);
> + break;
> + default:
> + abort ();
> + }
> +
> + argp++;
> + }
> +}
> +
> +extern void iamcu_noprintf (char *, ...);
> +
> +int
> +main (void)
> +{
> +#ifdef CHECK_VARARGS
> + float f = 258.0;
> + struct arg al[5];
> +
> + al[0].type = ARG_INT;
> + al[0].value.ivalue = 256;
> + al[1].type = ARG_DOUBLE;
> + al[1].value.dvalue = 257.0;
> + al[2].type = ARG_POINTER;
> + al[2].value.pvalue = al;
> + al[3].type = ARG_DOUBLE;
> + al[3].value.dvalue = f;
> + al[4].type = ARG_INT;
> + al[4].value.ivalue = 259;
> +
> + arglist = al;
> + noprintf("%d%f%p%f%d", 256, 257.0, al, f, 259);
> +
> + iamcu_noprintf ((char *) 0xabadbeef, 256, 257.0,
> + (void *) 0xbbadbeef, f, 259);
> +#endif
> +
> + return 0;
> +}
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2015-06-26 10:57 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-06-22 13:52 [i386, PATCH] Support new psABI for IA MCU Kirill Yukhin
2015-06-22 14:38 ` [i386, PATCH, 1/3] IA MCU psABI support: GCC changes Kirill Yukhin
2015-06-26 10:40 ` Uros Bizjak
2015-06-22 15:41 ` [i386, PATCH, 2/3] IA MCU psABI support: changes to libraries Kirill Yukhin
2015-06-26 10:54 ` Uros Bizjak
2015-06-23 9:46 ` [i386, PATCH, 3/3] IA MCU psABI support: testsuite Kirill Yukhin
2015-06-26 11:03 ` Uros Bizjak
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).