/* @(#)align_test.c 1.31 15/11/30 Copyright 1995-2015 J. Schilling */ #include #ifndef lint static UConst char sccsid[] = "@(#)align_test.c 1.31 15/11/30 Copyright 1995-2015 J. Schilling"; #endif /* * Generate machine dependant align.h * * Copyright (c) 1995-2015 J. Schilling */ /* * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * See the file CDDL.Schily.txt in this distribution for details. * A copy of the CDDL is also available via the Internet at * http://www.opensource.org/licenses/cddl1.txt * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file CDDL.Schily.txt from this distribution. */ #include #include #undef NO_LONGLONG /* Make sure that Llong will be long long */ #include #include /* Define missing prototypes */ /* * Be very careful here as MSVC does not implement long long but rather __int64 * and once someone makes 'long long' 128 bits on a 64 bit machine, we need to * check for a MSVC __int128 type. */ /* * CHECK_ALIGN needs SIGBUS, but DJGPP has no SIGBUS */ /*#define FORCE_ALIGN*/ /*#define OFF_ALIGN*/ /*#define CHECK_ALIGN*/ EXPORT int main __PR((int ac, char **av)); #if !defined(FORCE_ALIGN) && !defined(OFF_ALIGN) && !defined(CHECK_ALIGN) #define OFF_ALIGN #endif char buf[8192+1024]; char *buf_aligned; #ifdef FORCE_ALIGN # undef CHECK_ALIGN # undef OFF_ALIGN #endif #ifdef CHECK_ALIGN # undef FORCE_ALIGN # undef OFF_ALIGN #endif #ifdef OFF_ALIGN # undef FORCE_ALIGN # undef CHECK_ALIGN #endif #ifdef FORCE_ALIGN #define ALIGN_short sizeof (short) #define ALIGN_int sizeof (int) #define ALIGN_long sizeof (long) #define ALIGN_longlong sizeof (Llong) #define ALIGN_float sizeof (float) #define ALIGN_double sizeof (double) #define ALIGN_ldouble sizeof (long double) #define ALIGN_ptr sizeof (char *) #endif #ifdef CHECK_ALIGN #include #include LOCAL jmp_buf jb; LOCAL int check_align __PR((int (*)(char *, int), void (*)(char *, int), int)); LOCAL int check_short __PR((char *, int)); LOCAL int check_int __PR((char *, int)); LOCAL int check_long __PR((char *, int)); LOCAL int check_longlong __PR((char *, int)); LOCAL int check_float __PR((char *, int)); LOCAL int check_double __PR((char *, int)); #ifdef HAVE_LONGDOUBLE LOCAL int check_ldouble __PR((char *, int)); #endif LOCAL int check_ptr __PR((char *, int)); LOCAL int speed_check __PR((char *, void (*)(char *, int), int)); LOCAL void speed_short __PR((char *, int)); LOCAL void speed_int __PR((char *, int)); LOCAL void speed_long __PR((char *, int)); LOCAL void speed_longlong __PR((char *, int)); LOCAL void speed_float __PR((char *, int)); LOCAL void speed_double __PR((char *, int)); #ifdef HAVE_LONGDOUBLE LOCAL void speed_ldouble __PR((char *, int)); #endif LOCAL void speed_ptr __PR((char *, int)); #define ALIGN_short check_align(check_short, speed_short, sizeof (short)) #define ALIGN_int check_align(check_int, speed_int, sizeof (int)) #define ALIGN_long check_align(check_long, speed_long, sizeof (long)) #define ALIGN_longlong check_align(check_longlong, speed_longlong, sizeof (Llong)) #define ALIGN_float check_align(check_float, speed_float, sizeof (float)) #define ALIGN_double check_align(check_double, speed_double, sizeof (double)) #define ALIGN_ldouble check_align(check_ldouble, speed_ldouble, sizeof (long double)) #define ALIGN_ptr check_align(check_ptr, speed_ptr, sizeof (char *)) #endif #ifdef OFF_ALIGN #define sm_off(s, m) ((size_t)&((s)0)->m) LOCAL void used __PR((int i)); LOCAL int off_short __PR((void)); LOCAL int off_int __PR((void)); LOCAL int off_long __PR((void)); LOCAL int off_longlong __PR((void)); LOCAL int off_float __PR((void)); LOCAL int off_double __PR((void)); #ifdef HAVE_LONGDOUBLE LOCAL int off_ldouble __PR((void)); #endif LOCAL int off_ptr __PR((void)); #define ALIGN_short off_short() #define ALIGN_int off_int() #define ALIGN_long off_long() #define ALIGN_longlong off_longlong() #define ALIGN_float off_float() #define ALIGN_double off_double() #define ALIGN_ldouble off_ldouble() #define ALIGN_ptr off_ptr() #endif LOCAL void printmacs __PR((void)); #ifdef CHECK_ALIGN LOCAL void sig __PR((int)); LOCAL void sig(signo) int signo; { signal(signo, sig); longjmp(jb, 1); } #endif #if defined(mc68000) || defined(mc68020) #define MIN_ALIGN 2 #else #define MIN_ALIGN 2 #endif #define min_align(i) (((i) < MIN_ALIGN) ? MIN_ALIGN : (i)) /* * Make it LOCAL MacOS-X by default links against libcurses and * so we totherwise have a double defined "al". */ LOCAL char al[] = "alignment value for "; LOCAL char ms[] = "alignment mask for "; LOCAL char so[] = "sizeof "; LOCAL char sh[] = "short"; LOCAL char in[] = "int"; LOCAL char lo[] = "long"; LOCAL char ll[] = "long long"; LOCAL char fl[] = "float"; LOCAL char db[] = "double"; LOCAL char ld[] = "long double"; LOCAL char pt[] = "pointer"; LOCAL char mt[] = "max type"; #define xalign(x, a, m) (((char *)(x)) + ((a) - (((UIntptr_t)(x))&(m)))) EXPORT int main(ac, av) int ac; char **av; { char *p; int i; int s; int amax = 0; int smax = 0; #ifdef CHECK_ALIGN #ifdef SIGBUS signal(SIGBUS, sig); #endif #endif i = ((size_t)buf) % 1024; i = 1024 - i; p = &buf[i]; buf_aligned = p; #ifdef DEBUG fprintf(stderr, "buf: 0x%lX 0x%lX\n", (unsigned long)buf, (unsigned long)xalign(buf, 1024, 1023)); #endif printf("/*\n"); printf(" * This file has been generated automatically\n"); printf(" * by %s\n", sccsid); printf(" * do not edit by hand.\n"); printf(" */\n"); printf("#ifndef __ALIGN_H\n"); printf("#define __ALIGN_H\n\n"); s = sizeof (short); i = ALIGN_short; i = min_align(i); if (i > amax) amax = i; if (s > smax) smax = s; printf("\n"); printf("#define ALIGN_SHORT %d\t/* %s(%s *)\t*/\n", i, al, sh); printf("#define ALIGN_SMASK %d\t/* %s(%s *)\t*/\n", i-1, ms, sh); printf("#define SIZE_SHORT %d\t/* %s(%s)\t\t\t*/\n", s, so, sh); s = sizeof (int); i = ALIGN_int; i = min_align(i); if (i > amax) amax = i; if (s > smax) smax = s; printf("\n"); printf("#define ALIGN_INT %d\t/* %s(%s *)\t\t*/\n", i, al, in); printf("#define ALIGN_IMASK %d\t/* %s(%s *)\t\t*/\n", i-1, ms, in); printf("#define SIZE_INT %d\t/* %s(%s)\t\t\t\t*/\n", s, so, in); s = sizeof (long); i = ALIGN_long; i = min_align(i); if (i > amax) amax = i; if (s > smax) smax = s; printf("\n"); printf("#define ALIGN_LONG %d\t/* %s(%s *)\t\t*/\n", i, al, lo); printf("#define ALIGN_LMASK %d\t/* %s(%s *)\t\t*/\n", i-1, ms, lo); printf("#define SIZE_LONG %d\t/* %s(%s)\t\t\t*/\n", s, so, lo); #ifdef HAVE_LONGLONG s = sizeof (Llong); i = ALIGN_longlong; i = min_align(i); if (i > amax) amax = i; if (s > smax) smax = s; #endif printf("\n"); printf("#define ALIGN_LLONG %d\t/* %s(%s *)\t*/\n", i, al, ll); printf("#define ALIGN_LLMASK %d\t/* %s(%s *)\t*/\n", i-1, ms, ll); printf("#define SIZE_LLONG %d\t/* %s(%s)\t\t\t*/\n", s, so, ll); s = sizeof (float); i = ALIGN_float; i = min_align(i); if (i > amax) amax = i; if (s > smax) smax = s; printf("\n"); printf("#define ALIGN_FLOAT %d\t/* %s(%s *)\t*/\n", i, al, fl); printf("#define ALIGN_FMASK %d\t/* %s(%s *)\t*/\n", i-1, ms, fl); printf("#define SIZE_FLOAT %d\t/* %s(%s)\t\t\t*/\n", s, so, fl); s = sizeof (double); i = ALIGN_double; i = min_align(i); if (i > amax) amax = i; if (s > smax) smax = s; printf("\n"); printf("#define ALIGN_DOUBLE %d\t/* %s(%s *)\t*/\n", i, al, db); printf("#define ALIGN_DMASK %d\t/* %s(%s *)\t*/\n", i-1, ms, db); printf("#define SIZE_DOUBLE %d\t/* %s(%s)\t\t\t*/\n", s, so, db); #ifdef HAVE_LONGDOUBLE s = sizeof (long double); i = ALIGN_ldouble; i = min_align(i); if (i > amax) amax = i; if (s > smax) smax = s; #endif printf("\n"); printf("#define ALIGN_LDOUBLE %d\t/* %s(%s *)\t*/\n", i, al, ld); printf("#define ALIGN_LDMASK %d\t/* %s(%s *)\t*/\n", i-1, ms, ld); printf("#define SIZE_LDOUBLE %d\t/* %s(%s)\t\t\t*/\n", s, so, ld); s = sizeof (char *); i = ALIGN_ptr; i = min_align(i); if (i > amax) amax = i; if (s > smax) smax = s; printf("\n"); printf("#define ALIGN_PTR %d\t/* %s(%s *)\t*/\n", i, al, pt); printf("#define ALIGN_PMASK %d\t/* %s(%s *)\t*/\n", i-1, ms, pt); printf("#define SIZE_PTR %d\t/* %s(%s)\t\t\t*/\n", s, so, pt); printf("\n"); printf("#define ALIGN_TMAX %d\t/* %s(%s *)\t*/\n", amax, al, mt); printf("#define ALIGN_TMMASK %d\t/* %s(%s *)\t*/\n", amax-1, ms, mt); printf("#define SIZE_TMAX %d\t/* %s(%s)\t\t\t*/\n", smax, so, mt); printmacs(); printf("\n#endif /* __ALIGN_H */\n"); fflush(stdout); return (0); } LOCAL void printmacs() { printf("\n\n"); printf("/*\n * There used to be a cast to an int but we get a warning from GCC.\n"); printf(" * This warning message from GCC is wrong.\n"); printf(" * Believe me that this macro would even be usable if I would cast to short.\n"); printf(" * In order to avoid this warning, we are now using UIntptr_t\n */\n"); /*printf("\n");*/ /*printf("\n");*/ printf("#define xaligned(a, s) ((((UIntptr_t)(a)) & (s)) == 0)\n"); printf("#define x2aligned(a, b, s) (((((UIntptr_t)(a)) | ((UIntptr_t)(b))) & (s)) == 0)\n"); printf("\n"); printf("#define saligned(a) xaligned(a, ALIGN_SMASK)\n"); printf("#define s2aligned(a, b) x2aligned(a, b, ALIGN_SMASK)\n"); printf("\n"); printf("#define ialigned(a) xaligned(a, ALIGN_IMASK)\n"); printf("#define i2aligned(a, b) x2aligned(a, b, ALIGN_IMASK)\n"); printf("\n"); printf("#define laligned(a) xaligned(a, ALIGN_LMASK)\n"); printf("#define l2aligned(a, b) x2aligned(a, b, ALIGN_LMASK)\n"); printf("\n"); printf("#define llaligned(a) xaligned(a, ALIGN_LLMASK)\n"); printf("#define ll2aligned(a, b) x2aligned(a, b, ALIGN_LLMASK)\n"); printf("\n"); printf("#define faligned(a) xaligned(a, ALIGN_FMASK)\n"); printf("#define f2aligned(a, b) x2aligned(a, b, ALIGN_FMASK)\n"); printf("\n"); printf("#define daligned(a) xaligned(a, ALIGN_DMASK)\n"); printf("#define d2aligned(a, b) x2aligned(a, b, ALIGN_DMASK)\n"); printf("\n"); printf("#define ldaligned(a) xaligned(a, ALIGN_LDMASK)\n"); printf("#define ld2aligned(a, b) x2aligned(a, b, ALIGN_LDMASK)\n"); printf("\n"); printf("#define paligned(a) xaligned(a, ALIGN_PMASK)\n"); printf("#define p2aligned(a, b) x2aligned(a, b, ALIGN_PMASK)\n"); printf("\n"); printf("#define maligned(a) xaligned(a, ALIGN_TMMASK)\n"); printf("#define m2aligned(a, b) x2aligned(a, b, ALIGN_TMMASK)\n"); printf("\n\n"); printf("/*\n * There used to be a cast to an int but we get a warning from GCC.\n"); printf(" * This warning message from GCC is wrong.\n"); printf(" * Believe me that this macro would even be usable if I would cast to short.\n"); printf(" * In order to avoid this warning, we are now using UIntptr_t\n */\n"); printf("#define xalign(x, a, m) (((char *)(x)) + ((a) - 1 - ((((UIntptr_t)(x))-1)&(m))))\n"); printf("\n"); printf("#define salign(x) xalign((x), ALIGN_SHORT, ALIGN_SMASK)\n"); printf("#define ialign(x) xalign((x), ALIGN_INT, ALIGN_IMASK)\n"); printf("#define lalign(x) xalign((x), ALIGN_LONG, ALIGN_LMASK)\n"); printf("#define llalign(x) xalign((x), ALIGN_LLONG, ALIGN_LLMASK)\n"); printf("#define falign(x) xalign((x), ALIGN_FLOAT, ALIGN_FMASK)\n"); printf("#define dalign(x) xalign((x), ALIGN_DOUBLE, ALIGN_DMASK)\n"); printf("#define ldalign(x) xalign((x), ALIGN_LDOUBLE, ALIGN_LDMASK)\n"); printf("#define palign(x) xalign((x), ALIGN_PTR, ALIGN_PMASK)\n"); printf("#define malign(x) xalign((x), ALIGN_TMAX, ALIGN_TMMASK)\n"); } #ifdef CHECK_ALIGN /* * Routines to compute the alignement by checking if the assignement * causes a bus error. * Some systems (e.g. Linux on DEC Aplha) will allow to fetch any * type from any address. On these systems we must check the speed * because unaligned fetches will take more time. */ LOCAL int check_align(cfunc, sfunc, tsize) int (*cfunc)(); void (*sfunc)(); int tsize; { int calign; int align; int tcheck; int t; register int i; register char *p = buf_aligned; for (i = 1; i < 128; i++) { if (!setjmp(jb)) { (cfunc)(p, i); break; } } #ifdef DEBUG fprintf(stderr, "i: %d tsize: %d\n", i, tsize); #endif if (i == tsize) return (i); align = calign = i; tcheck = speed_check(p, sfunc, i); #ifdef DEBUG fprintf(stderr, "tcheck: %d\n", tcheck); #endif for (i = calign*2; i <= tsize; i *= 2) { t = speed_check(p, sfunc, i); #ifdef DEBUG fprintf(stderr, "tcheck: %d t: %d i: %d\n", tcheck, t, i); fprintf(stderr, "tcheck - t: %d ... * 3: %d\n", (tcheck - t), (tcheck - t) * 3); #endif if (((tcheck - t) > 0) && ((tcheck - t) * 3) > tcheck) { #ifdef DEBUG fprintf(stderr, "kleiner\n"); #endif align = i; tcheck = t; } } return (align); } LOCAL int check_short(p, i) char *p; int i; { short *sp; sp = (short *)&p[i]; *sp = 1; return (0); } LOCAL int check_int(p, i) char *p; int i; { int *ip; ip = (int *)&p[i]; *ip = 1; return (0); } LOCAL int check_long(p, i) char *p; int i; { long *lp; lp = (long *)&p[i]; *lp = 1; return (0); } #ifdef HAVE_LONGLONG LOCAL int check_longlong(p, i) char *p; int i; { Llong *llp; llp = (Llong *)&p[i]; *llp = 1; return (0); } #endif LOCAL int check_float(p, i) char *p; int i; { float *fp; fp = (float *)&p[i]; *fp = 1.0; return (0); } LOCAL int check_double(p, i) char *p; int i; { double *dp; dp = (double *)&p[i]; *dp = 1.0; return (0); } #ifdef HAVE_LONGDOUBLE LOCAL int check_ldouble(p, i) char *p; int i; { long double *dp; dp = (long double *)&p[i]; *dp = 1.0; return (0); } #endif LOCAL int check_ptr(p, i) char *p; int i; { char **pp; pp = (char **)&p[i]; *pp = (char *)1; return (0); } /* * Routines to compute the alignement by checking the speed of the * assignement. * Some systems (e.g. Linux on DEC Aplha) will allow to fetch any * type from any address. On these systems we must check the speed * because unaligned fetches will take more time. */ LOCAL void speed_short(p, n) char *p; int n; { short *sp; int i; sp = (short *)&p[n]; for (i = 1000000; --i >= 0; ) *sp = i; } LOCAL void speed_int(p, n) char *p; int n; { int *ip; int i; ip = (int *)&p[n]; for (i = 1000000; --i >= 0; ) *ip = i; } LOCAL void speed_long(p, n) char *p; int n; { long *lp; int i; lp = (long *)&p[n]; for (i = 1000000; --i >= 0; ) *lp = i; } #ifdef HAVE_LONGLONG LOCAL void speed_longlong(p, n) char *p; int n; { Llong *llp; int i; llp = (Llong *)&p[n]; for (i = 1000000; --i >= 0; ) *llp = i; } #endif LOCAL void speed_float(p, n) char *p; int n; { float *fp; int i; fp = (float *)&p[n]; for (i = 1000000; --i >= 0; ) *fp = i; } LOCAL void speed_double(p, n) char *p; int n; { double *dp; int i; dp = (double *)&p[n]; for (i = 1000000; --i >= 0; ) *dp = i; } #ifdef HAVE_LONGDOUBLE LOCAL void speed_ldouble(p, n) char *p; int n; { long double *dp; int i; dp = (long double *)&p[n]; for (i = 1000000; --i >= 0; ) *dp = i; } #endif LOCAL void speed_ptr(p, n) char *p; int n; { char **pp; int i; pp = (char **)&p[n]; for (i = 1000000; --i >= 0; ) *pp = (char *)i; } #include #include LOCAL int speed_check(p, sfunc, n) char *p; void (*sfunc)(); int n; { struct tms tm1; struct tms tm2; times(&tm1); (*sfunc)(p, n); times(&tm2); #ifdef DEBUG fprintf(stderr, "t1: %ld\n", (long)tm2.tms_utime-tm1.tms_utime); #endif return ((int)tm2.tms_utime-tm1.tms_utime); } #endif /* CHECK_ALIGN */ #ifdef OFF_ALIGN /* * Routines to compute the alignement by using the knowledge * of the C-compiler. * We define a structure and check the padding that has been inserted * by the compiler to keep the apropriate type on a properly aligned * address. */ LOCAL int used_var; LOCAL void used(i) int i; { used_var = i; } LOCAL int off_short() { struct ss { char c; short s; } ss; ss.c = 0; /* fool C-compiler */ used(ss.c); return (sm_off(struct ss *, s)); } LOCAL int off_int() { struct si { char c; int i; } si; si.c = 0; /* fool C-compiler */ used(si.c); return (sm_off(struct si *, i)); } LOCAL int off_long() { struct sl { char c; long l; } sl; sl.c = 0; /* fool C-compiler */ used(sl.c); return (sm_off(struct sl *, l)); } #ifdef HAVE_LONGLONG LOCAL int off_longlong() { struct sll { char c; Llong ll; } sll; sll.c = 0; /* fool C-compiler */ used(sll.c); return (sm_off(struct sll *, ll)); } #endif LOCAL int off_float() { struct sf { char c; float f; } sf; sf.c = 0; /* fool C-compiler */ used(sf.c); return (sm_off(struct sf *, f)); } LOCAL int off_double() { struct sd { char c; double d; } sd; sd.c = 0; /* fool C-compiler */ used(sd.c); return (sm_off(struct sd *, d)); } #ifdef HAVE_LONGDOUBLE LOCAL int off_ldouble() { struct sd { char c; long double ld; } sd; sd.c = 0; /* fool C-compiler */ used(sd.c); return (sm_off(struct sd *, ld)); } #endif LOCAL int off_ptr() { struct sp { char c; char *p; } sp; sp.c = 0; /* fool C-compiler */ used(sp.c); return (sm_off(struct sp *, p)); } #endif /* OFF_ALIGN */