| 1 | pub const supported = switch (builtin.cpu.arch) { |
| 2 | .aarch64, .riscv64, .x86_64 => true, |
| 3 | else => false, |
| 4 | }; |
| 5 | |
| 6 | /// Stores the cpu state of an inactive fiber. |
| 7 | pub const Context = switch (builtin.cpu.arch) { |
| 8 | .aarch64 => extern struct { |
| 9 | sp: u64, |
| 10 | fp: u64, |
| 11 | pc: u64, |
| 12 | }, |
| 13 | .riscv64 => extern struct { |
| 14 | sp: u64, |
| 15 | fp: u64, |
| 16 | pc: u64, |
| 17 | }, |
| 18 | .x86_64 => extern struct { |
| 19 | rsp: u64, |
| 20 | rbp: u64, |
| 21 | rip: u64, |
| 22 | }, |
| 23 | else => |arch| @compileError("unimplemented architecture: " ++ @tagName(arch)), |
| 24 | }; |
| 25 | |
| 26 | pub const Switch = extern struct { old: *Context, new: *Context }; |
| 27 | |
| 28 | /// Fills `s.old` with the current cpu state, and restores the cpu state stored in `s.new`. |
| 29 | pub inline fn contextSwitch(s: *const Switch) *const Switch { |
| 30 | return switch (builtin.cpu.arch) { |
| 31 | .aarch64 => asm volatile ( |
| 32 | \\ ldp x0, x2, [x1] |
| 33 | \\ ldr x3, [x2, #16] |
| 34 | \\ mov x4, sp |
| 35 | \\ stp x4, fp, [x0] |
| 36 | \\ adr x5, 0f |
| 37 | \\ ldp x4, fp, [x2] |
| 38 | \\ str x5, [x0, #16] |
| 39 | \\ mov sp, x4 |
| 40 | \\ br x3 |
| 41 | \\0: |
| 42 | : [received_message] "={x1}" (-> *const Switch), |
| 43 | : [message_to_send] "{x1}" (s), |
| 44 | : .{ |
| 45 | .x0 = true, |
| 46 | .x1 = true, |
| 47 | .x2 = true, |
| 48 | .x3 = true, |
| 49 | .x4 = true, |
| 50 | .x5 = true, |
| 51 | .x6 = true, |
| 52 | .x7 = true, |
| 53 | .x8 = true, |
| 54 | .x9 = true, |
| 55 | .x10 = true, |
| 56 | .x11 = true, |
| 57 | .x12 = true, |
| 58 | .x13 = true, |
| 59 | .x14 = true, |
| 60 | .x15 = true, |
| 61 | .x16 = true, |
| 62 | .x17 = true, |
| 63 | .x19 = true, |
| 64 | .x20 = true, |
| 65 | .x21 = true, |
| 66 | .x22 = true, |
| 67 | .x23 = true, |
| 68 | .x24 = true, |
| 69 | .x25 = true, |
| 70 | .x26 = true, |
| 71 | .x27 = true, |
| 72 | .x28 = true, |
| 73 | .x30 = true, |
| 74 | .z0 = true, |
| 75 | .z1 = true, |
| 76 | .z2 = true, |
| 77 | .z3 = true, |
| 78 | .z4 = true, |
| 79 | .z5 = true, |
| 80 | .z6 = true, |
| 81 | .z7 = true, |
| 82 | .z8 = true, |
| 83 | .z9 = true, |
| 84 | .z10 = true, |
| 85 | .z11 = true, |
| 86 | .z12 = true, |
| 87 | .z13 = true, |
| 88 | .z14 = true, |
| 89 | .z15 = true, |
| 90 | .z16 = true, |
| 91 | .z17 = true, |
| 92 | .z18 = true, |
| 93 | .z19 = true, |
| 94 | .z20 = true, |
| 95 | .z21 = true, |
| 96 | .z22 = true, |
| 97 | .z23 = true, |
| 98 | .z24 = true, |
| 99 | .z25 = true, |
| 100 | .z26 = true, |
| 101 | .z27 = true, |
| 102 | .z28 = true, |
| 103 | .z29 = true, |
| 104 | .z30 = true, |
| 105 | .z31 = true, |
| 106 | .p0 = true, |
| 107 | .p1 = true, |
| 108 | .p2 = true, |
| 109 | .p3 = true, |
| 110 | .p4 = true, |
| 111 | .p5 = true, |
| 112 | .p6 = true, |
| 113 | .p7 = true, |
| 114 | .p8 = true, |
| 115 | .p9 = true, |
| 116 | .p10 = true, |
| 117 | .p11 = true, |
| 118 | .p12 = true, |
| 119 | .p13 = true, |
| 120 | .p14 = true, |
| 121 | .p15 = true, |
| 122 | .fpcr = true, |
| 123 | .fpsr = true, |
| 124 | .ffr = true, |
| 125 | .memory = true, |
| 126 | }), |
| 127 | .riscv64 => asm volatile ( |
| 128 | \\ ld a0, 0(a1) |
| 129 | \\ ld a2, 8(a1) |
| 130 | \\ lla a3, 0f |
| 131 | \\ sd sp, 0(a0) |
| 132 | \\ sd fp, 8(a0) |
| 133 | \\ sd a3, 16(a0) |
| 134 | \\ ld sp, 0(a2) |
| 135 | \\ ld fp, 8(a2) |
| 136 | \\ ld a3, 16(a2) |
| 137 | \\ jr a3 |
| 138 | \\0: |
| 139 | : [received_message] "={a1}" (-> *const Switch), |
| 140 | : [message_to_send] "{a1}" (s), |
| 141 | : .{ |
| 142 | .x1 = true, |
| 143 | .x3 = true, |
| 144 | .x4 = true, |
| 145 | .x5 = true, |
| 146 | .x6 = true, |
| 147 | .x7 = true, |
| 148 | .x9 = true, |
| 149 | .x10 = true, |
| 150 | .x11 = true, |
| 151 | .x12 = true, |
| 152 | .x13 = true, |
| 153 | .x14 = true, |
| 154 | .x15 = true, |
| 155 | .x16 = true, |
| 156 | .x17 = true, |
| 157 | .x18 = true, |
| 158 | .x19 = true, |
| 159 | .x20 = true, |
| 160 | .x21 = true, |
| 161 | .x22 = true, |
| 162 | .x23 = true, |
| 163 | .x24 = true, |
| 164 | .x25 = true, |
| 165 | .x26 = true, |
| 166 | .x27 = true, |
| 167 | .x28 = true, |
| 168 | .x29 = true, |
| 169 | .x30 = true, |
| 170 | .x31 = true, |
| 171 | .f0 = true, |
| 172 | .f1 = true, |
| 173 | .f2 = true, |
| 174 | .f3 = true, |
| 175 | .f4 = true, |
| 176 | .f5 = true, |
| 177 | .f6 = true, |
| 178 | .f7 = true, |
| 179 | .f8 = true, |
| 180 | .f9 = true, |
| 181 | .f10 = true, |
| 182 | .f11 = true, |
| 183 | .f12 = true, |
| 184 | .f13 = true, |
| 185 | .f14 = true, |
| 186 | .f15 = true, |
| 187 | .f16 = true, |
| 188 | .f17 = true, |
| 189 | .f18 = true, |
| 190 | .f19 = true, |
| 191 | .f20 = true, |
| 192 | .f21 = true, |
| 193 | .f22 = true, |
| 194 | .f23 = true, |
| 195 | .f24 = true, |
| 196 | .f25 = true, |
| 197 | .f26 = true, |
| 198 | .f27 = true, |
| 199 | .f28 = true, |
| 200 | .f29 = true, |
| 201 | .f30 = true, |
| 202 | .f31 = true, |
| 203 | .v0 = true, |
| 204 | .v1 = true, |
| 205 | .v2 = true, |
| 206 | .v3 = true, |
| 207 | .v4 = true, |
| 208 | .v5 = true, |
| 209 | .v6 = true, |
| 210 | .v7 = true, |
| 211 | .v8 = true, |
| 212 | .v9 = true, |
| 213 | .v10 = true, |
| 214 | .v11 = true, |
| 215 | .v12 = true, |
| 216 | .v13 = true, |
| 217 | .v14 = true, |
| 218 | .v15 = true, |
| 219 | .v16 = true, |
| 220 | .v17 = true, |
| 221 | .v18 = true, |
| 222 | .v19 = true, |
| 223 | .v20 = true, |
| 224 | .v21 = true, |
| 225 | .v22 = true, |
| 226 | .v23 = true, |
| 227 | .v24 = true, |
| 228 | .v25 = true, |
| 229 | .v26 = true, |
| 230 | .v27 = true, |
| 231 | .v28 = true, |
| 232 | .v29 = true, |
| 233 | .v30 = true, |
| 234 | .v31 = true, |
| 235 | .vtype = true, |
| 236 | .vl = true, |
| 237 | .vxsat = true, |
| 238 | .vxrm = true, |
| 239 | .vcsr = true, |
| 240 | .fflags = true, |
| 241 | .frm = true, |
| 242 | .memory = true, |
| 243 | }), |
| 244 | .x86_64 => asm volatile ( |
| 245 | \\ movq 0(%%rsi), %%rax |
| 246 | \\ movq 8(%%rsi), %%rcx |
| 247 | \\ leaq 0f(%%rip), %%rdx |
| 248 | \\ movq %%rsp, 0(%%rax) |
| 249 | \\ movq %%rbp, 8(%%rax) |
| 250 | \\ movq %%rdx, 16(%%rax) |
| 251 | \\ movq 0(%%rcx), %%rsp |
| 252 | \\ movq 8(%%rcx), %%rbp |
| 253 | \\ jmpq *16(%%rcx) |
| 254 | \\0: |
| 255 | : [received_message] "={rsi}" (-> *const Switch), |
| 256 | : [message_to_send] "{rsi}" (s), |
| 257 | : .{ |
| 258 | .rax = true, |
| 259 | .rcx = true, |
| 260 | .rdx = true, |
| 261 | .rbx = true, |
| 262 | .rsi = true, |
| 263 | .rdi = true, |
| 264 | .r8 = true, |
| 265 | .r9 = true, |
| 266 | .r10 = true, |
| 267 | .r11 = true, |
| 268 | .r12 = true, |
| 269 | .r13 = true, |
| 270 | .r14 = true, |
| 271 | .r15 = true, |
| 272 | .mm0 = true, |
| 273 | .mm1 = true, |
| 274 | .mm2 = true, |
| 275 | .mm3 = true, |
| 276 | .mm4 = true, |
| 277 | .mm5 = true, |
| 278 | .mm6 = true, |
| 279 | .mm7 = true, |
| 280 | .zmm0 = true, |
| 281 | .zmm1 = true, |
| 282 | .zmm2 = true, |
| 283 | .zmm3 = true, |
| 284 | .zmm4 = true, |
| 285 | .zmm5 = true, |
| 286 | .zmm6 = true, |
| 287 | .zmm7 = true, |
| 288 | .zmm8 = true, |
| 289 | .zmm9 = true, |
| 290 | .zmm10 = true, |
| 291 | .zmm11 = true, |
| 292 | .zmm12 = true, |
| 293 | .zmm13 = true, |
| 294 | .zmm14 = true, |
| 295 | .zmm15 = true, |
| 296 | .zmm16 = true, |
| 297 | .zmm17 = true, |
| 298 | .zmm18 = true, |
| 299 | .zmm19 = true, |
| 300 | .zmm20 = true, |
| 301 | .zmm21 = true, |
| 302 | .zmm22 = true, |
| 303 | .zmm23 = true, |
| 304 | .zmm24 = true, |
| 305 | .zmm25 = true, |
| 306 | .zmm26 = true, |
| 307 | .zmm27 = true, |
| 308 | .zmm28 = true, |
| 309 | .zmm29 = true, |
| 310 | .zmm30 = true, |
| 311 | .zmm31 = true, |
| 312 | .fpsr = true, |
| 313 | .fpcr = true, |
| 314 | .mxcsr = true, |
| 315 | .rflags = true, |
| 316 | .dirflag = true, |
| 317 | .memory = true, |
| 318 | }), |
| 319 | else => |arch| @compileError("unimplemented architecture: " ++ @tagName(arch)), |
| 320 | }; |
| 321 | } |
| 322 | |
| 323 | const builtin = @import("builtin"); |