mirror of
https://github.com/ziglang/zig.git
synced 2026-02-14 05:20:34 +00:00
riscv: implement @abs
- add the `abs` MIR instruction - implement `@abs` by shifting to the right by `bits - 1`, and xoring.
This commit is contained in:
parent
060c475fcd
commit
28df64cba4
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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)}),
|
||||
};
|
||||
|
||||
|
||||
@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
@ -38,6 +38,9 @@ pub const Inst = struct {
|
||||
/// Subtraction
|
||||
sub,
|
||||
|
||||
/// Absolute Value, uses i_type payload.
|
||||
abs,
|
||||
|
||||
jal,
|
||||
/// Jumps. Uses `inst` payload.
|
||||
j,
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user