include/assembly.h (view raw)
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 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
/*! \file
* Wrapper for low-level assembler instructions.
*/
#ifndef ASSEMBLY_H
#define ASSEMBLY_H
#include <stdint.h>
/*!
* Sends a single byte to the specified port.
* \param msg The byte to be sent.
* \param port The destination port.
*/
__attribute((always_inline)) inline void outb(uint8_t msg, uint16_t port) {
__asm__ volatile ("outb %0, %1" : : "a" (msg), "Nd" (port));
}
/*!
* Retrieves a single byte from the specified port.
* \param port The source port.
* \return The recieved byte.
*/
__attribute((always_inline)) inline uint8_t inb(uint16_t port) {
uint8_t msg;
__asm__ volatile ("inb %1, %0" : "=a" (msg) : "Nd" (port));
return msg;
}
/*!
* nop
*/
__attribute__((always_inline)) inline void nop(void) {
__asm__ volatile ("nop");
}
/*!
* Deactivates all interrupts.
*/
__attribute__((always_inline)) inline void cli(void) {
__asm__ volatile ("cli");
}
/*!
* Reactivates all interrupts.
*/
__attribute__((always_inline)) inline void sti(void) {
__asm__ volatile ("sti");
}
/*!
* Pushes the contents of the EFLAGS register onto the stack.
*/
__attribute__((always_inline)) inline void pushf(void) {
__asm__ volatile ("pushf");
}
/*!
* Pops the contents of the EFLAGS register from the top of the stack.
*/
__attribute__((always_inline)) inline void popf(void) {
__asm__ volatile ("popf");
}
/*!
* Pushes the contents of the general purpose registers onto the stack.
*/
__attribute__((always_inline)) inline void pusha(void) {
__asm__ volatile ("pusha" : : : "eax", "ebx", "ecx", "edx", "esi", "edi");
}
/*!
* Pops the contents of the general purpose registers off the top of the stack.
*/
__attribute__((always_inline)) inline void popa(void) {
__asm__ volatile ("popa" : : : "eax", "ebx", "ecx", "edx", "esi", "edi");
}
/*!
* CPUID
*/
__attribute__((always_inline)) inline void cpuid(uint32_t eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx) {
__asm__ volatile ( "mov %3, %%eax;"
"cpuid;"
"mov %%ebx, %0;"
"mov %%ecx, %1;"
"mov %%edx, %2"
: "=m" (*ebx), "=m" (*ecx), "=m" (*edx)
: "Nd" (eax));
}
/*!
* Used to find out the current value of the flags register.
* \return Value of the EFLAGS-register.
*/
__attribute((always_inline)) inline uint32_t eflags() {
uint32_t eflags;
__asm__ volatile ("pushf; pop %%eax; mov %%eax, %0" : "=m" (eflags) : : "eax");
return eflags;
}
/*!
* Waits for the next interrupt.
*/
__attribute__((always_inline)) inline void hlt(void) {
__asm__ volatile ("hlt");
}
/*!
* Disables interrupts and returns the current EFLAGS-value.
* \return Current value of the EFLAGS-register.
*/
__attribute__((always_inline)) inline uint32_t disable_interrupts(void) {
uint32_t eflags;
__asm__ volatile ("pushf; cli; pop %%eax; mov %%eax, %0" : "=m" (eflags) : : "eax");
return eflags;
}
/*!
* Restores a prior state of the EFLAGS-register. Used in tandem with \m disable_interrupts.
* \param eflags Prior state of the EFLAGS-register.
*/
__attribute__((always_inline)) inline void restore_interrupts(uint32_t eflags) {
__asm__ volatile ("mov %0, %%eax; push %%eax; popf" : : "m" (eflags) : "eax");
}
/*!
* Causes an interrupt
*/
#define INT(n) __asm__ volatile ("int $" #n)
#endif