riscv: implement @floatFromInt

This commit is contained in:
David Rubin 2024-07-24 19:31:51 -07:00
parent 1a7d89a84d
commit c00a5ff792
No known key found for this signature in database
GPG Key ID: A4390FEB5F00C0A5
5 changed files with 82 additions and 7 deletions

View File

@ -6712,9 +6712,65 @@ fn airArrayToSlice(func: *Func, inst: Air.Inst.Index) !void {
fn airFloatFromInt(func: *Func, inst: Air.Inst.Index) !void {
const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement airFloatFromInt for {}", .{
func.target.cpu.arch,
});
const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
const pt = func.pt;
const zcu = pt.zcu;
const operand = try func.resolveInst(ty_op.operand);
const src_ty = func.typeOf(ty_op.operand);
const dst_ty = ty_op.ty.toType();
const src_reg, const src_lock = try func.promoteReg(src_ty, operand);
defer if (src_lock) |lock| func.register_manager.unlockReg(lock);
const is_unsigned = dst_ty.isUnsignedInt(zcu);
const src_bits = src_ty.bitSize(pt);
const dst_bits = dst_ty.bitSize(pt);
switch (src_bits) {
32, 64 => {},
else => try func.truncateRegister(src_ty, src_reg),
}
const int_mod: Mir.FcvtOp = switch (src_bits) {
8, 16, 32 => if (is_unsigned) .wu else .w,
64 => if (is_unsigned) .lu else .l,
else => return func.fail("TODO: airFloatFromInt src size: {d}", .{src_bits}),
};
const float_mod: enum { s, d } = switch (dst_bits) {
32 => .s,
64 => .d,
else => return func.fail("TODO: airFloatFromInt dst size {d}", .{dst_bits}),
};
const dst_reg, const dst_lock = try func.allocReg(.int);
defer func.register_manager.unlockReg(dst_lock);
_ = try func.addInst(.{
.tag = switch (float_mod) {
.s => switch (int_mod) {
.l => .fcvtsl,
.lu => .fcvtslu,
.w => .fcvtsw,
.wu => .fcvtswu,
},
.d => switch (int_mod) {
.l => .fcvtdl,
.lu => .fcvtdlu,
.w => .fcvtdw,
.wu => .fcvtdwu,
},
},
.data = .{ .rr = .{
.rd = dst_reg,
.rs = src_reg,
} },
});
break :result .{ .register = dst_reg };
};
return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
}
@ -6726,7 +6782,7 @@ fn airIntFromFloat(func: *Func, inst: Air.Inst.Index) !void {
const operand = try func.resolveInst(ty_op.operand);
const src_ty = func.typeOf(ty_op.operand);
const dst_ty = func.typeOfIndex(inst);
const dst_ty = ty_op.ty.toType();
const is_unsigned = dst_ty.isUnsignedInt(zcu);
const src_bits = src_ty.bitSize(pt);
@ -6740,7 +6796,7 @@ fn airIntFromFloat(func: *Func, inst: Air.Inst.Index) !void {
const int_mod: Mir.FcvtOp = switch (dst_bits) {
32 => if (is_unsigned) .wu else .w,
64 => if (is_unsigned) .lu else .l,
8, 16, 64 => if (is_unsigned) .lu else .l,
else => return func.fail("TODO: airIntFromFloat dst size: {d}", .{dst_bits}),
};

View File

@ -280,6 +280,16 @@ pub const Lir = struct {
.fcvtld => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fcvt = .{ .funct5 = 0b11000, .fmt = .D, .rm = 0b111, .width = .l } } },
.fcvtlud => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fcvt = .{ .funct5 = 0b11000, .fmt = .D, .rm = 0b111, .width = .lu } } },
.fcvtsw => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fcvt = .{ .funct5 = 0b11010, .fmt = .S, .rm = 0b111, .width = .w } } },
.fcvtswu => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fcvt = .{ .funct5 = 0b11010, .fmt = .S, .rm = 0b111, .width = .wu } } },
.fcvtsl => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fcvt = .{ .funct5 = 0b11010, .fmt = .S, .rm = 0b111, .width = .l } } },
.fcvtslu => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fcvt = .{ .funct5 = 0b11010, .fmt = .S, .rm = 0b111, .width = .lu } } },
.fcvtdw => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fcvt = .{ .funct5 = 0b11010, .fmt = .D, .rm = 0b111, .width = .w } } },
.fcvtdwu => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fcvt = .{ .funct5 = 0b11010, .fmt = .D, .rm = 0b111, .width = .wu } } },
.fcvtdl => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fcvt = .{ .funct5 = 0b11010, .fmt = .D, .rm = 0b111, .width = .l } } },
.fcvtdlu => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fcvt = .{ .funct5 = 0b11010, .fmt = .D, .rm = 0b111, .width = .lu } } },
// LOAD
.lb => .{ .opcode = .LOAD, .format = .I, .data = .{ .f = .{ .funct3 = 0b000 } } },

View File

@ -127,6 +127,16 @@ pub const Mnemonic = enum(u16) {
fcvtld,
fcvtlud,
fcvtsw,
fcvtswu,
fcvtsl,
fcvtslu,
fcvtdw,
fcvtdwu,
fcvtdl,
fcvtdlu,
fsgnjns,
fsgnjnd,

View File

@ -514,6 +514,7 @@ test "struct field explicit alignment" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // flaky
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
const S = struct {
const Node = struct {

View File

@ -104,7 +104,6 @@ test "@floatFromInt" {
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_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
const S = struct {
fn doTheTest() !void {
@ -163,7 +162,6 @@ test "@intFromFloat" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
try testIntFromFloats();
try comptime testIntFromFloats();