| ... | @@ -1,5 +1,6 @@ | ... | @@ -1,5 +1,6 @@ |
| 1 | const std = @import("std"); | 1 | const std = @import("std"); |
| 2 | const DW = std.dwarf; | 2 | const DW = std.dwarf; |
| | 3 | const assert = std.debug.assert; |
| 3 | const testing = std.testing; | 4 | const testing = std.testing; |
| 4 | | 5 | |
| 5 | // zig fmt: off | 6 | // zig fmt: off |
| ... | @@ -202,16 +203,33 @@ pub const Instruction = union(enum) { | ... | @@ -202,16 +203,33 @@ pub const Instruction = union(enum) { |
| 202 | opc: u2 = 0b10, | 203 | opc: u2 = 0b10, |
| 203 | sf: u1, | 204 | sf: u1, |
| 204 | }, | 205 | }, |
| 205 | SupervisorCall: packed struct { | 206 | ExceptionGeneration: packed struct { |
| 206 | fixed_1: u5 = 0b00001, | 207 | ll: u2, |
| | 208 | op2: u3, |
| 207 | imm16: u16, | 209 | imm16: u16, |
| 208 | fixed_2: u11 = 0b11010100000, | 210 | opc: u3, |
| | 211 | fixed: u8 = 0b1101_0100, |
| | 212 | }, |
| | 213 | UnconditionalBranchRegister: packed struct { |
| | 214 | op4: u5, |
| | 215 | rn: u5, |
| | 216 | op3: u6, |
| | 217 | op2: u5, |
| | 218 | opc: u4, |
| | 219 | fixed: u7 = 0b1101_011, |
| | 220 | }, |
| | 221 | UnconditionalBranchImmediate: packed struct { |
| | 222 | imm26: u26, |
| | 223 | fixed: u5 = 0b00101, |
| | 224 | op: u1, |
| 209 | }, | 225 | }, |
| 210 | | 226 | |
| 211 | pub fn toU32(self: Instruction) u32 { | 227 | pub fn toU32(self: Instruction) u32 { |
| 212 | return switch (self) { | 228 | return switch (self) { |
| 213 | .MoveWideWithZero => |v| @bitCast(u32, v), | 229 | .MoveWideWithZero => |v| @bitCast(u32, v), |
| 214 | .SupervisorCall => |v| @bitCast(u32, v), | 230 | .ExceptionGeneration => |v| @bitCast(u32, v), |
| | 231 | .UnconditionalBranchRegister => |v| @bitCast(u32, v), |
| | 232 | .UnconditionalBranchImmediate => |v| @bitCast(u32, v), |
| 215 | }; | 233 | }; |
| 216 | } | 234 | } |
| 217 | | 235 | |
| ... | @@ -243,10 +261,48 @@ pub const Instruction = union(enum) { | ... | @@ -243,10 +261,48 @@ pub const Instruction = union(enum) { |
| 243 | } | 261 | } |
| 244 | } | 262 | } |
| 245 | | 263 | |
| 246 | fn supervisorCall(imm16: u16) Instruction { | 264 | fn exceptionGeneration( |
| | 265 | opc: u3, |
| | 266 | op2: u3, |
| | 267 | ll: u2, |
| | 268 | imm16: u16, |
| | 269 | ) Instruction { |
| 247 | return Instruction{ | 270 | return Instruction{ |
| 248 | .SupervisorCall = .{ | 271 | .ExceptionGeneration = .{ |
| | 272 | .ll = ll, |
| | 273 | .op2 = op2, |
| 249 | .imm16 = imm16, | 274 | .imm16 = imm16, |
| | 275 | .opc = opc, |
| | 276 | }, |
| | 277 | }; |
| | 278 | } |
| | 279 | |
| | 280 | fn unconditionalBranchRegister( |
| | 281 | opc: u4, |
| | 282 | op2: u5, |
| | 283 | op3: u6, |
| | 284 | rn: Register, |
| | 285 | op4: u5, |
| | 286 | ) Instruction { |
| | 287 | return Instruction{ |
| | 288 | .UnconditionalBranchRegister = .{ |
| | 289 | .op4 = op4, |
| | 290 | .rn = rn.id(), |
| | 291 | .op3 = op3, |
| | 292 | .op2 = op2, |
| | 293 | .opc = opc, |
| | 294 | }, |
| | 295 | }; |
| | 296 | } |
| | 297 | |
| | 298 | fn unconditionalBranchImmediate( |
| | 299 | op: u1, |
| | 300 | offset: i28, |
| | 301 | ) Instruction { |
| | 302 | return Instruction{ |
| | 303 | .UnconditionalBranchImmediate = .{ |
| | 304 | .imm26 = @bitCast(u26, @intCast(i26, imm26 >> 2)), |
| | 305 | .op = op, |
| 250 | }, | 306 | }, |
| 251 | }; | 307 | }; |
| 252 | } | 308 | } |
| ... | @@ -257,10 +313,51 @@ pub const Instruction = union(enum) { | ... | @@ -257,10 +313,51 @@ pub const Instruction = union(enum) { |
| 257 | return moveWideWithZero(rd, imm16, shift); | 313 | return moveWideWithZero(rd, imm16, shift); |
| 258 | } | 314 | } |
| 259 | | 315 | |
| 260 | // Supervisor Call | 316 | // Exception generation |
| 261 | | 317 | |
| 262 | pub fn svc(imm16: u16) Instruction { | 318 | pub fn svc(imm16: u16) Instruction { |
| 263 | return supervisorCall(imm16); | 319 | return exceptionGeneration(0b000, 0b000, 0b01, imm16); |
| | 320 | } |
| | 321 | |
| | 322 | pub fn hvc(imm16: u16) Instruction { |
| | 323 | return exceptionGeneration(0b000, 0b000, 0b10, imm16); |
| | 324 | } |
| | 325 | |
| | 326 | pub fn smc(imm16: u16) Instruction { |
| | 327 | return exceptionGeneration(0b000, 0b000, 0b11, imm16); |
| | 328 | } |
| | 329 | |
| | 330 | pub fn brk(imm16: u16) Instruction { |
| | 331 | return exceptionGeneration(0b001, 0b000, 0b00, imm16); |
| | 332 | } |
| | 333 | |
| | 334 | pub fn hlt(imm16: u16) Instruction { |
| | 335 | return exceptionGeneration(0b010, 0b000, 0b00, imm16); |
| | 336 | } |
| | 337 | |
| | 338 | // Unconditional branch (register) |
| | 339 | |
| | 340 | pub fn br(rn: Register) Instruction { |
| | 341 | assert(rn.size() == 64); |
| | 342 | return unconditionalBranchRegister(0b0000, 0b11111, 0b000000, rn, 0b00000); |
| | 343 | } |
| | 344 | |
| | 345 | pub fn blr(rn: Register) Instruction { |
| | 346 | return unconditionalBranchRegister(0b0001, 0b11111, 0b000000, rn, 0b00000); |
| | 347 | } |
| | 348 | |
| | 349 | pub fn ret(rn: ?Register) Instruction { |
| | 350 | return unconditionalBranchRegister(0b0010, 0b11111, 0b000000, rn orelse .x30, 0b00000); |
| | 351 | } |
| | 352 | |
| | 353 | // Unconditional branch (immediate) |
| | 354 | |
| | 355 | pub fn b(offset: i28) Instruction { |
| | 356 | return unconditionalBranchImmediate(0, offset); |
| | 357 | } |
| | 358 | |
| | 359 | pub fn bl(offset: i28) Instruction { |
| | 360 | return unconditionalBranchImmediate(1, offset); |
| 264 | } | 361 | } |
| 265 | }; | 362 | }; |
| 266 | | 363 | |