XBYTE and hardware stack
TonyB_
Posts: 2,179
in Propeller 2
RET never popping $1FF can be a real nuisance in certain circumstances, as it prevents use of hardware stack from one bytecode to the next. It would be good in future to use TOS[31] = 1 as stack pop enable when TOS[8:0] = $1FF, thus push $8000_01FF if RET pop desired.
As $1FF is never popped now, the alternative is to do an XBYTE equivalent with separate instructions and I think the code below will do the job (no C/Z writes):
Corrections are welcome.
As $1FF is never popped now, the alternative is to do an XBYTE equivalent with separate instructions and I think the code below will do the job (no C/Z writes):
rfbyte pa 'pa = bytecode getptr pb 'pb = FIFO pointer mov temp,pa ... 'manipulate temp rdlut temp,temp 'read EXECF data execf temp
Corrections are welcome.
Comments
$1FF was chosen because it fits in 9 bits and cannot be practically used as a return address, since returning to INB would make no sense.
In the Spin2 interpreter, I sometimes do CALLs with RETs to get things done before resuming bytecode execution, which utilizes the $1FF on top of the current stack.
I'm not understanding what you cite as a problem.
Are you thinking about making a stack for bytecode calls? I don't think it's practical to do that. It seems you would have to maybe pop the $1FF, push the return address, then push $1FF again for a CALL. For a RET, you would pop the $1FF, pop the address, then push $1FF.
I agree that using the MSB as a pop inhibitor would have been good. MSB-1 could have invoked XBYTE.
N and N+1 are two successive bytecodes. N is a prefix for N+1 and some clean-up code for N is needed at the end of N+1. The code for N+1 is the same whether or not it has a prefix and only a table of data is different. The clean-up code for N restores the data to the default values.
N wants to push an address for the N+1 RET to return to, but
(a) N+1 will not be interpreted unless $1FF is top of stack.
(b) If N pushes its clean-up address then pushes $1FF, N+1 will be interpreted after the N RET but $1FF will never be popped.
The problem can be solved by simulating XBYTE with about half a dozen extra instructions, compared to only one for a modified XBYTE than can pop $1FF.
In that particular case, can't you just have N store the pointer to the cleanup code somewhere and do a in N+1? (the cleanup code would obviously have to clear cleanup_ptr)
So, you want N to be a wrapper for N+1, that executes the N+1 code with a different data table?
I haven't seen your code, but would it not be possible to have it such that the N code incorporates the setup, N+1, and clean-up code in a single sequence with two entry and exit points, with N skip pattern skipping the N+1 exit point?
If not, how about N executes a _RET_ SETQ2 {#}D for a near-duplicate copy of the N+1 byte code that uses the alternate data table?
From the Parallax Propeller 2 Documentation v33 - Rev B Silicon Google doc:
> Does the logic check for a full 32-bit TOS equal to $1FF?
Yes.
Then maybe you need an N+2 to clean up from N.
I tried different approaches, but it gets somehow messy very fast if you need to parse multibyte, variable length 'bytecodes'. I am sure that there is some simple solution, I just need to test more things out.
Just out of madness I looked at the IBM/360 opcodes, and hell yes, they are quite ordered. But they would need 'nibblecodes' aka 4 bit.
for a future revision it would be nice to have some trace of the last byte code(s) executed before.
Enjoy!
Mike
Some info that might be of interest:
I am getting more than 3x compression with XBYTE, i.e. skip pattern code would be > 3 as large if done as separate instructions (e.g. ~500 versus ~1700 longs).
On second thought, if the bytecodes are handled in a somewhat arbitrary order you'll need to have a flag somewhere outside of the code block that is set by N and checked by N+1 to see if N-cleanup is needed. A single long could hold up to 32 flags for multiple setups that need cleanup.