diff --git a/lib/std/builtin.zig b/lib/std/builtin.zig index e0e0edf906..b28e17e38b 100644 --- a/lib/std/builtin.zig +++ b/lib/std/builtin.zig @@ -760,9 +760,7 @@ pub fn default_panic(msg: []const u8, error_return_trace: ?*StackTrace, ret_addr @setCold(true); // stage2_riscv64 backend doesn't support loops yet. - if (builtin.zig_backend == .stage2_riscv64 or - builtin.cpu.arch == .riscv64) - { + if (builtin.zig_backend == .stage2_riscv64) { unreachable; } diff --git a/src/arch/riscv64/CodeGen.zig b/src/arch/riscv64/CodeGen.zig index 4e91c0852a..e7b2506a01 100644 --- a/src/arch/riscv64/CodeGen.zig +++ b/src/arch/riscv64/CodeGen.zig @@ -1385,8 +1385,44 @@ fn airPopcount(self: *Self, inst: Air.Inst.Index) !void { } fn airAbs(self: *Self, inst: Air.Inst.Index) !void { + const mod = self.bin_file.comp.module.?; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; - const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement airAbs for {}", .{self.target.cpu.arch}); + const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { + const ty = self.typeOf(ty_op.operand); + const scalar_ty = ty.scalarType(mod); + const operand = try self.resolveInst(ty_op.operand); + + switch (scalar_ty.zigTypeTag(mod)) { + .Int => if (ty.zigTypeTag(mod) == .Vector) { + return self.fail("TODO implement airAbs for {}", .{ty.fmt(mod)}); + } else { + const int_bits = ty.intInfo(mod).bits; + + if (int_bits > 32) { + return self.fail("TODO: airAbs for larger than 32 bits", .{}); + } + + // promote the src into a register + const src_mcv = try self.copyToNewRegister(inst, operand); + // temp register for shift + const temp_reg = try self.register_manager.allocReg(inst, gp); + + _ = try self.addInst(.{ + .tag = .abs, + .data = .{ + .i_type = .{ + .rs1 = src_mcv.register, + .rd = temp_reg, + .imm12 = @intCast(int_bits - 1), + }, + }, + }); + + break :result src_mcv; + }, + else => return self.fail("TODO: implement airAbs {}", .{scalar_ty.fmt(mod)}), + } + }; return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); } @@ -1603,8 +1639,6 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void { self.register_manager.getRegAssumeFree(src_reg, inst); break :dst src_mcv; }, - // don't need to allocate anything, can just be used immediately. - .stack_offset => src_mcv, else => return self.fail("TODO: airArg {s}", .{@tagName(src_mcv)}), }; diff --git a/src/arch/riscv64/Emit.zig b/src/arch/riscv64/Emit.zig index a82d5fb602..cfd61f8189 100644 --- a/src/arch/riscv64/Emit.zig +++ b/src/arch/riscv64/Emit.zig @@ -58,6 +58,7 @@ pub fn emitMir( .addi => try emit.mirIType(inst), .jalr => try emit.mirIType(inst), + .abs => try emit.mirIType(inst), .jal => try emit.mirJType(inst), @@ -200,6 +201,12 @@ fn mirIType(emit: *Emit, inst: Mir.Inst.Index) !void { .ldr_ptr_stack => try emit.writeInstruction(Instruction.add(i_type.rd, i_type.rs1, .sp)), + .abs => { + try emit.writeInstruction(Instruction.sraiw(i_type.rd, i_type.rs1, @intCast(i_type.imm12))); + try emit.writeInstruction(Instruction.xor(i_type.rs1, i_type.rs1, i_type.rd)); + try emit.writeInstruction(Instruction.subw(i_type.rs1, i_type.rs1, i_type.rd)); + }, + else => unreachable, } } diff --git a/src/arch/riscv64/Mir.zig b/src/arch/riscv64/Mir.zig index 4154c129cd..38d7fe59f0 100644 --- a/src/arch/riscv64/Mir.zig +++ b/src/arch/riscv64/Mir.zig @@ -38,6 +38,9 @@ pub const Inst = struct { /// Subtraction sub, + /// Absolute Value, uses i_type payload. + abs, + jal, /// Jumps. Uses `inst` payload. j, diff --git a/src/arch/riscv64/bits.zig b/src/arch/riscv64/bits.zig index 2239bd49f8..f987c7fc74 100644 --- a/src/arch/riscv64/bits.zig +++ b/src/arch/riscv64/bits.zig @@ -250,7 +250,7 @@ pub const Instruction = union(enum) { } pub fn srai(rd: Register, r1: Register, shamt: u6) Instruction { - return iType(0b0010011, 0b101, rd, r1, (1 << 10) + shamt); + return iType(0b0010011, 0b101, rd, r1, (@as(i12, 1) << 10) + shamt); } pub fn slti(rd: Register, r1: Register, imm: i12) Instruction { @@ -267,16 +267,16 @@ pub const Instruction = union(enum) { return iType(0b0011011, 0b000, rd, r1, imm); } - pub fn slliw(rd: Register, r1: Register, shamt: u5) Instruction { + pub fn slliw(rd: Register, r1: Register, shamt: u6) Instruction { return iType(0b0011011, 0b001, rd, r1, shamt); } - pub fn srliw(rd: Register, r1: Register, shamt: u5) Instruction { + pub fn srliw(rd: Register, r1: Register, shamt: u6) Instruction { return iType(0b0011011, 0b101, rd, r1, shamt); } - pub fn sraiw(rd: Register, r1: Register, shamt: u5) Instruction { - return iType(0b0011011, 0b101, rd, r1, (1 << 10) + shamt); + pub fn sraiw(rd: Register, r1: Register, shamt: u6) Instruction { + return iType(0b0011011, 0b101, rd, r1, (@as(i12, 1) << 10) + shamt); } // Upper Immediate diff --git a/src/target.zig b/src/target.zig index 99b9abcab8..ea58111bc1 100644 --- a/src/target.zig +++ b/src/target.zig @@ -507,7 +507,7 @@ pub fn zigBackend(target: std.Target, use_llvm: bool) std.builtin.CompilerBacken if (use_llvm) return .stage2_llvm; if (target.ofmt == .c) return .stage2_c; return switch (target.cpu.arch) { - .wasm32, .wasm64 => std.builtin.CompilerBackend.stage2_wasm, + .wasm32, .wasm64 => .stage2_wasm, .arm, .armeb, .thumb, .thumbeb => .stage2_arm, .x86_64 => .stage2_x86_64, .x86 => .stage2_x86,