diff --git a/src/codegen.zig b/src/codegen.zig index 47d33570d5..d946c913a9 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -2504,7 +2504,13 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { else => unreachable, // unexpected register size } }, - .immediate => return self.fail(src, "TODO implement genSetReg for aarch64 {}", .{mcv}), + .immediate => |x| { + if (x <= math.maxInt(u16)) { + mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.movz(reg, @intCast(u16, x), 0).toU32()); + } else { + return self.fail(src, "TODO genSetReg with 32,48,64bit immediates", .{}); + } + }, .register => return self.fail(src, "TODO implement genSetReg for aarch64 {}", .{mcv}), else => return self.fail(src, "TODO implement genSetReg for aarch64 {}", .{mcv}), }, diff --git a/src/codegen/aarch64.zig b/src/codegen/aarch64.zig index a55dcc4978..ca5bbfc1ea 100644 --- a/src/codegen/aarch64.zig +++ b/src/codegen/aarch64.zig @@ -193,6 +193,15 @@ test "FloatingPointRegister.toX" { /// Represents an instruction in the AArch64 instruction set pub const Instruction = union(enum) { + MoveWideWithZero: packed struct { + rd: u5, + imm16: u16, + hw: u2, + fixed: u6 = 0b100101, + opc: u2 = 0b10, + sf: u1, + }, + SupervisorCall: packed struct { fixed_1: u5 = 0b00001, imm16: u16, @@ -201,12 +210,39 @@ pub const Instruction = union(enum) { pub fn toU32(self: Instruction) u32 { return switch (self) { + .MoveWideWithZero => |v| @bitCast(u32, v), .SupervisorCall => |v| @bitCast(u32, v), }; } // Helper functions for assembly syntax functions + fn moveWideWithZero(rd: Register, imm16: u16, shift: u2) Instruction { + switch (rd.size()) { + 32 => { + return Instruction{ + .MoveWideWithZero = .{ + .rd = rd.id(), + .imm16 = imm16, + .hw = 0b01 & shift, // TODO shift should be an enum + .sf = 0, + }, + }; + }, + 64 => { + return Instruction{ + .MoveWideWithZero = .{ + .rd = rd.id(), + .imm16 = imm16, + .hw = shift, + .sf = 1, + }, + }; + }, + else => unreachable, // unexpected register size + } + } + fn supervisorCall(imm16: u16) Instruction { return Instruction{ .SupervisorCall = .{ @@ -215,6 +251,12 @@ pub const Instruction = union(enum) { }; } + // movz + + pub fn movz(rd: Register, imm16: u16, shift: u2) Instruction { + return moveWideWithZero(rd, imm16, shift); + } + // Supervisor Call pub fn svc(imm16: u16) Instruction { @@ -237,6 +279,30 @@ test "serialize instructions" { .inst = Instruction.svc(0x80), .expected = 0b1101_0100_000_0000000010000000_00001, }, + .{ // movz x1 #4 + .inst = Instruction.movz(.x1, 4, 0), + .expected = 0b1_10_100101_00_0000000000000100_00001, + }, + .{ // movz x1, #4, lsl 16 + .inst = Instruction.movz(.x1, 4, 1), + .expected = 0b1_10_100101_01_0000000000000100_00001, + }, + .{ // movz x1, #4, lsl 32 + .inst = Instruction.movz(.x1, 4, 2), + .expected = 0b1_10_100101_10_0000000000000100_00001, + }, + .{ // movz x1, #4, lsl 48 + .inst = Instruction.movz(.x1, 4, 3), + .expected = 0b1_10_100101_11_0000000000000100_00001, + }, + .{ // movz w1, #4 + .inst = Instruction.movz(.w1, 4, 0), + .expected = 0b0_10_100101_00_0000000000000100_00001, + }, + .{ // movz w1, #4, lsl 16 + .inst = Instruction.movz(.w1, 4, 1), + .expected = 0b0_10_100101_01_0000000000000100_00001, + }, }; for (testcases) |case| {