#ifndef IRQ_H
#define IRQ_H

#include <stddef.h>

#include "picorv32.h"

typedef void (*irqhandler_t)(unsigned int vector, size_t pc);
extern irqhandler_t __irq_handler_table[];

#define IRQHANDLER(x) \
  void irqhandler_ ##x (unsigned int, size_t);			     \
  void irqhandler_ ##x (unsigned int vector __attribute__((unused)), \
			size_t pc __attribute__((unused)))

typedef unsigned int irqmask_t;

static inline irqmask_t disable_irqs(void)
{
    return p_maskirq(~0U, 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);
}

#endif /* IRQ_H */
