| ... | @@ -193,6 +193,15 @@ test "FloatingPointRegister.toX" { | ... | @@ -193,6 +193,15 @@ test "FloatingPointRegister.toX" { |
| 193 | | 193 | |
| 194 | /// Represents an instruction in the AArch64 instruction set | 194 | /// Represents an instruction in the AArch64 instruction set |
| 195 | pub const Instruction = union(enum) { | 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 | SupervisorCall: packed struct { | 205 | SupervisorCall: packed struct { |
| 197 | fixed_1: u5 = 0b00001, | 206 | fixed_1: u5 = 0b00001, |
| 198 | imm16: u16, | 207 | imm16: u16, |
| ... | @@ -201,12 +210,39 @@ pub const Instruction = union(enum) { | ... | @@ -201,12 +210,39 @@ pub const Instruction = union(enum) { |
| 201 | | 210 | |
| 202 | pub fn toU32(self: Instruction) u32 { | 211 | pub fn toU32(self: Instruction) u32 { |
| 203 | return switch (self) { | 212 | return switch (self) { |
| | 213 | .MoveWideWithZero => |v| @bitCast(u32, v), |
| 204 | .SupervisorCall => |v| @bitCast(u32, v), | 214 | .SupervisorCall => |v| @bitCast(u32, v), |
| 205 | }; | 215 | }; |
| 206 | } | 216 | } |
| 207 | | 217 | |
| 208 | // Helper functions for assembly syntax functions | 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 | fn supervisorCall(imm16: u16) Instruction { | 246 | fn supervisorCall(imm16: u16) Instruction { |
| 211 | return Instruction{ | 247 | return Instruction{ |
| 212 | .SupervisorCall = .{ | 248 | .SupervisorCall = .{ |
| ... | @@ -215,6 +251,12 @@ pub const Instruction = union(enum) { | ... | @@ -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 | // Supervisor Call | 260 | // Supervisor Call |
| 219 | | 261 | |
| 220 | pub fn svc(imm16: u16) Instruction { | 262 | pub fn svc(imm16: u16) Instruction { |
| ... | @@ -237,6 +279,30 @@ test "serialize instructions" { | ... | @@ -237,6 +279,30 @@ test "serialize instructions" { |
| 237 | .inst = Instruction.svc(0x80), | 279 | .inst = Instruction.svc(0x80), |
| 238 | .expected = 0b1101_0100_000_0000000010000000_00001, | 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 | for (testcases) |case| { | 308 | for (testcases) |case| { |