Wed Sep 2 12:38:07 2020 UTC ()
Pull up following revision(s) (requested by thorpej in ticket #1071):

	sys/arch/alpha/alpha/fp_complete.c: revision 1.24

- compare_{le,lt)(): Use float64_{le,lt}_quiet() to avoid raising
exceptions on QNaNs.
- alpha_fp_interpret(): Instructions are 32-bits wide, so don't use a
uint64_t to contain them.
- alpha_fp_complete(): Operations on NaNs trap on Alpha, but the exception
summary reports INV (invalid operation) rather than SWC (software
completion) in this case.  So also interpret the instruction if INV
is set in the exception summary.  This will emulate operations on
NaN and correctly suppress FP traps for QNaNs.

This fixes bin/55633, which was caused by:
-> Input string "nanotime" is passed to awk's internal is_number().
-> strtod() interprets as "nan" and returns QNaN as the result.
-> Result compared against HUGE_VAL, blows up because cmptle is called
with a NaN operand, and the hardware doesn't care that it's quiet.


(martin)
diff -r1.23 -r1.23.4.1 src/sys/arch/alpha/alpha/fp_complete.c

cvs diff -r1.23 -r1.23.4.1 src/sys/arch/alpha/alpha/fp_complete.c (expand / switch to unified diff)

--- src/sys/arch/alpha/alpha/fp_complete.c 2019/03/25 19:24:30 1.23
+++ src/sys/arch/alpha/alpha/fp_complete.c 2020/09/02 12:38:07 1.23.4.1
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: fp_complete.c,v 1.23 2019/03/25 19:24:30 maxv Exp $ */ 1/* $NetBSD: fp_complete.c,v 1.23.4.1 2020/09/02 12:38:07 martin Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2001 Ross Harvey 4 * Copyright (c) 2001 Ross Harvey
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
@@ -25,27 +25,27 @@ @@ -25,27 +25,27 @@
25 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 25 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 26 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
27 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE. 33 * POSSIBILITY OF SUCH DAMAGE.
34 */ 34 */
35 35
36#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ 36#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
37 37
38__KERNEL_RCSID(0, "$NetBSD: fp_complete.c,v 1.23 2019/03/25 19:24:30 maxv Exp $"); 38__KERNEL_RCSID(0, "$NetBSD: fp_complete.c,v 1.23.4.1 2020/09/02 12:38:07 martin Exp $");
39 39
40#include <sys/param.h> 40#include <sys/param.h>
41#include <sys/systm.h> 41#include <sys/systm.h>
42#include <sys/proc.h> 42#include <sys/proc.h>
43#include <sys/atomic.h> 43#include <sys/atomic.h>
44#include <sys/evcnt.h> 44#include <sys/evcnt.h>
45 45
46#include <machine/cpu.h> 46#include <machine/cpu.h>
47#include <machine/fpu.h> 47#include <machine/fpu.h>
48#include <machine/reg.h> 48#include <machine/reg.h>
49#include <machine/alpha.h> 49#include <machine/alpha.h>
50#include <alpha/alpha/db_instruction.h> 50#include <alpha/alpha/db_instruction.h>
51 51
@@ -189,33 +189,33 @@ lds(unsigned int rn, s_float *v, struct  @@ -189,33 +189,33 @@ lds(unsigned int rn, s_float *v, struct
189 alpha_lds(rn, v); 189 alpha_lds(rn, v);
190} 190}
191 191
192static inline void 192static inline void
193ldt(unsigned int rn, t_float *v, struct lwp *l) 193ldt(unsigned int rn, t_float *v, struct lwp *l)
194{ 194{
195 POSTFILTER_SUBNORMAL(l, v); 195 POSTFILTER_SUBNORMAL(l, v);
196 alpha_ldt(rn, v); 196 alpha_ldt(rn, v);
197} 197}
198 198
199static float64 199static float64
200compare_lt(float64 a, float64 b) 200compare_lt(float64 a, float64 b)
201{ 201{
202 return CMP_RESULT(float64_lt(a, b)); 202 return CMP_RESULT(float64_lt_quiet(a, b));
203} 203}
204 204
205static float64 205static float64
206compare_le(float64 a, float64 b) 206compare_le(float64 a, float64 b)
207{ 207{
208 return CMP_RESULT(float64_le(a, b)); 208 return CMP_RESULT(float64_le_quiet(a, b));
209} 209}
210 210
211static float64 211static float64
212compare_un(float64 a, float64 b) 212compare_un(float64 a, float64 b)
213{ 213{
214 if (float64_is_nan(a) | float64_is_nan(b)) { 214 if (float64_is_nan(a) | float64_is_nan(b)) {
215 if (float64_is_signaling_nan(a) | float64_is_signaling_nan(b)) 215 if (float64_is_signaling_nan(a) | float64_is_signaling_nan(b))
216 float_set_invalid(); 216 float_set_invalid();
217 return CMP_RESULT(1); 217 return CMP_RESULT(1);
218 } 218 }
219 return CMP_RESULT(0); 219 return CMP_RESULT(0);
220} 220}
221 221
@@ -492,27 +492,27 @@ float64_unk(float64 a, float64 b) @@ -492,27 +492,27 @@ float64_unk(float64 a, float64 b)
492 * 1 1 1 0 . . . cvtXt/g (cvtqt, cvt[dq]g only) 492 * 1 1 1 0 . . . cvtXt/g (cvtqt, cvt[dq]g only)
493 * 1 1 1 1 . . . cvtXq/q (cvttq, cvtgq) 493 * 1 1 1 1 . . . cvtXq/q (cvttq, cvtgq)
494 * | | 494 * | |
495 * 15 14 13|12 11 10 09|08 07 06 05 the twilight zone 495 * 15 14 13|12 11 10 09|08 07 06 05 the twilight zone
496 * --------======------============ 496 * --------======------============
497 * TRAP : RND : SRC : FUNCTION : 497 * TRAP : RND : SRC : FUNCTION :
498 * /s /i /u x x 1 0 1 1 0 0 . . . cvtts, /siu only 0, 1, 5, 7 498 * /s /i /u x x 1 0 1 1 0 0 . . . cvtts, /siu only 0, 1, 5, 7
499 * 0 1 0 1 0 1 0 1 1 0 0 . . . cvtst (src == T (!)) 2ac NOT /S 499 * 0 1 0 1 0 1 0 1 1 0 0 . . . cvtst (src == T (!)) 2ac NOT /S
500 * 1 1 0 1 0 1 0 1 1 0 0 . . . cvtst/s (src == T (!)) 6ac 500 * 1 1 0 1 0 1 0 1 1 0 0 . . . cvtst/s (src == T (!)) 6ac
501 * x 0 x x x x 0 1 1 1 1 . . . cvttq/_ (src == T) 501 * x 0 x x x x 0 1 1 1 1 . . . cvttq/_ (src == T)
502 */ 502 */
503 503
504static void 504static void
505alpha_fp_interpret(alpha_instruction *pc, struct lwp *l, uint64_t bits) 505alpha_fp_interpret(alpha_instruction *pc, struct lwp *l, uint32_t bits)
506{ 506{
507 s_float sfa, sfb, sfc; 507 s_float sfa, sfb, sfc;
508 t_float tfa, tfb, tfc; 508 t_float tfa, tfb, tfc;
509 alpha_instruction inst; 509 alpha_instruction inst;
510 510
511 inst.bits = bits; 511 inst.bits = bits;
512 switch(inst.generic_format.opcode) { 512 switch(inst.generic_format.opcode) {
513 default: 513 default:
514 /* this "cannot happen" */ 514 /* this "cannot happen" */
515 this_cannot_happen(2, inst.bits); 515 this_cannot_happen(2, inst.bits);
516 return; 516 return;
517 case op_any_float: 517 case op_any_float:
518 if (inst.float_format.function == op_cvtql_sv || 518 if (inst.float_format.function == op_cvtql_sv ||
@@ -624,33 +624,35 @@ alpha_fp_complete(u_long a0, u_long a1,  @@ -624,33 +624,35 @@ alpha_fp_complete(u_long a0, u_long a1,
624{ 624{
625 int t; 625 int t;
626 int sig; 626 int sig;
627 uint64_t op_class; 627 uint64_t op_class;
628 alpha_instruction inst; 628 alpha_instruction inst;
629 /* "trigger_pc" is Compaq's term for the earliest faulting op */ 629 /* "trigger_pc" is Compaq's term for the earliest faulting op */
630 alpha_instruction *trigger_pc, *usertrap_pc; 630 alpha_instruction *trigger_pc, *usertrap_pc;
631 alpha_instruction *pc, *win_begin, tsw[TSWINSIZE]; 631 alpha_instruction *pc, *win_begin, tsw[TSWINSIZE];
632 632
633 sig = SIGFPE; 633 sig = SIGFPE;
634 pc = (alpha_instruction *)l->l_md.md_tf->tf_regs[FRAME_PC]; 634 pc = (alpha_instruction *)l->l_md.md_tf->tf_regs[FRAME_PC];
635 trigger_pc = pc - 1; /* for ALPHA_AMASK_PAT case */ 635 trigger_pc = pc - 1; /* for ALPHA_AMASK_PAT case */
636 if (cpu_amask & ALPHA_AMASK_PAT) { 636 if (cpu_amask & ALPHA_AMASK_PAT) {
637 if (a0 & 1 || alpha_fp_sync_complete) { 637 /* SWC | INV */
 638 if (a0 & 3 || alpha_fp_sync_complete) {
638 sig = alpha_fp_complete_at(trigger_pc, l, ucode); 639 sig = alpha_fp_complete_at(trigger_pc, l, ucode);
639 goto done; 640 goto done;
640 } 641 }
641 } 642 }
642 *ucode = a0; 643 *ucode = a0;
643 if (!(a0 & 1)) 644 /* SWC | INV */
 645 if (!(a0 & 3))
644 return sig; 646 return sig;
645/* 647/*
646 * At this point we are somewhere in the trap shadow of one or more instruc- 648 * At this point we are somewhere in the trap shadow of one or more instruc-
647 * tions that have trapped with software completion specified. We have a mask 649 * tions that have trapped with software completion specified. We have a mask
648 * of the registers written by trapping instructions. 650 * of the registers written by trapping instructions.
649 * 651 *
650 * Now step backwards through the trap shadow, clearing bits in the 652 * Now step backwards through the trap shadow, clearing bits in the
651 * destination write mask until the trigger instruction is found, and 653 * destination write mask until the trigger instruction is found, and
652 * interpret this one instruction in SW. If a SIGFPE is not required, back up 654 * interpret this one instruction in SW. If a SIGFPE is not required, back up
653 * the PC until just after this instruction and restart. This will execute all 655 * the PC until just after this instruction and restart. This will execute all
654 * trap shadow instructions between the trigger pc and the trap pc twice. 656 * trap shadow instructions between the trigger pc and the trap pc twice.
655 */ 657 */
656 trigger_pc = 0; 658 trigger_pc = 0;