1use x86_64::registers::segmentation::{GS, Segment64};
6
7pub(crate) fn get_base() -> u64 {
9 GS::read_base().as_u64()
10}
11
12use crate::cpu::local::single_instr::{
13 SingleInstructionAddAssign, SingleInstructionBitAndAssign, SingleInstructionBitOrAssign,
14 SingleInstructionBitXorAssign, SingleInstructionLoad, SingleInstructionStore,
15 SingleInstructionSubAssign,
16};
17
18macro_rules! impl_numeric_single_instruction_for {
19 ($([$typ: ty, $inout_type: ident, $register_format: expr])*) => {$(
20
21 impl SingleInstructionAddAssign<$typ> for $typ {
22 unsafe fn add_assign(offset: *mut Self, val: Self) {
23 unsafe {
32 core::arch::asm!(
33 concat!("add gs:[{0}], {1", $register_format, "}"),
34 in(reg) offset,
35 in($inout_type) val,
36 options(nostack),
37 );
38 }
39 }
40 }
41
42 impl SingleInstructionSubAssign<$typ> for $typ {
43 unsafe fn sub_assign(offset: *mut Self, val: Self) {
44 unsafe {
46 core::arch::asm!(
47 concat!("sub gs:[{0}], {1", $register_format, "}"),
48 in(reg) offset,
49 in($inout_type) val,
50 options(nostack),
51 );
52 }
53 }
54 }
55
56 impl SingleInstructionBitAndAssign<$typ> for $typ {
57 unsafe fn bitand_assign(offset: *mut Self, val: Self) {
58 unsafe {
60 core::arch::asm!(
61 concat!("and gs:[{0}], {1", $register_format, "}"),
62 in(reg) offset,
63 in($inout_type) val,
64 options(nostack),
65 );
66 }
67 }
68 }
69
70 impl SingleInstructionBitOrAssign<$typ> for $typ {
71 unsafe fn bitor_assign(offset: *mut Self, val: Self) {
72 unsafe {
74 core::arch::asm!(
75 concat!("or gs:[{0}], {1", $register_format, "}"),
76 in(reg) offset,
77 in($inout_type) val,
78 options(nostack),
79 );
80 }
81 }
82 }
83
84 impl SingleInstructionBitXorAssign<$typ> for $typ {
85 unsafe fn bitxor_assign(offset: *mut Self, val: Self) {
86 unsafe {
88 core::arch::asm!(
89 concat!("xor gs:[{0}], {1", $register_format, "}"),
90 in(reg) offset,
91 in($inout_type) val,
92 options(nostack),
93 );
94 }
95 }
96 }
97
98 impl SingleInstructionLoad for $typ {
99 unsafe fn load(offset: *const Self) -> Self {
100 let val: Self;
101 unsafe {
103 core::arch::asm!(
104 concat!("mov {0", $register_format, "}, gs:[{1}]"),
105 out($inout_type) val,
106 in(reg) offset,
107 options(nostack, readonly),
108 );
109 }
110 val
111 }
112 }
113
114 impl SingleInstructionStore for $typ {
115 unsafe fn store(offset: *mut Self, val: Self) {
116 unsafe {
118 core::arch::asm!(
119 concat!("mov gs:[{0}], {1", $register_format, "}"),
120 in(reg) offset,
121 in($inout_type) val,
122 options(nostack),
123 );
124 }
125 }
126 }
127
128 )*};
129}
130
131impl_numeric_single_instruction_for!(
132 [u64, reg, ":r"]
133 [usize, reg, ":r"]
134 [u32, reg, ":e"]
135 [u16, reg, ":x"]
136 [u8, reg_byte, ""]
137 [i64, reg, ":r"]
138 [isize, reg, ":r"]
139 [i32, reg, ":e"]
140 [i16, reg, ":x"]
141 [i8, reg_byte, ""]
142);
143
144macro_rules! impl_generic_single_instruction_for {
145 ($([<$gen_type:ident $(, $more_gen_type:ident)*>, $typ:ty])*) => {$(
146
147 impl<$gen_type $(, $more_gen_type)*> SingleInstructionLoad for $typ {
148 unsafe fn load(offset: *const Self) -> Self {
149 let val: Self;
150 unsafe {
152 core::arch::asm!(
153 concat!("mov {0}, gs:[{1}]"),
154 out(reg) val,
155 in(reg) offset,
156 options(nostack, readonly),
157 );
158 }
159 val
160 }
161 }
162
163 impl<$gen_type $(, $more_gen_type)*> SingleInstructionStore for $typ {
164 unsafe fn store(offset: *mut Self, val: Self) {
165 unsafe {
167 core::arch::asm!(
168 concat!("mov gs:[{0}], {1}"),
169 in(reg) offset,
170 in(reg) val,
171 options(nostack),
172 );
173 }
174 }
175 }
176 )*}
177}
178
179impl_generic_single_instruction_for!(
180 [<T>, *const T]
181 [<T>, *mut T]
182 [<T, R>, fn(T) -> R]
183);
184
185impl SingleInstructionLoad for bool {
190 unsafe fn load(offset: *const Self) -> Self {
191 let val: u8;
192 unsafe {
194 core::arch::asm!(
195 "mov {0}, gs:[{1}]",
196 out(reg_byte) val,
197 in(reg) offset,
198 options(nostack, readonly),
199 );
200 }
201 debug_assert!(val == 1 || val == 0);
202 val == 1
203 }
204}
205
206impl SingleInstructionStore for bool {
207 unsafe fn store(offset: *mut Self, val: Self) {
208 let val: u8 = if val { 1 } else { 0 };
209 unsafe {
211 core::arch::asm!(
212 "mov gs:[{0}], {1}",
213 in(reg) offset,
214 in(reg_byte) val,
215 options(nostack),
216 );
217 }
218 }
219}