| author | |
| committer | |
| log | c00a5ff792e78564673d0dc76b901c98b938bb9b |
| tree | f95878ab09d8666ebf4a610869241635130ed3e3 |
| parent | 1a7d89a84d7fef87eb45da8207bbeb852e3f0c02 |
| signature |
5 files changed, 82 insertions(+), 7 deletions(-)
src/arch/riscv64/CodeGen.zig+61-5| ... | @@ -6712,9 +6712,65 @@ fn airArrayToSlice(func: *Func, inst: Air.Inst.Index) !void { | ... | @@ -6712,9 +6712,65 @@ fn airArrayToSlice(func: *Func, inst: Air.Inst.Index) !void { |
| 6712 | 6712 | ||
| 6713 | fn airFloatFromInt(func: *Func, inst: Air.Inst.Index) !void { | 6713 | fn airFloatFromInt(func: *Func, inst: Air.Inst.Index) !void { |
| 6714 | const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; | 6714 | const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 6715 | const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement airFloatFromInt for {}", .{ | 6715 | const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: { |
| 6716 | func.target.cpu.arch, | 6716 | const pt = func.pt; |
| 6717 | }); | 6717 | const zcu = pt.zcu; |
| 6718 | |||
| 6719 | const operand = try func.resolveInst(ty_op.operand); | ||
| 6720 | |||
| 6721 | const src_ty = func.typeOf(ty_op.operand); | ||
| 6722 | const dst_ty = ty_op.ty.toType(); | ||
| 6723 | |||
| 6724 | const src_reg, const src_lock = try func.promoteReg(src_ty, operand); | ||
| 6725 | defer if (src_lock) |lock| func.register_manager.unlockReg(lock); | ||
| 6726 | |||
| 6727 | const is_unsigned = dst_ty.isUnsignedInt(zcu); | ||
| 6728 | const src_bits = src_ty.bitSize(pt); | ||
| 6729 | const dst_bits = dst_ty.bitSize(pt); | ||
| 6730 | |||
| 6731 | switch (src_bits) { | ||
| 6732 | 32, 64 => {}, | ||
| 6733 | else => try func.truncateRegister(src_ty, src_reg), | ||
| 6734 | } | ||
| 6735 | |||
| 6736 | const int_mod: Mir.FcvtOp = switch (src_bits) { | ||
| 6737 | 8, 16, 32 => if (is_unsigned) .wu else .w, | ||
| 6738 | 64 => if (is_unsigned) .lu else .l, | ||
| 6739 | else => return func.fail("TODO: airFloatFromInt src size: {d}", .{src_bits}), | ||
| 6740 | }; | ||
| 6741 | |||
| 6742 | const float_mod: enum { s, d } = switch (dst_bits) { | ||
| 6743 | 32 => .s, | ||
| 6744 | 64 => .d, | ||
| 6745 | else => return func.fail("TODO: airFloatFromInt dst size {d}", .{dst_bits}), | ||
| 6746 | }; | ||
| 6747 | |||
| 6748 | const dst_reg, const dst_lock = try func.allocReg(.int); | ||
| 6749 | defer func.register_manager.unlockReg(dst_lock); | ||
| 6750 | |||
| 6751 | _ = try func.addInst(.{ | ||
| 6752 | .tag = switch (float_mod) { | ||
| 6753 | .s => switch (int_mod) { | ||
| 6754 | .l => .fcvtsl, | ||
| 6755 | .lu => .fcvtslu, | ||
| 6756 | .w => .fcvtsw, | ||
| 6757 | .wu => .fcvtswu, | ||
| 6758 | }, | ||
| 6759 | .d => switch (int_mod) { | ||
| 6760 | .l => .fcvtdl, | ||
| 6761 | .lu => .fcvtdlu, | ||
| 6762 | .w => .fcvtdw, | ||
| 6763 | .wu => .fcvtdwu, | ||
| 6764 | }, | ||
| 6765 | }, | ||
| 6766 | .data = .{ .rr = .{ | ||
| 6767 | .rd = dst_reg, | ||
| 6768 | .rs = src_reg, | ||
| 6769 | } }, | ||
| 6770 | }); | ||
| 6771 | |||
| 6772 | break :result .{ .register = dst_reg }; | ||
| 6773 | }; | ||
| 6718 | return func.finishAir(inst, result, .{ ty_op.operand, .none, .none }); | 6774 | return func.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 6719 | } | 6775 | } |
| 6720 | 6776 | ||
| ... | @@ -6726,7 +6782,7 @@ fn airIntFromFloat(func: *Func, inst: Air.Inst.Index) !void { | ... | @@ -6726,7 +6782,7 @@ fn airIntFromFloat(func: *Func, inst: Air.Inst.Index) !void { |
| 6726 | 6782 | ||
| 6727 | const operand = try func.resolveInst(ty_op.operand); | 6783 | const operand = try func.resolveInst(ty_op.operand); |
| 6728 | const src_ty = func.typeOf(ty_op.operand); | 6784 | const src_ty = func.typeOf(ty_op.operand); |
| 6729 | const dst_ty = func.typeOfIndex(inst); | 6785 | const dst_ty = ty_op.ty.toType(); |
| 6730 | 6786 | ||
| 6731 | const is_unsigned = dst_ty.isUnsignedInt(zcu); | 6787 | const is_unsigned = dst_ty.isUnsignedInt(zcu); |
| 6732 | const src_bits = src_ty.bitSize(pt); | 6788 | const src_bits = src_ty.bitSize(pt); |
| ... | @@ -6740,7 +6796,7 @@ fn airIntFromFloat(func: *Func, inst: Air.Inst.Index) !void { | ... | @@ -6740,7 +6796,7 @@ fn airIntFromFloat(func: *Func, inst: Air.Inst.Index) !void { |
| 6740 | 6796 | ||
| 6741 | const int_mod: Mir.FcvtOp = switch (dst_bits) { | 6797 | const int_mod: Mir.FcvtOp = switch (dst_bits) { |
| 6742 | 32 => if (is_unsigned) .wu else .w, | 6798 | 32 => if (is_unsigned) .wu else .w, |
| 6743 | 64 => if (is_unsigned) .lu else .l, | 6799 | 8, 16, 64 => if (is_unsigned) .lu else .l, |
| 6744 | else => return func.fail("TODO: airIntFromFloat dst size: {d}", .{dst_bits}), | 6800 | else => return func.fail("TODO: airIntFromFloat dst size: {d}", .{dst_bits}), |
| 6745 | }; | 6801 | }; |
| 6746 | 6802 |
src/arch/riscv64/encoding.zig+10| ... | @@ -280,6 +280,16 @@ pub const Lir = struct { | ... | @@ -280,6 +280,16 @@ pub const Lir = struct { |
| 280 | .fcvtld => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fcvt = .{ .funct5 = 0b11000, .fmt = .D, .rm = 0b111, .width = .l } } }, | 280 | .fcvtld => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fcvt = .{ .funct5 = 0b11000, .fmt = .D, .rm = 0b111, .width = .l } } }, |
| 281 | .fcvtlud => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fcvt = .{ .funct5 = 0b11000, .fmt = .D, .rm = 0b111, .width = .lu } } }, | 281 | .fcvtlud => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fcvt = .{ .funct5 = 0b11000, .fmt = .D, .rm = 0b111, .width = .lu } } }, |
| 282 | 282 | ||
| 283 | .fcvtsw => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fcvt = .{ .funct5 = 0b11010, .fmt = .S, .rm = 0b111, .width = .w } } }, | ||
| 284 | .fcvtswu => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fcvt = .{ .funct5 = 0b11010, .fmt = .S, .rm = 0b111, .width = .wu } } }, | ||
| 285 | .fcvtsl => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fcvt = .{ .funct5 = 0b11010, .fmt = .S, .rm = 0b111, .width = .l } } }, | ||
| 286 | .fcvtslu => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fcvt = .{ .funct5 = 0b11010, .fmt = .S, .rm = 0b111, .width = .lu } } }, | ||
| 287 | |||
| 288 | .fcvtdw => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fcvt = .{ .funct5 = 0b11010, .fmt = .D, .rm = 0b111, .width = .w } } }, | ||
| 289 | .fcvtdwu => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fcvt = .{ .funct5 = 0b11010, .fmt = .D, .rm = 0b111, .width = .wu } } }, | ||
| 290 | .fcvtdl => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fcvt = .{ .funct5 = 0b11010, .fmt = .D, .rm = 0b111, .width = .l } } }, | ||
| 291 | .fcvtdlu => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fcvt = .{ .funct5 = 0b11010, .fmt = .D, .rm = 0b111, .width = .lu } } }, | ||
| 292 | |||
| 283 | // LOAD | 293 | // LOAD |
| 284 | 294 | ||
| 285 | .lb => .{ .opcode = .LOAD, .format = .I, .data = .{ .f = .{ .funct3 = 0b000 } } }, | 295 | .lb => .{ .opcode = .LOAD, .format = .I, .data = .{ .f = .{ .funct3 = 0b000 } } }, |
src/arch/riscv64/mnem.zig+10| ... | @@ -127,6 +127,16 @@ pub const Mnemonic = enum(u16) { | ... | @@ -127,6 +127,16 @@ pub const Mnemonic = enum(u16) { |
| 127 | fcvtld, | 127 | fcvtld, |
| 128 | fcvtlud, | 128 | fcvtlud, |
| 129 | 129 | ||
| 130 | fcvtsw, | ||
| 131 | fcvtswu, | ||
| 132 | fcvtsl, | ||
| 133 | fcvtslu, | ||
| 134 | |||
| 135 | fcvtdw, | ||
| 136 | fcvtdwu, | ||
| 137 | fcvtdl, | ||
| 138 | fcvtdlu, | ||
| 139 | |||
| 130 | fsgnjns, | 140 | fsgnjns, |
| 131 | fsgnjnd, | 141 | fsgnjnd, |
| 132 | 142 |
test/behavior/align.zig+1| ... | @@ -514,6 +514,7 @@ test "struct field explicit alignment" { | ... | @@ -514,6 +514,7 @@ test "struct field explicit alignment" { |
| 514 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 514 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 515 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 515 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 516 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // flaky | 516 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // flaky |
| 517 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | ||
| 517 | 518 | ||
| 518 | const S = struct { | 519 | const S = struct { |
| 519 | const Node = struct { | 520 | const Node = struct { |
test/behavior/cast.zig-2| ... | @@ -104,7 +104,6 @@ test "@floatFromInt" { | ... | @@ -104,7 +104,6 @@ test "@floatFromInt" { |
| 104 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 104 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 105 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 105 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 106 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 106 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 107 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | ||
| 108 | 107 | ||
| 109 | const S = struct { | 108 | const S = struct { |
| 110 | fn doTheTest() !void { | 109 | fn doTheTest() !void { |
| ... | @@ -163,7 +162,6 @@ test "@intFromFloat" { | ... | @@ -163,7 +162,6 @@ test "@intFromFloat" { |
| 163 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 162 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 164 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | 163 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 165 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 164 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 166 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | ||
| 167 | 165 | ||
| 168 | try testIntFromFloats(); | 166 | try testIntFromFloats(); |
| 169 | try comptime testIntFromFloats(); | 167 | try comptime testIntFromFloats(); |