From aa9df72f714c0bd3c8653ea0c5431d43543b6f6f Mon Sep 17 00:00:00 2001 From: joachimschmidt557 Date: Sun, 8 Nov 2020 20:21:36 +0100 Subject: [PATCH] stage2 AArch64: MoveWideImmediate instructions + test coverage --- src/codegen/aarch64.zig | 96 ++++++++++++++++++++++++++--------------- 1 file changed, 61 insertions(+), 35 deletions(-) diff --git a/src/codegen/aarch64.zig b/src/codegen/aarch64.zig index 3b433eb267..6ceeaea47e 100644 --- a/src/codegen/aarch64.zig +++ b/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 movz(rd: Register, imm16: u16, shift: u2) Instruction { - return moveWideWithZero(rd, imm16, shift); + 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 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,6 +386,30 @@ test "serialize instructions" { }; const testcases = [_]Testcase{ + .{ // 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, 16), + .expected = 0b1_10_100101_01_0000000000000100_00001, + }, + .{ // movz x1, #4, lsl 32 + .inst = Instruction.movz(.x1, 4, 32), + .expected = 0b1_10_100101_10_0000000000000100_00001, + }, + .{ // movz x1, #4, lsl 48 + .inst = Instruction.movz(.x1, 4, 48), + .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, 16), + .expected = 0b0_10_100101_01_0000000000000100_00001, + }, .{ // svc #0 .inst = Instruction.svc(0), .expected = 0b1101_0100_000_0000000000000000_00001, @@ -376,29 +418,13 @@ 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, + .{ // ret + .inst = Instruction.ret(null), + .expected = 0b1101_011_00_10_11111_0000_00_11110_00000, }, - .{ // 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, + .{ // bl #0x10 + .inst = Instruction.bl(0x10), + .expected = 0b1_00101_00_0000_0000_0000_0000_0000_0100, }, };