| ... | ... | @@ -193,6 +193,15 @@ test "FloatingPointRegister.toX" { |
| 193 | 193 | |
| 194 | 194 | /// Represents an instruction in the AArch64 instruction set |
| 195 | 195 | pub const Instruction = union(enum) { |
| 196 | MoveWideWithZero: packed struct { |
| 197 | rd: u5, |
| 198 | imm16: u16, |
| 199 | hw: u2, |
| 200 | fixed: u6 = 0b100101, |
| 201 | opc: u2 = 0b10, |
| 202 | sf: u1, |
| 203 | }, |
| 204 | |
| 196 | 205 | SupervisorCall: packed struct { |
| 197 | 206 | fixed_1: u5 = 0b00001, |
| 198 | 207 | imm16: u16, |
| ... | ... | @@ -201,12 +210,39 @@ pub const Instruction = union(enum) { |
| 201 | 210 | |
| 202 | 211 | pub fn toU32(self: Instruction) u32 { |
| 203 | 212 | return switch (self) { |
| 213 | .MoveWideWithZero => |v| @bitCast(u32, v), |
| 204 | 214 | .SupervisorCall => |v| @bitCast(u32, v), |
| 205 | 215 | }; |
| 206 | 216 | } |
| 207 | 217 | |
| 208 | 218 | // Helper functions for assembly syntax functions |
| 209 | 219 | |
| 220 | fn moveWideWithZero(rd: Register, imm16: u16, shift: u2) Instruction { |
| 221 | switch (rd.size()) { |
| 222 | 32 => { |
| 223 | return Instruction{ |
| 224 | .MoveWideWithZero = .{ |
| 225 | .rd = rd.id(), |
| 226 | .imm16 = imm16, |
| 227 | .hw = 0b01 & shift, // TODO shift should be an enum |
| 228 | .sf = 0, |
| 229 | }, |
| 230 | }; |
| 231 | }, |
| 232 | 64 => { |
| 233 | return Instruction{ |
| 234 | .MoveWideWithZero = .{ |
| 235 | .rd = rd.id(), |
| 236 | .imm16 = imm16, |
| 237 | .hw = shift, |
| 238 | .sf = 1, |
| 239 | }, |
| 240 | }; |
| 241 | }, |
| 242 | else => unreachable, // unexpected register size |
| 243 | } |
| 244 | } |
| 245 | |
| 210 | 246 | fn supervisorCall(imm16: u16) Instruction { |
| 211 | 247 | return Instruction{ |
| 212 | 248 | .SupervisorCall = .{ |
| ... | ... | @@ -215,6 +251,12 @@ pub const Instruction = union(enum) { |
| 215 | 251 | }; |
| 216 | 252 | } |
| 217 | 253 | |
| 254 | // movz |
| 255 | |
| 256 | pub fn movz(rd: Register, imm16: u16, shift: u2) Instruction { |
| 257 | return moveWideWithZero(rd, imm16, shift); |
| 258 | } |
| 259 | |
| 218 | 260 | // Supervisor Call |
| 219 | 261 | |
| 220 | 262 | pub fn svc(imm16: u16) Instruction { |
| ... | ... | @@ -237,6 +279,30 @@ test "serialize instructions" { |
| 237 | 279 | .inst = Instruction.svc(0x80), |
| 238 | 280 | .expected = 0b1101_0100_000_0000000010000000_00001, |
| 239 | 281 | }, |
| 282 | .{ // movz x1 #4 |
| 283 | .inst = Instruction.movz(.x1, 4, 0), |
| 284 | .expected = 0b1_10_100101_00_0000000000000100_00001, |
| 285 | }, |
| 286 | .{ // movz x1, #4, lsl 16 |
| 287 | .inst = Instruction.movz(.x1, 4, 1), |
| 288 | .expected = 0b1_10_100101_01_0000000000000100_00001, |
| 289 | }, |
| 290 | .{ // movz x1, #4, lsl 32 |
| 291 | .inst = Instruction.movz(.x1, 4, 2), |
| 292 | .expected = 0b1_10_100101_10_0000000000000100_00001, |
| 293 | }, |
| 294 | .{ // movz x1, #4, lsl 48 |
| 295 | .inst = Instruction.movz(.x1, 4, 3), |
| 296 | .expected = 0b1_10_100101_11_0000000000000100_00001, |
| 297 | }, |
| 298 | .{ // movz w1, #4 |
| 299 | .inst = Instruction.movz(.w1, 4, 0), |
| 300 | .expected = 0b0_10_100101_00_0000000000000100_00001, |
| 301 | }, |
| 302 | .{ // movz w1, #4, lsl 16 |
| 303 | .inst = Instruction.movz(.w1, 4, 1), |
| 304 | .expected = 0b0_10_100101_01_0000000000000100_00001, |
| 305 | }, |
| 240 | 306 | }; |
| 241 | 307 | |
| 242 | 308 | for (testcases) |case| { |