diff options
| -rw-r--r-- | amd64/all.h | 20 | ||||
| -rw-r--r-- | amd64/emit.c | 1 | ||||
| -rw-r--r-- | amd64/isel.c | 1 | ||||
| -rw-r--r-- | common.h | 13 | ||||
| -rw-r--r-- | endian.h | 133 | ||||
| -rw-r--r-- | ir.c | 35 | ||||
| -rw-r--r-- | obj.c | 2 |
7 files changed, 150 insertions, 55 deletions
diff --git a/amd64/all.h b/amd64/all.h index a038ffd..42f4d23 100644 --- a/amd64/all.h +++ b/amd64/all.h @@ -12,26 +12,6 @@ enum reg { #undef R }; -static inline void -wr16le(uchar *p, ushort x) -{ - p[0] = x >> 0; p[1] = x >> 8; -} - -static inline void -wr32le(uchar *p, uint x) -{ - p[0] = x >> 0; p[1] = x >> 8; - p[2] = x >> 16; p[3] = x >> 24; -} - -static inline void -wr64le(uchar *p, uvlong x) -{ - wr32le(p+0, x>>00); - wr32le(p+4, x>>32); -} - void amd64_isel(struct function *); void amd64_emit(struct function *); diff --git a/amd64/emit.c b/amd64/emit.c index ec04de7..a02cba2 100644 --- a/amd64/emit.c +++ b/amd64/emit.c @@ -1,5 +1,6 @@ #include "all.h" #include "../obj.h" +#include "../endian.h" /** Instruction operands ** * diff --git a/amd64/isel.c b/amd64/isel.c index 4c0656a..942e962 100644 --- a/amd64/isel.c +++ b/amd64/isel.c @@ -1,4 +1,5 @@ #include "all.h" +#include "../endian.h" static void fixarg(struct function *fn, union ref *r, struct instr *ins, struct block *blk, int *curi) @@ -17,6 +17,13 @@ typedef unsigned long long uvlong; typedef signed long long vlong; typedef unsigned uint; + +#ifdef __has_builtin +#define HAS_BUILTIN(b) __has_builtin(__builtin_##b) +#else +#define HAS_BUILTIN(_) 0 +#endif +#define static_assert(x) _Static_assert(x, #x) #define in_range(x, Lo, Hi) ((uint) (x) - (Lo) <= (Hi) - (Lo)) /* lo <= x <= hi; lo > 0, hi > 0 */ #define alignup(x, A) (((x) + ((A) - 1)) & -(A)) #define arraylength(a) (sizeof(a) / sizeof 0[a]) @@ -32,7 +39,7 @@ struct span { }; void _assertfmt(const char *file, int line, const char *func, const char *expr); -#ifdef __GNUC__ +#if HAS_BUILTIN(trap) #define assert(x) (!(x) ? _assertfmt(__FILE__,__LINE__,__func__,#x), __builtin_trap() : (void)0) #else #define assert(x) (void)(!(x) ? _assertfmt(__FILE__,__LINE__,__func__,#x), *(volatile int *)0 : 0) @@ -58,7 +65,7 @@ ptrhash(const void *p) { } static inline uint popcnt(uvlong x) { -#if defined __has_builtin && __has_builtin(__builtin_popcountll) +#if HAS_BUILTIN(popcountll) return __builtin_popcountll(x); #else uint n = 0; @@ -72,7 +79,7 @@ ispo2(uvlong x) { } static inline uint ilog2(uint x) { /* assumes x is a power of 2 */ -#if defined __has_builtin && __has_builtin(__builtin_ctz) +#if HAS_BUILTIN(ctz) return __builtin_ctz(x); #else uint n = 0; diff --git a/endian.h b/endian.h new file mode 100644 index 0000000..8448c79 --- /dev/null +++ b/endian.h @@ -0,0 +1,133 @@ +#ifndef ENDIAN_H_ +#define ENDIAN_H_ + +#include "common.h" + +/*** Macros and functions for endian specific memory access ***/ + +/** byte-swapping functions **/ + +#if HAS_BUILTIN(bswap16) +#define bswap16 __builtin_bswap16 +#else +static inline ushort +bswap16(ushort x) { + return x >> 8 | x << 8; +} +#endif + +#if HAS_BUILTIN(bswap32) +#define bswap32 __builtin_bswap32 +#else +static inline uint +bswap32(uint x) { + return x >> 24 & 0x000000FF | x >> 8 & 0x0000FF00 + | x << 8 & 0x00FF0000 | x << 24 & 0xFF000000; +} +#endif + +#if HAS_BUILTIN(bswap64) +#define bswap64 __builtin_bswap64 +#else +static inline uvlong +bswap64(uvlong x) { + return (uvlong) bswap32(x) << 32 | bswap32(x >> 32); +} +#endif + +#if (defined __BYTE_ORDER__ && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) || \ + defined __hppa__ || defined __m68k__ || defined mc68000 || defined _M_M68K || \ + (defined __MIPS__ && defined __MIPSEB__) || \ + defined __ppc__ || defined __POWERPC__ || defined __powerpc__ || defined __PPC__ || \ + defined __sparc__ +#define HOST_BIG_ENDIAN +#define hostntarg_sameendian() (targ_bigendian) +#else +#define HOST_LIL_ENDIAN +#define hostntarg_sameendian() (!targ_bigendian) +#endif + +/** little-endian memory writes **/ + +static inline void +wr16le(uchar *p, ushort x) +{ +#ifndef HOST_LIL_ENDIAN + x = bswap16(x); +#endif + memcpy(p, &x, sizeof x); +} + +static inline void +wr32le(uchar *p, uint x) +{ +#ifndef HOST_LIL_ENDIAN + x = bswap32(x); +#endif + memcpy(p, &x, sizeof x); +} + +static inline void +wr64le(uchar *p, uvlong x) +{ +#ifndef HOST_LIL_ENDIAN + x = bswap64(x); +#endif + memcpy(p, &x, sizeof x); +} + +/** big-endian memory writes **/ + +static inline void +wr16be(uchar *p, ushort x) +{ +#ifndef HOST_BIG_ENDIAN + x = bswap16(x); +#endif + memcpy(p, &x, sizeof x); +} + +static inline void +wr32be(uchar *p, uint x) +{ +#ifndef HOST_BIG_ENDIAN + x = bswap32(x); +#endif + memcpy(p, &x, sizeof x); +} + +static inline void +wr64be(uchar *p, uvlong x) +{ +#ifndef HOST_BIG_ENDIAN + x = bswap64(x); +#endif + memcpy(p, &x, sizeof x); +} + +/** target-endian memory writes **/ + +static inline void +wr16targ(uchar *p, ushort x) +{ + if (!hostntarg_sameendian()) x = bswap16(x); + memcpy(p, &x, sizeof x); +} + +static inline void +wr32targ(uchar *p, uint x) +{ + if (!hostntarg_sameendian()) x = bswap32(x); + memcpy(p, &x, sizeof x); +} + +static inline void +wr64targ(uchar *p, uvlong x) +{ + if (!hostntarg_sameendian()) x = bswap64(x); + memcpy(p, &x, sizeof x); +} + +#endif /* ENDIAN_H_ */ + +/* vim:set ts=3 sw=3 expandtab: */ @@ -1,5 +1,5 @@ #include "ir.h" -#include "common.h" +#include "endian.h" uchar type2cls[NTYPETAG]; uchar cls2siz[KF8+1]; @@ -87,33 +87,6 @@ addcon(const struct xcon *con) } } -static void -targwrite2(uchar *d, ushort x) -{ - if (targ_bigendian) - d[0] = x >> 8, d[1] = x; - else - d[0] = x, d[1] = x >> 8; -} - -static void -targwrite4(uchar *d, uint x) -{ - if (targ_bigendian) - d[0] = x >> 24, d[1] = x >> 16, d[2] = x >> 8, d[3] = x; - else - d[0] = x, d[1] = x >> 8, d[2] = x >> 16, d[3] = x >> 24; -} - -static void -targwrite8(uchar *d, uvlong x) -{ - if (targ_bigendian) - targwrite4(d, x >> 32), targwrite4(d + 4, x); - else - targwrite4(d, x), targwrite4(d + 4, x >> 32); -} - void conputdat(struct irdat *dat, uint off, enum typetag t, const void *src) { @@ -137,9 +110,9 @@ conputdat(struct irdat *dat, uint off, enum typetag t, const void *src) switch (siz) { case 1: pdat[off] = *(uchar *)src; break; - case 2: targwrite2(&pdat[off], *(ushort *)src); break; - case 4: targwrite4(&pdat[off], *(uint *)src); break; - case 8: targwrite8(&pdat[off], *(uvlong *)src); break; + case 2: wr16targ(&pdat[off], *(ushort *)src); break; + case 4: wr32targ(&pdat[off], *(uint *)src); break; + case 8: wr64targ(&pdat[off], *(uvlong *)src); break; default: assert(0); } } @@ -51,7 +51,7 @@ objreloc(const char *sym, enum relockind reloc, enum section section, uint off, void objfini(void) { - static char buf[1<<10]; + static char buf[1<<12]; struct wbuf out = FDBUF(buf, sizeof buf, open(objout.file, O_WRONLY | O_CREAT | O_TRUNC, 0666)); if (out.fd < 0) fatal(NULL, "could not open %'s for writing: %s", objout.file, strerror(errno)); |