aboutsummaryrefslogtreecommitdiff
path: root/mirai/asm/interrupts/stubs.zig
blob: f56965231f70ba9d5d3573d06088716f5d7dbf48 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
//! Interrupt Handler Stub Assembly

const std = @import("std");

pub const push_zero = "push $0\n";

pub fn push_vector(comptime vector: u8) []const u8 {
    return comptime std.fmt.comptimePrint("push ${d}\n", .{vector});
}

pub const push_all =
    \\push %%rax
    \\push %%rbx
    \\push %%rcx
    \\push %%rdx
    \\push %%rsi
    \\push %%rdi
    \\push %%rbp
    \\push %%r8
    \\push %%r9
    \\push %%r10
    \\push %%r11
    \\push %%r12
    \\push %%r13
    \\push %%r14
    \\push %%r15
;

pub const pop_all =
    \\pop %%r15
    \\pop %%r14
    \\pop %%r13
    \\pop %%r12
    \\pop %%r11
    \\pop %%r10
    \\pop %%r9
    \\pop %%r8
    \\pop %%rbp
    \\pop %%rdi
    \\pop %%rsi
    \\pop %%rdx
    \\pop %%rcx
    \\pop %%rbx
    \\pop %%rax
;

pub const iret_cleanup =
    \\add $16, %%rsp
    \\iretq
;

pub const call_exception_dispatch =
    \\mov %%rsp, %%rdi
    \\call exception_dispatch
;

pub const call_irq_dispatch =
    \\mov %%rsp, %%rdi
    \\call irq_dispatch
;

pub fn exception_stub(comptime vector: u8, comptime has_error_code: bool) []const u8 {
    return (if (!has_error_code) push_zero else "") ++
        push_vector(vector) ++
        push_all ++
        call_exception_dispatch ++
        pop_all ++
        iret_cleanup;
}

pub fn irq_stub(comptime irq: u8) []const u8 {
    return push_zero ++
        push_vector(irq + 32) ++
        push_all ++
        call_irq_dispatch ++
        pop_all ++
        iret_cleanup;
}

pub fn make_exception_handler(comptime vector: u8, comptime has_error_code: bool) fn () callconv(.Naked) void {
    return struct {
        fn handler() callconv(.Naked) void {
            asm volatile (exception_stub(vector, has_error_code));
        }
    }.handler;
}

pub fn make_irq_handler(comptime irq: u8) fn () callconv(.Naked) void {
    return struct {
        fn handler() callconv(.Naked) void {
            asm volatile (irq_stub(irq));
        }
    }.handler;
}