Shop OBEX P1 Docs P2 Docs Learn Events
How about a JMPLNK instruction? — Parallax Forums

How about a JMPLNK instruction?

This is the inner address interpreter loop in Tachyon:
doNEXT       	rdword	X,PTRA++ 		'read word code instruction address
		call	X                     	' could call cog or hub code
		jmp	#doNEXT 

Looking at it I was thinking that the jmp was a real waste of time and if CALL could push a specified address rather than the PC it would mean I could have a tighter loop. So essentially we could have a CALL instruction that I can simulate like this:
doNEXT       	rdword	X,PTRA++ 		'read word code instruction address
		push	#doNext
		jmp	X                     	' could call cog or hub code

So with a JMPLNK instruction it would be coded like this:
doNEXT       	rdword	X,PTRA++ 		'read word code instruction address
		jmplnk	X,#doNext       ' call cog or hub code but use doNext as the return address

I'm just asking this because I think that it might be quite easy to implement.

Comments

  • jmgjmg Posts: 15,173
    edited 2015-10-29 04:39

    Why not the JMPREL opcode ?
    doNEXT       	rdword	X,PTRA++ 		'read word code instruction address
    		jmprel	X       ' table jump
    
    'rets become
    		jmp	doNEXT
    

  • JMPREL doesn't push anything. He wants a CALL that pushes whatever he wants and not necessarily the address of the next instruction.
  • cgraceycgracey Posts: 14,152
    jmg wrote: »
    Why not the JMPREL opcode ?
    doNEXT       	rdword	X,PTRA++ 		'read word code instruction address
    		jmprel	X       ' table jump
    
    'rets become
    		jmp	doNEXT
    

    I bet it's most convenient to have things end in RET, so that they can call each other, too, before returning.
  • cgraceycgracey Posts: 14,152
    This is the inner address interpreter loop in Tachyon:
    doNEXT       	rdword	X,PTRA++ 		'read word code instruction address
    		call	X                     	' could call cog or hub code
    		jmp	#doNEXT 
    

    Looking at it I was thinking that the jmp was a real waste of time and if CALL could push a specified address rather than the PC it would mean I could have a tighter loop. So essentially we could have a CALL instruction that I can simulate like this:
    doNEXT       	rdword	X,PTRA++ 		'read word code instruction address
    		push	#doNext
    		jmp	X                     	' could call cog or hub code
    

    So with a JMPLNK instruction it would be coded like this:
    doNEXT       	rdword	X,PTRA++ 		'read word code instruction address
    		jmplnk	X,#doNext       ' call cog or hub code but use doNext as the return address
    

    I'm just asking this because I think that it might be quite easy to implement.

    Interesting idea. This wouldn't be too hard to make, but we've only got the opcode space for register-based JMPs, not any more immediate-address JMPs.

    Is there a "next level" we could even take this to, so that it does even more?
  • jmgjmg Posts: 15,173
    cgracey wrote: »
    I bet it's most convenient to have things end in RET, so that they can call each other, too, before returning.

    Of course :)
    - but the JMPREL is in there, and there is not yet a JMPLNK...

  • In P1 I would just rdbyte and jmp to the first 256 longs in the cog and to return all the routines ended up doing a "jmp unext" where unext was setup with doNext but it allowed me to redirect all "rets" if I needed to. Now with the P2 it is easy to call and to return so even Forth words can be called themselves.

    Now jmg says "why not the jmprel opcode?" but I don't really know what jmprel does although I keep inviting "everybody" to contribute to the documentation, even if it is describing one little instruction. My eyes keep getting blurry just formatting the stuff.

    As for jmplnk or whatever it was just a suggestion and if we can make it happen then great but otherwise I wouldn't worry too much although I will keep looking into it.



  • jmgjmg Posts: 15,173
    Now jmg says "why not the jmprel opcode?" but I don't really know what jmprel does
    A code example was given here :

    https://forums.parallax.com/discussion/comment/1347205#Comment_1347205
  • evanhevanh Posts: 15,915
    edited 2015-10-29 07:04
    I'm struggling to see any advantage that JMPREL delivers in this context. It's just for evenly space routines I guess. No need to have a pointer table.
  • cgraceycgracey Posts: 14,152
    edited 2015-10-29 07:21
    evanh wrote: »
    I'm struggling to see any advantage that JMPREL delivers.

    It's very handy for jumping forward into a table of JMP instructions.

    Here is without JMPREL in cog exec:
    	add	index,#table
    	jmp	index
    
    table	jmp	#pgm0
    	jmp	#pgm1
    	jmp	#pgm2
    	jmp	#pgm3
    

    Here is without JMPREL in hub exec:
    	shl	index,#2
    	loc	adra,#table
    	add	adra,index
    	jmp	adra
    
    table	jmp	#pgm0
    	jmp	#pgm1
    	jmp	#pgm2
    	jmp	#pgm3
    

    Here is with JMPREL:
    	jmprel	index		'works in both cog and hub
    	jmp	#pgm0
    	jmp	#pgm1
    	jmp	#pgm2
    	jmp	#pgm3
    
  • evanhevanh Posts: 15,915
    edited 2015-10-29 08:48
    Go to bed Chip! I really shouldn't have blurted that comment so quickly without narrowing the context of my thoughts first. I think I edited it four times in the end.

    Reading up on the JMP instruction, I hadn't considered a jump table like that being capable of full range addressing but surprisingly it is. :)
  • evanhevanh Posts: 15,915
    edited 2015-10-29 09:15
    Hmm, what Peter really wants here is a CALLREL equivalent to JMPREL.

    Err, none of these help him because he is not using any table lookup. The Forth program instructions are the routine pointers. Just like a CPU instruction set.
  • SeairthSeairth Posts: 2,474
    edited 2015-10-29 11:14
    Why not just do:
    doNEXT       	rdword	X,PTRA++ 		'read word code instruction address
    		jmp	X                     	' could call cog or hub code
    

    and have each of your routines do a "jmp #doNEXT" instead of "ret"?

    On the other hand, if you need an indirect return address, maybe you could use CALLD like:
    doNEXT          rdword  X, PTRA++
                    calld   adrb, X wc, wz
    

    Then, to return, you would call "calld adrb, adrb wc, wz" instead of "ret". Note that you could take advantage of the interrupt instruction/register aliases. So, you could do:
                    mov     iret1, #doNEXT  'set up "return" address
    doNEXT          rdword  X, PTRA++       
                    jmp     X
    

    Then, in your routines elsewhere, call "reti1" instead of "ret".
  • Seairth wrote: »
    Why not just do:

    I made TF2 sub-routine threaded so everything ends up returning to whatever called it, not always the doNext loop which also means I can just as easily call a print routine from assembly code etc. The implementation is definitely not sluggish but while we are still at this pre-nascent stage I thought that a jmplnk would be fairly easy to implement although as Chip pointed out, there aren't any parking spaces left for that kind of instruction :(


  • evanhevanh Posts: 15,915
    edited 2015-10-29 12:04
    Seairth wrote: »
    doNEXT          rdword  X, PTRA++
                    calld   adrb, X wc, wz
    

    Then, to return, you would call "calld adrb, adrb wc, wz" instead of "ret".

    This one looks effective. Peter, I presume you were expecting a single level stack only?

    EDIT: Ah, Smile. The return address needs to be doNEXT, not two instructions later. Doh! Maybe that iret1 thingy then ...?
  • Would it be possible to use REP for the jump to do next?

    Enjoy!

    Mike
  • msrobots wrote: »
    Would it be possible to use REP for the jump to do next?

    Enjoy!

    Mike

    No. If you jump out of a REP, the rep gets terminated.
  • cgraceycgracey Posts: 14,152
    msrobots wrote: »
    Would it be possible to use REP for the jump to do next?

    Enjoy!

    Mike

    No. If you jump out of a REP, the rep gets terminated.

    I got rid of this terminate-REP-on-branch behavior because it was slowing things down and was only there because it was needed on Prop2-hot. Don't put branches in REP blocks, anymore, or chaos will ensue!
  • ElectrodudeElectrodude Posts: 1,657
    edited 2015-10-31 20:08
    cgracey wrote: »
    msrobots wrote: »
    Would it be possible to use REP for the jump to do next?

    Enjoy!

    Mike

    No. If you jump out of a REP, the rep gets terminated.

    I got rid of this terminate-REP-on-branch behavior because it was slowing things down and was only there because it was needed on Prop2-hot. Don't put branches in REP blocks, anymore, or chaos will ensue!

    Cool! So, if you jump while in a REP, the PC will still get reset to the instruction after the REP after however many instructions the REP was told to REP for? Sounds fun!

  • jmgjmg Posts: 15,173
    cgracey wrote: »
    I got rid of this terminate-REP-on-branch behavior because it was slowing things down and was only there because it was needed on Prop2-hot. Don't put branches in REP blocks, anymore, or chaos will ensue!
    The tools could easily warn on this ?

    Is even an equal-length-internal-branch out too ?

    ie is REP counting opcodes, before forcing reload of PC ?

  • msrobots wrote: »
    Would it be possible to use REP for the jump to do next?

    Enjoy!

    Mike

    No. If you jump out of a REP, the rep gets terminated.

    so no calls to subroutines inside of a REP loop?

    Mike

  • ElectrodudeElectrodude Posts: 1,657
    edited 2015-10-31 21:11
    msrobots wrote: »
    msrobots wrote: »
    Would it be possible to use REP for the jump to do next?

    Enjoy!

    Mike

    No. If you jump out of a REP, the rep gets terminated.

    so no calls to subroutines inside of a REP loop?

    Mike

    First of all, read what Chip said. Jumps don't terminate REP anymore, but REP doesn't account for them, either. If you jumped somewhere or called something, the PC would get reset half way through your subroutine, which would be bad.

    I'm guessing that you theoretically could call a subroutine as long as it still took the same number of instructions, but those cases would be very rare and hard to implement properly in software.
  • jmgjmg Posts: 15,173
    I'm guessing that you theoretically could call a subroutine as long as it still took the same number of instructions, but those cases would be very rare and hard to implement properly in software.
    If that is even possible, depends on the HW design of REP, hence my question above.

    Balancing software paths is not uncommon, but it would be useful to know how REP works, and just what is possible/forbidden inside REP.
    Ideally, the tools should track that & warn.

    IIRC, HUB/LUT R/W access is legal inside REP, so REP likely tracks PC++ ?

  • It's just a simple looping circuit without any complex state handling needed for subs, etc...

  • @Electrodude,

    reading alone does not mean understanding also. The way you describe it, there might be a way to write really confusing code.

    So to understand this right, REP (in opposite to say DJNZ) does provide a seamless loop of them instructions and the 'jump' from last to first instruction does not take any clock cycles and just sets the PC back?

    So basically what I do on the P1 when I 'unroll' a loop?

    Interesting.

    Mike
  • evanhevanh Posts: 15,915
    edited 2015-10-31 21:56
    Yeah, it'll just be an address equality compare for where to loop back from. I can't see it counting instructions. One question will be what Cog resources does it use that, say, a CALL/RET also uses? But probably the biggest worry is striking another REP in one of the subroutines. That's fatal for certain.
  • jmgjmg Posts: 15,173
    msrobots wrote: »
    So to understand this right, REP (in opposite to say DJNZ) does provide a seamless loop of them instructions and the 'jump' from last to first instruction does not take any clock cycles and just sets the PC back?

    So basically what I do on the P1 when I 'unroll' a loop?

    Interesting.

    Yes, REP shines most on the smallest loops, and allows you to avoid 'unroll' a loop, saving code space.

Sign In or Register to comment.