| author | |
| committer | |
| log | d69c48370a0381c7dce463c68b2097dd8fa67eb7 |
| tree | a5f2fc954e7bd6b73164c8ef1c8742b5f2827649 |
| parent | 206e66858c69cd667aad3779837493968bfcd228 |
| signature |
8 files changed, 112 insertions(+), 11 deletions(-)
src/arch/riscv64/CodeGen.zig+68-3| ... | ... | @@ -3377,18 +3377,83 @@ fn airAbs(func: *Func, inst: Air.Inst.Index) !void { |
| 3377 | 3377 | const ty = func.typeOf(ty_op.operand); |
| 3378 | 3378 | const scalar_ty = ty.scalarType(zcu); |
| 3379 | 3379 | const operand = try func.resolveInst(ty_op.operand); |
| 3380 | _ = operand; | |
| 3381 | 3380 | |
| 3382 | 3381 | switch (scalar_ty.zigTypeTag(zcu)) { |
| 3383 | 3382 | .Int => if (ty.zigTypeTag(zcu) == .Vector) { |
| 3384 | 3383 | return func.fail("TODO implement airAbs for {}", .{ty.fmt(zcu)}); |
| 3385 | 3384 | } else { |
| 3386 | return func.fail("TODO: implement airAbs for Int", .{}); | |
| 3385 | const return_mcv = try func.copyToNewRegister(inst, operand); | |
| 3386 | const operand_reg = return_mcv.register; | |
| 3387 | ||
| 3388 | const temp_reg, const temp_lock = try func.allocReg(.int); | |
| 3389 | defer func.register_manager.unlockReg(temp_lock); | |
| 3390 | ||
| 3391 | _ = try func.addInst(.{ | |
| 3392 | .tag = .srai, | |
| 3393 | .ops = .rri, | |
| 3394 | .data = .{ .i_type = .{ | |
| 3395 | .rd = temp_reg, | |
| 3396 | .rs1 = operand_reg, | |
| 3397 | .imm12 = Immediate.s(63), | |
| 3398 | } }, | |
| 3399 | }); | |
| 3400 | ||
| 3401 | _ = try func.addInst(.{ | |
| 3402 | .tag = .xor, | |
| 3403 | .ops = .rrr, | |
| 3404 | .data = .{ .r_type = .{ | |
| 3405 | .rd = operand_reg, | |
| 3406 | .rs1 = operand_reg, | |
| 3407 | .rs2 = temp_reg, | |
| 3408 | } }, | |
| 3409 | }); | |
| 3410 | ||
| 3411 | _ = try func.addInst(.{ | |
| 3412 | .tag = .sub, | |
| 3413 | .ops = .rrr, | |
| 3414 | .data = .{ .r_type = .{ | |
| 3415 | .rd = operand_reg, | |
| 3416 | .rs1 = operand_reg, | |
| 3417 | .rs2 = temp_reg, | |
| 3418 | } }, | |
| 3419 | }); | |
| 3420 | ||
| 3421 | break :result return_mcv; | |
| 3422 | }, | |
| 3423 | .Float => { | |
| 3424 | const float_bits = scalar_ty.floatBits(zcu.getTarget()); | |
| 3425 | switch (float_bits) { | |
| 3426 | 16 => return func.fail("TODO: airAbs 16-bit float", .{}), | |
| 3427 | 32 => {}, | |
| 3428 | 64 => {}, | |
| 3429 | 80 => return func.fail("TODO: airAbs 80-bit float", .{}), | |
| 3430 | 128 => return func.fail("TODO: airAbs 128-bit float", .{}), | |
| 3431 | else => unreachable, | |
| 3432 | } | |
| 3433 | ||
| 3434 | const return_mcv = try func.copyToNewRegister(inst, operand); | |
| 3435 | const operand_reg = return_mcv.register; | |
| 3436 | ||
| 3437 | assert(operand_reg.class() == .float); | |
| 3438 | ||
| 3439 | _ = try func.addInst(.{ | |
| 3440 | .tag = .pseudo, | |
| 3441 | .ops = .pseudo_fabs, | |
| 3442 | .data = .{ | |
| 3443 | .fabs = .{ | |
| 3444 | .rd = operand_reg, | |
| 3445 | .rs = operand_reg, | |
| 3446 | .bits = float_bits, | |
| 3447 | }, | |
| 3448 | }, | |
| 3449 | }); | |
| 3450 | ||
| 3451 | break :result return_mcv; | |
| 3387 | 3452 | }, |
| 3388 | 3453 | else => return func.fail("TODO: implement airAbs {}", .{scalar_ty.fmt(zcu)}), |
| 3389 | 3454 | } |
| 3390 | 3455 | |
| 3391 | break :result .{.unreach}; | |
| 3456 | break :result .unreach; | |
| 3392 | 3457 | }; |
| 3393 | 3458 | return func.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 3394 | 3459 | } |
src/arch/riscv64/Encoding.zig+8| ... | ... | @@ -130,6 +130,7 @@ pub const Mnemonic = enum { |
| 130 | 130 | fles, |
| 131 | 131 | |
| 132 | 132 | fsgnjns, |
| 133 | fsgnjxs, | |
| 133 | 134 | |
| 134 | 135 | // D extension (64-bit float) |
| 135 | 136 | faddd, |
| ... | ... | @@ -150,6 +151,7 @@ pub const Mnemonic = enum { |
| 150 | 151 | fled, |
| 151 | 152 | |
| 152 | 153 | fsgnjnd, |
| 154 | fsgnjxd, | |
| 153 | 155 | |
| 154 | 156 | pub fn encoding(mnem: Mnemonic) Enc { |
| 155 | 157 | return switch (mnem) { |
| ... | ... | @@ -218,6 +220,9 @@ pub const Mnemonic = enum { |
| 218 | 220 | .fsgnjns => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00100, .fmt = .S, .rm = 0b000 } } }, |
| 219 | 221 | .fsgnjnd => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00100, .fmt = .D, .rm = 0b000 } } }, |
| 220 | 222 | |
| 223 | .fsgnjxs => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00100, .fmt = .S, .rm = 0b0010} } }, | |
| 224 | .fsgnjxd => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00100, .fmt = .D, .rm = 0b0010} } }, | |
| 225 | ||
| 221 | 226 | |
| 222 | 227 | // LOAD |
| 223 | 228 | |
| ... | ... | @@ -392,6 +397,9 @@ pub const InstEnc = enum { |
| 392 | 397 | |
| 393 | 398 | .fsgnjns, |
| 394 | 399 | .fsgnjnd, |
| 400 | ||
| 401 | .fsgnjxs, | |
| 402 | .fsgnjxd, | |
| 395 | 403 | => .R, |
| 396 | 404 | |
| 397 | 405 | .ecall, |
src/arch/riscv64/Lower.zig+20| ... | ... | @@ -208,6 +208,26 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct { |
| 208 | 208 | }); |
| 209 | 209 | }, |
| 210 | 210 | |
| 211 | .pseudo_fabs => { | |
| 212 | const fabs = inst.data.fabs; | |
| 213 | assert(fabs.rs.class() == .float and fabs.rd.class() == .float); | |
| 214 | ||
| 215 | const mnem: Encoding.Mnemonic = switch (fabs.bits) { | |
| 216 | 16 => return lower.fail("TODO: airAbs Float 16", .{}), | |
| 217 | 32 => .fsgnjxs, | |
| 218 | 64 => .fsgnjxd, | |
| 219 | 80 => return lower.fail("TODO: airAbs Float 80", .{}), | |
| 220 | 128 => return lower.fail("TODO: airAbs Float 128", .{}), | |
| 221 | else => unreachable, | |
| 222 | }; | |
| 223 | ||
| 224 | try lower.emit(mnem, &.{ | |
| 225 | .{ .reg = fabs.rs }, | |
| 226 | .{ .reg = fabs.rd }, | |
| 227 | .{ .reg = fabs.rd }, | |
| 228 | }); | |
| 229 | }, | |
| 230 | ||
| 211 | 231 | .pseudo_compare => { |
| 212 | 232 | const compare = inst.data.compare; |
| 213 | 233 | const op = compare.op; |
src/arch/riscv64/Mir.zig+13| ... | ... | @@ -76,6 +76,8 @@ pub const Inst = struct { |
| 76 | 76 | fmuls, |
| 77 | 77 | fdivs, |
| 78 | 78 | |
| 79 | fabss, | |
| 80 | ||
| 79 | 81 | fmins, |
| 80 | 82 | fmaxs, |
| 81 | 83 | |
| ... | ... | @@ -94,6 +96,8 @@ pub const Inst = struct { |
| 94 | 96 | fmuld, |
| 95 | 97 | fdivd, |
| 96 | 98 | |
| 99 | fabsd, | |
| 100 | ||
| 97 | 101 | fmind, |
| 98 | 102 | fmaxd, |
| 99 | 103 | |
| ... | ... | @@ -194,6 +198,12 @@ pub const Inst = struct { |
| 194 | 198 | rs: Register, |
| 195 | 199 | }, |
| 196 | 200 | |
| 201 | fabs: struct { | |
| 202 | rd: Register, | |
| 203 | rs: Register, | |
| 204 | bits: u16, | |
| 205 | }, | |
| 206 | ||
| 197 | 207 | compare: struct { |
| 198 | 208 | rd: Register, |
| 199 | 209 | rs1: Register, |
| ... | ... | @@ -273,6 +283,9 @@ pub const Inst = struct { |
| 273 | 283 | /// Jumps. Uses `inst` payload. |
| 274 | 284 | pseudo_j, |
| 275 | 285 | |
| 286 | /// Floating point absolute value. | |
| 287 | pseudo_fabs, | |
| 288 | ||
| 276 | 289 | /// Dead inst, ignored by the emitter. |
| 277 | 290 | pseudo_dead, |
| 278 | 291 |
test/behavior/abs.zig+3-5| ... | ... | @@ -6,7 +6,6 @@ test "@abs integers" { |
| 6 | 6 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 7 | 7 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 8 | 8 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 9 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | |
| 10 | 9 | |
| 11 | 10 | try comptime testAbsIntegers(); |
| 12 | 11 | try testAbsIntegers(); |
| ... | ... | @@ -93,18 +92,17 @@ test "@abs floats" { |
| 93 | 92 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 94 | 93 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 95 | 94 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; |
| 96 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | |
| 97 | 95 | |
| 98 | 96 | try comptime testAbsFloats(f16); |
| 99 | try testAbsFloats(f16); | |
| 97 | if (builtin.zig_backend != .stage2_riscv64) try testAbsFloats(f16); | |
| 100 | 98 | try comptime testAbsFloats(f32); |
| 101 | 99 | try testAbsFloats(f32); |
| 102 | 100 | try comptime testAbsFloats(f64); |
| 103 | 101 | try testAbsFloats(f64); |
| 104 | 102 | try comptime testAbsFloats(f80); |
| 105 | if (builtin.zig_backend != .stage2_wasm and builtin.zig_backend != .stage2_spirv64) try testAbsFloats(f80); | |
| 103 | if (builtin.zig_backend != .stage2_wasm and builtin.zig_backend != .stage2_spirv64 and builtin.zig_backend != .stage2_riscv64) try testAbsFloats(f80); | |
| 106 | 104 | try comptime testAbsFloats(f128); |
| 107 | if (builtin.zig_backend != .stage2_wasm and builtin.zig_backend != .stage2_spirv64) try testAbsFloats(f128); | |
| 105 | if (builtin.zig_backend != .stage2_wasm and builtin.zig_backend != .stage2_spirv64 and builtin.zig_backend != .stage2_riscv64) try testAbsFloats(f128); | |
| 108 | 106 | } |
| 109 | 107 | |
| 110 | 108 | fn testAbsFloats(comptime T: type) !void { |
test/behavior/cast.zig-1| ... | ... | @@ -2608,7 +2608,6 @@ test "@as does not corrupt values with incompatible representations" { |
| 2608 | 2608 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 2609 | 2609 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 2610 | 2610 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; |
| 2611 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | |
| 2612 | 2611 | |
| 2613 | 2612 | const x: f32 = @as(f16, blk: { |
| 2614 | 2613 | if (false) { |
test/behavior/floatop.zig-1| ... | ... | @@ -999,7 +999,6 @@ test "@abs f32/f64" { |
| 999 | 999 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1000 | 1000 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 1001 | 1001 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 1002 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | |
| 1003 | 1002 | |
| 1004 | 1003 | try testFabs(f32); |
| 1005 | 1004 | try comptime testFabs(f32); |
test/behavior/math.zig-1| ... | ... | @@ -1814,7 +1814,6 @@ test "absFloat" { |
| 1814 | 1814 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1815 | 1815 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 1816 | 1816 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 1817 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | |
| 1818 | 1817 | |
| 1819 | 1818 | try testAbsFloat(); |
| 1820 | 1819 | try comptime testAbsFloat(); |