-
-
Notifications
You must be signed in to change notification settings - Fork 23
/
x86real.h
156 lines (128 loc) · 4.06 KB
/
x86real.h
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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
// ReC98
// -----
// Declarations for 16-bit x86 Real Mode features: I/O ports, CPU registers,
// interrupts, certain instructions, and segmented memory. Ports to other
// architectures would remove this file and rewrite any code that then causes
// compile errors.
#ifndef X86REAL_H
#define X86REAL_H
#include "platform.h"
// Turbo C++ 4.0J's <conio.h> tries to redefine them otherwise.
#define _PORT_DEFS
// This file is a subset of Turbo C++ 4.0's <dos.h>, for the most part.
#if !(defined(__TURBOC__) && defined(__MSDOS__) && defined(__DOS_H))
/// Opcodes
/// -------
void __emit__(uint8_t __byte, ...);
void __int__(int16_t __interruptnum);
#define disable() __emit__((uint8_t)(0xfa)) /* MSC name */
#define enable() __emit__((uint8_t)(0xfb)) /* MSC name */
#define geninterrupt(i) __int__(i) /* Interrupt instruction */
/// -------
/// I/O ports
/// ---------
uint8_t __inportb__(uint16_t __portid);
uint16_t __inportw__(uint16_t __portid);
uint8_t __outportb__(uint16_t __portid, uint8_t __value);
uint16_t __outportw__(uint16_t __portid, uint16_t __value);
#define inport(__portid) __inportw__(__portid)
#define inportb(__portid) __inportb__(__portid)
#define outport(__portid, __value) ((void) __outportw__(__portid, __value))
#define outportb(__portid, __value) ((void) __outportb__(__portid, __value))
/// ---------
/// Registers
/// ---------
struct WORDREGS {
uint16_t ax;
uint16_t bx;
uint16_t cx;
uint16_t dx;
uint16_t si;
uint16_t di;
uint16_t cflag;
uint16_t flags;
};
struct BYTEREGS {
uint8_t al;
uint8_t ah;
uint8_t bl;
uint8_t bh;
uint8_t cl;
uint8_t ch;
uint8_t dl;
uint8_t dh;
};
union REGS {
struct WORDREGS w;
struct BYTEREGS h;
};
struct SREGS {
uint16_t es;
uint16_t cs;
uint16_t ss;
uint16_t ds;
};
void segread(struct SREGS *__segp);
/// ---------
/// Interrupts
/// ----------
#ifdef __cplusplus
extern "C" {
void interrupt (__far * __cdecl getvect(int __interruptno))(...);
void __cdecl setvect(
int __interruptno, void interrupt (__far *__isr)(...)
);
int __cdecl int86(
int __intno, union REGS *__inregs, union REGS *__outregs
);
}
#else
void interrupt (__far * __cdecl getvect(int __interruptno))();
void __cdecl setvect(int __interruptno, void interrupt(__far *__isr)());
int __cdecl int86(int __intno, union REGS *__inregs, union REGS *__outregs);
#endif
/// ----------
/// Segmented memory
/// ----------------
#define MK_FP(seg,off) ((void __seg *)(seg) + (void __near *)(off))
#define FP_SEG(fp) ((uint16_t)(void __seg *)(void __far *)(fp))
#define FP_OFF(fp) ((uint16_t)(fp))
#ifdef __cplusplus
int16_t inline peek(uint16_t __segment, uint16_t __offset) {
return (*((int16_t __far *)MK_FP(__segment, __offset)));
}
int8_t inline peekb(uint16_t __segment, uint16_t __offset) {
return (*((int8_t __far *)MK_FP(__segment, __offset)));
}
void inline poke(uint16_t __segment, uint16_t __offset, int16_t __value) {
(*((int16_t __far *)MK_FP(__segment, __offset)) = __value);
}
void inline pokeb(uint16_t __segment, uint16_t __offset, int8_t __value) {
(*((int8_t __far *)MK_FP(__segment, __offset)) = __value);
}
#endif
/// ----------------
#endif
// Optimally inlined variants
// --------------------------
// Also required in C++ code from time to time. The naming scheme is inspired
// by Turbo C++ 4.0J's intrinsics, but using only a single underscore to avoid
// collisions.
#define _peek_(a,b) (*((int16_t __far * )MK_FP((a),(b))))
#define _peekb_(a,b) (*(( int8_t __far * )MK_FP((a),(b))))
#define _poke_(a,b,c) (*((int16_t __far * )MK_FP((a),(b))) = (int16_t)(c))
#define _pokeb_(a,b,c) (*(( int8_t __far * )MK_FP((a),(b))) = ( int8_t)(c))
// Alternate versions for 8-bit port numbers that don't spill the port number
// to DX.
#ifdef __cplusplus
#define _outportb_(port, val) { \
_AL = val; \
__emit__(0xE6, port); /* OUT port, AL */ \
}
inline uint8_t _inportb_(uint8_t port) {
__emit__(0xE4, port); // IN AL, port
return _AL;
}
#endif
// --------------------------
#endif /* X86REAL_H */