Commit ea6f3e3fd1

joachimschmidt557 <joachim.schmidt557@outlook.com>
2021-01-17 22:40:14
stage2 AArch64: add add/subtract (immediate) instructions
1 parent c6cb02c
Changed files (1)
src
codegen
src/codegen/aarch64.zig
@@ -274,6 +274,16 @@ pub const Instruction = union(enum) {
         opc: u2,
         sf: u1,
     },
+    AddSubtractImmediate: packed struct {
+        rd: u5,
+        rn: u5,
+        imm12: u12,
+        sh: u1,
+        fixed: u6 = 0b100010,
+        s: u1,
+        op: u1,
+        sf: u1,
+    },
 
     pub const Shift = struct {
         shift: Type = .lsl,
@@ -304,6 +314,7 @@ pub const Instruction = union(enum) {
             .UnconditionalBranchImmediate => |v| @bitCast(u32, v),
             .NoOperation => |v| @bitCast(u32, v),
             .LogicalShiftedRegister => |v| @bitCast(u32, v),
+            .AddSubtractImmediate => |v| @bitCast(u32, v),
         };
     }
 
@@ -671,6 +682,31 @@ pub const Instruction = union(enum) {
         }
     }
 
+    fn addSubtractImmediate(
+        op: u1,
+        s: u1,
+        rd: Register,
+        rn: Register,
+        imm12: u12,
+        shift: bool,
+    ) Instruction {
+        return Instruction{
+            .AddSubtractImmediate = .{
+                .rd = rd.id(),
+                .rn = rn.id(),
+                .imm12 = imm12,
+                .sh = @boolToInt(shift),
+                .s = s,
+                .op = op,
+                .sf = switch (rd.size()) {
+                    32 => 0b0,
+                    64 => 0b1,
+                    else => unreachable, // unexpected register size
+                },
+            },
+        };
+    }
+
     // Helper functions for assembly syntax functions
 
     // Move wide (immediate)
@@ -850,6 +886,24 @@ pub const Instruction = union(enum) {
     pub fn bics(rd: Register, rn: Register, rm: Register, shift: Shift) Instruction {
         return logicalShiftedRegister(0b11, 0b1, shift, rd, rn, rm);
     }
+
+    // Add/subtract (immediate)
+
+    pub fn add(rd: Register, rn: Register, imm: u12, shift: bool) Instruction {
+        return addSubtractImmediate(0b0, 0b0, rd, rn, imm, shift);
+    }
+
+    pub fn adds(rd: Register, rn: Register, imm: u12, shift: bool) Instruction {
+        return addSubtractImmediate(0b0, 0b1, rd, rn, imm, shift);
+    }
+
+    pub fn sub(rd: Register, rn: Register, imm: u12, shift: bool) Instruction {
+        return addSubtractImmediate(0b1, 0b0, rd, rn, imm, shift);
+    }
+
+    pub fn subs(rd: Register, rn: Register, imm: u12, shift: bool) Instruction {
+        return addSubtractImmediate(0b1, 0b1, rd, rn, imm, shift);
+    }
 };
 
 test "" {
@@ -979,6 +1033,14 @@ test "serialize instructions" {
             .inst = Instruction.@"and"(.x0, .x4, .x2, .{ .shift = .lsl, .amount = 0x8 }),
             .expected = 0b1_00_01010_00_0_00010_001000_00100_00000,
         },
+        .{ // add x0, x10, #10
+            .inst = Instruction.add(.x0, .x10, 10, false),
+            .expected = 0b1_0_0_100010_0_0000_0000_1010_01010_00000,
+        },
+        .{ // subs x0, x5, #11, lsl #12
+            .inst = Instruction.subs(.x0, .x5, 11, true),
+            .expected = 0b1_1_1_100010_1_0000_0000_1011_00101_00000,
+        },
     };
 
     for (testcases) |case| {