NaN() blows awk up on 386

Fri, 29 Apr 2016 10:57:02 EDT
qu7uux@[REDACTED]

Now that awk(1) doesn’t use APE strtod() et al., it fails when lib.c:is_number() is passed a string that can be interpreted as NaN by strtod(2).

It seems that FPINVAL being set on this terminal makes NaN() trap upon return, when it doesn’t on others. This only occurs on my 386 terminals (arm untested). It looks like it might be because of fpinit() in /sys/src/9/pc/l.s, but I don’t understand this enough to know.

Below, an example of awk failing[1], then a test demonstrating behavior when altering fcr flags[2], on two machines. Finally, [3] shows a possible cause.

[1] awk failure

% echo $objtype 386 % aux/cpuid vendor GenuineIntel procmodel 00000f29 / 00010809 features fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat features pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe features cid xtpr extmodel 00000000 / 00000000 procname Intel® Pentium® 4 CPU 2.80GHz % bind -ac /dist/plan9front /; cd /; hg log | sed 1q changeset: 5284:03b6fd929637

% cd /sys/man % mk for (i in [0-8]){

/sys/lib/man/secindex $i > $i/INDEX
/sys/lib/man/mkhtmlindex $i > $i/INDEX.html

} mk lookindex /sys/lib/man/mksearchindex > searchindex # index for man2html searches sys: fp: invalid operation fppc=0x10fc9 status=0x8081 pc=0x000074c3 awk 3631: suicide: sys: fp: invalid operation fppc=0x10fc9 status=0x8081 pc=0x000074c3 sys: fp: invalid operation fppc=0x10fc9 status=0xc081 pc=0x000074c3 awk 3787: suicide: sys: fp: invalid operation fppc=0x10fc9 status=0xc081 pc=0x000074c3 sys: fp: invalid operation fppc=0x10fc9 status=0x8081 pc=0x000074c3 awk 4004: suicide: sys: fp: invalid operation fppc=0x10fc9 status=0x8081 pc=0x000074c3 sys: fp: invalid operation fppc=0x10fc9 status=0x8081 pc=0x000074c3 awk 4033: suicide: sys: fp: invalid operation fppc=0x10fc9 status=0x8081 pc=0x000074c3 builtin cd /sys/lib/man/lookman mkindex sys: fp: invalid operation fppc=0x10fc9 status=0xc081 pc=0x000074c3 awk 11816: suicide: sys: fp: invalid operation fppc=0x10fc9 status=0xc081 pc=0x000074c3 mk: for (i in … : exit status=rc 1620: mksearchindex 11814: mksearchindex 11815: awk 11816: sys: fp: invalid operation fppc=0x10fc9 status=0xc081 pc=0x000074

% acid 4033 /proc/4033/text:386 plan 9 executable /sys/lib/acid/port /sys/lib/acid/386 acid: stk() is_number(s=0x2acc8)+0x4b /sys/src/cmd/awk/lib.c:698 getrec(pbuf=0x1c1dc,pbufsize=0x1c000,isrecord=0x1)+0x2ac /sys/src/cmd/awk/lib.c:146 program(a=0x39390)+0x126 /sys/src/cmd/awk/run.c:196 execute(u=0x39380)+0xb5 /sys/src/cmd/awk/run.c:163 run(a=0x39380)+0x14 /sys/src/cmd/awk/run.c:137 main(argv=0xdfffee20,argc=0x2)+0x220 /sys/src/cmd/awk/main.c:168 _main+0x31 /sys/src/libc/386/main9.s:16 acid: (is_number:s\s) nanoseconds to exit the output queue and acid: echo kill > /proc/4033/ctl

% acid 11816 /proc/11816/text:386 plan 9 executable /sys/lib/acid/port /sys/lib/acid/386 acid: stk() is_number(s=0x2acc8)+0x4b /sys/src/cmd/awk/lib.c:698 getrec(pbuf=0x1c1dc,pbufsize=0x1c000,isrecord=0x1)+0x2ac /sys/src/cmd/awk/lib.c:146 program(a=0x35a18)+0x126 /sys/src/cmd/awk/run.c:196 execute(u=0x35a08)+0xb5 /sys/src/cmd/awk/run.c:163 run(a=0x35a08)+0x14 /sys/src/cmd/awk/run.c:137 main(argv=0xdfffef50,argc=0x1)+0x220 /sys/src/cmd/awk/main.c:168 _main+0x31 /sys/src/libc/386/main9.s:16 acid: (is_number:s\s) nan /sys/man/2/0intro acid: echo kill > /proc/11816/ctl %

[2] test using setfcr(2)

% ed test.c ?test.c i

include <u.h>

include <libc.h>

void main(int, char**) {

ulong f;

f = getfcr();
print("%#lux, %#ux\n", f, FPINVAL);
if(f &#38; FPINVAL){
    print("FPINVAL set\n");
    //setfcr(f &#38; ~FPINVAL);
}
NaN();

} . w 205 q

% 8c -FTVw test.c && 8l -o 8.test test.8 && 8.test 0xdfff024d, 0x1 FPINVAL set 8.test 1568: suicide: sys: fp: invalid operation fppc=0x10f4 status=0x8081 pc=0x00001063

% acid 1568 /proc/1568/text:386 plan 9 executable /sys/lib/acid/port /sys/lib/acid/386 acid: stk() main()+0x43 /usr/glenda/test.c:15 main+0x31 /sys/src/libc/386/main9.s:16 acid: src(PC) /usr/glenda/test.c:15 10 print(“%#lux, %#ux\n”, f, FPINVAL); 11 if(f & FPINVAL){ 12 print(“FPINVAL set\n”); 13 //setfcr(f & ~FPINVAL); 14 } >15 NaN(); 16 } acid: asm(PC) main+0x43 0x00001063 FMOVDP F0,F0 main+0x45 0x00001065 ADDL $0x18,SP main+0x48 0x00001068 RET main 0x00001069 SUBL $0x48,SP acid: fpr() F0 -Inf F1 -Inf F2 -Inf F3 -Inf F4 -Inf F5 -Inf F6 0 F7 0 control 0x027f status 0x0001 tag 0x00 ip 0x000010f4 cs selector 0x0023 opcode 0x0544 data operand 0xdfffef40 operand selector 0x001b acid: echo kill > /proc/1568/ctl

% sed ’s,//,,‘ test.c > test2.c % grep setfcr test2.c

    setfcr(f &#38; ~FPINVAL);

% 8c -FTVw test2.c && 8l -o 8.test2 test2.8 && 8.test2 0xdfff024d, 0x1 FPINVAL set % echo $status 8.test2 1592: main %

on another machine (pentium mmx):

% aux/cpuid vendor GenuineIntel procmodel 00000543 / 00000000 features fpu vme de pse tsc msr mce cx8 mmx % 8c -FTVw test.c && 8l -o 8.test test.8 && 8.test 0xdfff024d, 0x1 FPINVAL set 8.test 351: suicide: sys: fp: invalid operation fppc=0x10f4 status=0x8081 pc=0x00001063 % sed ’s,//,,‘ test.c > test2.c % 8c -FTVw test2.c && 8l -o 8.test2 test2.8 && 8.test2 0xdfff024d, 0x1 FPINVAL set %

[3] pcf vs. pc64

on another another machine, pc64:

% aux/cpuid vendor GenuineIntel procmodel 00040651 / 03100800 features fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat features pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe features pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 fma cx16 xtpr pdcm pcid sse4_1 sse4_2 features movbe popcnt tscdeadline aes xsave avx f16c rdrnd features xsaveopt extmodel 00000000 / 00000000 extfeatures syscall nx pg1g tscp lm extfeatures ahf64 lzcnt procname Intel® Core™ i7-4510U CPU @ 2.00GHz physbits 39 virtbits 48 % 6c -FTVw test.c && 6l -o 6.test test.6 && 6.test 0x680, 0x80 FPINVAL is set %

same machine, but pcf:

% 8c -FTVw test.c && 8l -o 8.test test.8 && 8.test 0xdfff024d, 0x1 FPINVAL set 8.test3 1094: suicide: sys: fp: invalid operation fppc=0x1112 status=0x8081 pc=0x00001081 % sed ’s,//,,‘ test.c > test2.c % 8c -FTVw test2.c && 8l -o 8.test2 test2.8 && 8.test2 0xdfff024d, 0x1 FPINVAL set %

no fpinit() for amd64, hence not affected?

% grep -n setfcr /sys/src/9/pc64/ % grep -n setfcr /sys/src/9/pc/ /sys/src/9/pc/l.s:594: / setfcr(FPPDBL|FPRNR|FPINVAL|FPZDIV|FPOVFL) / % ed /sys/src/9/pc/l.s 590,600p TEXT fpinit(SB), $0 / enable and init /

FPON
FINIT
WAIT
/* setfcr(FPPDBL|FPRNR|FPINVAL|FPZDIV|FPOVFL) */
/* note that low 6 bits are masks, not enables, on this chip */
PUSHW   $0x0232
FLDCW   0(SP)
POPW    AX
WAIT
RET

% grep fpinit /sys/src/9/pc/ /sys/src/9/pc/fns.h:void fpinit(void); /sys/src/9/pc/l.s:TEXT fpinit(SB), $0 / enable and init / /sys/src/9/pc/main.c: fpinit(); %