Patchwork [1/2] linux-user: Define target alignment size

login
register
mail settings
Submitter Laurent Vivier
Date Feb. 13, 2011, 2:22 a.m.
Message ID <1297563761-2786-2-git-send-email-laurent@vivier.eu>
Download mbox | patch
Permalink /patch/82967/
State New
Headers show

Comments

Laurent Vivier - Feb. 13, 2011, 2:22 a.m.
Datatype alignment can be found using following application:

int main(void)
{
	printf("alignof(short) %ld\n", __alignof__(short));
	printf("alignof(int) %ld\n", __alignof__(int));
	printf("alignof(long) %ld\n", __alignof__(long));
	printf("alignof(long long) %ld\n", __alignof__(long long));
}

This patch includes following alignments:

i386

   alignof(short) 2
   alignof(int) 4
   alignof(long) 4
   alignof(long long) 8

 x86_64

   alignof(short) 2
   alignof(int) 4
   alignof(long) 8
   alignof(long long) 8

 arm

   alignof(short) 2
   alignof(int) 4
   alignof(long) 4
   alignof(long long) 4

 m68k (680x0)

   alignof(short) 2
   alignof(int) 2
   alignof(long) 2
   alignof(long long) 2

 mips

   alignof(short) 2
   alignof(int) 4
   alignof(long) 4
   alignof(long long) 8

 ppc

   alignof(short) 2
   alignof(int) 4
   alignof(long) 4
   alignof(long long) 8

for other targets, use by default (2,4,4,8).

Please, update for your favorite target...

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
v2: compute align size for each basic datatype

 configure  |   13 +++++++++++++
 cpu-defs.h |   14 ++++++++++----
 2 files changed, 23 insertions(+), 4 deletions(-)
Blue Swirl - Feb. 13, 2011, 8:24 a.m.
On Sun, Feb 13, 2011 at 4:22 AM, Laurent Vivier <laurent@vivier.eu> wrote:
> Datatype alignment can be found using following application:
>
> int main(void)
> {
>        printf("alignof(short) %ld\n", __alignof__(short));
>        printf("alignof(int) %ld\n", __alignof__(int));
>        printf("alignof(long) %ld\n", __alignof__(long));
>        printf("alignof(long long) %ld\n", __alignof__(long long));
> }
>
> This patch includes following alignments:
>
> i386
>
>   alignof(short) 2
>   alignof(int) 4
>   alignof(long) 4
>   alignof(long long) 8
>
>  x86_64
>
>   alignof(short) 2
>   alignof(int) 4
>   alignof(long) 8
>   alignof(long long) 8
>
>  arm
>
>   alignof(short) 2
>   alignof(int) 4
>   alignof(long) 4
>   alignof(long long) 4
>
>  m68k (680x0)
>
>   alignof(short) 2
>   alignof(int) 2
>   alignof(long) 2
>   alignof(long long) 2
>
>  mips
>
>   alignof(short) 2
>   alignof(int) 4
>   alignof(long) 4
>   alignof(long long) 8
>
>  ppc
>
>   alignof(short) 2
>   alignof(int) 4
>   alignof(long) 4
>   alignof(long long) 8
>
> for other targets, use by default (2,4,4,8).
>
> Please, update for your favorite target...

For Sparc32 (I think also sparc32plus), the default is OK.

For Sparc64, please use 2, 4, 8, 8. I'd guess other 64 bit platforms
(Alpha, MIPS64, PPC64 etc) should use the same.

Does GCC produce correct code using the attributes on strictly aligned
host, when the target is less strictly aligned?

Should the alignment of floating point variables be specified as well?
The strict alignment required for doubles is 4, but recommended
alignment is 8, I'm not sure which one is used for structures
containing doubles.
Laurent Vivier - Feb. 13, 2011, 5:12 p.m.
Le dimanche 13 février 2011 à 10:24 +0200, Blue Swirl a écrit :
> On Sun, Feb 13, 2011 at 4:22 AM, Laurent Vivier <laurent@vivier.eu> wrote:
> > Datatype alignment can be found using following application:
> >
> > int main(void)
> > {
> >        printf("alignof(short) %ld\n", __alignof__(short));
> >        printf("alignof(int) %ld\n", __alignof__(int));
> >        printf("alignof(long) %ld\n", __alignof__(long));
> >        printf("alignof(long long) %ld\n", __alignof__(long long));
> > }
> >
> > This patch includes following alignments:
> >
> > i386
> >
> >   alignof(short) 2
> >   alignof(int) 4
> >   alignof(long) 4
> >   alignof(long long) 8
> >
> >  x86_64
> >
> >   alignof(short) 2
> >   alignof(int) 4
> >   alignof(long) 8
> >   alignof(long long) 8
> >
> >  arm
> >
> >   alignof(short) 2
> >   alignof(int) 4
> >   alignof(long) 4
> >   alignof(long long) 4
> >
> >  m68k (680x0)
> >
> >   alignof(short) 2
> >   alignof(int) 2
> >   alignof(long) 2
> >   alignof(long long) 2
> >
> >  mips
> >
> >   alignof(short) 2
> >   alignof(int) 4
> >   alignof(long) 4
> >   alignof(long long) 8
> >
> >  ppc
> >
> >   alignof(short) 2
> >   alignof(int) 4
> >   alignof(long) 4
> >   alignof(long long) 8
> >
> > for other targets, use by default (2,4,4,8).
> >
> > Please, update for your favorite target...
> 
> For Sparc32 (I think also sparc32plus), the default is OK.
> 
> For Sparc64, please use 2, 4, 8, 8. I'd guess other 64 bit platforms
> (Alpha, MIPS64, PPC64 etc) should use the same.

OK, I update my patch.

> Does GCC produce correct code using the attributes on strictly aligned
> host, when the target is less strictly aligned?

It seems it is OK. I did some tests into a mips-linux-user chroot (sparc
one is broken ;-) ) :

mips is a strictly aligned host, from gcc/config/mips/mips.h:

#define STRICT_ALIGNMENT 1

aligments are:

   alignof(short) 2
   alignof(int) 4
   alignof(long) 4
   alignof(long long) 8

We try to align int on 2.

#include <stdio.h>

typedef int target_int __attribute__((aligned(2)));

struct {
        char Z;
        target_int A;
} B;

int main(void)
{
        B.A = 0xdeadbeaf;
        printf("%d: %x\n", __alignof__(B.A), B.A);
}

./test_align
2: deadbeaf

disass:

        lw      $2,%got(B)($28)
        li      $3,-559087616                   # 0xffffffffdead0000
        ori     $3,$3,0xbeaf
        swl     $3,2($2)
        swr     $3,5($2)

normal case:

        lw      $3,%got(B)($28)
        li      $2,-559087616                   # 0xffffffffdead0000
        ori     $2,$2,0xbeaf
        sw      $2,4($3)

So, gcc seems smart enough to split the memory access in several ones
compatible with the strict alignment rules.

> Should the alignment of floating point variables be specified as well?

At the moment it seems useless.

> The strict alignment required for doubles is 4, but recommended
> alignment is 8, I'm not sure which one is used for structures
> containing doubles.

if necessary, some tests will be helpfull.

Thank you for your comments.

Regards,
Laurent

Patch

diff --git a/configure b/configure
index 25381e5..efc6fa4 100755
--- a/configure
+++ b/configure
@@ -2919,6 +2919,10 @@  target_nptl="no"
 interp_prefix1=`echo "$interp_prefix" | sed "s/%M/$target_arch2/g"`
 echo "CONFIG_QEMU_INTERP_PREFIX=\"$interp_prefix1\"" >> $config_target_mak
 gdb_xml_files=""
+target_short_alignment=2
+target_int_alignment=4
+target_long_alignment=4
+target_long_long_alignment=8
 
 TARGET_ARCH="$target_arch2"
 TARGET_BASE_ARCH=""
@@ -2931,6 +2935,7 @@  case "$target_arch2" in
   x86_64)
     TARGET_BASE_ARCH=i386
     target_phys_bits=64
+    target_long_alignment=8
   ;;
   alpha)
     target_phys_bits=64
@@ -2942,6 +2947,7 @@  case "$target_arch2" in
     target_nptl="yes"
     gdb_xml_files="arm-core.xml arm-vfp.xml arm-vfp3.xml arm-neon.xml"
     target_phys_bits=32
+    target_long_long_alignment=4
   ;;
   cris)
     target_nptl="yes"
@@ -2951,6 +2957,9 @@  case "$target_arch2" in
     bflt="yes"
     gdb_xml_files="cf-core.xml cf-fp.xml"
     target_phys_bits=32
+    target_int_alignment=2
+    target_long_alignment=2
+    target_long_long_alignment=2
   ;;
   microblaze)
     bflt="yes"
@@ -3029,6 +3038,10 @@  case "$target_arch2" in
     exit 1
   ;;
 esac
+echo "TARGET_SHORT_ALIGNMENT=$target_short_alignment" >> $config_target_mak
+echo "TARGET_INT_ALIGNMENT=$target_int_alignment" >> $config_target_mak
+echo "TARGET_LONG_ALIGNMENT=$target_long_alignment" >> $config_target_mak
+echo "TARGET_LONG_LONG_ALIGNMENT=$target_long_long_alignment" >> $config_target_mak
 echo "TARGET_ARCH=$TARGET_ARCH" >> $config_target_mak
 target_arch_name="`echo $TARGET_ARCH | tr '[:lower:]' '[:upper:]'`"
 echo "TARGET_$target_arch_name=y" >> $config_target_mak
diff --git a/cpu-defs.h b/cpu-defs.h
index 8d4bf86..98c6718 100644
--- a/cpu-defs.h
+++ b/cpu-defs.h
@@ -37,16 +37,22 @@ 
 
 #define TARGET_LONG_SIZE (TARGET_LONG_BITS / 8)
 
+typedef int16_t target_short __attribute__ ((aligned(TARGET_SHORT_ALIGNMENT)));
+typedef uint16_t target_ushort __attribute__((aligned(TARGET_SHORT_ALIGNMENT)));
+typedef int32_t target_int __attribute__((aligned(TARGET_INT_ALIGNMENT)));
+typedef uint32_t target_uint __attribute__((aligned(TARGET_INT_ALIGNMENT)));
+typedef int64_t target_long_long __attribute__((aligned(TARGET_LONG_LONG_ALIGNMENT)));
+typedef uint64_t target_ulong_long __attribute__((aligned(TARGET_LONG_LONG_ALIGNMENT)));
 /* target_ulong is the type of a virtual address */
 #if TARGET_LONG_SIZE == 4
-typedef int32_t target_long;
-typedef uint32_t target_ulong;
+typedef int32_t target_long __attribute__((aligned(TARGET_LONG_ALIGNMENT)));
+typedef uint32_t target_ulong __attribute__((aligned(TARGET_LONG_ALIGNMENT)));
 #define TARGET_FMT_lx "%08x"
 #define TARGET_FMT_ld "%d"
 #define TARGET_FMT_lu "%u"
 #elif TARGET_LONG_SIZE == 8
-typedef int64_t target_long;
-typedef uint64_t target_ulong;
+typedef int64_t target_long __attribute__((aligned(TARGET_LONG_ALIGNMENT)));
+typedef uint64_t target_ulong __attribute__((aligned(TARGET_LONG_ALIGNMENT)));
 #define TARGET_FMT_lx "%016" PRIx64
 #define TARGET_FMT_ld "%" PRId64
 #define TARGET_FMT_lu "%" PRIu64