| ... | ... | @@ -1,5 +1,6 @@ |
| 1 | 1 | const std = @import("std"); |
| 2 | 2 | const DW = std.dwarf; |
| 3 | const assert = std.debug.assert; |
| 3 | 4 | const testing = std.testing; |
| 4 | 5 | |
| 5 | 6 | // zig fmt: off |
| ... | ... | @@ -202,16 +203,33 @@ pub const Instruction = union(enum) { |
| 202 | 203 | opc: u2 = 0b10, |
| 203 | 204 | sf: u1, |
| 204 | 205 | }, |
| 205 | | SupervisorCall: packed struct { |
| 206 | | fixed_1: u5 = 0b00001, |
| 206 | ExceptionGeneration: packed struct { |
| 207 | ll: u2, |
| 208 | op2: u3, |
| 207 | 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 | 227 | pub fn toU32(self: Instruction) u32 { |
| 212 | 228 | return switch (self) { |
| 213 | 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 | 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 | 270 | return Instruction{ |
| 248 | | .SupervisorCall = .{ |
| 271 | .ExceptionGeneration = .{ |
| 272 | .ll = ll, |
| 273 | .op2 = op2, |
| 249 | 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 | 313 | return moveWideWithZero(rd, imm16, shift); |
| 258 | 314 | } |
| 259 | 315 | |
| 260 | | // Supervisor Call |
| 316 | // Exception generation |
| 261 | 317 | |
| 262 | 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 | |