Add move wide with zero (movz) instruction

This commit is contained in:
Jakub Konka 2020-11-08 14:49:31 +01:00
parent d601b0f4eb
commit 4ef6864a15
2 changed files with 73 additions and 1 deletions

View File

@ -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}),
},

View File

@ -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| {