| author | |
| committer | |
| log | c10d1c6a75f818eda092ef7912fd3c2b996632f0 |
| tree | bfaf9037294f5d140ee03facfa39ec935dfe1c08 |
| parent | 083b7b483e1ad83d62ed7029822a82fff14953c5 |
| signature |
7 files changed, 366 insertions(+), 128 deletions(-)
src/arch/riscv64/CodeGen.zig+108-26| ... | @@ -2075,6 +2075,7 @@ fn binOp( | ... | @@ -2075,6 +2075,7 @@ fn binOp( |
| 2075 | .add, | 2075 | .add, |
| 2076 | .sub, | 2076 | .sub, |
| 2077 | .mul, | 2077 | .mul, |
| 2078 | .div_float, | ||
| 2078 | .cmp_eq, | 2079 | .cmp_eq, |
| 2079 | .cmp_neq, | 2080 | .cmp_neq, |
| 2080 | .cmp_gt, | 2081 | .cmp_gt, |
| ... | @@ -2086,10 +2087,11 @@ fn binOp( | ... | @@ -2086,10 +2087,11 @@ fn binOp( |
| 2086 | switch (lhs_ty.zigTypeTag(zcu)) { | 2087 | switch (lhs_ty.zigTypeTag(zcu)) { |
| 2087 | .Float => { | 2088 | .Float => { |
| 2088 | const float_bits = lhs_ty.floatBits(zcu.getTarget()); | 2089 | const float_bits = lhs_ty.floatBits(zcu.getTarget()); |
| 2089 | if (float_bits <= 32) { | 2090 | const float_reg_bits: u32 = if (self.hasFeature(.d)) 64 else 32; |
| 2091 | if (float_bits <= float_reg_bits) { | ||
| 2090 | return self.binOpFloat(tag, lhs, lhs_ty, rhs, rhs_ty); | 2092 | return self.binOpFloat(tag, lhs, lhs_ty, rhs, rhs_ty); |
| 2091 | } else { | 2093 | } else { |
| 2092 | return self.fail("TODO: binary operations for floats with bits > 32", .{}); | 2094 | return self.fail("TODO: binary operations for floats with bits > {d}", .{float_reg_bits}); |
| 2093 | } | 2095 | } |
| 2094 | }, | 2096 | }, |
| 2095 | .Vector => return self.fail("TODO binary operations on vectors", .{}), | 2097 | .Vector => return self.fail("TODO binary operations on vectors", .{}), |
| ... | @@ -2255,6 +2257,7 @@ fn binOpRegister( | ... | @@ -2255,6 +2257,7 @@ fn binOpRegister( |
| 2255 | .cmp_lte => .lte, | 2257 | .cmp_lte => .lte, |
| 2256 | else => unreachable, | 2258 | else => unreachable, |
| 2257 | }, | 2259 | }, |
| 2260 | .size = self.memSize(lhs_ty), | ||
| 2258 | }, | 2261 | }, |
| 2259 | }, | 2262 | }, |
| 2260 | }); | 2263 | }); |
| ... | @@ -2285,28 +2288,90 @@ fn binOpFloat( | ... | @@ -2285,28 +2288,90 @@ fn binOpFloat( |
| 2285 | 2288 | ||
| 2286 | const mir_tag: Mir.Inst.Tag = switch (tag) { | 2289 | const mir_tag: Mir.Inst.Tag = switch (tag) { |
| 2287 | .add => if (float_bits == 32) .fadds else .faddd, | 2290 | .add => if (float_bits == 32) .fadds else .faddd, |
| 2288 | .cmp_eq => if (float_bits == 32) .feqs else .feqd, | 2291 | .sub => if (float_bits == 32) .fsubs else .fsubd, |
| 2292 | .mul => if (float_bits == 32) .fmuls else .fmuld, | ||
| 2293 | .div_float => if (float_bits == 32) .fdivs else .fdivd, | ||
| 2294 | |||
| 2295 | .cmp_eq, | ||
| 2296 | .cmp_neq, | ||
| 2297 | .cmp_gt, | ||
| 2298 | .cmp_gte, | ||
| 2299 | .cmp_lt, | ||
| 2300 | .cmp_lte, | ||
| 2301 | => .pseudo, | ||
| 2302 | |||
| 2289 | else => return self.fail("TODO: binOpFloat mir_tag {s}", .{@tagName(tag)}), | 2303 | else => return self.fail("TODO: binOpFloat mir_tag {s}", .{@tagName(tag)}), |
| 2290 | }; | 2304 | }; |
| 2291 | 2305 | ||
| 2292 | const return_class: abi.RegisterClass = switch (tag) { | 2306 | const return_class: abi.RegisterClass = switch (tag) { |
| 2293 | .add => .float, | 2307 | .add, |
| 2294 | .cmp_eq => .int, | 2308 | .sub, |
| 2309 | .mul, | ||
| 2310 | .div_float, | ||
| 2311 | => .float, | ||
| 2312 | |||
| 2313 | .cmp_eq, | ||
| 2314 | .cmp_neq, | ||
| 2315 | .cmp_gt, | ||
| 2316 | .cmp_gte, | ||
| 2317 | .cmp_lt, | ||
| 2318 | .cmp_lte, | ||
| 2319 | => .int, | ||
| 2295 | else => unreachable, | 2320 | else => unreachable, |
| 2296 | }; | 2321 | }; |
| 2297 | 2322 | ||
| 2298 | const dest_reg, const dest_lock = try self.allocReg(return_class); | 2323 | const dest_reg, const dest_lock = try self.allocReg(return_class); |
| 2299 | defer self.register_manager.unlockReg(dest_lock); | 2324 | defer self.register_manager.unlockReg(dest_lock); |
| 2300 | 2325 | ||
| 2301 | _ = try self.addInst(.{ | 2326 | switch (tag) { |
| 2302 | .tag = mir_tag, | 2327 | .add, |
| 2303 | .ops = .rrr, | 2328 | .sub, |
| 2304 | .data = .{ .r_type = .{ | 2329 | .mul, |
| 2305 | .rd = dest_reg, | 2330 | .div_float, |
| 2306 | .rs1 = lhs_reg, | 2331 | => { |
| 2307 | .rs2 = rhs_reg, | 2332 | _ = try self.addInst(.{ |
| 2308 | } }, | 2333 | .tag = mir_tag, |
| 2309 | }); | 2334 | .ops = .rrr, |
| 2335 | .data = .{ .r_type = .{ | ||
| 2336 | .rd = dest_reg, | ||
| 2337 | .rs1 = lhs_reg, | ||
| 2338 | .rs2 = rhs_reg, | ||
| 2339 | } }, | ||
| 2340 | }); | ||
| 2341 | }, | ||
| 2342 | |||
| 2343 | .cmp_eq, | ||
| 2344 | .cmp_neq, | ||
| 2345 | .cmp_gt, | ||
| 2346 | .cmp_gte, | ||
| 2347 | .cmp_lt, | ||
| 2348 | .cmp_lte, | ||
| 2349 | => { | ||
| 2350 | _ = try self.addInst(.{ | ||
| 2351 | .tag = .pseudo, | ||
| 2352 | .ops = .pseudo_compare, | ||
| 2353 | .data = .{ | ||
| 2354 | .compare = .{ | ||
| 2355 | .rd = dest_reg, | ||
| 2356 | .rs1 = lhs_reg, | ||
| 2357 | .rs2 = rhs_reg, | ||
| 2358 | .op = switch (tag) { | ||
| 2359 | .cmp_eq => .eq, | ||
| 2360 | .cmp_neq => .neq, | ||
| 2361 | .cmp_gt => .gt, | ||
| 2362 | .cmp_gte => .gte, | ||
| 2363 | .cmp_lt => .lt, | ||
| 2364 | .cmp_lte => .lte, | ||
| 2365 | else => unreachable, | ||
| 2366 | }, | ||
| 2367 | .size = self.memSize(lhs_ty), | ||
| 2368 | }, | ||
| 2369 | }, | ||
| 2370 | }); | ||
| 2371 | }, | ||
| 2372 | |||
| 2373 | else => unreachable, | ||
| 2374 | } | ||
| 2310 | 2375 | ||
| 2311 | return MCValue{ .register = dest_reg }; | 2376 | return MCValue{ .register = dest_reg }; |
| 2312 | } | 2377 | } |
| ... | @@ -2360,7 +2425,27 @@ fn airSubSat(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2360,7 +2425,27 @@ fn airSubSat(self: *Self, inst: Air.Inst.Index) !void { |
| 2360 | 2425 | ||
| 2361 | fn airMul(self: *Self, inst: Air.Inst.Index) !void { | 2426 | fn airMul(self: *Self, inst: Air.Inst.Index) !void { |
| 2362 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; | 2427 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 2363 | const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement mul for {}", .{self.target.cpu.arch}); | 2428 | const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: { |
| 2429 | const lhs = try self.resolveInst(bin_op.lhs); | ||
| 2430 | const rhs = try self.resolveInst(bin_op.rhs); | ||
| 2431 | const lhs_ty = self.typeOf(bin_op.lhs); | ||
| 2432 | const rhs_ty = self.typeOf(bin_op.rhs); | ||
| 2433 | |||
| 2434 | break :result try self.binOp(.mul, lhs, lhs_ty, rhs, rhs_ty); | ||
| 2435 | }; | ||
| 2436 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); | ||
| 2437 | } | ||
| 2438 | |||
| 2439 | fn airDiv(self: *Self, inst: Air.Inst.Index) !void { | ||
| 2440 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; | ||
| 2441 | const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: { | ||
| 2442 | const lhs = try self.resolveInst(bin_op.lhs); | ||
| 2443 | const rhs = try self.resolveInst(bin_op.rhs); | ||
| 2444 | const lhs_ty = self.typeOf(bin_op.lhs); | ||
| 2445 | const rhs_ty = self.typeOf(bin_op.rhs); | ||
| 2446 | |||
| 2447 | break :result try self.binOp(.div_float, lhs, lhs_ty, rhs, rhs_ty); | ||
| 2448 | }; | ||
| 2364 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); | 2449 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 2365 | } | 2450 | } |
| 2366 | 2451 | ||
| ... | @@ -2672,12 +2757,6 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2672,12 +2757,6 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 2672 | return self.fail("TODO implement airShlWithOverflow for {}", .{self.target.cpu.arch}); | 2757 | return self.fail("TODO implement airShlWithOverflow for {}", .{self.target.cpu.arch}); |
| 2673 | } | 2758 | } |
| 2674 | 2759 | ||
| 2675 | fn airDiv(self: *Self, inst: Air.Inst.Index) !void { | ||
| 2676 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; | ||
| 2677 | const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement div for {}", .{self.target.cpu.arch}); | ||
| 2678 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); | ||
| 2679 | } | ||
| 2680 | |||
| 2681 | fn airRem(self: *Self, inst: Air.Inst.Index) !void { | 2760 | fn airRem(self: *Self, inst: Air.Inst.Index) !void { |
| 2682 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; | 2761 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 2683 | const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement rem for {}", .{self.target.cpu.arch}); | 2762 | const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement rem for {}", .{self.target.cpu.arch}); |
| ... | @@ -3742,6 +3821,9 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3742,6 +3821,9 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void { |
| 3742 | const arg_ty = self.typeOfIndex(inst); | 3821 | const arg_ty = self.typeOfIndex(inst); |
| 3743 | 3822 | ||
| 3744 | const dst_mcv = try self.allocRegOrMem(inst, false); | 3823 | const dst_mcv = try self.allocRegOrMem(inst, false); |
| 3824 | |||
| 3825 | log.debug("airArg {} -> {}", .{ src_mcv, dst_mcv }); | ||
| 3826 | |||
| 3745 | try self.genCopy(arg_ty, dst_mcv, src_mcv); | 3827 | try self.genCopy(arg_ty, dst_mcv, src_mcv); |
| 3746 | 3828 | ||
| 3747 | try self.genArgDbgInfo(inst, src_mcv); | 3829 | try self.genArgDbgInfo(inst, src_mcv); |
| ... | @@ -4135,10 +4217,10 @@ fn airCmp(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4135,10 +4217,10 @@ fn airCmp(self: *Self, inst: Air.Inst.Index) !void { |
| 4135 | }, | 4217 | }, |
| 4136 | .Float => { | 4218 | .Float => { |
| 4137 | const float_bits = lhs_ty.floatBits(self.target.*); | 4219 | const float_bits = lhs_ty.floatBits(self.target.*); |
| 4138 | if (float_bits > 32) { | 4220 | const float_reg_size: u32 = if (self.hasFeature(.d)) 64 else 32; |
| 4139 | return self.fail("TODO: airCmp float > 32 bits", .{}); | 4221 | if (float_bits > float_reg_size) { |
| 4222 | return self.fail("TODO: airCmp float > 64/32 bits", .{}); | ||
| 4140 | } | 4223 | } |
| 4141 | |||
| 4142 | break :result try self.binOpFloat(tag, lhs, lhs_ty, rhs, lhs_ty); | 4224 | break :result try self.binOpFloat(tag, lhs, lhs_ty, rhs, lhs_ty); |
| 4143 | }, | 4225 | }, |
| 4144 | else => unreachable, | 4226 | else => unreachable, |
| ... | @@ -6141,6 +6223,8 @@ fn resolveCallingConventionValues( | ... | @@ -6141,6 +6223,8 @@ fn resolveCallingConventionValues( |
| 6141 | }; | 6223 | }; |
| 6142 | } | 6224 | } |
| 6143 | 6225 | ||
| 6226 | var param_float_reg_i: usize = 0; | ||
| 6227 | |||
| 6144 | for (param_types, result.args) |ty, *arg| { | 6228 | for (param_types, result.args) |ty, *arg| { |
| 6145 | if (!ty.hasRuntimeBitsIgnoreComptime(zcu)) { | 6229 | if (!ty.hasRuntimeBitsIgnoreComptime(zcu)) { |
| 6146 | assert(cc == .Unspecified); | 6230 | assert(cc == .Unspecified); |
| ... | @@ -6151,8 +6235,6 @@ fn resolveCallingConventionValues( | ... | @@ -6151,8 +6235,6 @@ fn resolveCallingConventionValues( |
| 6151 | var arg_mcv: [2]MCValue = undefined; | 6235 | var arg_mcv: [2]MCValue = undefined; |
| 6152 | var arg_mcv_i: usize = 0; | 6236 | var arg_mcv_i: usize = 0; |
| 6153 | 6237 | ||
| 6154 | var param_float_reg_i: usize = 0; | ||
| 6155 | |||
| 6156 | const classes = mem.sliceTo(&abi.classifySystem(ty, zcu), .none); | 6238 | const classes = mem.sliceTo(&abi.classifySystem(ty, zcu), .none); |
| 6157 | 6239 | ||
| 6158 | for (classes) |class| switch (class) { | 6240 | for (classes) |class| switch (class) { |
src/arch/riscv64/Encoding.zig+97-18| ... | @@ -111,21 +111,46 @@ pub const Mnemonic = enum { | ... | @@ -111,21 +111,46 @@ pub const Mnemonic = enum { |
| 111 | ebreak, | 111 | ebreak, |
| 112 | unimp, | 112 | unimp, |
| 113 | 113 | ||
| 114 | // float mnemonics | 114 | // F extension (32-bit float) |
| 115 | fadds, | 115 | fadds, |
| 116 | faddd, | 116 | fsubs, |
| 117 | fmuls, | ||
| 118 | fdivs, | ||
| 117 | 119 | ||
| 118 | feqs, | 120 | fmins, |
| 119 | feqd, | 121 | fmaxs, |
| 120 | 122 | ||
| 121 | fld, | 123 | fsqrts, |
| 122 | flw, | ||
| 123 | 124 | ||
| 124 | fsd, | 125 | flw, |
| 125 | fsw, | 126 | fsw, |
| 126 | 127 | ||
| 128 | feqs, | ||
| 129 | flts, | ||
| 130 | fles, | ||
| 131 | |||
| 127 | fsgnjns, | 132 | fsgnjns, |
| 128 | 133 | ||
| 134 | // D extension (64-bit float) | ||
| 135 | faddd, | ||
| 136 | fsubd, | ||
| 137 | fmuld, | ||
| 138 | fdivd, | ||
| 139 | |||
| 140 | fmind, | ||
| 141 | fmaxd, | ||
| 142 | |||
| 143 | fsqrtd, | ||
| 144 | |||
| 145 | fld, | ||
| 146 | fsd, | ||
| 147 | |||
| 148 | feqd, | ||
| 149 | fltd, | ||
| 150 | fled, | ||
| 151 | |||
| 152 | fsgnjnd, | ||
| 153 | |||
| 129 | pub fn encoding(mnem: Mnemonic) Enc { | 154 | pub fn encoding(mnem: Mnemonic) Enc { |
| 130 | return switch (mnem) { | 155 | return switch (mnem) { |
| 131 | // zig fmt: off | 156 | // zig fmt: off |
| ... | @@ -163,39 +188,66 @@ pub const Mnemonic = enum { | ... | @@ -163,39 +188,66 @@ pub const Mnemonic = enum { |
| 163 | .fadds => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00000, .fmt = .S, .rm = 0b111 } } }, | 188 | .fadds => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00000, .fmt = .S, .rm = 0b111 } } }, |
| 164 | .faddd => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00000, .fmt = .D, .rm = 0b111 } } }, | 189 | .faddd => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00000, .fmt = .D, .rm = 0b111 } } }, |
| 165 | 190 | ||
| 191 | .fsubs => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00001, .fmt = .S, .rm = 0b111 } } }, | ||
| 192 | .fsubd => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00001, .fmt = .D, .rm = 0b111 } } }, | ||
| 193 | |||
| 194 | .fmuls => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00010, .fmt = .S, .rm = 0b111 } } }, | ||
| 195 | .fmuld => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00010, .fmt = .D, .rm = 0b111 } } }, | ||
| 196 | |||
| 197 | .fdivs => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00011, .fmt = .S, .rm = 0b111 } } }, | ||
| 198 | .fdivd => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00011, .fmt = .D, .rm = 0b111 } } }, | ||
| 199 | |||
| 200 | .fmins => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00101, .fmt = .S, .rm = 0b000 } } }, | ||
| 201 | .fmind => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00101, .fmt = .D, .rm = 0b000 } } }, | ||
| 202 | |||
| 203 | .fmaxs => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00101, .fmt = .S, .rm = 0b001 } } }, | ||
| 204 | .fmaxd => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00101, .fmt = .D, .rm = 0b001 } } }, | ||
| 205 | |||
| 206 | .fsqrts => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b01011, .fmt = .S, .rm = 0b111 } } }, | ||
| 207 | .fsqrtd => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b01011, .fmt = .D, .rm = 0b111 } } }, | ||
| 208 | |||
| 209 | .fles => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b10100, .fmt = .S, .rm = 0b000 } } }, | ||
| 210 | .fled => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b10100, .fmt = .D, .rm = 0b000 } } }, | ||
| 211 | |||
| 212 | .flts => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b10100, .fmt = .S, .rm = 0b001 } } }, | ||
| 213 | .fltd => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b10100, .fmt = .D, .rm = 0b001 } } }, | ||
| 214 | |||
| 166 | .feqs => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b10100, .fmt = .S, .rm = 0b010 } } }, | 215 | .feqs => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b10100, .fmt = .S, .rm = 0b010 } } }, |
| 167 | .feqd => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b10100, .fmt = .D, .rm = 0b010 } } }, | 216 | .feqd => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b10100, .fmt = .D, .rm = 0b010 } } }, |
| 168 | 217 | ||
| 169 | .fsgnjns => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00100, .fmt = .S, .rm = 0b000 } } }, | 218 | .fsgnjns => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00100, .fmt = .S, .rm = 0b000 } } }, |
| 219 | .fsgnjnd => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00100, .fmt = .D, .rm = 0b000 } } }, | ||
| 220 | |||
| 170 | 221 | ||
| 171 | // LOAD | 222 | // LOAD |
| 172 | 223 | ||
| 173 | .ld => .{ .opcode = .LOAD, .data = .{ .fo = .{ .funct3 = 0b011 } } }, | ||
| 174 | .lw => .{ .opcode = .LOAD, .data = .{ .fo = .{ .funct3 = 0b010 } } }, | ||
| 175 | .lwu => .{ .opcode = .LOAD, .data = .{ .fo = .{ .funct3 = 0b110 } } }, | ||
| 176 | .lh => .{ .opcode = .LOAD, .data = .{ .fo = .{ .funct3 = 0b001 } } }, | ||
| 177 | .lhu => .{ .opcode = .LOAD, .data = .{ .fo = .{ .funct3 = 0b101 } } }, | ||
| 178 | .lb => .{ .opcode = .LOAD, .data = .{ .fo = .{ .funct3 = 0b000 } } }, | 224 | .lb => .{ .opcode = .LOAD, .data = .{ .fo = .{ .funct3 = 0b000 } } }, |
| 225 | .lh => .{ .opcode = .LOAD, .data = .{ .fo = .{ .funct3 = 0b001 } } }, | ||
| 226 | .lw => .{ .opcode = .LOAD, .data = .{ .fo = .{ .funct3 = 0b010 } } }, | ||
| 227 | .ld => .{ .opcode = .LOAD, .data = .{ .fo = .{ .funct3 = 0b011 } } }, | ||
| 179 | .lbu => .{ .opcode = .LOAD, .data = .{ .fo = .{ .funct3 = 0b100 } } }, | 228 | .lbu => .{ .opcode = .LOAD, .data = .{ .fo = .{ .funct3 = 0b100 } } }, |
| 229 | .lhu => .{ .opcode = .LOAD, .data = .{ .fo = .{ .funct3 = 0b101 } } }, | ||
| 230 | .lwu => .{ .opcode = .LOAD, .data = .{ .fo = .{ .funct3 = 0b110 } } }, | ||
| 180 | 231 | ||
| 181 | 232 | ||
| 182 | // STORE | 233 | // STORE |
| 183 | 234 | ||
| 184 | .sd => .{ .opcode = .STORE, .data = .{ .fo = .{ .funct3 = 0b011 } } }, | ||
| 185 | .sw => .{ .opcode = .STORE, .data = .{ .fo = .{ .funct3 = 0b010 } } }, | ||
| 186 | .sh => .{ .opcode = .STORE, .data = .{ .fo = .{ .funct3 = 0b001 } } }, | ||
| 187 | .sb => .{ .opcode = .STORE, .data = .{ .fo = .{ .funct3 = 0b000 } } }, | 235 | .sb => .{ .opcode = .STORE, .data = .{ .fo = .{ .funct3 = 0b000 } } }, |
| 236 | .sh => .{ .opcode = .STORE, .data = .{ .fo = .{ .funct3 = 0b001 } } }, | ||
| 237 | .sw => .{ .opcode = .STORE, .data = .{ .fo = .{ .funct3 = 0b010 } } }, | ||
| 238 | .sd => .{ .opcode = .STORE, .data = .{ .fo = .{ .funct3 = 0b011 } } }, | ||
| 188 | 239 | ||
| 189 | 240 | ||
| 190 | // LOAD_FP | 241 | // LOAD_FP |
| 191 | 242 | ||
| 192 | .fld => .{ .opcode = .LOAD_FP, .data = .{ .fo = .{ .funct3 = 0b011 } } }, | ||
| 193 | .flw => .{ .opcode = .LOAD_FP, .data = .{ .fo = .{ .funct3 = 0b010 } } }, | 243 | .flw => .{ .opcode = .LOAD_FP, .data = .{ .fo = .{ .funct3 = 0b010 } } }, |
| 244 | .fld => .{ .opcode = .LOAD_FP, .data = .{ .fo = .{ .funct3 = 0b011 } } }, | ||
| 245 | |||
| 194 | 246 | ||
| 195 | // STORE_FP | 247 | // STORE_FP |
| 196 | 248 | ||
| 197 | .fsd => .{ .opcode = .STORE_FP, .data = .{ .fo = .{ .funct3 = 0b011 } } }, | ||
| 198 | .fsw => .{ .opcode = .STORE_FP, .data = .{ .fo = .{ .funct3 = 0b010 } } }, | 249 | .fsw => .{ .opcode = .STORE_FP, .data = .{ .fo = .{ .funct3 = 0b010 } } }, |
| 250 | .fsd => .{ .opcode = .STORE_FP, .data = .{ .fo = .{ .funct3 = 0b011 } } }, | ||
| 199 | 251 | ||
| 200 | 252 | ||
| 201 | // JALR | 253 | // JALR |
| ... | @@ -310,9 +362,36 @@ pub const InstEnc = enum { | ... | @@ -310,9 +362,36 @@ pub const InstEnc = enum { |
| 310 | 362 | ||
| 311 | .fadds, | 363 | .fadds, |
| 312 | .faddd, | 364 | .faddd, |
| 365 | |||
| 366 | .fsubs, | ||
| 367 | .fsubd, | ||
| 368 | |||
| 369 | .fmuls, | ||
| 370 | .fmuld, | ||
| 371 | |||
| 372 | .fdivs, | ||
| 373 | .fdivd, | ||
| 374 | |||
| 375 | .fmins, | ||
| 376 | .fmind, | ||
| 377 | |||
| 378 | .fmaxs, | ||
| 379 | .fmaxd, | ||
| 380 | |||
| 381 | .fsqrts, | ||
| 382 | .fsqrtd, | ||
| 383 | |||
| 384 | .fles, | ||
| 385 | .fled, | ||
| 386 | |||
| 387 | .flts, | ||
| 388 | .fltd, | ||
| 389 | |||
| 313 | .feqs, | 390 | .feqs, |
| 314 | .feqd, | 391 | .feqd, |
| 392 | |||
| 315 | .fsgnjns, | 393 | .fsgnjns, |
| 394 | .fsgnjnd, | ||
| 316 | => .R, | 395 | => .R, |
| 317 | 396 | ||
| 318 | .ecall, | 397 | .ecall, |
src/arch/riscv64/Lower.zig+136-69| ... | @@ -139,7 +139,7 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct { | ... | @@ -139,7 +139,7 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct { |
| 139 | 139 | ||
| 140 | switch (dst_class) { | 140 | switch (dst_class) { |
| 141 | .float => { | 141 | .float => { |
| 142 | try lower.emit(.fsgnjns, &.{ | 142 | try lower.emit(if (lower.hasFeature(.d)) .fsgnjnd else .fsgnjns, &.{ |
| 143 | .{ .reg = rr.rd }, | 143 | .{ .reg = rr.rd }, |
| 144 | .{ .reg = rr.rs }, | 144 | .{ .reg = rr.rs }, |
| 145 | .{ .reg = rr.rs }, | 145 | .{ .reg = rr.rs }, |
| ... | @@ -176,9 +176,11 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct { | ... | @@ -176,9 +176,11 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct { |
| 176 | .pseudo_load_symbol => { | 176 | .pseudo_load_symbol => { |
| 177 | const payload = inst.data.payload; | 177 | const payload = inst.data.payload; |
| 178 | const data = lower.mir.extraData(Mir.LoadSymbolPayload, payload).data; | 178 | const data = lower.mir.extraData(Mir.LoadSymbolPayload, payload).data; |
| 179 | const dst_reg: bits.Register = @enumFromInt(data.register); | ||
| 180 | assert(dst_reg.class() == .int); | ||
| 179 | 181 | ||
| 180 | try lower.emit(.lui, &.{ | 182 | try lower.emit(.lui, &.{ |
| 181 | .{ .reg = @enumFromInt(data.register) }, | 183 | .{ .reg = dst_reg }, |
| 182 | .{ .imm = lower.reloc(.{ .load_symbol_reloc = .{ | 184 | .{ .imm = lower.reloc(.{ .load_symbol_reloc = .{ |
| 183 | .atom_index = data.atom_index, | 185 | .atom_index = data.atom_index, |
| 184 | .sym_index = data.sym_index, | 186 | .sym_index = data.sym_index, |
| ... | @@ -187,14 +189,16 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct { | ... | @@ -187,14 +189,16 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct { |
| 187 | 189 | ||
| 188 | // the above reloc implies this one | 190 | // the above reloc implies this one |
| 189 | try lower.emit(.addi, &.{ | 191 | try lower.emit(.addi, &.{ |
| 190 | .{ .reg = @enumFromInt(data.register) }, | 192 | .{ .reg = dst_reg }, |
| 191 | .{ .reg = @enumFromInt(data.register) }, | 193 | .{ .reg = dst_reg }, |
| 192 | .{ .imm = Immediate.s(0) }, | 194 | .{ .imm = Immediate.s(0) }, |
| 193 | }); | 195 | }); |
| 194 | }, | 196 | }, |
| 195 | 197 | ||
| 196 | .pseudo_lea_rm => { | 198 | .pseudo_lea_rm => { |
| 197 | const rm = inst.data.rm; | 199 | const rm = inst.data.rm; |
| 200 | assert(rm.r.class() == .int); | ||
| 201 | |||
| 198 | const frame = rm.m.toFrameLoc(lower.mir); | 202 | const frame = rm.m.toFrameLoc(lower.mir); |
| 199 | 203 | ||
| 200 | try lower.emit(.addi, &.{ | 204 | try lower.emit(.addi, &.{ |
| ... | @@ -212,78 +216,135 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct { | ... | @@ -212,78 +216,135 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct { |
| 212 | const rs1 = compare.rs1; | 216 | const rs1 = compare.rs1; |
| 213 | const rs2 = compare.rs2; | 217 | const rs2 = compare.rs2; |
| 214 | 218 | ||
| 215 | switch (op) { | 219 | const class = rs1.class(); |
| 216 | .eq => { | 220 | const size = compare.size.bitSize(); |
| 217 | try lower.emit(.xor, &.{ | 221 | |
| 218 | .{ .reg = rd }, | 222 | switch (class) { |
| 219 | .{ .reg = rs1 }, | 223 | .int => switch (op) { |
| 220 | .{ .reg = rs2 }, | 224 | .eq => { |
| 221 | }); | 225 | try lower.emit(.xor, &.{ |
| 222 | 226 | .{ .reg = rd }, | |
| 223 | try lower.emit(.sltiu, &.{ | 227 | .{ .reg = rs1 }, |
| 224 | .{ .reg = rd }, | 228 | .{ .reg = rs2 }, |
| 225 | .{ .reg = rd }, | 229 | }); |
| 226 | .{ .imm = Immediate.s(1) }, | 230 | |
| 227 | }); | 231 | try lower.emit(.sltiu, &.{ |
| 232 | .{ .reg = rd }, | ||
| 233 | .{ .reg = rd }, | ||
| 234 | .{ .imm = Immediate.s(1) }, | ||
| 235 | }); | ||
| 236 | }, | ||
| 237 | .neq => { | ||
| 238 | try lower.emit(.xor, &.{ | ||
| 239 | .{ .reg = rd }, | ||
| 240 | .{ .reg = rs1 }, | ||
| 241 | .{ .reg = rs2 }, | ||
| 242 | }); | ||
| 243 | |||
| 244 | try lower.emit(.sltu, &.{ | ||
| 245 | .{ .reg = rd }, | ||
| 246 | .{ .reg = .zero }, | ||
| 247 | .{ .reg = rd }, | ||
| 248 | }); | ||
| 249 | }, | ||
| 250 | .gt => { | ||
| 251 | try lower.emit(.sltu, &.{ | ||
| 252 | .{ .reg = rd }, | ||
| 253 | .{ .reg = rs1 }, | ||
| 254 | .{ .reg = rs2 }, | ||
| 255 | }); | ||
| 256 | }, | ||
| 257 | .gte => { | ||
| 258 | try lower.emit(.sltu, &.{ | ||
| 259 | .{ .reg = rd }, | ||
| 260 | .{ .reg = rs1 }, | ||
| 261 | .{ .reg = rs2 }, | ||
| 262 | }); | ||
| 263 | |||
| 264 | try lower.emit(.xori, &.{ | ||
| 265 | .{ .reg = rd }, | ||
| 266 | .{ .reg = rd }, | ||
| 267 | .{ .imm = Immediate.s(1) }, | ||
| 268 | }); | ||
| 269 | }, | ||
| 270 | .lt => { | ||
| 271 | try lower.emit(.slt, &.{ | ||
| 272 | .{ .reg = rd }, | ||
| 273 | .{ .reg = rs1 }, | ||
| 274 | .{ .reg = rs2 }, | ||
| 275 | }); | ||
| 276 | }, | ||
| 277 | .lte => { | ||
| 278 | try lower.emit(.slt, &.{ | ||
| 279 | .{ .reg = rd }, | ||
| 280 | .{ .reg = rs2 }, | ||
| 281 | .{ .reg = rs1 }, | ||
| 282 | }); | ||
| 283 | |||
| 284 | try lower.emit(.xori, &.{ | ||
| 285 | .{ .reg = rd }, | ||
| 286 | .{ .reg = rd }, | ||
| 287 | .{ .imm = Immediate.s(1) }, | ||
| 288 | }); | ||
| 289 | }, | ||
| 228 | }, | 290 | }, |
| 229 | .neq => { | 291 | .float => switch (op) { |
| 230 | try lower.emit(.xor, &.{ | 292 | // eq |
| 231 | .{ .reg = rd }, | 293 | .eq => { |
| 232 | .{ .reg = rs1 }, | 294 | try lower.emit(if (size == 64) .feqd else .feqs, &.{ |
| 233 | .{ .reg = rs2 }, | 295 | .{ .reg = rd }, |
| 234 | }); | 296 | .{ .reg = rs1 }, |
| 235 | 297 | .{ .reg = rs2 }, | |
| 236 | try lower.emit(.sltu, &.{ | 298 | }); |
| 237 | .{ .reg = rd }, | 299 | }, |
| 238 | .{ .reg = .zero }, | 300 | // !(eq) |
| 239 | .{ .reg = rd }, | 301 | .neq => { |
| 240 | }); | 302 | try lower.emit(if (size == 64) .feqd else .feqs, &.{ |
| 241 | }, | 303 | .{ .reg = rd }, |
| 242 | .gt => { | 304 | .{ .reg = rs1 }, |
| 243 | try lower.emit(.sltu, &.{ | 305 | .{ .reg = rs2 }, |
| 244 | .{ .reg = rd }, | 306 | }); |
| 245 | .{ .reg = rs1 }, | 307 | try lower.emit(.xori, &.{ |
| 246 | .{ .reg = rs2 }, | 308 | .{ .reg = rd }, |
| 247 | }); | 309 | .{ .reg = rd }, |
| 248 | }, | 310 | .{ .imm = Immediate.s(1) }, |
| 249 | .gte => { | 311 | }); |
| 250 | try lower.emit(.sltu, &.{ | 312 | }, |
| 251 | .{ .reg = rd }, | 313 | .lt => { |
| 252 | .{ .reg = rs1 }, | 314 | try lower.emit(if (size == 64) .fltd else .flts, &.{ |
| 253 | .{ .reg = rs2 }, | 315 | .{ .reg = rd }, |
| 254 | }); | 316 | .{ .reg = rs1 }, |
| 255 | 317 | .{ .reg = rs2 }, | |
| 256 | try lower.emit(.xori, &.{ | 318 | }); |
| 257 | .{ .reg = rd }, | 319 | }, |
| 258 | .{ .reg = rd }, | 320 | .lte => { |
| 259 | .{ .imm = Immediate.s(1) }, | 321 | try lower.emit(if (size == 64) .fled else .fles, &.{ |
| 260 | }); | 322 | .{ .reg = rd }, |
| 261 | }, | 323 | .{ .reg = rs1 }, |
| 262 | .lt => { | 324 | .{ .reg = rs2 }, |
| 263 | try lower.emit(.slt, &.{ | 325 | }); |
| 264 | .{ .reg = rd }, | 326 | }, |
| 265 | .{ .reg = rs1 }, | 327 | .gt => { |
| 266 | .{ .reg = rs2 }, | 328 | try lower.emit(if (size == 64) .fltd else .flts, &.{ |
| 267 | }); | 329 | .{ .reg = rd }, |
| 268 | }, | 330 | .{ .reg = rs2 }, |
| 269 | .lte => { | 331 | .{ .reg = rs1 }, |
| 270 | try lower.emit(.slt, &.{ | 332 | }); |
| 271 | .{ .reg = rd }, | 333 | }, |
| 272 | .{ .reg = rs2 }, | 334 | .gte => { |
| 273 | .{ .reg = rs1 }, | 335 | try lower.emit(if (size == 64) .fled else .fles, &.{ |
| 274 | }); | 336 | .{ .reg = rd }, |
| 275 | 337 | .{ .reg = rs2 }, | |
| 276 | try lower.emit(.xori, &.{ | 338 | .{ .reg = rs1 }, |
| 277 | .{ .reg = rd }, | 339 | }); |
| 278 | .{ .reg = rd }, | 340 | }, |
| 279 | .{ .imm = Immediate.s(1) }, | ||
| 280 | }); | ||
| 281 | }, | 341 | }, |
| 282 | } | 342 | } |
| 283 | }, | 343 | }, |
| 284 | 344 | ||
| 285 | .pseudo_not => { | 345 | .pseudo_not => { |
| 286 | const rr = inst.data.rr; | 346 | const rr = inst.data.rr; |
| 347 | assert(rr.rs.class() == .int and rr.rd.class() == .int); | ||
| 287 | 348 | ||
| 288 | try lower.emit(.xori, &.{ | 349 | try lower.emit(.xori, &.{ |
| 289 | .{ .reg = rr.rd }, | 350 | .{ .reg = rr.rd }, |
| ... | @@ -408,6 +469,12 @@ pub fn fail(lower: *Lower, comptime format: []const u8, args: anytype) Error { | ... | @@ -408,6 +469,12 @@ pub fn fail(lower: *Lower, comptime format: []const u8, args: anytype) Error { |
| 408 | return error.LowerFail; | 469 | return error.LowerFail; |
| 409 | } | 470 | } |
| 410 | 471 | ||
| 472 | fn hasFeature(lower: *Lower, feature: std.Target.riscv.Feature) bool { | ||
| 473 | const target = lower.bin_file.comp.module.?.getTarget(); | ||
| 474 | const features = target.cpu.features; | ||
| 475 | return std.Target.riscv.featureSetHas(features, feature); | ||
| 476 | } | ||
| 477 | |||
| 411 | const Lower = @This(); | 478 | const Lower = @This(); |
| 412 | 479 | ||
| 413 | const abi = @import("abi.zig"); | 480 | const abi = @import("abi.zig"); |
src/arch/riscv64/Mir.zig+25| ... | @@ -72,15 +72,39 @@ pub const Inst = struct { | ... | @@ -72,15 +72,39 @@ pub const Inst = struct { |
| 72 | 72 | ||
| 73 | // F extension (32-bit float) | 73 | // F extension (32-bit float) |
| 74 | fadds, | 74 | fadds, |
| 75 | fsubs, | ||
| 76 | fmuls, | ||
| 77 | fdivs, | ||
| 78 | |||
| 79 | fmins, | ||
| 80 | fmaxs, | ||
| 81 | |||
| 82 | fsqrts, | ||
| 83 | |||
| 75 | flw, | 84 | flw, |
| 76 | fsw, | 85 | fsw, |
| 86 | |||
| 77 | feqs, | 87 | feqs, |
| 88 | flts, | ||
| 89 | fles, | ||
| 78 | 90 | ||
| 79 | // D extension (64-bit float) | 91 | // D extension (64-bit float) |
| 80 | faddd, | 92 | faddd, |
| 93 | fsubd, | ||
| 94 | fmuld, | ||
| 95 | fdivd, | ||
| 96 | |||
| 97 | fmind, | ||
| 98 | fmaxd, | ||
| 99 | |||
| 100 | fsqrtd, | ||
| 101 | |||
| 81 | fld, | 102 | fld, |
| 82 | fsd, | 103 | fsd, |
| 104 | |||
| 83 | feqd, | 105 | feqd, |
| 106 | fltd, | ||
| 107 | fled, | ||
| 84 | 108 | ||
| 85 | /// A pseudo-instruction. Used for anything that isn't 1:1 with an | 109 | /// A pseudo-instruction. Used for anything that isn't 1:1 with an |
| 86 | /// assembly instruction. | 110 | /// assembly instruction. |
| ... | @@ -182,6 +206,7 @@ pub const Inst = struct { | ... | @@ -182,6 +206,7 @@ pub const Inst = struct { |
| 182 | lt, | 206 | lt, |
| 183 | lte, | 207 | lte, |
| 184 | }, | 208 | }, |
| 209 | size: Memory.Size, | ||
| 185 | }, | 210 | }, |
| 186 | 211 | ||
| 187 | reloc: struct { | 212 | reloc: struct { |
test/behavior/cast.zig-2| ... | @@ -1717,7 +1717,6 @@ test "peer type resolution: float and comptime-known fixed-width integer" { | ... | @@ -1717,7 +1717,6 @@ test "peer type resolution: float and comptime-known fixed-width integer" { |
| 1717 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 1717 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1718 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 1718 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 1719 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; | 1719 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; |
| 1720 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | ||
| 1721 | 1720 | ||
| 1722 | const i: u8 = 100; | 1721 | const i: u8 = 100; |
| 1723 | var f: f32 = 1.234; | 1722 | var f: f32 = 1.234; |
| ... | @@ -2586,7 +2585,6 @@ test "@intFromBool on vector" { | ... | @@ -2586,7 +2585,6 @@ test "@intFromBool on vector" { |
| 2586 | 2585 | ||
| 2587 | test "numeric coercions with undefined" { | 2586 | test "numeric coercions with undefined" { |
| 2588 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; | 2587 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; |
| 2589 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | ||
| 2590 | 2588 | ||
| 2591 | const from: i32 = undefined; | 2589 | const from: i32 = undefined; |
| 2592 | var to: f32 = from; | 2590 | var to: f32 = from; |
test/behavior/floatop.zig-12| ... | @@ -22,8 +22,6 @@ test "add f16" { | ... | @@ -22,8 +22,6 @@ test "add f16" { |
| 22 | } | 22 | } |
| 23 | 23 | ||
| 24 | test "add f32/f64" { | 24 | test "add f32/f64" { |
| 25 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | ||
| 26 | |||
| 27 | try testAdd(f32); | 25 | try testAdd(f32); |
| 28 | try comptime testAdd(f32); | 26 | try comptime testAdd(f32); |
| 29 | try testAdd(f64); | 27 | try testAdd(f64); |
| ... | @@ -60,8 +58,6 @@ test "sub f16" { | ... | @@ -60,8 +58,6 @@ test "sub f16" { |
| 60 | } | 58 | } |
| 61 | 59 | ||
| 62 | test "sub f32/f64" { | 60 | test "sub f32/f64" { |
| 63 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | ||
| 64 | |||
| 65 | try testSub(f32); | 61 | try testSub(f32); |
| 66 | try comptime testSub(f32); | 62 | try comptime testSub(f32); |
| 67 | try testSub(f64); | 63 | try testSub(f64); |
| ... | @@ -98,8 +94,6 @@ test "mul f16" { | ... | @@ -98,8 +94,6 @@ test "mul f16" { |
| 98 | } | 94 | } |
| 99 | 95 | ||
| 100 | test "mul f32/f64" { | 96 | test "mul f32/f64" { |
| 101 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | ||
| 102 | |||
| 103 | try testMul(f32); | 97 | try testMul(f32); |
| 104 | try comptime testMul(f32); | 98 | try comptime testMul(f32); |
| 105 | try testMul(f64); | 99 | try testMul(f64); |
| ... | @@ -1622,7 +1616,6 @@ test "comptime inf >= runtime 1" { | ... | @@ -1622,7 +1616,6 @@ test "comptime inf >= runtime 1" { |
| 1622 | test "comptime isNan(nan * 1)" { | 1616 | test "comptime isNan(nan * 1)" { |
| 1623 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 1617 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 1624 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 1618 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1625 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | ||
| 1626 | 1619 | ||
| 1627 | const nan_times_one = comptime std.math.nan(f64) * 1; | 1620 | const nan_times_one = comptime std.math.nan(f64) * 1; |
| 1628 | try std.testing.expect(std.math.isNan(nan_times_one)); | 1621 | try std.testing.expect(std.math.isNan(nan_times_one)); |
| ... | @@ -1630,7 +1623,6 @@ test "comptime isNan(nan * 1)" { | ... | @@ -1630,7 +1623,6 @@ test "comptime isNan(nan * 1)" { |
| 1630 | test "runtime isNan(nan * 1)" { | 1623 | test "runtime isNan(nan * 1)" { |
| 1631 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 1624 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 1632 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 1625 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1633 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | ||
| 1634 | 1626 | ||
| 1635 | const nan_times_one = std.math.nan(f64) * 1; | 1627 | const nan_times_one = std.math.nan(f64) * 1; |
| 1636 | try std.testing.expect(std.math.isNan(nan_times_one)); | 1628 | try std.testing.expect(std.math.isNan(nan_times_one)); |
| ... | @@ -1638,7 +1630,6 @@ test "runtime isNan(nan * 1)" { | ... | @@ -1638,7 +1630,6 @@ test "runtime isNan(nan * 1)" { |
| 1638 | test "comptime isNan(nan * 0)" { | 1630 | test "comptime isNan(nan * 0)" { |
| 1639 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 1631 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 1640 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 1632 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1641 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | ||
| 1642 | 1633 | ||
| 1643 | const nan_times_zero = comptime std.math.nan(f64) * 0; | 1634 | const nan_times_zero = comptime std.math.nan(f64) * 0; |
| 1644 | try std.testing.expect(std.math.isNan(nan_times_zero)); | 1635 | try std.testing.expect(std.math.isNan(nan_times_zero)); |
| ... | @@ -1648,7 +1639,6 @@ test "comptime isNan(nan * 0)" { | ... | @@ -1648,7 +1639,6 @@ test "comptime isNan(nan * 0)" { |
| 1648 | test "runtime isNan(nan * 0)" { | 1639 | test "runtime isNan(nan * 0)" { |
| 1649 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 1640 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 1650 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 1641 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1651 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | ||
| 1652 | 1642 | ||
| 1653 | const nan_times_zero = std.math.nan(f64) * 0; | 1643 | const nan_times_zero = std.math.nan(f64) * 0; |
| 1654 | try std.testing.expect(std.math.isNan(nan_times_zero)); | 1644 | try std.testing.expect(std.math.isNan(nan_times_zero)); |
| ... | @@ -1658,7 +1648,6 @@ test "runtime isNan(nan * 0)" { | ... | @@ -1658,7 +1648,6 @@ test "runtime isNan(nan * 0)" { |
| 1658 | test "comptime isNan(inf * 0)" { | 1648 | test "comptime isNan(inf * 0)" { |
| 1659 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 1649 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 1660 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 1650 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1661 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | ||
| 1662 | 1651 | ||
| 1663 | const inf_times_zero = comptime std.math.inf(f64) * 0; | 1652 | const inf_times_zero = comptime std.math.inf(f64) * 0; |
| 1664 | try std.testing.expect(std.math.isNan(inf_times_zero)); | 1653 | try std.testing.expect(std.math.isNan(inf_times_zero)); |
| ... | @@ -1668,7 +1657,6 @@ test "comptime isNan(inf * 0)" { | ... | @@ -1668,7 +1657,6 @@ test "comptime isNan(inf * 0)" { |
| 1668 | test "runtime isNan(inf * 0)" { | 1657 | test "runtime isNan(inf * 0)" { |
| 1669 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 1658 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 1670 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 1659 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1671 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | ||
| 1672 | 1660 | ||
| 1673 | const inf_times_zero = std.math.inf(f64) * 0; | 1661 | const inf_times_zero = std.math.inf(f64) * 0; |
| 1674 | try std.testing.expect(std.math.isNan(inf_times_zero)); | 1662 | try std.testing.expect(std.math.isNan(inf_times_zero)); |
test/behavior/math.zig-1| ... | @@ -236,7 +236,6 @@ test "float equality" { | ... | @@ -236,7 +236,6 @@ test "float equality" { |
| 236 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 236 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 237 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 237 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 238 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 238 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 239 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | ||
| 240 | 239 | ||
| 241 | const x: f64 = 0.012; | 240 | const x: f64 = 0.012; |
| 242 | const y: f64 = x + 1.0; | 241 | const y: f64 = x + 1.0; |