Shop OBEX P1 Docs P2 Docs Learn Events
XBYTE and hardware stack — Parallax Forums

XBYTE and hardware stack

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):
	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

  • cgraceycgracey Posts: 14,133
    But why would you ever RETurn to INB ($1FF)?

    $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.
  • This issue is not theoretical and is as follows:

    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.
  • For
    TonyB_ wrote: »
    This issue is not theoretical and is as follows:

    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.

    In that particular case, can't you just have N store the pointer to the cleanup code somewhere and do a
    _ret_ tjnz cleanup_ptr,cleanup_ptr
    
    in N+1? (the cleanup code would obviously have to clear cleanup_ptr)
  • TonyB_TonyB_ Posts: 2,108
    edited 2020-02-18 00:19
    deleted
  • TonyB_ wrote: »
    This issue is not theoretical and is as follows:

    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.

    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:
    To alter the XBYTE mode for the next bytecode, only, a '_RET_ SETQ2 {#}D' instruction can be executed. This is useful for engaging singular bytecodes from alternate sets, without having to restore the original XBYTE mode, afterwards.
  • Thanks for the suggestions. SETQ2 would not help at all sometimes and at other times would require lots of LUT RAM space that is not available. N does not know what comes next and N+1 does not know what came before.
  • Does the logic check for a full 32-bit TOS equal to $1FF?
  • cgraceycgracey Posts: 14,133
    > @TonyB_ said:
    > Does the logic check for a full 32-bit TOS equal to $1FF?

    Yes.
  • TonyB_ wrote: »
    Thanks for the suggestions. SETQ2 would not help at all sometimes and at other times would require lots of LUT RAM space that is not available. N does not know what comes next and N+1 does not know what came before.

    Then maybe you need an N+2 to clean up from N.
  • msrobotsmsrobots Posts: 3,701
    edited 2020-02-16 04:55
    I haven't really grooked chips ideas behind XBYTE. It is nice for byte code, but gets more complicated to use for emulators.

    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
  • Does RFVAR help?
  • TonyB_TonyB_ Posts: 2,108
    edited 2020-02-16 11:30
    Instead of modifying $1FF, I think it would be better to use $1FE for a 'one-time' XBYTE, with RET popping $1FE:
    'N, N+1, N+2 are successive bytecodes
    'TOS = $1FF
      
    'N
      		...
      		push	#N_cleanup
    	_ret_	push	#$1FE		'start N+1 with TOS = N_cleanup
      
      
    'N+1
    		...
    	 _ret_	...			'start N+2 with TOS = $1FF if no prefix N
    					'else branch to N_cleanup
    
    N_cleanup
    		...
    	 _ret_	...			'start N+2 with TOS = $1FF
    
    
  • TonyB_TonyB_ Posts: 2,108
    edited 2020-02-17 10:22
    dnalor wrote: »
    Does RFVAR help?
    Unfortunately no. A future one-time XBYTE as described above would save longs and cycles but until then it could be simulated.

    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).
  • AJLAJL Posts: 512
    edited 2020-02-17 15:18
    Could you have a NOP immediately before the _ret_ of N+1, have N change it to a CALL to N-cleanup, and have the N-cleanup code change it back to a NOP?

    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.
  • It turns out N+1 could clean up for prefix N. It's only one instruction but would have to be done all the time, adding two cycles to N+1 whether or not prefix was present. Testing for a prefix would just waste more time.
Sign In or Register to comment.