aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2023-06-18 22:26:53 +0200
committerlemon <lsof@mailbox.org>2023-06-18 22:26:53 +0200
commit4f979636327bb1acb371d3094554da6cc4672973 (patch)
treef1bdf1546eb83991339c1c8eeaf77cbbeb16ff21
parentb246b0f1f617d34560402c734630369145c2dee1 (diff)
add endian.h for endian dependent stuff
-rw-r--r--amd64/all.h20
-rw-r--r--amd64/emit.c1
-rw-r--r--amd64/isel.c1
-rw-r--r--common.h13
-rw-r--r--endian.h133
-rw-r--r--ir.c35
-rw-r--r--obj.c2
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)
diff --git a/common.h b/common.h
index 05d6ddd..f6dc5e3 100644
--- a/common.h
+++ b/common.h
@@ -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: */
diff --git a/ir.c b/ir.c
index 08966a3..216ed6e 100644
--- a/ir.c
+++ b/ir.c
@@ -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);
}
}
diff --git a/obj.c b/obj.c
index f2b0623..127dedd 100644
--- a/obj.c
+++ b/obj.c
@@ -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));