CALL with passing flags
ke4pjw
Posts: 1,169
If I do the following PASM2, will it pass the C flag into the #rx routine?
MODC _SET call #rx wc
Comments
Sigh, no, that won't work with relative addressing.
Normal CALL/RET/RET doesn't touch the flag bits.
So CALL will pass the flags to the called routine? Seems to be a lot about it saving the state of the flags and everything in the manual, but it does not say if it passes them or not. I suppose I can test. I really wish I could do JMP/RET in inline PASM.
All the CALL instructions save the flags, but only
RET WCZ
actually restores them (and you can generalize this: only instructions with a W* effect suffix will ever change the flag bits)You can. If you couldn't do branches inline ASM would be mighty pointless. Not sure how many stack levels you can use without it messing up (the internal call stack just drops the oldest value on overflow). Not sure if CALLA/RETA work (i.e. PTRA is pointed at the spin stack on inline asm entry).
I think it may be a matter of CALL not modifying the flags. I tried this bit of code and it did work.
This version seems to suggest that the flags are not saved and restored with call and ret. The set_led code clears C which causes the P57 LED to go on and stay on after the first call to set_led.
>
Yeah, I am having trouble understanding what that means. If I have C set, perform a CALL, does the C flag persist into the routine?
When using RET with inline PASM, it will immediately return from the whole PUB. You must use CALL to execute a routine with a RET. It sets up another stack, etc. I think it can be called 4 or 5 deep. I am not wanting to do recursion though. I just wanted to jump to another routine and return to the JMP.
Bah. I think I just need to nuke what I was attempting to do and start over from scratch. Too many gotchas at this point for me to keep track of.
Yes. As said, only instructions with a WC/WZ/WCZ effect will change the flag bits.
My simple little LED blinker demonstrates that it does.
I missed that. I added wcz to the ret line in the set_led routine and the behavior is as expected with save/restore.
The PASM manual I printed a few weeks ago says that RET can "optionally restore the C and Z flag state as it was prior."
So it sounds like the C or Z does get passed into the CALLed routine, but cannot be passed back out.
As Ada pointed out, you must add WCZ to the RET at the end of your routine to restore saved flags. This is what the manual means by optionally -- you have the option to add WCZ to RET.
I verified that with this:
As you can see, the set_led routine always clears C. By adding WCZ to RET the state of C before CALL is restored.
Terry,
In general, the C and Z flags are left alone unless applying an optional WC, WZ, or WCZ to the instruction. This even applies to something like the RCL instruction. Which, btw, explicitly uses C flag as part of its 33-bit bit-rotation.
So, that general rule means CALL will leave the flags untouched. What state the flag were in before CALLing will stay the same inside the subroutine. Here's an entry from the instruction spreadsheet:
CALL D {WC/WZ/WCZ} Call to D by pushing {C, Z, 10'b0, PC[19:0]} onto stack. C = D[31], Z = D[30], PC = D[19:0].
So, it puts a copy of the flags and program counter onto the stack. But that doesn't change the flags. What can change the flags is if WCZ is specified - note the curly brackets for optional part of instruction.
The last sentence with C=D[31] shows what will happen if the optional parts are used.
The explicit flag writes that are available on the CALL instruction, when performing a CALL to an absolute address, is what threw me off. Also the description of it saving the flags for the RET. Nothing explicitly states flags carry into the CALL routine. I think to most people that is implicit with a JMP, but with a new stack and everything with CALL, it wasn't as obvious.
Thanks everyone! Much appreciated!
Oh, a CALL machine instruction is not same as a language based call - Which may introduce some sort of context. With the machine instruction, the stack is still the same stack. Just one new entry added.