Shop OBEX P1 Docs P2 Docs Learn Events
EXECF (including XBYTE) — Parallax Forums

EXECF (including XBYTE)

I can't see a reason why anyone would ever use EXECF with the first skip bit set to 1. Why would you ever jump deliberately to an instruction and not execute it, when you could jump directly to the first instruction that you do want to execute?

I've looked at the latest Spin2 interpreter and the first skip bit is 0 for every bytecode from 00 to FF (with only the last two unused). Therefore, I think it would be safe to assume the instruction at the jump address will be executed, in which case a skip bit of 0 could be inserted automatically at the start of the skip pattern.

This would give us 22 skippable instructions after the first, increasing the length of the skip sequence from 22 to 23. I've already hit the current limit of 22 in XBYTE.

Comments

  • cgraceycgracey Posts: 14,133
    edited 2018-10-23 23:03
    Yes, but what about a case where you have a random mask and you are dynamically creating skip patterns for constant points of entry. Also, all that circuitry is extremely tenuous and I don't have the time to spool that up in my head again. It is what it is, for now. Hopefully, it has no bugs.
  • TonyB_ wrote: »
    I can't see a reason why anyone would ever use EXECF with the first skip bit set to 1. Why would you ever jump deliberately to an instruction and not execute it, when you could jump directly to the first instruction that you do want to execute?
    An interpreter might well have a common routine that does a bunch of things but for which the first instruction should be skipped in certain cases (e.g. some opcodes negate an operand, others do not). Granted, a clever programmer can avoid this by providing different entry points, but (a) this is not necessarily the "obvious" way to do it, and (b) the interpreter might be machine generated, in which case it's perhaps not as obvious to the compiler that this should be done.

  • As a concrete example the ZOG ZPU interpreter for P2 does have a routine that uses the first bit (in fact the first N bits):
    zpu_storesp_N
    			'' use an EXECF mask to select just one of the wrlongs
    			wrlong	tos,ptrb[1]  	' only one
    			wrlong	tos,ptrb[2]	' only one
    			wrlong	tos,ptrb[3]	' only one
    			wrlong	tos,ptrb[4]	' only one
    			wrlong	tos,ptrb[5]  	' only one
    			wrlong	tos,ptrb[6]	' only one
    			wrlong	tos,ptrb[7]	' only one
    			wrlong	tos,ptrb[8]	' only one
    	_ret_		rdlong	tos,++ptrb
    ...
    ' from the opcode table
    {51}    long  zpu_storesp_N | %0_1111_1110 << 10
    {52}    long  zpu_storesp_N | %0_1111_1101 << 10
    {53}    long  zpu_storesp_N | %0_1111_1011 << 10
    {54}    long  zpu_storesp_N | %0_1111_0111 << 10
    {55}    long  zpu_storesp_N | %0_1110_1111 << 10
    {56}    long  zpu_storesp_N | %0_1101_1111 << 10
    {57}    long  zpu_storesp_N | %0_1011_1111 << 10
    {58}    long  zpu_storesp_N | %0_0111_1111 << 10
    
    
  • TonyB_TonyB_ Posts: 2,126
    edited 2018-10-24 00:46
    ersmith wrote: »
    As a concrete example the ZOG ZPU interpreter for P2 does have a routine that uses the first bit (in fact the first N bits):
    zpu_storesp_N
    			'' use an EXECF mask to select just one of the wrlongs
    			wrlong	tos,ptrb[1]  	' only one
    			wrlong	tos,ptrb[2]	' only one
    			wrlong	tos,ptrb[3]	' only one
    			wrlong	tos,ptrb[4]	' only one
    			wrlong	tos,ptrb[5]  	' only one
    			wrlong	tos,ptrb[6]	' only one
    			wrlong	tos,ptrb[7]	' only one
    			wrlong	tos,ptrb[8]	' only one
    	_ret_		rdlong	tos,++ptrb
    ...
    ' from the opcode table
    {51}    long  zpu_storesp_N | %0_1111_1110 << 10
    {52}    long  zpu_storesp_N | %0_1111_1101 << 10
    {53}    long  zpu_storesp_N | %0_1111_1011 << 10
    {54}    long  zpu_storesp_N | %0_1111_0111 << 10
    {55}    long  zpu_storesp_N | %0_1110_1111 << 10
    {56}    long  zpu_storesp_N | %0_1101_1111 << 10
    {57}    long  zpu_storesp_N | %0_1011_1111 << 10
    {58}    long  zpu_storesp_N | %0_0111_1111 << 10
    
    

    All of those initial skip bits of 1 are avoidable, but if you don't want to change the opcode table then you could simply insert a NOP at the beginning:
    zpu_storesp_N
    			nop			' 1st skip bit = 0 automatically
    			'' use an EXECF mask to select just one of the wrlongs
    			wrlong	tos,ptrb[1]  	' only one
    			wrlong	tos,ptrb[2]	' only one
    			wrlong	tos,ptrb[3]	' only one
    			wrlong	tos,ptrb[4]	' only one
    			wrlong	tos,ptrb[5]  	' only one
    			wrlong	tos,ptrb[6]	' only one
    			wrlong	tos,ptrb[7]	' only one
    			wrlong	tos,ptrb[8]	' only one
    	_ret_		rdlong	tos,++ptrb
    ...
    ' from the opcode table
    {51}    long  zpu_storesp_N | %0_1111_1110 << 10
    {52}    long  zpu_storesp_N | %0_1111_1101 << 10
    {53}    long  zpu_storesp_N | %0_1111_1011 << 10
    {54}    long  zpu_storesp_N | %0_1111_0111 << 10
    {55}    long  zpu_storesp_N | %0_1110_1111 << 10
    {56}    long  zpu_storesp_N | %0_1101_1111 << 10
    {57}    long  zpu_storesp_N | %0_1011_1111 << 10
    {58}    long  zpu_storesp_N | %0_0111_1111 << 10
    

    {52}..{58} would take the same time as now and {51}..{58} an identical time. Note that the NOP would not reduce the useable skip pattern length.

    Existing patterns with first skip bits always 0 could also stay the same, as follows.

    Before
    	long	op_notb	|              %01111111101110 << 10	'7B	!!exp
    	long	op_not	|              %011111110_____ << 10	'7C	!exp
    	long	op_neg	|              %01111110______ << 10	'7D	-exp
    	long	op_abs	|              %0111110_______ << 10	'7E	ABS exp
    	long	op_ncod	|              %011110________ << 10	'7F	ENCOD exp
    	long	op_dcod	|              %01110_________ << 10	'80	DECOD exp
    	long	op_ones	|              %0110__________ << 10	'81	ONES exp
    	long	op_sqrt	|              %0101111111110_ << 10	'82	SQRT exp
    	long	op_log	|              %010111111110__ << 10	'83	LOG exp
    	long	op_exp	|              %01011111110___ << 10	'84	EXP exp
    

    After
    	long	op_notb	|              %01111111101110 << 9	'7B	!!exp
    	long	op_not	|              %011111110_____ << 9	'7C	!exp
    	long	op_neg	|              %01111110______ << 9	'7D	-exp
    	long	op_abs	|              %0111110_______ << 9	'7E	ABS exp
    	long	op_ncod	|              %011110________ << 9	'7F	ENCOD exp
    	long	op_dcod	|              %01110_________ << 9	'80	DECOD exp
    	long	op_ones	|              %0110__________ << 9	'81	ONES exp
    	long	op_sqrt	|              %0101111111110_ << 9	'82	SQRT exp
    	long	op_log	|              %010111111110__ << 9	'83	LOG exp
    	long	op_exp	|              %01011111110___ << 9	'84	EXP exp
    

    This is about EXECF in XBYTE, which wouldn't have random masks and dynamically created skip patterns.
  • TonyB_ wrote: »
    This is about EXECF in XBYTE, which wouldn't have random masks and dynamically created skip patterns.

    A JIT compiler might create an XBYTE interpreter on the fly. Or, more likely, a compiler running on the PC might create a custom interpreter based on the instructions it sees in the program. Both of which could work around the change you propose, of course. and in the abstract your idea's a good one. But it's rather late in the day for us to be changing the instruction set. I think Chip definitely has the right idea to leave well enough alone for now. I hope he does take your proposal into account for P3.
  • Cluso99Cluso99 Posts: 18,069
    Keep it as is.
Sign In or Register to comment.