jkp@sauna.hut.fi (Jyrki Kuoppala) (02/06/91)
When porting emacs to pc532-Minix, I noticed there's a bug in the setjmp library routine - it doesn't save registers r3-r7 (and f4-f7) which I think it should do. This seems like a serious bug and I'm surprised it has caused so little trouble when compiling all the other software I have on the pc532. At the end of this message there's a fixed setjmp.s (it's in gas format as I just moved to use GNU tools, but converting to Bruce syntax shouldn't be difficult) and a test program to test the functioning of setjmp. I now have a complete environment (including libc) working with the GNU tools: gcc 1.39 with patches, gas 1.38.1 with patches, GNU binutils with patches, GNU make 3.59, emacs 18.57 (subprocesses don't work yet), bash 1.05.1, GNU fileutils etc. G++ will be easy now when gas and GNU ld are used; gdb is next on my list. Most of the diffs to get these up are (or will be soon) available for anon. ftp from nic.funet.fi in directory pub/misc/pc532/GNU-hut. They're still not very pretty to look at, but they work, mostly. I think some programs require kernel additions like some more support for flags of open(2) and non-blocking I/O, fcntl flags etc. Gas and binutils didn't cope with the ns32k family properly without some fixing. Bootstrapping with the broken Minix programs was also painful. If there's interest, I could perhaps make the binaries available (hmm, I don't know what the various copyright restrictions with Minix and GNU software have to say to that). I'd like to scrap all the Minix library routines (except the syscalls, of course - they'll have to wait until we get free Mach 3.0) for a free libc. Any good free library sources out there ? Here's setjmp.s: #APP # # jkp@cs.hut.fi added saving & restoring of r3-r7 & f4-f7 5 Feb 1991 sj_fp=0 sj_sp=4 sj_pc=8 sj_r3=12 sj_r4=16 sj_r5=20 sj_r6=24 sj_r7=28 sj_f4=32 sj_f5=36 sj_f6=40 sj_f7=44 .text .globl _setjmp _setjmp: movd 4(sp),r0 #ptr to struct addr 0(fp),sj_fp(r0) #save fp addr 0(sp),sj_sp(r0) #save sp addr 0(r3),sj_r3(r0) #save r3 addr 0(r4),sj_r4(r0) #save r4 addr 0(r5),sj_r5(r0) #save r5 addr 0(r6),sj_r6(r0) #save r6 addr 0(r7),sj_r7(r0) #save r7 addr 0(f4),sj_f4(r0) #save f4 addr 0(f5),sj_f5(r0) #save f5 addr 0(f6),sj_f6(r0) #save f6 addr 0(f7),sj_f7(r0) #save f7 movd 0(sp),sj_pc(r0) #save return address movqd 0,r0 #return 0 ret 0 .globl _longjmp _longjmp: movd 8(sp),r0 #return value cmpqd 0,r0 #never return 0 bne longjmp1 movqd 1,r0 longjmp1: movd 4(sp),r1 #pointer to env movd sj_f7(r1),f7 #restore f7 movd sj_f6(r1),f6 #restore f6 movd sj_f5(r1),f5 #restore f5 movd sj_f4(r1),f4 #restore f4 movd sj_r7(r1),r7 #restore r7 movd sj_r6(r1),r6 #restore r6 movd sj_r5(r1),r5 #restore r5 movd sj_r4(r1),r4 #restore r4 movd sj_r3(r1),r3 #restore r3 lprd sp,sj_sp(r1) #restore sp lprd fp,sj_fp(r1) #restore fp movd sj_pc(r1),0(sp) #restore return adr ret 0 Remember to change _JBLEN from 3 to 12 in /usr/include/setjmp.h Here's the test program: #include <stdio.h> #include <setjmp.h> jmp_buf env; void foo() { register int b = 2; fprintf (stderr, "b = %d\n", b); } void bar() { register int c = 3; fprintf (stderr, "c = %d\n", 3); longjmp(env, 1); } main() { register int a = 1; foo(); if (setjmp (env)) fprintf (stderr, "a = %d\n", a); else { bar(); } } It outputs: b = 2 c = 3 a = 1 when everything is OK, but b = 2 c = 3 a = 3 when the bug exists. //Jyrki
ian@sibyl.eleceng.ua.oz.au (02/07/91)
Jyrki Kuoppala writes:
- When porting emacs to pc532-Minix, I noticed there's a bug in the
- setjmp library routine - it doesn't save registers r3-r7 (and f4-f7)
- which I think it should do.
- Here's the test program:
-
- #include <stdio.h>
- #include <setjmp.h>
-
- jmp_buf env;
- void foo()
- {
- register int b = 2;
- fprintf (stderr, "b = %d\n", b);
- }
-
- void bar()
- {
- register int c = 3;
- fprintf (stderr, "c = %d\n", 3);
- longjmp(env, 1);
- }
-
- main()
- {
- register int a = 1;
- foo();
- if (setjmp (env))
- fprintf (stderr, "a = %d\n", a);
- else {
- bar();
- }
- }
-
- It outputs:
-
- b = 2
- c = 3
- a = 1
-
- when everything is OK, but
-
- b = 2
- c = 3
- a = 3
I believe in ANSI C, there is no requirement to save registers in setjump.
Variables which have to be accessed after the setjump should be marked
volatile. Yes, some people have said that is ugly and nor the way it
should be done, but I pretty sure, that is the way it is!
Ian
news@daver.bungi.com (02/08/91)
Ian writes: >Jyrki Kuoppala writes: > - When porting emacs to pc532-Minix, I noticed there's a bug in the > - setjmp library routine - it doesn't save registers r3-r7 (and f4-f7) > - which I think it should do. ... >I believe in ANSI C, there is no requirement to save registers in setjump. >Variables which have to be accessed after the setjump should be marked >volatile. Yes, some people have said that is ugly and nor the way it >should be done, but I pretty sure, that is the way it is! I write: Ian is correct. Nevertheless all of the following compilers produce the result that Jyrki K's claims is correct: Gcc on 386 Gcc on Sun-3 (68020) Cc on 386 (pcc based) Cc on Sun (probably pcc based) Microsoft C (claims to be ANSI compatible) So it seems that's the way it isn't. I suspect that register variables ought to be preserved despite what the ANSI standard says, particularly since well optimized C compilers put everything they can into registers whether or not they are declared register. Jonathan Ryshpan <...!uunet!hitachi!jon>
news@bungi.com.YorkU.CA (02/08/91)
> > Jyrki Kuoppala writes: > - When porting emacs to pc532-Minix, I noticed there's a bug in the > - setjmp library routine - it doesn't save registers r3-r7 (and f4-f7) > - which I think it should do. [stuff deleted] Ian write: > I believe in ANSI C, there is no requirement to save registers in setjump. > Variables which have to be accessed after the setjump should be marked > volatile. Yes, some people have said that is ugly and nor the way it > should be done, but I pretty sure, that is the way it is! Some time back I ran into this setjump issue while trying to make all the 1.5.10 /usr/src/test programs run successfully. In a nutshell I decided to set ANSI C aside and save all registers. The essence of the decision was (1) that I have yet to run across a situation were saving all registers creates an adverse consequence (thats not to say they do not exist), (2) on numerious occasions not saving the registers has caused me a problem, and (3) in the large, the overhead of saving all registers is minimal. You might say I decided to switch rather than fight. Alternatively, it might be argued that I put off the problem for someone else to solve. Never the less, this is one instance where I do not see the merit of strict ANSI C conformance. My reading of ANSI C is that saving all registers is not in itself a violation of the standard. Rather that the consequence of doing so may on occasion lead to unknowingly writing non-portable code (ie. code that in someway depends upon setjmp saving all registers). Considering that the setjump issue is a problem that we all share, perhaps it would be useful for all of us to adopt a common solution. That is, we collectively agree to (a) save all registers, or (b) actively go on a bug hunt :-). Otherwise, this problem will continue to be a source of frustration, wasted time, generate message traffic, etc. Any thoughts pro or con ?? Obviously, my vote is for ignoring ANSI C and saving all registers -- that is unless someone makes a good case against. johnc -- John Connin: manatee Orlando, Florida UUCP: {uunet,ge-dab,ucf-cs}!tarpit!tous!manatee!johnc
mea@mea.utu.fi (Matti Aarnio) (02/08/91)
Ian writes: >Jyrki Kuoppala (jkp) writes: > - When porting emacs to pc532-Minix, I noticed there's a bug in the > - setjmp library routine - it doesn't save registers r3-r7 (and f4-f7) > - which I think it should do. ... >I believe in ANSI C, there is no requirement to save registers in setjump. >Variables which have to be accessed after the setjump should be marked >volatile. Yes, some people have said that is ugly and nor the way it >should be done, but I pretty sure, that is the way it is! Actually GCC document quite EXPLICITELY tell you to make sure that variables needing to be preserved across setjump()/longjump() MUST NOT STAY IN REGISTERS. A way to force GCC to do this (normally GCC just ignores register keyword and uses own heuristics!) is to take address of variable. Even though that address might not be used, and simplest optimation will drop instructions for it, this is the way: foo() { int a,b,c; /* Have potential to get into registers */ &b; /* Make sure GCC won't let it stay in register. */ /* Across func calls at least. */ do your jumps } But of course you knew it, didn't you ? JKP especially. /Matti Aarnio <mea@utu.fi> <mea@nic.funet.fi>
jkp@sauna.hut.fi (Jyrki Kuoppala) (02/09/91)
>Considering that the setjump issue is a problem that we all share, >perhaps it would be useful for all of us to adopt a common solution. >That is, we collectively agree to (a) save all registers, or (b) >actively go on a bug hunt :-). Otherwise, this problem will >continue to be a source of frustration, wasted time, generate message >traffic, etc. > Umm, actually I save only the registers that are not allowed to be clobbered by the gcc calling convention - is there a reason to save them all (other than someone using -fcall-saved-regs or changing the convention) ? //Jyrki
culberts@hplwbc.hpl.hp.com (Bruce Culbertson) (02/09/91)
> Jyrki Kuoppala (jkp) writes: > When porting emacs to pc532-Minix, I noticed there's a bug in the > setjmp library routine - it doesn't save registers r3-r7 (and f4-f7) > which I think it should do. This seems like a serious bug and I'm > surprised it has caused so little trouble when compiling all the other > software I have on the pc532. I have read the various man pages for BSD, SysV, etc. and I think my setjmp/longjmp actually conforms to the functionality it is required to support. However, I agree with Jyrki completely -- many programs we all know and love incorrectly expect more from setjmp/longjmp and it is a real pain if setjmp/longjmp does not preserve as much of the environment as possible. I have already made similar changes to the setjmp/longjmp in the soon-to-be released 1.3/1.5 hybrid pc532-Minix. > I now have a complete environment (including libc) working with the > GNU tools: gcc 1.39 with patches, gas 1.38.1 with patches, GNU > binutils with patches, GNU make 3.59, emacs 18.57 (subprocesses don't > work yet), bash 1.05.1, GNU fileutils etc. ... Great! This is a really nice contribution. > Bootstrapping with the broken Minix programs was also painful. May I request that people not make vague negative comments like this. What features of what programs are broken? An OS and C implementation are not broken just because they cannot compile and support all the GNU programs. I will attempt to fix bugs if I know what they are. > addr 0(f4),sj_f4(r0) #save f4 > addr 0(f5),sj_f5(r0) #save f5 > addr 0(f6),sj_f6(r0) #save f6 > addr 0(f7),sj_f7(r0) #save f7 I these are illegal instructions. If you look at the instruction encoding, you will see that there is no way to specify an addressing mode like "0(f4)". If gas does not catch this, it probably encodes it as "0(r4)", which is not what you want. The following should work: movf f4,sj_f4(r0) #save f4 movf f5,sj_f5(r0) #save f5 movf f6,sj_f6(r0) #save f6 movf f7,sj_f7(r0) #save f7 Cheers, Bruce Culbertson
jkp@sauna.hut.fi (Jyrki Kuoppala) (02/09/91)
Bruce writes: >> Bootstrapping with the broken Minix programs was also painful. > >May I request that people not make vague negative comments like this. >What features of what programs are broken? An OS and C implementation >are not broken just because they cannot compile and support all the >GNU programs. I will attempt to fix bugs if I know what they are. I haven't found anything that wrong in the C or library implementation (except the setjmp problem). It's just that the /bin/sh functionality is not quite what the various configuration and installation scripts expect, the same goes for the make program (it fails to make gcc, for example). Also ls did something very strange, and also various other programs I don't remember which I've now replaced with GNU or other free stuff. Sorry, I haven't put any effort to finding out what the bugs exactly are since I'm trying to use the Minix programs as little as possible to use as free a system as possible. >> addr 0(f7),sj_f7(r0) #save f7 ... >I these are illegal instructions. OK, thanks, I'll fix them - I never did study the ns32k assembler ;-) //Jyrki
tim@proton.amd.com (Tim Olson) (02/12/91)
In article <9102072159.AA02808@halsoft> writes: | Ian writes: | >Jyrki Kuoppala writes: | > - When porting emacs to pc532-Minix, I noticed there's a bug in the | > - setjmp library routine - it doesn't save registers r3-r7 (and f4-f7) | > - which I think it should do. | ... | >I believe in ANSI C, there is no requirement to save registers in setjump. | >Variables which have to be accessed after the setjump should be marked | >volatile. Yes, some people have said that is ugly and nor the way it | >should be done, but I pretty sure, that is the way it is! | | I suspect that register variables ought to be preserved despite what the | ANSI standard says, particularly since well optimized C compilers put | everything they can into registers whether or not they are declared | register. Actually, the most "correct" implementation of setjmp/longjmp is to ensure that all automatic variables, like statics and externals, have the value they had at the time of the longjmp. Saving register values in the jmpbuf causes those that were actually in registers to have the values they had at the time of the setjmp (but externals and automatics not in registers have their longjmp value). The reason the ANSI standard specified that the values of non-volatile automatics are not to be relied upon (how's that for a double-negative! ;-) is that: 1) There exist "correct" implementations (VAX with stack-unwind longjmp, register-windowed RISC processors). 2) There exist "register save" implementations. 3) Forcing one or the other to be the standard would be prohibitive on various architectures. -- -- Tim Olson Advanced Micro Devices (tim@amd.com)