1/* @title: Assembly Routines */
2#pragma once
3#include <stdbool.h>
4#include <stdint.h>
5
6//
7//
8//
9//
10//
11// =========| IN - BYTE, WORD, LONG, SB, SW, SL |=========
12//
13//
14//
15//
16//
17
18static inline uint8_t inb(uint16_t port) {
19 uint8_t ret;
20 asm volatile("inb %1, %0" : "=a"(ret) : "Nd"(port));
21 return ret;
22}
23
24static inline uint16_t inw(uint16_t port) {
25 uint16_t ret;
26 asm volatile("inw %1, %0" : "=a"(ret) : "Nd"(port));
27 return ret;
28}
29
30static inline uint32_t inl(uint16_t port) {
31 uint32_t ret;
32 asm volatile("inl %1, %0" : "=a"(ret) : "Nd"(port));
33 return ret;
34}
35
36static inline void insb(uint16_t port, void *addr, uint32_t count) {
37 asm volatile("rep insb" : "+D"(addr), "+c"(count) : "d"(port) : "memory");
38}
39
40static inline void insw(uint16_t port, void *addr, uint32_t count) {
41 asm volatile("rep insw" : "+D"(addr), "+c"(count) : "d"(port) : "memory");
42}
43
44static inline void insl(uint16_t port, void *addr, uint32_t count) {
45 asm volatile("rep insl" : "+D"(addr), "+c"(count) : "d"(port) : "memory");
46}
47
48//
49//
50//
51//
52//
53// ========| OUT - BYTE, WORD, LONG, SB, SW, SL |========
54//
55//
56//
57//
58//
59
60static inline void outb(uint16_t port, uint8_t value) {
61 asm volatile("outb %0, %1" : : "a"(value), "Nd"(port));
62}
63
64static inline void outw(uint16_t port, uint16_t value) {
65 asm volatile("outw %1, %0" ::"dN"(port), "a"(value));
66}
67
68static inline void outl(uint16_t port, uint32_t value) {
69 asm volatile("outl %0, %1" : : "a"(value), "Nd"(port));
70}
71
72static inline void outsw(uint16_t port, const void *addr, uint32_t count) {
73 asm volatile("rep outsw" : "+S"(addr), "+c"(count) : "d"(port) : "memory");
74}
75
76static inline void outsb(uint16_t port, const void *addr, uint32_t count) {
77 asm volatile("rep outsb" : "+S"(addr), "+c"(count) : "d"(port) : "memory");
78}
79
80static inline void outsl(uint16_t port, const void *addr, uint32_t count) {
81 asm volatile("rep outsl" : "+S"(addr), "+c"(count) : "d"(port) : "memory");
82}
83
84//
85//
86//
87//
88//
89// =============================| MISC |==============================
90//
91//
92//
93//
94//
95
96static inline void write_cr8(uint64_t cr8) {
97 asm volatile("mov %0, %%cr8" ::"r"(cr8));
98}
99
100static inline uint64_t rdtsc(void) {
101 uint32_t lo, hi;
102 asm volatile("rdtsc" : "=a"(lo), "=d"(hi));
103 return ((uint64_t) hi << 32) | lo;
104}
105
106static inline void cpuid_count(uint32_t leaf, uint32_t subleaf, uint32_t *eax,
107 uint32_t *ebx, uint32_t *ecx, uint32_t *edx) {
108 asm volatile("cpuid"
109 : "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx)
110 : "a"(leaf), "c"(subleaf));
111}
112
113static inline uint64_t read_cr4() {
114 uint64_t cr4;
115 asm volatile("mov %%cr4, %0" : "=r"(cr4));
116 return cr4;
117}
118
119static inline void write_cr4(uint64_t cr4) {
120 asm volatile("mov %0, %%cr4" : : "r"(cr4));
121}
122
123static inline uint32_t get_core_id(void) {
124 uint32_t eax, ebx, ecx, edx;
125
126 eax = 1;
127 asm volatile("cpuid"
128 : "=b"(ebx), "=a"(eax), "=c"(ecx), "=d"(edx)
129 : "a"(eax));
130
131 return (ebx >> 24) & 0xFF;
132}
133
134static inline bool are_interrupts_enabled() {
135 unsigned long flags;
136 asm volatile("pushf\n\t"
137 "pop %0\n\t"
138 : "=r"(flags)
139 :
140 :);
141 return (flags & (1 << 9)) != 0;
142}
143
144#define MSR_GS_BASE 0xC0000101
145
146static inline void wrmsr(uint32_t msr, uint64_t value) {
147 uint32_t lo = value & 0xFFFFFFFF;
148 uint32_t hi = value >> 32;
149 asm volatile("wrmsr" ::"c"(msr), "a"(lo), "d"(hi) : "memory");
150}
151
152static inline uint64_t rdmsr(uint32_t msr) {
153 uint64_t lo, hi;
154 asm volatile("rdmsr" : "=a"(lo), "=d"(hi) : "c"(msr));
155 return (hi << 32U) | lo;
156}
157
158static inline void io_wait(void) {
159 outb(port: 0x80, value: 0);
160}
161
162static inline void clear_interrupts(void) {
163 asm volatile("cli");
164}
165
166static inline void restore_interrupts(void) {
167 asm volatile("sti");
168}
169
170static inline void enable_interrupts(void) {
171 asm volatile("sti");
172}
173
174static inline void disable_interrupts(void) {
175 asm volatile("cli");
176}
177
178static inline void invlpg(uint64_t virt) {
179 asm volatile("invlpg (%0)" : : "r"(virt) : "memory");
180}
181
182static inline uint64_t read_cr3() {
183 uint64_t cr3;
184 asm volatile("mov %%cr3, %0" : "=r"(cr3));
185 return cr3;
186}
187
188static inline void write_cr3(uint64_t cr3) {
189 asm volatile("mov %0, %%cr3" ::"r"(cr3));
190}
191
192static inline void tlb_flush() {
193 uint64_t cr3 = read_cr3();
194 write_cr3(cr3);
195}
196
197static inline void cpu_relax(void) {
198 asm volatile("pause");
199}
200
201static inline void wait_for_interrupt(void) {
202 asm volatile("hlt");
203}
204
205static inline void hcf(void) {
206 asm volatile("cli; hlt");
207}
208
209static inline int clz(uint8_t a) {
210 return __builtin_clz(a);
211}
212
213static inline void memory_barrier() {
214 asm volatile("mfence" ::: "memory");
215}
216