# Copyright (c) 2021 Dennis Wölfing
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

cat << EOF
/* This file was autogenerated from $0. */
#include <dennix/kernel/kernel.h>

extern "C" {
struct idt_entry {
    uint16_t offset_low;
    uint16_t selector;
    uint8_t ist;
    uint8_t flags;
    uint16_t offset_mid;
#ifdef __x86_64__
    uint32_t offset_high;
    uint32_t reserved;
#endif
};

#ifdef __i386__
#define IDT_ENTRY(offset, selector, flags) { \\
    (uint16_t)((uintptr_t)(offset) & 0xFFFF), \\
    (selector), \\
    0, \\
    (flags), \\
    (uint16_t)(((uintptr_t)(offset) >> 16) & 0xFFFF) \\
}
#elif defined(__x86_64__)
#define IDT_ENTRY(offset, selector, flags) { \\
    (uint16_t)((uintptr_t)(offset) & 0xFFFF), \\
    (selector), \\
    0, \\
    (flags), \\
    (uint16_t)(((uintptr_t)(offset) >> 16) & 0xFFFF), \\
    (uint32_t)(((uintptr_t)(offset) >> 32) & 0xFFFFFFFF), \\
    0 \\
}
#endif

#define IDT_INTERRUPT_GATE 0xE
#define IDT_TRAP_GATE 0xF
#define IDT_RING0 (0 << 5)
#define IDT_RING3 (3 << 5)
#define IDT_PRESENT (1 << 7)

extern void syscallHandler();
EOF

for i in $(seq 0 255); do
    echo "extern void isr_$i();"
done

cat << EOF
idt_entry idt[] = {
EOF

# CPU exceptions
for i in $(seq 0 20); do
    echo "IDT_ENTRY(isr_$i, 0x8, IDT_INTERRUPT_GATE | IDT_RING0 | IDT_PRESENT),"
done

# Reserved
for i in $(seq 21 31); do
    echo "IDT_ENTRY(0, 0, 0),"
done

# IRQ0 - IRQ15
for i in $(seq 32 47); do
    echo "IDT_ENTRY(isr_$i, 0x8, IDT_INTERRUPT_GATE | IDT_RING0 | IDT_PRESENT),"
done

# Software interrupts
cat << EOF
IDT_ENTRY(syscallHandler, 0x8, IDT_TRAP_GATE | IDT_RING3 | IDT_PRESENT),
IDT_ENTRY(isr_49, 0x8, IDT_INTERRUPT_GATE | IDT_RING3 | IDT_PRESENT),
IDT_ENTRY(isr_50, 0x8, IDT_INTERRUPT_GATE | IDT_RING3 | IDT_PRESENT),
EOF

# IRQ16 - IRQ219, Spurious Interrupt
for i in $(seq 51 255); do
    echo "IDT_ENTRY(isr_$i, 0x8, IDT_INTERRUPT_GATE | IDT_RING0 | IDT_PRESENT),"
done

cat << EOF
};

uint16_t idt_size = sizeof(idt) - 1;
} /* extern "C" */
EOF
