Shop OBEX P1 Docs P2 Docs Learn Events
P2 JMP/CALL addresses to COG/LUT/HUB — Parallax Forums

P2 JMP/CALL addresses to COG/LUT/HUB

I haven't tested this so I am unsure of the precise way the jmp/call addresses work with respect to cog, lut and hub addresses.

Let me explain. the silicon checks the address, and if the address <$200 it is COG, if it is <$400 it is LUT.
So, this code is fine, no problems here...
        org   0         ' COG
cog     ...

        org   $200      ' LUT
lut     ...

        orgh  $1000     ' HUB
hub     ...        

        jmp   #cog
        jmp   #lut
        jmp   #hub
Above, COG/LUT $400 is equivalent to HUB $1000 because cog and lut is in longs and hub is in bytes.
$400   = %0000_0100_0000_0000
$1000 = %0001_0000_0000_0000

So, I am pondering if this will work
        orgh  $400
hub2    ...

        jmp   #hub2

Any ideas before I test it???
«13

Comments

  • $400 is not equivalent to $1000
  • Cluso99Cluso99 Posts: 18,066
    ozpropdev wrote: »
    $400 is not equivalent to $1000
    Yes, I realise that.

    But if you code as we normally do, from org $0 upwards, and this is placed in hub as we normally do, then the first 2KB for cog occupies hub $000-$1FF, and lut follows on normally from $200-$3FF, then the normal hub code for hubexec would normally be from $1000 which equals cog $400 because $400 << 2 = $1000.

    Anyway, I tested my question, and a JMP/CALL to hub $400 does indeed work.

    So, in fact we only lose 1KB of space where hubexec will not run, not the 4KB that I had previously expected :smiley:
  • Cluso99Cluso99 Posts: 18,066
    Here is the test program...

    It uses the ROM monitor/debugger for serial output.
  • My hubexec programs normally start at $400.
  • Cluso99 wrote: »
            org   0         ' COG
    cog     ...
    
            org   $200      ' LUT
    lut     ...
    
            orgh  $1000     ' HUB
    hub     ...        
    
            jmp   #cog
            jmp   #lut
            jmp   #hub
    
    Above, COG/LUT $400 is equivalent to HUB $1000 because cog and lut is in longs and hub is in bytes.

    COG/LUT $400 is invalid though.
    Your example above sets hub address to $1000 whuch is exactly that, hub address $1000..

    BTW Nearly all the code I have posted here on this forum has used ORGH $400.

  • Cluso99Cluso99 Posts: 18,066
    edited 2019-08-08 01:20
    Dave Hein wrote: »
    My hubexec programs normally start at $400.
    ozpropdev wrote: »
    Cluso99 wrote: »
            org   0         ' COG
    cog     ...
    
            org   $200      ' LUT
    lut     ...
    
            orgh  $1000     ' HUB
    hub     ...        
    
            jmp   #cog
            jmp   #lut
            jmp   #hub
    
    Above, COG/LUT $400 is equivalent to HUB $1000 because cog and lut is in longs and hub is in bytes.

    COG/LUT $400 is invalid though.
    Your example above sets hub address to $1000 whuch is exactly that, hub address $1000..

    BTW Nearly all the code I have posted here on this forum has used ORGH $400.

    If you use orgh $400 then either you only have a cog/lut combined program of 1KB total, or you are loading the cog manually from a higher hub location.

    I have just relocated my cog code and lut code above the hubexec code which now starts at orgh $400, and I have a stub cog program at org $0 orgh $0 that copies up my cog & lut programs and then jumps to them. It's a bit fiddley as you have to go back to hubexec to copy them up or otherwise you overwrite the running code :(

    Hub address $1000 follows on from a 2KB cog and 2KB lut code space in hub.
  • Cluso99 wrote: »
    Dave Hein wrote: »
    My hubexec programs normally start at $400.
    ozpropdev wrote: »
    Cluso99 wrote: »
            org   0         ' COG
    cog     ...
    
            org   $200      ' LUT
    lut     ...
    
            orgh  $1000     ' HUB
    hub     ...        
    
            jmp   #cog
            jmp   #lut
            jmp   #hub
    
    Above, COG/LUT $400 is equivalent to HUB $1000 because cog and lut is in longs and hub is in bytes.

    COG/LUT $400 is invalid though.
    Your example above sets hub address to $1000 whuch is exactly that, hub address $1000..

    BTW Nearly all the code I have posted here on this forum has used ORGH $400.

    If you use orgh $400 then either you only have a cog/lut combined program of 1KB total, or you are loading the cog manually from a higher hub location.

    I have just relocated my cog code and lut code above the hubexec code which now starts at orgh $400, and I have a stub cog program at org $0 orgh $0 that copies up my cog & lut programs and then jumps to them. It's a bit fiddley as you have to go back to hubexec to copy them up or otherwise you overwrite the running code :(

    Hub address $1000 follows on from a 2KB cog and 2KB lut code space in hub.

    No No @Cluso99 your thinking is wrong. There is no need to shift. It is $3FF where lut ends. We have 2K reg and 2k lut. you wish you had $200 longs as registers, but its just $200 bytes …

    The save place starts at $400

    Enjoy!

    Mike
  • Cluso99 wrote: »
    If you use orgh $400 then either you only have a cog/lut combined program of 1KB total, or you are loading the cog manually from a higher hub location.
    Or the cog is loaded automatically and the lut is loaded from a higher hub location.

  • Cluso99Cluso99 Posts: 18,066
    What I am saying guys, is that hubexec can run from 1KB up to 512KB for a 512KB chip.

    I had always incorrectly assumed that hubexec could only run from 4KB and above, because of the fact that there is 2KB for cog and 2KB for lut.

    This all stems from the fact that I have an app that requires hubexec addresses to be a maximum of 12-bits. This meant addresses <$1000. So I can have hubexec code from $400-$FFF, which is 3KB of hubexec code.
  • msrobots wrote: »
    Cluso99 wrote: »
    Dave Hein wrote: »
    My hubexec programs normally start at $400.
    ozpropdev wrote: »
    Cluso99 wrote: »
            org   0         ' COG
    cog     ...
    
            org   $200      ' LUT
    lut     ...
    
            orgh  $1000     ' HUB
    hub     ...        
    
            jmp   #cog
            jmp   #lut
            jmp   #hub
    
    Above, COG/LUT $400 is equivalent to HUB $1000 because cog and lut is in longs and hub is in bytes.

    COG/LUT $400 is invalid though.
    Your example above sets hub address to $1000 whuch is exactly that, hub address $1000..

    BTW Nearly all the code I have posted here on this forum has used ORGH $400.

    If you use orgh $400 then either you only have a cog/lut combined program of 1KB total, or you are loading the cog manually from a higher hub location.

    I have just relocated my cog code and lut code above the hubexec code which now starts at orgh $400, and I have a stub cog program at org $0 orgh $0 that copies up my cog & lut programs and then jumps to them. It's a bit fiddley as you have to go back to hubexec to copy them up or otherwise you overwrite the running code :(

    Hub address $1000 follows on from a 2KB cog and 2KB lut code space in hub.

    No No @Cluso99 your thinking is wrong. There is no need to shift. It is $3FF where lut ends. We have 2K reg and 2k lut. you wish you had $200 longs as registers, but its just $200 bytes …

    The save place starts at $400

    Enjoy!

    Mike

    That's not quite right.
    We have $200 longs for cog ram and SFRs (addressed as $0-$1FF) and $200 longs for lut ram (addressed as $200 - $3FF), but hub ram is byte addressed.


    If you wanted a single load code image, starting at address 0 that contained a full cog image, followed by a full lut image, and then some hubexec code, that hubexec code would need to sit at (or above) $1000 in hub ram, but that doesn't set the lowest limit for hubexec; that is set by the PC interpretation which allows hubexec from $400.
  • msrobotsmsrobots Posts: 3,701
    edited 2019-08-08 09:13
    I was blind and "The Great Cusso99" is right again. We all missed it, but $400 HUB is not 4Kb. it's one Kb.
    All of us use $400 because we have small programs it works. Even FastSpin does. BUT IT IS WRONG.

    SAVE HUB starts at $1000 not $400.


    Whow
  • evanhevanh Posts: 15,126
    :)
    I wouldn't call either wrong. Just there is a caveat to using orgh $400 is all.
  • Cluso99Cluso99 Posts: 18,066
    edited 2019-08-08 09:46
    msrobots wrote: »
    we have 2Kb of COG RAM that are 512 longs or $200 BYTES

    same goes for LUT. 512 Longs $200 BYTES.

    Two Kilobyte COG two Kilobyte Lut makes 4KB lower HUB or 0-$1FF, $200-#3FF and everything at and after $400is free.

    A COG has 512 longs as register not 2K or 2048. It is 2 K BYTES not two K longs.

    Mike
    No Mike. AJL’s statements are correct, which is what i’ve been saying from the beginning.

    $200 longs for cog is $800 bytes in hub.
    $200 longs for lut is another $800 bytes in hub.
    If both these are placed in hub, then the first free hub byte for hubexec will be $1000.

    Why i started this thread was because of the above paragraph, i had always (incorrectly) assumed that hubexec could only ever start at $1000 as otherwise the silicon would not know if a jmp/call was to cog, lut or hub. My wrong presumption was that cog and lut jmp and call addresses were stored as byte addresses ie shifted left 2 zero bits.

    But the cog and lut addresses, are always 10 bits, with internal silicon taking care of the fact they are long addresses, not byte addresses.

    The great quirk is that for the silicon to determine that cog and lut addresses are all addresses less than $400 (<$400). So any address $400+ is hub, and $400 hub is a byte address which is only immediately above 1KB.

    So, having jmp/call use the first 4KB of cog+lut addresses in longs (10 bits), and thereafter all addresses as bytes (11+ bits), means we only have lost the ability to run hubexec for the first 1KB of hub. ie in a 512KB hub, only the first 1KB cannot be used for hubexec, or 511KB can be used for hubexec, which starts at byte $400 in hub.

    By placing the cog and lut main code in an alternate higher location in hub, I have 3KB of hubexec space between $400-$FFF hub that I can run while keeping those addresses in a table of 12-bits (uses the fact that $FFF is 12-bits with the higher bits all zeros).

    Why does this matter to me? Well, as a number of you may know, in P1 i often use a long to store 3 9-bit cog addresses for tables of routines. ie In my spin interpreter, i use a 256 long table, where each long represents a bytecode. So each bytecode has up to 3 subroutines that can be performed for each bytecode. So i decode the bytecode and use a series of MOVS and SHR #9 to get each subroutine address (i call the vectors).

    In my Z80 code I need to sometimes have the first routine be hubexec as i cannot fit all the code in cog or lut. So my long tables have the first routine as 12-bits (cog/lut/hub) followed by two 10-bit cog/lut addresses. My code now fits in 2KB cog plus 2KB lut plus 3KB hub. The tables are higher in hub.
  • AJLAJL Posts: 512
    edited 2019-08-08 09:52
    msrobots wrote: »
    I was blind and "The Great Cusso99" is right again. We all missed it, but $400 HUB is not 4Kb. it's one Kb.
    All of us use $400 because we have small programs it works. Even FastSpin does. BUT IT IS WRONG.

    SAVE HUB starts at $1000 not $400.


    Whow

    Not really.
    This long vs byte addressing issue only relates to hubexec; reading and writing to hub ram is always byte addressed.

    Code for cog and lut execution can sit anywhere in hub ram because it isn't going be executed there.

    One could just as easily create a single load image with the hubexec code first, followed by any cog and lut image(s), but it would need to be loaded into hub ram no lower than $400.

  • evanhevanh Posts: 15,126
    The caveat comes about because of the binary file order ... which is loaded into hubRAM first before being COGINIT'd to cogRAM. As Cluso rightly pointed out, there is only 1 kB of hubRAM below $400 so any initial cog0 code has to sqeeze in below $400 bytes if there is an ORGH $400. The assembler should give an error if it doesn't fit.
  • Cluso99Cluso99 Posts: 18,066
    @AJL,
    Not quite. When the P2 starts initially by downloading, and for that matter from FLASH and SD, Cog 0 starts by having the first 2KB (less special registers) copied from hub $0.

    So in order to have cog and lut fully loaded with code (4KB) while reserving hub $400+ for hubexec, there needs to be a stub in hub $0 (1KB max) that can copy additional cog and from elsewhere, or at least above the hubexec code at $400.

    So, anyone using hub orgh $400 can only have a 1KB cog program start, and load the rest by code.

    This is why I have always used hub orgh $1000 in the past, which reserves 2KB for cog followed by 2KB lut. Lut could have been loaded from elsewhere, so hub could start from $800, just reserving 2KB for COG #0.
  • msrobotsmsrobots Posts: 3,701
    edited 2019-08-08 10:04
    @Cluso99 is exactly right and we did it WRONG all the time.

    I feel dumb again, but I am happy he found it out. Lemmings we are...

    Mike
  • I use ORGH $400 to ensure that any LOC @ instructions will return corret values.
    If my "cog0" code happens to grow larger than 1k bytes ($400) the compiler lets me know and I can simply replace the ORGH $400 with a single ORGH and continue onwards and upwards. :)

  • Cluso99 wrote: »
    @AJL,
    Not quite. When the P2 starts initially by downloading, and for that matter from FLASH and SD, Cog 0 starts by having the first 2KB (less special registers) copied from hub $0.

    So in order to have cog and lut fully loaded with code (4KB) while reserving hub $400+ for hubexec, there needs to be a stub in hub $0 (1KB max) that can copy additional cog and from elsewhere, or at least above the hubexec code at $400.

    So, anyone using hub orgh $400 can only have a 1KB cog program start, and load the rest by code.

    This is why I have always used hub orgh $1000 in the past, which reserves 2KB for cog followed by 2KB lut. Lut could have been loaded from elsewhere, so hub could start from $800, just reserving 2KB for COG #0.

    Context is everything. My comments were in response to Mike claiming that we've all been doing it WRONG.

    On initial startup this may be the case, but to suggest that sacrificing 3K of hub ram in the general case in order to avoid this corner case seems to be the wrong approach.
    Brian follows the approach I would advocate: aim for $400 until you run out of room, then reassess.

    The very fact that this discussion is happening now, rather than six months ago, suggests to me that it is not a significant problem; certainly not worth sacrificing 3K of 511K ram to avoid having to think about the limitation.
  • One idea that occurred to me is that having a way to force ORGH to be at least some value would be useful, e.g. perhaps we could write:
        orgh   >$400
    
    to say that the current hub address must be at least $400; if it is less than that to pad with 0s until $400 is reached, otherwise to just go with the current hub address.

    This should be easy to add to fastspin, but I'm not sure if this is the best syntax. We could also create a new "orghmin" directive instead, but that seems a bit ugly.

    @cgracey, do you think adding something like this to PNut is both desirable and relatively easy to accomplish?
  • Cluso99Cluso99 Posts: 18,066
    Eric,
    I don’t think any changes are necessary. I’d just presumed that i needed to leave 4KB in hub before hubexec. I therefore always started hub at $1000.
    We have FIT to test for cog/lut size.

    It wasn’t until I was thinking about trying to use hub addresses with 12bits that I thought about the actual silicon functioning.

    It’s probably a cursory note in the tricks and traps.
  • Cluso99 wrote: »
    I don’t think any changes are necessary. I’d just presumed that i needed to leave 4KB in hub before hubexec. I therefore always started hub at $1000.
    We have FIT to test for cog/lut size.
    I think it would be nice to automate the process that @ozpropdev described (and which is the same one I use), namely that if the COG code fits below $400 then we use ORGH $400, otherwise we use just plain ORGH. That process is usually fine, but could break if the COG code shrinks again after we switch from "ORGH $400" to "ORGH".

    To summarize:

    (1) Hubexec needs to start at $400 or later.
    (2) The space from $0 to $3ff is often used for COG code (among other things)
    (3) If that COG code is less than 1K in size then we need to use "ORGH $400" to force the hubexec code to start at $400.
    (4) If the COG code is more than 1K in size, then "ORGH $400" will give an error. In that case we can use just plain "ORGH" and let the hubexec start at whatever place it ends up (it's above $400).
    (5) If we use just plain "ORGH" but the COG code shrinks back below 1K, the hubexec code will start too low.

    So it'd be handy to have a way to say "switch to HUB mode but make sure it's at at HUB address $400 or later"
  • ersmith wrote: »
    Cluso99 wrote: »
    I don’t think any changes are necessary. I’d just presumed that i needed to leave 4KB in hub before hubexec. I therefore always started hub at $1000.
    We have FIT to test for cog/lut size.
    I think it would be nice to automate the process that @ozpropdev described (and which is the same one I use), namely that if the COG code fits below $400 then we use ORGH $400, otherwise we use just plain ORGH. That process is usually fine, but could break if the COG code shrinks again after we switch from "ORGH $400" to "ORGH".

    To summarize:

    (1) Hubexec needs to start at $400 or later.
    (2) The space from $0 to $3ff is often used for COG code (among other things)
    (3) If that COG code is less than 1K in size then we need to use "ORGH $400" to force the hubexec code to start at $400.
    (4) If the COG code is more than 1K in size, then "ORGH $400" will give an error. In that case we can use just plain "ORGH" and let the hubexec start at whatever place it ends up (it's above $400).
    (5) If we use just plain "ORGH" but the COG code shrinks back below 1K, the hubexec code will start too low.

    So it'd be handy to have a way to say "switch to HUB mode but make sure it's at at HUB address $400 or later"

    Can you do bounds checking on a plain ORGH within the compiler/assembler and add filler if necessary?

    That would be one less thing for the programmer to have to consider.
  • evanhevanh Posts: 15,126
    A new assembler directive maybe?

  • Cluso99Cluso99 Posts: 18,066
    Eric,
    Thinking about it further, perhaps an orgh operator option of
    ORG >=$400
    could be useful.

    But it’s up to you.

    I’m just delighted to be able to put hubexec code in hub $400-$FFF.
  • cgraceycgracey Posts: 14,133
    ersmith wrote: »
    One idea that occurred to me is that having a way to force ORGH to be at least some value would be useful, e.g. perhaps we could write:
        orgh   >$400
    
    to say that the current hub address must be at least $400; if it is less than that to pad with 0s until $400 is reached, otherwise to just go with the current hub address.

    This should be easy to add to fastspin, but I'm not sure if this is the best syntax. We could also create a new "orghmin" directive instead, but that seems a bit ugly.

    @cgracey, do you think adding something like this to PNut is both desirable and relatively easy to accomplish?

    The problem is that ORGH gets used for data, as well as hub-exec code. Any label should reflect the contextual address. I think the programmer just has to know that he can't jump to hub-exec code below $400. He might want to have some snippets of code below $400, though, that get moved at runtime to somewhere else for execution. So, I don't think it would be good to change the rules about ORGH.
  • evanhevanh Posts: 15,126
    edited 2019-08-09 09:50
    I think you've misunderstood there Chip. Eric is talking about an extra/modified directive that works like the dynamic packing of ORGH-without-parameters but can still be specified with a minimum address that it will zero fill to.
  • cgraceycgracey Posts: 14,133
    edited 2019-08-09 10:01
    evanh wrote: »
    I think you've misunderstood there Chip. Eric is talking about an extra/modified directive that works like the dynamic packing of ORGH-without-parameters but can still be specified with a minimum address that it will zero fill to.

    Okay. If you do an 'ORGH $400', it will zero-fill to $400, already. I guess what is wanted is an ORGH variant that will zero-fill to $400, in case the current address is below $400.
  • evanhevanh Posts: 15,126
    Oh, maybe the way to do it is have exactly that occur when there is no parameter. So that the only way to get below $400 is to specify an address.

  • cgraceycgracey Posts: 14,133
    evanh wrote: »
    Oh, maybe the way to do it is have exactly that occur when there is no parameter. So that the only way to get below $400 is to specify an address.

    But I often switch between ORG and ORGH sections without addresses, so that they stack up.
Sign In or Register to comment.