#pragma once

#include "types.h"

struct __attribute__((packed)) interrupt_frame {
    uword_t ip;
    uword_t cs;
    uword_t flags;
    uword_t sp;
    uword_t ss;
};

/*
 * Exceptions
 * ==========*/
__attribute__((interrupt, noreturn))
void exception_handler_div_by_zero(struct interrupt_frame* frame);

__attribute__((interrupt, noreturn))
void exception_handler_general_protection_fault(struct interrupt_frame* frame, int err);

__attribute__((interrupt, noreturn))
void exception_handler_double_fault(struct interrupt_frame* frame);

__attribute__((interrupt, noreturn))
void exception_default(struct interrupt_frame* frame);

/**
 * Interrupts
 * ==========
 */
__attribute__((interrupt, noreturn))
void interrupt_default(struct interrupt_frame* frame);

__attribute__((interrupt))
void interrupt_handler_1(struct interrupt_frame* frame);

/**
 * IRQs
 * ====
 */
__attribute__((interrupt)) void irq_handler_0(struct interrupt_frame*);
__attribute__((interrupt)) void irq_handler_1(struct interrupt_frame*);
__attribute__((interrupt)) void irq_handler_2(struct interrupt_frame*);
__attribute__((interrupt)) void irq_handler_3(struct interrupt_frame*);
__attribute__((interrupt)) void irq_handler_4(struct interrupt_frame*);
__attribute__((interrupt)) void irq_handler_5(struct interrupt_frame*);
__attribute__((interrupt)) void irq_handler_6(struct interrupt_frame*);
__attribute__((interrupt)) void irq_handler_7(struct interrupt_frame*);
__attribute__((interrupt)) void irq_handler_8(struct interrupt_frame*);
__attribute__((interrupt)) void irq_handler_9(struct interrupt_frame*);
__attribute__((interrupt)) void irq_handler_10(struct interrupt_frame*);
__attribute__((interrupt)) void irq_handler_11(struct interrupt_frame*);
__attribute__((interrupt)) void irq_handler_12(struct interrupt_frame*);
__attribute__((interrupt)) void irq_handler_13(struct interrupt_frame*);
__attribute__((interrupt)) void irq_handler_14(struct interrupt_frame*);
__attribute__((interrupt)) void irq_handler_15(struct interrupt_frame*);


/*
 * Exception and interrupt stubs
 * =============================
 * Everything below this line is a horrible compile time crime.
 * */


#include "idt.h"
#include "kernel_state.h"

/* This function is a horrible crime */
static void idt_init_stubs(struct idt_gate_descriptor idt[]) {
	#define EXCEPTION_STUB(n) exception_stub_##n

	#define DESC(func) \
		idt_encode_descriptor( \
				func, \
				segment(SEGMENT_KERNEL_CODE, SEGMENT_GDT, 0), \
				IDT_DPL_3, \
				IDT_GATE_TYPE_TRAP32)

	#define DECLARE_EXCEPTION_STUB(n) \
		__attribute__((interrupt)) void EXCEPTION_STUB(n)(struct interrupt_frame*); \
		idt[n] = DESC(EXCEPTION_STUB(n))
	DECLARE_EXCEPTION_STUB(0);
	DECLARE_EXCEPTION_STUB(1);
	DECLARE_EXCEPTION_STUB(2);
	DECLARE_EXCEPTION_STUB(3);
	DECLARE_EXCEPTION_STUB(4);
	DECLARE_EXCEPTION_STUB(5);
	DECLARE_EXCEPTION_STUB(6);
	DECLARE_EXCEPTION_STUB(7);
	DECLARE_EXCEPTION_STUB(8);
	DECLARE_EXCEPTION_STUB(9);
	DECLARE_EXCEPTION_STUB(10);
	DECLARE_EXCEPTION_STUB(11);
	DECLARE_EXCEPTION_STUB(12);
	DECLARE_EXCEPTION_STUB(13);
	DECLARE_EXCEPTION_STUB(14);
	DECLARE_EXCEPTION_STUB(15);
	DECLARE_EXCEPTION_STUB(16);
	DECLARE_EXCEPTION_STUB(17);
	DECLARE_EXCEPTION_STUB(18);
	DECLARE_EXCEPTION_STUB(19);
	DECLARE_EXCEPTION_STUB(20);
	DECLARE_EXCEPTION_STUB(21);
	DECLARE_EXCEPTION_STUB(22);
	DECLARE_EXCEPTION_STUB(23);
	DECLARE_EXCEPTION_STUB(24);
	DECLARE_EXCEPTION_STUB(25);
	DECLARE_EXCEPTION_STUB(26);
	DECLARE_EXCEPTION_STUB(27);
	DECLARE_EXCEPTION_STUB(28);
	DECLARE_EXCEPTION_STUB(29);
	DECLARE_EXCEPTION_STUB(30);
	DECLARE_EXCEPTION_STUB(31);
	DECLARE_EXCEPTION_STUB(32);
	DECLARE_EXCEPTION_STUB(33);
	DECLARE_EXCEPTION_STUB(34);
	DECLARE_EXCEPTION_STUB(35);
	DECLARE_EXCEPTION_STUB(36);
	DECLARE_EXCEPTION_STUB(37);
	DECLARE_EXCEPTION_STUB(38);
	DECLARE_EXCEPTION_STUB(39);
	DECLARE_EXCEPTION_STUB(40);
	DECLARE_EXCEPTION_STUB(41);
	DECLARE_EXCEPTION_STUB(42);
	DECLARE_EXCEPTION_STUB(43);
	DECLARE_EXCEPTION_STUB(44);
	DECLARE_EXCEPTION_STUB(45);
	DECLARE_EXCEPTION_STUB(46);
	DECLARE_EXCEPTION_STUB(47);
	DECLARE_EXCEPTION_STUB(48);
	DECLARE_EXCEPTION_STUB(49);
	DECLARE_EXCEPTION_STUB(50);
	DECLARE_EXCEPTION_STUB(51);
	DECLARE_EXCEPTION_STUB(52);
	DECLARE_EXCEPTION_STUB(53);
	DECLARE_EXCEPTION_STUB(54);
	DECLARE_EXCEPTION_STUB(55);
	DECLARE_EXCEPTION_STUB(56);
	DECLARE_EXCEPTION_STUB(57);
	DECLARE_EXCEPTION_STUB(58);
	DECLARE_EXCEPTION_STUB(59);
	DECLARE_EXCEPTION_STUB(60);
	DECLARE_EXCEPTION_STUB(61);
	DECLARE_EXCEPTION_STUB(62);
	DECLARE_EXCEPTION_STUB(63);
	DECLARE_EXCEPTION_STUB(64);
	DECLARE_EXCEPTION_STUB(65);
	DECLARE_EXCEPTION_STUB(66);
	DECLARE_EXCEPTION_STUB(67);
	DECLARE_EXCEPTION_STUB(68);
	DECLARE_EXCEPTION_STUB(69);
	DECLARE_EXCEPTION_STUB(70);
	DECLARE_EXCEPTION_STUB(71);
	DECLARE_EXCEPTION_STUB(72);
	DECLARE_EXCEPTION_STUB(73);
	DECLARE_EXCEPTION_STUB(74);
	DECLARE_EXCEPTION_STUB(75);
	DECLARE_EXCEPTION_STUB(76);
	DECLARE_EXCEPTION_STUB(77);
	DECLARE_EXCEPTION_STUB(78);
	DECLARE_EXCEPTION_STUB(79);
	DECLARE_EXCEPTION_STUB(80);
	DECLARE_EXCEPTION_STUB(81);
	DECLARE_EXCEPTION_STUB(82);
	DECLARE_EXCEPTION_STUB(83);
	DECLARE_EXCEPTION_STUB(84);
	DECLARE_EXCEPTION_STUB(85);
	DECLARE_EXCEPTION_STUB(86);
	DECLARE_EXCEPTION_STUB(87);
	DECLARE_EXCEPTION_STUB(88);
	DECLARE_EXCEPTION_STUB(89);
	DECLARE_EXCEPTION_STUB(90);
	DECLARE_EXCEPTION_STUB(91);
	DECLARE_EXCEPTION_STUB(92);
	DECLARE_EXCEPTION_STUB(93);
	DECLARE_EXCEPTION_STUB(94);
	DECLARE_EXCEPTION_STUB(95);
	DECLARE_EXCEPTION_STUB(96);
	DECLARE_EXCEPTION_STUB(97);
	DECLARE_EXCEPTION_STUB(98);
	DECLARE_EXCEPTION_STUB(99);
	DECLARE_EXCEPTION_STUB(100);
	DECLARE_EXCEPTION_STUB(101);
	DECLARE_EXCEPTION_STUB(102);
	DECLARE_EXCEPTION_STUB(103);
	DECLARE_EXCEPTION_STUB(104);
	DECLARE_EXCEPTION_STUB(105);
	DECLARE_EXCEPTION_STUB(106);
	DECLARE_EXCEPTION_STUB(107);
	DECLARE_EXCEPTION_STUB(108);
	DECLARE_EXCEPTION_STUB(109);
	DECLARE_EXCEPTION_STUB(110);
	DECLARE_EXCEPTION_STUB(111);
	DECLARE_EXCEPTION_STUB(112);
	DECLARE_EXCEPTION_STUB(113);
	DECLARE_EXCEPTION_STUB(114);
	DECLARE_EXCEPTION_STUB(115);
	DECLARE_EXCEPTION_STUB(116);
	DECLARE_EXCEPTION_STUB(117);
	DECLARE_EXCEPTION_STUB(118);
	DECLARE_EXCEPTION_STUB(119);
	DECLARE_EXCEPTION_STUB(120);
	DECLARE_EXCEPTION_STUB(121);
	DECLARE_EXCEPTION_STUB(122);
	DECLARE_EXCEPTION_STUB(123);
	DECLARE_EXCEPTION_STUB(124);
	DECLARE_EXCEPTION_STUB(125);
	DECLARE_EXCEPTION_STUB(126);
	DECLARE_EXCEPTION_STUB(127);
	DECLARE_EXCEPTION_STUB(128);
	DECLARE_EXCEPTION_STUB(129);
	DECLARE_EXCEPTION_STUB(130);
	DECLARE_EXCEPTION_STUB(131);
	DECLARE_EXCEPTION_STUB(132);
	DECLARE_EXCEPTION_STUB(133);
	DECLARE_EXCEPTION_STUB(134);
	DECLARE_EXCEPTION_STUB(135);
	DECLARE_EXCEPTION_STUB(136);
	DECLARE_EXCEPTION_STUB(137);
	DECLARE_EXCEPTION_STUB(138);
	DECLARE_EXCEPTION_STUB(139);
	DECLARE_EXCEPTION_STUB(140);
	DECLARE_EXCEPTION_STUB(141);
	DECLARE_EXCEPTION_STUB(142);
	DECLARE_EXCEPTION_STUB(143);
	DECLARE_EXCEPTION_STUB(144);
	DECLARE_EXCEPTION_STUB(145);
	DECLARE_EXCEPTION_STUB(146);
	DECLARE_EXCEPTION_STUB(147);
	DECLARE_EXCEPTION_STUB(148);
	DECLARE_EXCEPTION_STUB(149);
	DECLARE_EXCEPTION_STUB(150);
	DECLARE_EXCEPTION_STUB(151);
	DECLARE_EXCEPTION_STUB(152);
	DECLARE_EXCEPTION_STUB(153);
	DECLARE_EXCEPTION_STUB(154);
	DECLARE_EXCEPTION_STUB(155);
	DECLARE_EXCEPTION_STUB(156);
	DECLARE_EXCEPTION_STUB(157);
	DECLARE_EXCEPTION_STUB(158);
	DECLARE_EXCEPTION_STUB(159);
	DECLARE_EXCEPTION_STUB(160);
	DECLARE_EXCEPTION_STUB(161);
	DECLARE_EXCEPTION_STUB(162);
	DECLARE_EXCEPTION_STUB(163);
	DECLARE_EXCEPTION_STUB(164);
	DECLARE_EXCEPTION_STUB(165);
	DECLARE_EXCEPTION_STUB(166);
	DECLARE_EXCEPTION_STUB(167);
	DECLARE_EXCEPTION_STUB(168);
	DECLARE_EXCEPTION_STUB(169);
	DECLARE_EXCEPTION_STUB(170);
	DECLARE_EXCEPTION_STUB(171);
	DECLARE_EXCEPTION_STUB(172);
	DECLARE_EXCEPTION_STUB(173);
	DECLARE_EXCEPTION_STUB(174);
	DECLARE_EXCEPTION_STUB(175);
	DECLARE_EXCEPTION_STUB(176);
	DECLARE_EXCEPTION_STUB(177);
	DECLARE_EXCEPTION_STUB(178);
	DECLARE_EXCEPTION_STUB(179);
	DECLARE_EXCEPTION_STUB(180);
	DECLARE_EXCEPTION_STUB(181);
	DECLARE_EXCEPTION_STUB(182);
	DECLARE_EXCEPTION_STUB(183);
	DECLARE_EXCEPTION_STUB(184);
	DECLARE_EXCEPTION_STUB(185);
	DECLARE_EXCEPTION_STUB(186);
	DECLARE_EXCEPTION_STUB(187);
	DECLARE_EXCEPTION_STUB(188);
	DECLARE_EXCEPTION_STUB(189);
	DECLARE_EXCEPTION_STUB(190);
	DECLARE_EXCEPTION_STUB(191);
	DECLARE_EXCEPTION_STUB(192);
	DECLARE_EXCEPTION_STUB(193);
	DECLARE_EXCEPTION_STUB(194);
	DECLARE_EXCEPTION_STUB(195);
	DECLARE_EXCEPTION_STUB(196);
	DECLARE_EXCEPTION_STUB(197);
	DECLARE_EXCEPTION_STUB(198);
	DECLARE_EXCEPTION_STUB(199);
	DECLARE_EXCEPTION_STUB(200);
	DECLARE_EXCEPTION_STUB(201);
	DECLARE_EXCEPTION_STUB(202);
	DECLARE_EXCEPTION_STUB(203);
	DECLARE_EXCEPTION_STUB(204);
	DECLARE_EXCEPTION_STUB(205);
	DECLARE_EXCEPTION_STUB(206);
	DECLARE_EXCEPTION_STUB(207);
	DECLARE_EXCEPTION_STUB(208);
	DECLARE_EXCEPTION_STUB(209);
	DECLARE_EXCEPTION_STUB(210);
	DECLARE_EXCEPTION_STUB(211);
	DECLARE_EXCEPTION_STUB(212);
	DECLARE_EXCEPTION_STUB(213);
	DECLARE_EXCEPTION_STUB(214);
	DECLARE_EXCEPTION_STUB(215);
	DECLARE_EXCEPTION_STUB(216);
	DECLARE_EXCEPTION_STUB(217);
	DECLARE_EXCEPTION_STUB(218);
	DECLARE_EXCEPTION_STUB(219);
	DECLARE_EXCEPTION_STUB(220);
	DECLARE_EXCEPTION_STUB(221);
	DECLARE_EXCEPTION_STUB(222);
	DECLARE_EXCEPTION_STUB(223);
	DECLARE_EXCEPTION_STUB(224);
	DECLARE_EXCEPTION_STUB(225);
	DECLARE_EXCEPTION_STUB(226);
	DECLARE_EXCEPTION_STUB(227);
	DECLARE_EXCEPTION_STUB(228);
	DECLARE_EXCEPTION_STUB(229);
	DECLARE_EXCEPTION_STUB(230);
	DECLARE_EXCEPTION_STUB(231);
	DECLARE_EXCEPTION_STUB(232);
	DECLARE_EXCEPTION_STUB(233);
	DECLARE_EXCEPTION_STUB(234);
	DECLARE_EXCEPTION_STUB(235);
	DECLARE_EXCEPTION_STUB(236);
	DECLARE_EXCEPTION_STUB(237);
	DECLARE_EXCEPTION_STUB(238);
	DECLARE_EXCEPTION_STUB(239);
	DECLARE_EXCEPTION_STUB(240);
	DECLARE_EXCEPTION_STUB(241);
	DECLARE_EXCEPTION_STUB(242);
	DECLARE_EXCEPTION_STUB(243);
	DECLARE_EXCEPTION_STUB(244);
	DECLARE_EXCEPTION_STUB(245);
	DECLARE_EXCEPTION_STUB(246);
	DECLARE_EXCEPTION_STUB(247);
	DECLARE_EXCEPTION_STUB(248);
	DECLARE_EXCEPTION_STUB(249);
	DECLARE_EXCEPTION_STUB(250);
	DECLARE_EXCEPTION_STUB(251);
	DECLARE_EXCEPTION_STUB(252);
	DECLARE_EXCEPTION_STUB(253);
	DECLARE_EXCEPTION_STUB(254);
	DECLARE_EXCEPTION_STUB(255);
	#undef DESC
	#undef DECLARE_EXCEPTION_STUB
}
