#ifndef FW_H
#define FW_H

#include <stdarg.h>
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include "picorv32.h"
#include "irq.h"

/* Use builtin memcpy and memset optimizations */
#define memset(s,c,n)	__builtin_memset(s,c,n)
#define memcpy(d,s,n)	__builtin_memcpy(d,s,n)
#define memmove(d,s,n)	__builtin_memmove(d,s,n)
extern void *
__memcpy_aligned(void * __restrict, const void * __restrict, size_t);

#define likely(x)	__builtin_expect(!!(x), 1)
#define unlikely(x)	__builtin_expect(!!(x), 0)

/* Handy composite pointer types */
typedef union xptr {
    uint32_t *l;
    uint16_t *w;
    uint8_t  *b;
    void     *v;
    size_t    a;
} xptr_t;
typedef union xcptr {
    const uint32_t *l;
    const uint16_t *w;
    const uint8_t  *b;
    const void     *v;
    size_t          a;
} xcptr_t;

/* The container_of construct: if p is a pointer to member m of
   container class c, then return a pointer to the container of which
   *p is a member. */
#ifndef container_of
# define container_of(p, c, m) ((c *)((char *)(p) - offsetof(c,m)))
#endif

#define offset_diff(c, m1, m2) ((ptrdiff_t)offsetof(c,m2) - (ptrdiff_t)offsetof(c,m1))

#define min(a,b) (((a) < (b)) ? (a) : (b))
#define max(a,b) (((a) > (b)) ? (a) : (b))

#define ARRAY_SIZE (sizeof(a)/sizeof(a[0]))

#define no_return void __attribute__((noreturn))

#define __dram_text	__attribute__((section(".dram.text")))
#define __dram_rodata	__attribute__((section(".dram.rodata")))
#define __dram_data	__attribute__((section(".dram.data")))
#define __dram_bss	__attribute__((section(".dram.bss")))
#define __dram_noinit	__attribute__((section(".dram.noinit")))

extern const size_t __rom_offset;

extern no_return _die(void);
extern no_return exit(int);
extern no_return _exit(int);

extern const uint8_t _end[];
extern void *_sbrk(size_t);

extern uint32_t timer_irq_start;
static inline uint32_t timer_count(void)
{
    extern volatile uint32_t timer_irq_count;
    return timer_irq_count;
}
extern void init(void);

extern void mount_abcdrives(void);

extern void read_rtc(void);
extern void write_rtc(void);
extern bool do_write_rtc;
extern void rtc_abc_init(void);
extern void rtc_abc_io_poll(void);
extern void disk_cache_init(void);

extern uint32_t romcopy_time[2];

extern void run_test_image(void);

#endif /* FW_H */
