aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorKoakuma <koachan@protonmail.com>2022-06-16 23:53:22 +0700
committerKoakuma <koachan@protonmail.com>2022-06-24 21:19:33 +0700
commit4d15284c3cbeefa771baa2b69866b2f0252f147b (patch)
treee7525ac6b6ee1e4a494c17159206dcce9ed64867 /src
parent513ab4eb568da6fb926dd33ae067d31cf4831e79 (diff)
downloadzig-4d15284c3cbeefa771baa2b69866b2f0252f147b.tar.gz
zig-4d15284c3cbeefa771baa2b69866b2f0252f147b.zip
stage2: sparc64: Implement SPARCv9 shifts
Diffstat (limited to 'src')
-rw-r--r--src/arch/sparc64/CodeGen.zig7
-rw-r--r--src/arch/sparc64/Emit.zig44
-rw-r--r--src/arch/sparc64/Mir.zig1
-rw-r--r--src/arch/sparc64/bits.zig48
4 files changed, 86 insertions, 14 deletions
diff --git a/src/arch/sparc64/CodeGen.zig b/src/arch/sparc64/CodeGen.zig
index 515d77032f..4bd1652ac1 100644
--- a/src/arch/sparc64/CodeGen.zig
+++ b/src/arch/sparc64/CodeGen.zig
@@ -2337,7 +2337,6 @@ fn binOpImmediate(
.sllx => .{
.shift = .{
.is_imm = true,
- .width = ShiftWidth.shift64,
.rd = dest_reg,
.rs1 = lhs_reg,
.rs2_or_imm = .{ .imm = @intCast(u6, rhs.immediate) },
@@ -2459,7 +2458,6 @@ fn binOpRegister(
.sllx => .{
.shift = .{
.is_imm = false,
- .width = ShiftWidth.shift64,
.rd = dest_reg,
.rs1 = lhs_reg,
.rs2_or_imm = .{ .rs2 = rhs_reg },
@@ -2940,7 +2938,6 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
.data = .{
.shift = .{
.is_imm = true,
- .width = .shift64,
.rd = reg,
.rs1 = reg,
.rs2_or_imm = .{ .imm = 12 },
@@ -2971,7 +2968,6 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
.data = .{
.shift = .{
.is_imm = true,
- .width = .shift64,
.rd = reg,
.rs1 = reg,
.rs2_or_imm = .{ .imm = 32 },
@@ -3768,7 +3764,6 @@ fn truncRegister(
.data = .{
.shift = .{
.is_imm = true,
- .width = ShiftWidth.shift64,
.rd = dest_reg,
.rs1 = operand_reg,
.rs2_or_imm = .{ .imm = @intCast(u6, 64 - int_bits) },
@@ -3783,7 +3778,6 @@ fn truncRegister(
.data = .{
.shift = .{
.is_imm = true,
- .width = ShiftWidth.shift32,
.rd = dest_reg,
.rs1 = dest_reg,
.rs2_or_imm = .{ .imm = @intCast(u6, int_bits) },
@@ -3800,7 +3794,6 @@ fn truncRegister(
.data = .{
.shift = .{
.is_imm = true,
- .width = ShiftWidth.shift32,
.rd = dest_reg,
.rs1 = operand_reg,
.rs2_or_imm = .{ .imm = 0 },
diff --git a/src/arch/sparc64/Emit.zig b/src/arch/sparc64/Emit.zig
index e1546fbc28..44680c2e12 100644
--- a/src/arch/sparc64/Emit.zig
+++ b/src/arch/sparc64/Emit.zig
@@ -115,12 +115,12 @@ pub fn emitMir(
.sethi => try emit.mirSethi(inst),
- .sll => @panic("TODO implement sparc64 sll"),
- .srl => @panic("TODO implement sparc64 srl"),
- .sra => @panic("TODO implement sparc64 sra"),
- .sllx => @panic("TODO implement sparc64 sllx"),
- .srlx => @panic("TODO implement sparc64 srlx"),
- .srax => @panic("TODO implement sparc64 srax"),
+ .sll => try emit.mirShift(inst),
+ .srl => try emit.mirShift(inst),
+ .sra => try emit.mirShift(inst),
+ .sllx => try emit.mirShift(inst),
+ .srlx => try emit.mirShift(inst),
+ .srax => try emit.mirShift(inst),
.stb => try emit.mirArithmetic3Op(inst),
.sth => try emit.mirArithmetic3Op(inst),
@@ -370,6 +370,38 @@ fn mirSethi(emit: *Emit, inst: Mir.Inst.Index) !void {
try emit.writeInstruction(Instruction.sethi(imm, rd));
}
+fn mirShift(emit: *Emit, inst: Mir.Inst.Index) !void {
+ const tag = emit.mir.instructions.items(.tag)[inst];
+ const data = emit.mir.instructions.items(.data)[inst].shift;
+
+ const rd = data.rd;
+ const rs1 = data.rs1;
+
+ if (data.is_imm) {
+ const imm = data.rs2_or_imm.imm;
+ switch (tag) {
+ .sll => try emit.writeInstruction(Instruction.sll(u5, rs1, @truncate(u5, imm), rd)),
+ .srl => try emit.writeInstruction(Instruction.srl(u5, rs1, @truncate(u5, imm), rd)),
+ .sra => try emit.writeInstruction(Instruction.sra(u5, rs1, @truncate(u5, imm), rd)),
+ .sllx => try emit.writeInstruction(Instruction.sllx(u6, rs1, imm, rd)),
+ .srlx => try emit.writeInstruction(Instruction.srlx(u6, rs1, imm, rd)),
+ .srax => try emit.writeInstruction(Instruction.srax(u6, rs1, imm, rd)),
+ else => unreachable,
+ }
+ } else {
+ const rs2 = data.rs2_or_imm.rs2;
+ switch (tag) {
+ .sll => try emit.writeInstruction(Instruction.sll(Register, rs1, rs2, rd)),
+ .srl => try emit.writeInstruction(Instruction.srl(Register, rs1, rs2, rd)),
+ .sra => try emit.writeInstruction(Instruction.sra(Register, rs1, rs2, rd)),
+ .sllx => try emit.writeInstruction(Instruction.sllx(Register, rs1, rs2, rd)),
+ .srlx => try emit.writeInstruction(Instruction.srlx(Register, rs1, rs2, rd)),
+ .srax => try emit.writeInstruction(Instruction.srax(Register, rs1, rs2, rd)),
+ else => unreachable,
+ }
+ }
+}
+
fn mirTrap(emit: *Emit, inst: Mir.Inst.Index) !void {
const tag = emit.mir.instructions.items(.tag)[inst];
const data = emit.mir.instructions.items(.data)[inst].trap;
diff --git a/src/arch/sparc64/Mir.zig b/src/arch/sparc64/Mir.zig
index 25b4a4ce2c..3ae84d0961 100644
--- a/src/arch/sparc64/Mir.zig
+++ b/src/arch/sparc64/Mir.zig
@@ -299,7 +299,6 @@ pub const Inst = struct {
/// Used by e.g. sllx
shift: struct {
is_imm: bool,
- width: Instruction.ShiftWidth,
rd: Register,
rs1: Register,
rs2_or_imm: union {
diff --git a/src/arch/sparc64/bits.zig b/src/arch/sparc64/bits.zig
index 5c856ea756..a722d06dee 100644
--- a/src/arch/sparc64/bits.zig
+++ b/src/arch/sparc64/bits.zig
@@ -1313,6 +1313,54 @@ pub const Instruction = union(enum) {
return format2a(0b100, imm, rd);
}
+ pub fn sll(comptime s2: type, rs1: Register, rs2: s2, rd: Register) Instruction {
+ return switch (s2) {
+ Register => format3k(0b11, 0b10_0101, .shift32, rs1, rs2, rd),
+ u5 => format3l(0b11, 0b10_0101, rs1, rs2, rd),
+ else => unreachable,
+ };
+ }
+
+ pub fn srl(comptime s2: type, rs1: Register, rs2: s2, rd: Register) Instruction {
+ return switch (s2) {
+ Register => format3k(0b11, 0b10_0110, .shift32, rs1, rs2, rd),
+ u5 => format3l(0b11, 0b10_0110, rs1, rs2, rd),
+ else => unreachable,
+ };
+ }
+
+ pub fn sra(comptime s2: type, rs1: Register, rs2: s2, rd: Register) Instruction {
+ return switch (s2) {
+ Register => format3k(0b11, 0b10_0111, .shift32, rs1, rs2, rd),
+ u5 => format3l(0b11, 0b10_0111, rs1, rs2, rd),
+ else => unreachable,
+ };
+ }
+
+ pub fn sllx(comptime s2: type, rs1: Register, rs2: s2, rd: Register) Instruction {
+ return switch (s2) {
+ Register => format3k(0b11, 0b10_0101, .shift64, rs1, rs2, rd),
+ u6 => format3m(0b11, 0b10_0101, rs1, rs2, rd),
+ else => unreachable,
+ };
+ }
+
+ pub fn srlx(comptime s2: type, rs1: Register, rs2: s2, rd: Register) Instruction {
+ return switch (s2) {
+ Register => format3k(0b11, 0b10_0110, .shift64, rs1, rs2, rd),
+ u6 => format3m(0b11, 0b10_0110, rs1, rs2, rd),
+ else => unreachable,
+ };
+ }
+
+ pub fn srax(comptime s2: type, rs1: Register, rs2: s2, rd: Register) Instruction {
+ return switch (s2) {
+ Register => format3k(0b11, 0b10_0111, .shift64, rs1, rs2, rd),
+ u6 => format3m(0b11, 0b10_0111, rs1, rs2, rd),
+ else => unreachable,
+ };
+ }
+
pub fn stb(comptime s2: type, rs1: Register, rs2: s2, rd: Register) Instruction {
return switch (s2) {
Register => format3a(0b11, 0b00_0101, rs1, rs2, rd),