diff options
| author | Koakuma <koachan@protonmail.com> | 2022-06-16 23:53:22 +0700 |
|---|---|---|
| committer | Koakuma <koachan@protonmail.com> | 2022-06-24 21:19:33 +0700 |
| commit | 4d15284c3cbeefa771baa2b69866b2f0252f147b (patch) | |
| tree | e7525ac6b6ee1e4a494c17159206dcce9ed64867 /src | |
| parent | 513ab4eb568da6fb926dd33ae067d31cf4831e79 (diff) | |
| download | zig-4d15284c3cbeefa771baa2b69866b2f0252f147b.tar.gz zig-4d15284c3cbeefa771baa2b69866b2f0252f147b.zip | |
stage2: sparc64: Implement SPARCv9 shifts
Diffstat (limited to 'src')
| -rw-r--r-- | src/arch/sparc64/CodeGen.zig | 7 | ||||
| -rw-r--r-- | src/arch/sparc64/Emit.zig | 44 | ||||
| -rw-r--r-- | src/arch/sparc64/Mir.zig | 1 | ||||
| -rw-r--r-- | src/arch/sparc64/bits.zig | 48 |
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), |
