Commit 4ef6864a15

Jakub Konka <kubkon@jakubkonka.com>
2020-11-08 14:49:31
Add move wide with zero (movz) instruction
1 parent d601b0f
Changed files (2)
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}),
                 },