Commit 4ef6864a15
Changed files (2)
src
codegen
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| {
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}),
},