Commit aa9df72f71

joachimschmidt557 <joachim.schmidt557@outlook.com>
2020-11-08 20:21:36
stage2 AArch64: MoveWideImmediate instructions + test coverage
1 parent 4c8f692
Changed files (1)
src
codegen
src/codegen/aarch64.zig
@@ -195,12 +195,12 @@ test "FloatingPointRegister.toX" {
 
 /// Represents an instruction in the AArch64 instruction set
 pub const Instruction = union(enum) {
-    MoveWideWithZero: packed struct {
+    MoveWideImmediate: packed struct {
         rd: u5,
         imm16: u16,
         hw: u2,
         fixed: u6 = 0b100101,
-        opc: u2 = 0b10,
+        opc: u2,
         sf: u1,
     },
     ExceptionGeneration: packed struct {
@@ -226,7 +226,7 @@ pub const Instruction = union(enum) {
 
     pub fn toU32(self: Instruction) u32 {
         return switch (self) {
-            .MoveWideWithZero => |v| @bitCast(u32, v),
+            .MoveWideImmediate => |v| @bitCast(u32, v),
             .ExceptionGeneration => |v| @bitCast(u32, v),
             .UnconditionalBranchRegister => |v| @bitCast(u32, v),
             .UnconditionalBranchImmediate => |v| @bitCast(u32, v),
@@ -235,24 +235,33 @@ pub const Instruction = union(enum) {
 
     // Helper functions for assembly syntax functions
 
-    fn moveWideWithZero(rd: Register, imm16: u16, shift: u2) Instruction {
+    fn moveWideImmediate(
+        opc: u2,
+        rd: Register,
+        imm16: u16,
+        shift: u6,
+    ) Instruction {
         switch (rd.size()) {
             32 => {
+                assert(shift % 16 == 0 and shift <= 16);
                 return Instruction{
-                    .MoveWideWithZero = .{
+                    .MoveWideImmediate = .{
                         .rd = rd.id(),
                         .imm16 = imm16,
-                        .hw = 0b01 & shift, // TODO shift should be an enum
+                        .hw = @intCast(u2, shift / 16),
+                        .opc = opc,
                         .sf = 0,
                     },
                 };
             },
             64 => {
+                assert(shift % 16 == 0 and shift <= 48);
                 return Instruction{
-                    .MoveWideWithZero = .{
+                    .MoveWideImmediate = .{
                         .rd = rd.id(),
                         .imm16 = imm16,
-                        .hw = shift,
+                        .hw = @intCast(u2, shift / 16),
+                        .opc = opc,
                         .sf = 1,
                     },
                 };
@@ -284,6 +293,8 @@ pub const Instruction = union(enum) {
         rn: Register,
         op4: u5,
     ) Instruction {
+        assert(rn.size() == 64);
+
         return Instruction{
             .UnconditionalBranchRegister = .{
                 .op4 = op4,
@@ -301,16 +312,24 @@ pub const Instruction = union(enum) {
     ) Instruction {
         return Instruction{
             .UnconditionalBranchImmediate = .{
-                .imm26 = @bitCast(u26, @intCast(i26, imm26 >> 2)),
+                .imm26 = @bitCast(u26, @intCast(i26, offset >> 2)),
                 .op = op,
             },
         };
     }
 
-    // movz
+    // Move wide (immediate)
+
+    pub fn movn(rd: Register, imm16: u16, shift: u6) Instruction {
+        return moveWideImmediate(0b00, rd, imm16, shift);
+    }
+
+    pub fn movz(rd: Register, imm16: u16, shift: u6) Instruction {
+        return moveWideImmediate(0b10, rd, imm16, shift);
+    }
 
-    pub fn movz(rd: Register, imm16: u16, shift: u2) Instruction {
-        return moveWideWithZero(rd, imm16, shift);
+    pub fn movk(rd: Register, imm16: u16, shift: u6) Instruction {
+        return moveWideImmediate(0b11, rd, imm16, shift);
     }
 
     // Exception generation
@@ -338,7 +357,6 @@ pub const Instruction = union(enum) {
     // Unconditional branch (register)
 
     pub fn br(rn: Register) Instruction {
-        assert(rn.size() == 64);
         return unconditionalBranchRegister(0b0000, 0b11111, 0b000000, rn, 0b00000);
     }
 
@@ -368,28 +386,20 @@ test "serialize instructions" {
     };
 
     const testcases = [_]Testcase{
-        .{ // svc #0
-            .inst = Instruction.svc(0),
-            .expected = 0b1101_0100_000_0000000000000000_00001,
-        },
-        .{ // svc #0x80 ; typical on Darwin
-            .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),
+            .inst = Instruction.movz(.x1, 4, 16),
             .expected = 0b1_10_100101_01_0000000000000100_00001,
         },
         .{ // movz x1, #4, lsl 32
-            .inst = Instruction.movz(.x1, 4, 2),
+            .inst = Instruction.movz(.x1, 4, 32),
             .expected = 0b1_10_100101_10_0000000000000100_00001,
         },
         .{ // movz x1, #4, lsl 48
-            .inst = Instruction.movz(.x1, 4, 3),
+            .inst = Instruction.movz(.x1, 4, 48),
             .expected = 0b1_10_100101_11_0000000000000100_00001,
         },
         .{ // movz w1, #4
@@ -397,9 +407,25 @@ test "serialize instructions" {
             .expected = 0b0_10_100101_00_0000000000000100_00001,
         },
         .{ // movz w1, #4, lsl 16
-            .inst = Instruction.movz(.w1, 4, 1),
+            .inst = Instruction.movz(.w1, 4, 16),
             .expected = 0b0_10_100101_01_0000000000000100_00001,
         },
+        .{ // svc #0
+            .inst = Instruction.svc(0),
+            .expected = 0b1101_0100_000_0000000000000000_00001,
+        },
+        .{ // svc #0x80 ; typical on Darwin
+            .inst = Instruction.svc(0x80),
+            .expected = 0b1101_0100_000_0000000010000000_00001,
+        },
+        .{ // ret
+            .inst = Instruction.ret(null),
+            .expected = 0b1101_011_00_10_11111_0000_00_11110_00000,
+        },
+        .{ // bl #0x10
+            .inst = Instruction.bl(0x10),
+            .expected = 0b1_00101_00_0000_0000_0000_0000_0000_0100,
+        },
     };
 
     for (testcases) |case| {