From: Kevin V. <kv...@lu...> - 2001-05-29 19:44:30
|
> You reversed what I did in 1.74 because of the >#if 1 // bug id #223659, fixed in mcs51/ds390/gen.c 20010513 ... > Now it is broken again for the ds390 port. Fixed. I did not go back to the old way, however; I changed the rules here. Now the register bank(s) used by called functions are saved at entry to the ISR instead of just before the call to the function. This has the big advantage of only saving the register bank once instead of the horrible "push the entire bank/call/pop the entire bank" code we got before (inside a loop even!), and the smaller advantage of allowing me to keep using my "improved parameter passing" code (which really is better for the non-ISR case). It has the small disadvantage of requiring the ISR to save its local in-use registers on the stack before calling any function, which really shouldn't be necessary if the called function uses a different register bank. I think it is a net gain overall. Sandeep, since I think this is a real improvement, I think it should go in the mcs51 port as well. Let me know if you agree. I had never before really looked at the whole 'using' thing, and it seems to me that the rules are not obvious. I think the following rules for using 'using' are correct. If everybody agrees that these are right, I think they should be added to the documentation. btw, I think these rules are the same regardless of my changes. <begin proposed documentation> 1: The 'using' attribute (which tells the compiler to use a register bank other than the default bank zero) should only be applied to 'interrupt' functions (see note A below). This will in most circumstances make the generated ISR code more efficient since it will not have to save registers on the stack. 2: The 'using' attribute will have no effect on the generated code for a non-'interrupt' function (but may occasionally be useful anyway; see note A). 3: An 'interrupt' function using a non-zero bank will assume that it can trash that register bank, and will not save it. Since high-priority interrupts can interrupt low-priority ones on the 8051 and friends, this means that if a high-priority ISR 'using' a particular bank occurs while processing a low-priority ISR 'using' the same bank, terrible and bad things can happen. To prevent this, no single register bank should be 'used' by both a high priority and a low priority ISR. This is probably most easily done by having all high priority ISRs use one bank and all low priority ISRs use another. If you have an ISR which can change priority at runtime, you're on your own: I suggest using the default bank zero and taking the small performance hit. 4: It is most efficient if your ISR calls no other functions. 5: If your ISR must call other functions, it is most efficient if those functions use the same bank as the ISR (see note A below); the next best is if the called functions use bank zero. It is very inefficient to call a function using a different, non-zero bank from an ISR. (note A: possible exception: if a function is called ONLY from 'interrupt' functions using a particular bank, it can be declared with the same 'using' attribute as the calling 'interrupt' functions. For instance, if you have several ISRs using bank one, and all of them call memcpy(), it might make sense to create a specialized version of memcpy() 'using 1', since this would prevent the ISR from having to save bank zero to the stack on entry and switch to bank zero before calling the function). <end proposed documentation> My head hurts. Peace, Kevin |