mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 13:54:21 +00:00
riscv: integer + float @abs
This commit is contained in:
parent
206e66858c
commit
d69c48370a
8 changed files with 112 additions and 11 deletions
|
|
@ -3377,18 +3377,83 @@ fn airAbs(func: *Func, inst: Air.Inst.Index) !void {
|
||||||
const ty = func.typeOf(ty_op.operand);
|
const ty = func.typeOf(ty_op.operand);
|
||||||
const scalar_ty = ty.scalarType(zcu);
|
const scalar_ty = ty.scalarType(zcu);
|
||||||
const operand = try func.resolveInst(ty_op.operand);
|
const operand = try func.resolveInst(ty_op.operand);
|
||||||
_ = operand;
|
|
||||||
|
|
||||||
switch (scalar_ty.zigTypeTag(zcu)) {
|
switch (scalar_ty.zigTypeTag(zcu)) {
|
||||||
.Int => if (ty.zigTypeTag(zcu) == .Vector) {
|
.Int => if (ty.zigTypeTag(zcu) == .Vector) {
|
||||||
return func.fail("TODO implement airAbs for {}", .{ty.fmt(zcu)});
|
return func.fail("TODO implement airAbs for {}", .{ty.fmt(zcu)});
|
||||||
} else {
|
} else {
|
||||||
return func.fail("TODO: implement airAbs for Int", .{});
|
const return_mcv = try func.copyToNewRegister(inst, operand);
|
||||||
|
const operand_reg = return_mcv.register;
|
||||||
|
|
||||||
|
const temp_reg, const temp_lock = try func.allocReg(.int);
|
||||||
|
defer func.register_manager.unlockReg(temp_lock);
|
||||||
|
|
||||||
|
_ = try func.addInst(.{
|
||||||
|
.tag = .srai,
|
||||||
|
.ops = .rri,
|
||||||
|
.data = .{ .i_type = .{
|
||||||
|
.rd = temp_reg,
|
||||||
|
.rs1 = operand_reg,
|
||||||
|
.imm12 = Immediate.s(63),
|
||||||
|
} },
|
||||||
|
});
|
||||||
|
|
||||||
|
_ = try func.addInst(.{
|
||||||
|
.tag = .xor,
|
||||||
|
.ops = .rrr,
|
||||||
|
.data = .{ .r_type = .{
|
||||||
|
.rd = operand_reg,
|
||||||
|
.rs1 = operand_reg,
|
||||||
|
.rs2 = temp_reg,
|
||||||
|
} },
|
||||||
|
});
|
||||||
|
|
||||||
|
_ = try func.addInst(.{
|
||||||
|
.tag = .sub,
|
||||||
|
.ops = .rrr,
|
||||||
|
.data = .{ .r_type = .{
|
||||||
|
.rd = operand_reg,
|
||||||
|
.rs1 = operand_reg,
|
||||||
|
.rs2 = temp_reg,
|
||||||
|
} },
|
||||||
|
});
|
||||||
|
|
||||||
|
break :result return_mcv;
|
||||||
|
},
|
||||||
|
.Float => {
|
||||||
|
const float_bits = scalar_ty.floatBits(zcu.getTarget());
|
||||||
|
switch (float_bits) {
|
||||||
|
16 => return func.fail("TODO: airAbs 16-bit float", .{}),
|
||||||
|
32 => {},
|
||||||
|
64 => {},
|
||||||
|
80 => return func.fail("TODO: airAbs 80-bit float", .{}),
|
||||||
|
128 => return func.fail("TODO: airAbs 128-bit float", .{}),
|
||||||
|
else => unreachable,
|
||||||
|
}
|
||||||
|
|
||||||
|
const return_mcv = try func.copyToNewRegister(inst, operand);
|
||||||
|
const operand_reg = return_mcv.register;
|
||||||
|
|
||||||
|
assert(operand_reg.class() == .float);
|
||||||
|
|
||||||
|
_ = try func.addInst(.{
|
||||||
|
.tag = .pseudo,
|
||||||
|
.ops = .pseudo_fabs,
|
||||||
|
.data = .{
|
||||||
|
.fabs = .{
|
||||||
|
.rd = operand_reg,
|
||||||
|
.rs = operand_reg,
|
||||||
|
.bits = float_bits,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
break :result return_mcv;
|
||||||
},
|
},
|
||||||
else => return func.fail("TODO: implement airAbs {}", .{scalar_ty.fmt(zcu)}),
|
else => return func.fail("TODO: implement airAbs {}", .{scalar_ty.fmt(zcu)}),
|
||||||
}
|
}
|
||||||
|
|
||||||
break :result .{.unreach};
|
break :result .unreach;
|
||||||
};
|
};
|
||||||
return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
|
return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -130,6 +130,7 @@ pub const Mnemonic = enum {
|
||||||
fles,
|
fles,
|
||||||
|
|
||||||
fsgnjns,
|
fsgnjns,
|
||||||
|
fsgnjxs,
|
||||||
|
|
||||||
// D extension (64-bit float)
|
// D extension (64-bit float)
|
||||||
faddd,
|
faddd,
|
||||||
|
|
@ -150,6 +151,7 @@ pub const Mnemonic = enum {
|
||||||
fled,
|
fled,
|
||||||
|
|
||||||
fsgnjnd,
|
fsgnjnd,
|
||||||
|
fsgnjxd,
|
||||||
|
|
||||||
pub fn encoding(mnem: Mnemonic) Enc {
|
pub fn encoding(mnem: Mnemonic) Enc {
|
||||||
return switch (mnem) {
|
return switch (mnem) {
|
||||||
|
|
@ -218,6 +220,9 @@ pub const Mnemonic = enum {
|
||||||
.fsgnjns => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00100, .fmt = .S, .rm = 0b000 } } },
|
.fsgnjns => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00100, .fmt = .S, .rm = 0b000 } } },
|
||||||
.fsgnjnd => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00100, .fmt = .D, .rm = 0b000 } } },
|
.fsgnjnd => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00100, .fmt = .D, .rm = 0b000 } } },
|
||||||
|
|
||||||
|
.fsgnjxs => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00100, .fmt = .S, .rm = 0b0010} } },
|
||||||
|
.fsgnjxd => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00100, .fmt = .D, .rm = 0b0010} } },
|
||||||
|
|
||||||
|
|
||||||
// LOAD
|
// LOAD
|
||||||
|
|
||||||
|
|
@ -392,6 +397,9 @@ pub const InstEnc = enum {
|
||||||
|
|
||||||
.fsgnjns,
|
.fsgnjns,
|
||||||
.fsgnjnd,
|
.fsgnjnd,
|
||||||
|
|
||||||
|
.fsgnjxs,
|
||||||
|
.fsgnjxd,
|
||||||
=> .R,
|
=> .R,
|
||||||
|
|
||||||
.ecall,
|
.ecall,
|
||||||
|
|
|
||||||
|
|
@ -208,6 +208,26 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
.pseudo_fabs => {
|
||||||
|
const fabs = inst.data.fabs;
|
||||||
|
assert(fabs.rs.class() == .float and fabs.rd.class() == .float);
|
||||||
|
|
||||||
|
const mnem: Encoding.Mnemonic = switch (fabs.bits) {
|
||||||
|
16 => return lower.fail("TODO: airAbs Float 16", .{}),
|
||||||
|
32 => .fsgnjxs,
|
||||||
|
64 => .fsgnjxd,
|
||||||
|
80 => return lower.fail("TODO: airAbs Float 80", .{}),
|
||||||
|
128 => return lower.fail("TODO: airAbs Float 128", .{}),
|
||||||
|
else => unreachable,
|
||||||
|
};
|
||||||
|
|
||||||
|
try lower.emit(mnem, &.{
|
||||||
|
.{ .reg = fabs.rs },
|
||||||
|
.{ .reg = fabs.rd },
|
||||||
|
.{ .reg = fabs.rd },
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
.pseudo_compare => {
|
.pseudo_compare => {
|
||||||
const compare = inst.data.compare;
|
const compare = inst.data.compare;
|
||||||
const op = compare.op;
|
const op = compare.op;
|
||||||
|
|
|
||||||
|
|
@ -76,6 +76,8 @@ pub const Inst = struct {
|
||||||
fmuls,
|
fmuls,
|
||||||
fdivs,
|
fdivs,
|
||||||
|
|
||||||
|
fabss,
|
||||||
|
|
||||||
fmins,
|
fmins,
|
||||||
fmaxs,
|
fmaxs,
|
||||||
|
|
||||||
|
|
@ -94,6 +96,8 @@ pub const Inst = struct {
|
||||||
fmuld,
|
fmuld,
|
||||||
fdivd,
|
fdivd,
|
||||||
|
|
||||||
|
fabsd,
|
||||||
|
|
||||||
fmind,
|
fmind,
|
||||||
fmaxd,
|
fmaxd,
|
||||||
|
|
||||||
|
|
@ -194,6 +198,12 @@ pub const Inst = struct {
|
||||||
rs: Register,
|
rs: Register,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
fabs: struct {
|
||||||
|
rd: Register,
|
||||||
|
rs: Register,
|
||||||
|
bits: u16,
|
||||||
|
},
|
||||||
|
|
||||||
compare: struct {
|
compare: struct {
|
||||||
rd: Register,
|
rd: Register,
|
||||||
rs1: Register,
|
rs1: Register,
|
||||||
|
|
@ -273,6 +283,9 @@ pub const Inst = struct {
|
||||||
/// Jumps. Uses `inst` payload.
|
/// Jumps. Uses `inst` payload.
|
||||||
pseudo_j,
|
pseudo_j,
|
||||||
|
|
||||||
|
/// Floating point absolute value.
|
||||||
|
pseudo_fabs,
|
||||||
|
|
||||||
/// Dead inst, ignored by the emitter.
|
/// Dead inst, ignored by the emitter.
|
||||||
pseudo_dead,
|
pseudo_dead,
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@ test "@abs integers" {
|
||||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||||
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
||||||
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
|
||||||
|
|
||||||
try comptime testAbsIntegers();
|
try comptime testAbsIntegers();
|
||||||
try testAbsIntegers();
|
try testAbsIntegers();
|
||||||
|
|
@ -93,18 +92,17 @@ test "@abs floats" {
|
||||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||||
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
||||||
if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
|
||||||
|
|
||||||
try comptime testAbsFloats(f16);
|
try comptime testAbsFloats(f16);
|
||||||
try testAbsFloats(f16);
|
if (builtin.zig_backend != .stage2_riscv64) try testAbsFloats(f16);
|
||||||
try comptime testAbsFloats(f32);
|
try comptime testAbsFloats(f32);
|
||||||
try testAbsFloats(f32);
|
try testAbsFloats(f32);
|
||||||
try comptime testAbsFloats(f64);
|
try comptime testAbsFloats(f64);
|
||||||
try testAbsFloats(f64);
|
try testAbsFloats(f64);
|
||||||
try comptime testAbsFloats(f80);
|
try comptime testAbsFloats(f80);
|
||||||
if (builtin.zig_backend != .stage2_wasm and builtin.zig_backend != .stage2_spirv64) try testAbsFloats(f80);
|
if (builtin.zig_backend != .stage2_wasm and builtin.zig_backend != .stage2_spirv64 and builtin.zig_backend != .stage2_riscv64) try testAbsFloats(f80);
|
||||||
try comptime testAbsFloats(f128);
|
try comptime testAbsFloats(f128);
|
||||||
if (builtin.zig_backend != .stage2_wasm and builtin.zig_backend != .stage2_spirv64) try testAbsFloats(f128);
|
if (builtin.zig_backend != .stage2_wasm and builtin.zig_backend != .stage2_spirv64 and builtin.zig_backend != .stage2_riscv64) try testAbsFloats(f128);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn testAbsFloats(comptime T: type) !void {
|
fn testAbsFloats(comptime T: type) !void {
|
||||||
|
|
|
||||||
|
|
@ -2608,7 +2608,6 @@ test "@as does not corrupt values with incompatible representations" {
|
||||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||||
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
||||||
if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
|
||||||
|
|
||||||
const x: f32 = @as(f16, blk: {
|
const x: f32 = @as(f16, blk: {
|
||||||
if (false) {
|
if (false) {
|
||||||
|
|
|
||||||
|
|
@ -999,7 +999,6 @@ test "@abs f32/f64" {
|
||||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||||
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
||||||
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
|
||||||
|
|
||||||
try testFabs(f32);
|
try testFabs(f32);
|
||||||
try comptime testFabs(f32);
|
try comptime testFabs(f32);
|
||||||
|
|
|
||||||
|
|
@ -1814,7 +1814,6 @@ test "absFloat" {
|
||||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||||
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
||||||
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
|
||||||
|
|
||||||
try testAbsFloat();
|
try testAbsFloat();
|
||||||
try comptime testAbsFloat();
|
try comptime testAbsFloat();
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue