#ifndef _TT_POKE_H_
#define _TT_POKE_H_

/****************************************************************************************************************/

#include <tt/types.h>

/****************************************************************************************************************/

// Access a value in big endian byte order from an unaligned address
static __inline void poke32be(void *x, uint32 val) {
  uint8 *dst = (uint8 *)x;
  dst[3] = val;
  dst[2] = val >> 8;
  dst[1] = val >> 16;
  dst[0] = val >> 24;
}

static __inline uint32 peek32be(const void *x) {
  const uint8 *src = (const uint8 *)x;
  return (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3];
}

static __inline void poke16be(void *x, uint16 val) {
  uint8 *dst = (uint8 *)x;
  dst[1] = val;
  dst[0] = val >> 8;
}

static __inline uint16 peek16be(const void *x) { return (((const uint8 *)x)[0] << 8) | ((const uint8 *)x)[1]; }
static __inline int16 peeks16be(const void *x) { return (((const  int8 *)x)[0] << 8) | ((const uint8 *)x)[1]; }

// Access a value in little endian byte order from an unaligned address
static __inline void poke32le(void *x, uint32 val) {
  uint8 *dst = (uint8 *)x;
  dst[0] = val;
  dst[1] = val >> 8;
  dst[2] = val >> 16;
  dst[3] = val >> 24;
}

static __inline uint32 peek32le(const void *x) {
  const uint8 *src = (const uint8 *)x;
  return (src[3] << 24) | (src[2] << 16) | (src[1] << 8) | src[0];
}

static __inline void poke16le(void *x, uint16 val) {
  uint8 *dst = (uint8 *)x;
  dst[0] = val;
  dst[1] = val >> 8;
}

static __inline uint16 peek16le(const void *x) { return (((const uint8 *)x)[1] << 8) | ((const uint8 *)x)[0]; }
static __inline int16 peeks16le(const void *x) { return (((const  int8 *)x)[1] << 8) | ((const uint8 *)x)[0]; }

// Access a value in host byte order from an unaligned address
#define peek32 peek32le
#define peek16 peek16le

#define poke32 poke32le
#define poke16 poke16le

/****************************************************************************************************************/

// Copy unaligned values around
static __inline void copy16(void *dst, const void *src) {
  uint8 *d = (uint8 *)dst;
  const uint8 *s = (const uint8 *)src;
  d[0] = s[0];
  d[1] = s[1];
}

static __inline void copy32(void *dst, const void *src) {
  uint8 *d = (uint8 *)dst;
  const uint8 *s = (const uint8 *)src;
  d[0] = s[0];
  d[1] = s[1];
  d[2] = s[2];
  d[3] = s[3];
}

static __inline void copy48(void *dst, const void *src) {
  uint8 *d = (uint8 *)dst;
  const uint8 *s = (const uint8 *)src;
  d[0] = s[0];
  d[1] = s[1];
  d[2] = s[2];
  d[3] = s[3];
  d[4] = s[4];
  d[4] = s[4];
}

/****************************************************************************************************************/
#endif
