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 uint64_t rdtsc_ordered(void) {
107 uint32_t lo, hi;
108 asm volatile("lfence\n\t"
109 "rdtsc"
110 : "=a"(lo), "=d"(hi));
111 return ((uint64_t) hi << 32) | lo;
112}
113
114static inline void cpuid_count(uint32_t leaf, uint32_t subleaf, uint32_t *eax,
115 uint32_t *ebx, uint32_t *ecx, uint32_t *edx) {
116 asm volatile("cpuid"
117 : "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx)
118 : "a"(leaf), "c"(subleaf));
119}
120
121static inline uint64_t read_cr0() {
122 uint64_t cr0;
123 asm volatile("mov %%cr0, %0" : "=r"(cr0));
124 return cr0;
125}
126
127static inline void write_cr0(uint64_t cr0) {
128 asm volatile("mov %0, %%cr0" : : "r"(cr0) : "memory");
129}
130
131static inline uint64_t read_cr4() {
132 uint64_t cr4;
133 asm volatile("mov %%cr4, %0" : "=r"(cr4));
134 return cr4;
135}
136
137static inline void write_cr4(uint64_t cr4) {
138 asm volatile("mov %0, %%cr4" : : "r"(cr4));
139}
140
141static inline uint32_t get_core_id(void) {
142 uint32_t eax, ebx, ecx, edx;
143
144 eax = 1;
145 asm volatile("cpuid"
146 : "=b"(ebx), "=a"(eax), "=c"(ecx), "=d"(edx)
147 : "a"(eax));
148
149 return (ebx >> 24) & 0xFF;
150}
151
152static inline bool are_interrupts_enabled() {
153 unsigned long flags;
154 asm volatile("pushf\n\t"
155 "pop %0\n\t"
156 : "=r"(flags)
157 :
158 :);
159 return (flags & (1 << 9)) != 0;
160}
161
162#define MSR_GS_BASE 0xC0000101
163
164static inline void wrmsr(uint32_t msr, uint64_t value) {
165 uint32_t lo = value & 0xFFFFFFFF;
166 uint32_t hi = value >> 32;
167 asm volatile("wrmsr" ::"c"(msr), "a"(lo), "d"(hi) : "memory");
168}
169
170static inline uint64_t rdmsr(uint32_t msr) {
171 uint64_t lo, hi;
172 asm volatile("rdmsr" : "=a"(lo), "=d"(hi) : "c"(msr));
173 return (hi << 32U) | lo;
174}
175
176static inline void io_wait(void) {
177 outb(port: 0x80, value: 0);
178}
179
180static inline void clear_interrupts(void) {
181 asm volatile("cli");
182}
183
184static inline void restore_interrupts(void) {
185 asm volatile("sti");
186}
187
188static inline void enable_interrupts(void) {
189 asm volatile("sti");
190}
191
192static inline void disable_interrupts(void) {
193 asm volatile("cli");
194}
195
196static inline void invlpg(uint64_t virt) {
197 asm volatile("invlpg (%0)" : : "r"(virt) : "memory");
198}
199
200static inline uint64_t read_cr2() {
201 uint64_t cr2;
202 asm volatile("mov %%cr2, %0" : "=r"(cr2));
203 return cr2;
204}
205
206static inline uint64_t read_cr3() {
207 uint64_t cr3;
208 asm volatile("mov %%cr3, %0" : "=r"(cr3));
209 return cr3;
210}
211
212static inline void write_cr3(uint64_t cr3) {
213 asm volatile("mov %0, %%cr3" ::"r"(cr3));
214}
215
216static inline void tlb_flush() {
217 uint64_t cr3 = read_cr3();
218 write_cr3(cr3);
219}
220
221static inline void cpu_relax(void) {
222 asm volatile("pause");
223}
224
225static inline void wait_for_interrupt(void) {
226 asm volatile("hlt");
227}
228
229static inline void hcf(void) {
230 asm volatile("cli; hlt");
231}
232
233static inline void do_idle_insn() {
234 asm volatile("sti\n\thlt" ::: "memory");
235}
236
237static inline int clz(uint8_t a) {
238 return __builtin_clz(a);
239}
240
241static inline void memory_barrier() {
242 asm volatile("mfence" ::: "memory");
243}
244