#ifndef IRQ_H
#define IRQ_H

#include "compiler.h"
#include "picorv32.h"
#include "iodevs.h"		/* For _IRQ constants */

typedef void (*irqhandler_t)(unsigned int);
extern irqhandler_t __irq_handler_table[];

#define IRQHANDLER_DECL(x,n)						\
    void irqhandler_##x##_##n (unsigned int vector __unused)

#define IRQHANDLER(x,n)				\
    IRQHANDLER_DECL(x,n);			\
    __hot __text_hot IRQHANDLER_DECL(x,n)

IRQHANDLER_DECL(spurious,0);

typedef unsigned int irqmask_t;

/* Disable IRQs except fatal system errors (to facilitate debugging) */
static inline irqmask_t disable_irqs(void)
{
    return p_maskirq(~((1 << EBREAK_IRQ)|(1 << BUSERR_IRQ)), 0);
}
static inline irqmask_t restore_irqs(irqmask_t mask)
{
    return p_maskirq(mask, 0);
}
static inline irqmask_t restore_irq(irqmask_t mask, unsigned int vector)
{
    const irqmask_t bit = 1U << vector;
    return p_maskirq(mask & bit, ~bit);
}
static inline irqmask_t mask_irqs(irqmask_t mask)
{
    return p_maskirq(mask, ~mask);
}
static inline irqmask_t mask_irq(unsigned int vector)
{
    return mask_irqs(1U << vector);
}
static inline irqmask_t unmask_irqs(irqmask_t mask)
{
    return p_maskirq(0, ~mask);
}
static inline irqmask_t unmask_irq(unsigned int vector)
{
    return unmask_irqs(1U << vector);
}
static inline irqmask_t irqmask(void)
{
    return p_maskirq(0, ~0);
}

static inline irqmask_t waitfor(unsigned int vector)
{
    const irqmask_t mask = 1U << vector;
    return p_waitirq(mask, 0);
}

/* Wait for any enabled IRQ */
static inline irqmask_t wait_for_irq(void)
{
    const irqmask_t mask = irqmask();
    return p_waitirq(mask, mask);
}

size_t rdxreg(unsigned int reg);
void wrxreg(unsigned int reg, size_t val);

#define IRQ_PC_REGISTER			"s10"
#define IRQ_VECTOR_MASK_REGISTER	"s11"

#endif /* IRQ_H */
