Shop OBEX P1 Docs P2 Docs Learn Events
The addressing conundrum — Parallax Forums

The addressing conundrum

Since this topic has now spread across 3 or more other threads, I figured this deserved a thread of its own.

As things stand now (2015-09-29 FPGA Image):

* All instruction addressing is byte-oriented
* Cog and LUT instruction addresses must still be long-aligned
* Hub instruction addresses below $1000 must be offset by one byte

* Hub data addressing is byte-oriented
* Cog and LUT data addressing is long-oriented

* All ORGx directives are byte-oriented

* All #immediate labels are byte-oriented.
* Any instruction that is operating on words or long must divide the #immediate by 2 or 4 to get the correct value
* All @relative labels are long-oriented
* All other labels (those indicating a register) are long-oriented.

Now... how do we make this simpler?
«13456789

Comments

  • rjo__rjo__ Posts: 2,114
    I have no idea.

    But I really appreciate the summary.

    Things aren't quite as confusing as the list seems at first glance... For example... we can easily remember that cog and lut addresses are long because we don't have byte and word variants for RDLUT and WRLUT...I will probably never write a hub instruction below $1000 because that is were the guru's put stuff... # only has nine bits ... as always. The most complicated org statement I have ever written is ... ORG, so I'm going to have to study ORG again:) etc. etc.

    I think the biggest problem isn't the rules... it is knowing exactly what the rules are.
    As you have said... to glean this summary, you had to go to multiple threads. There are many issues similarly spread around.

    One way to fix this "conundrum" would be to place active help in the user's tools ... a dropdown cheat sheet. Or... You type in RDLUT... the tool hints the addressing and alignment rule or links to more a more complete description, etc, etc. A great place for imagination and creativity.

    Addressing is important, but functionality trumps convenience in my mind.
    What is fun to me... is something that really works well. Learning how to do that is always going to be somewhat of a pain.

    At present, important conversations are so exhaustive and spread over so many threads that the final state of many issues is essentially unknown to most.

    Until the rules are all in one concise document, it is almost impossible to do anything anyway:)

    After we have that, then most of us will need simple, well documented snippets... which will flood in.







  • #immediate to me is just a number - the assembler just generates a number and shoves however many bits it can into the field you are placing it into - maybe giving an error if you try to put too many bits into the field.

    It shouldn't have an concept of bytes or longs or addressing associated with it.
  • AleAle Posts: 2,363
    The addresses used by hubexec are offset by 1 byte but how is it is memory ? it is not "mis-aligned", is it ? it is just a gimmick for the assembler and/or the P2 itself, like thumb or mips16 code, right ? (they use bit 0 to indicate change of encoding, but are 16 bit aligned)
  • No, it's actually misaligned by one byte in hubram. It's horrible, please try to convince Chip to change it.
  • AribaAriba Posts: 2,690
    Ale

    The instructions are located really at the non-long aligned address in memory, but you can't call this mis-aligned :smile:

    It's not that hard:
    Hubexec can execute from any address, cog and lut code can execute only from long aligned addresses under $1000.
    Every non-long aligned address always selects hubexec, also in the 0..$1000 range.
    So you can use this fact to execute hubexec in the lower memory.

    Andy
  • ElectrodudeElectrodude Posts: 1,651
    edited 2015-09-30 17:51
    Wouldn't it be so much simpler just to completely disallow hubexec below $1000 and have cog 0 execution start at $1000 on boot? If it complicates the cold boot code, why does it matter? That hardware is only used once per boot, so it doesn't really matter if it's slow or complicated.
  • RaymanRayman Posts: 14,557
    I'm wondering how this is going to work when there are multiple hubexec routines in your code...
    I think all the examples have only one "orgh" directive and they are all "orgh 1". I assume the "1" is the absolute address and not an offset command.

    What do you do if you want to add a second "orgh" starting point? Seems like you have to count lines... Then you have to wonder what to do if the first one gets bigger, right?

    BTW: I think "orgh 1" "orgh 2" and "orgh 3" would all work, it's just "orgh 0" that would try to run in a cog...
  • Wouldn't it be so much simpler just to completely disallow hubexec below $1000 and have cog 0 execution start at $1000 on boot? If it complicates the cold boot code, why does it matter? That hardware is only used once per boot, so it doesn't really matter if it's slow or complicated.
    I like this option. In fact, the built-in loader could be made to load into hub memory starting at $1000 so no ROM space is wasted.

  • David Betz wrote: »
    Wouldn't it be so much simpler just to completely disallow hubexec below $1000 and have cog 0 execution start at $1000 on boot? If it complicates the cold boot code, why does it matter? That hardware is only used once per boot, so it doesn't really matter if it's slow or complicated.
    I like this option. In fact, the built-in loader could be made to load into hub memory starting at $1000 so no ROM space is wasted.

    Exactly.

    Also, virtually any program that has 508KB of code (512KB - $1000) is sure to have at least $1000 bytes of non-machine-code data (bytecode, tables, strings, arrays, buffers, etc.). Those first $1000 bytes certainly won't be wasted if they can't be hubexec'd from.
  • Rayman wrote: »
    I'm wondering how this is going to work when there are multiple hubexec routines in your code...
    I think all the examples have only one "orgh" directive and they are all "orgh 1". I assume the "1" is the absolute address and not an offset command.

    What do you do if you want to add a second "orgh" starting point? Seems like you have to count lines... Then you have to wonder what to do if the first one gets bigger, right?

    One way this could be handled is to have the ORGx without a number simply mean "switch context". That way, even if you have something like:
    ORGH 1
    ' hub code
    
    ORG 8<<2
    'cog code
    
    ORGH
    ' more hub code
    
    

    In the above example, hub offset will still be increasing in the ORG context so that when you hit the second ORGH, it switches the context back with the correct offset. The same rule would apply to ORG, though this would probably be less commonly used.
  • Seairth wrote: »
    Rayman wrote: »
    I'm wondering how this is going to work when there are multiple hubexec routines in your code...
    I think all the examples have only one "orgh" directive and they are all "orgh 1". I assume the "1" is the absolute address and not an offset command.

    What do you do if you want to add a second "orgh" starting point? Seems like you have to count lines... Then you have to wonder what to do if the first one gets bigger, right?

    One way this could be handled is to have the ORGx without a number simply mean "switch context". That way, even if you have something like:
    ORGH 1
    ' hub code
    
    ORG 8<<2
    'cog code
    
    ORGH
    ' more hub code
    
    

    In the above example, hub offset will still be increasing in the ORG context so that when you hit the second ORGH, it switches the context back with the correct offset. The same rule would apply to ORG, though this would probably be less commonly used.
    That should work. I think it's fairly common in other assemblers. At least I remember using an assembler that worked that way in the ancient past.

  • cgraceycgracey Posts: 14,134
    edited 2015-09-30 20:14
    What about making cog exec addresses $00000..$001FF, LUT exec addresses $00200..$003FF, and hub exec addresses $00400..$FFFFF?

    The PC steps by 1 in cog and LUT exec, and by 4 in hub exec. This would solve the problem of cog and LUT addresses being all spread out by 4x. It would also fix the #reg problem. It would mean that cog and LUT code would be assembled differently from hub code because of address reckoning. This would be like Prop1, but with hub exec code having spread out addresses. Hub code would not be compatible with cog and LUT code because of the assembled addresses.

    All this would achieve, in reality, would be a simpler perspective for the user. It would take a tiny bit more logic. Maybe it's what is needed.

    It would also get rid of the overlapped cog/LUT exec and hub exec address spaces. It would cancel the entire long-alignment conundrum, as well.
  • Why not just make everything long addresses except HUB, which continues to have RDBYTE, RDWORD, RDLONG, etc?

    It's 32bit, it should all be 32bit reads, in fact your byte stuff is just masking a 32bit read, correct?
  • cgracey wrote: »
    What about making cog exec addresses $00000..$001FF, LUT exec addresses $00200..$003FF, and hub exec addresses $00400..$FFFFF?

    The PC steps by 1 in cog and LUT exec, and by 4 in hub exec. This would solve the problem of cog and LUT addresses being all spread out by 4x. It would also fix the #reg problem. It would mean that cog and LUT code would be assembled differently from hub code because of address reckoning. This would be like Prop1, but with hub exec code having spread out addresses. Hub code would not be compatible with cog and LUT code because of the assembled addresses.

    All this would achieve, in reality, would be a simpler perspective for the user. It would take a tiny bit more logic. Maybe it's what is needed.
    It would be too bad to have to "fix" this problem by changing the hardware. It seems more like a tool problem. Is the real issue the meaning of the # character? Why not just do what others have suggested and get rid of the need to use that for jmp instructions? Just do what every other assembler does and handle:

    jmp foo

    The way PASM currently handles:

    jmp #foo>>2

    Then the assembler can know how to pack bits into the instruction and the meaning of # is not altered.

  • jmgjmg Posts: 15,171
    David Betz wrote: »
    It would be too bad to have to "fix" this problem by changing the hardware. It seems more like a tool problem. Is the real issue the meaning of the # character? Why not just do what others have suggested and get rid of the need to use that for jmp instructions? Just do what every other assembler does and handle:

    jmp foo

    The way PASM currently handles:

    jmp #foo>>2

    Then the assembler can know how to pack bits into the instruction and the meaning of # is not altered.

    I agree - the best place to start, is to clean up the most common usages, and Labels with Jumps/branches are fundamental ASM core operations.
    Let the tools help.

    Adding segments also allows the tools to check what users are doing, more than a simple ORG

    ORG with a 'magic number' is more cryptic than an explicit segment name.

    Other MCUs have explicit opcodes for byte and word data handling, which keeps things clear.

  • I just thought of something else. What happens of you use an AUGS instruction with DJZ for example? Normally that instruction has a 9 bit S field and it indicates the destination of the jump as a long address not a byte address. Is the same true if you use AUGS? Is the 32 bit resulting address also a long address or is it a byte address? If it is a long address then there is no way to target a non-aligned instruction in hub memory. That doesn't bother me because I see little value in non-aligned instructions but it is a little odd if other instructions can target non-aligned addresses.
  • jmgjmg Posts: 15,171
    Rayman wrote: »
    I'm wondering how this is going to work when there are multiple hubexec routines in your code...
    I think all the examples have only one "orgh" directive and they are all "orgh 1". I assume the "1" is the absolute address and not an offset command.

    What do you do if you want to add a second "orgh" starting point? Seems like you have to count lines... Then you have to wonder what to do if the first one gets bigger, right?

    BTW: I think "orgh 1" "orgh 2" and "orgh 3" would all work, it's just "orgh 0" that would try to run in a cog...

    This is why SEGMENT makes more sense than a hard ORG.
    SEGMENT can include any align that segment demands, and allows easy merge of code.
    SEGMENT also allows a linker to be used, which is more common in a mix of ASM and HLL
  • jmgjmg Posts: 15,171
    Seairth wrote: »
    ..

    * Hub data addressing is byte-oriented
    * Cog and LUT data addressing is long-oriented

    This also makes a case for SEGMENT, and in some segments certain data types may be prohibited (this can be tool-checked)
    ie if byte and word are allowed only in HUB, that means .byte & .word storage allocators would give an error if used in COG or LUT segments, but .long is legal in all
    (maybe with an align variant )

  • Roy ElthamRoy Eltham Posts: 3,000
    edited 2015-09-30 21:06
    You can't use "jmp foo", it's already got a meaning.

    jmp foo puts the value of foo into the S portion of the instruction and leave the I flag off. This causes it to use the register at foo to get the address to jump to.
    jmp #foo puts the value of foo into the S portion of the instruction and sets the I flag on. This causes it to jump to the address where foo is at.


    I'm actually in favor of just having all execution be long aligned, so the PC doesn't need the lower 2 bits. We only need word and byte access for data to/from the hub.
  • David BetzDavid Betz Posts: 14,516
    edited 2015-09-30 21:11
    Roy Eltham wrote: »
    You can't use "jmp foo", it's already got a meaning.

    jmp foo puts the value of foo into the S portion of the instruction and leave the I flag off. This causes it to use the register at foo to get the address to jump to.
    jmp #foo puts the value of foo into the S portion of the instruction and sets the I flag on. This causes it to jump to the address where foo is at.


    I'm actually in favor of just having all execution be long aligned, so the PC doesn't need the lower 2 bits. We only need word and byte access for data to/from the hub.
    I understand that "jmp foo" has a meaning. That meaning is typically coded as "jmp @foo" in other assemblers. Of course, Chip used @ to mean relative addressing so something would have to be done about that if we were to move to this new model.

  • jmgjmg Posts: 15,171
    edited 2015-09-30 21:29
    David Betz wrote: »
    I understand that "jmp foo" has a meaning. That meaning is typically coded as "jmp @foo" in other assemblers. Of course, Chip used @ to mean relative addressing so something would have to be done about that if we were to move to this new model.

    Other Assemblers just use simple labels (no prefix) and relative is a tool-choice.
    Users need not worry about if a relative jump, or absolute jump is encoded.
    Simple and clean. ( @Rn is used by MSP430, 8051...)

  • David BetzDavid Betz Posts: 14,516
    edited 2015-09-30 21:29
    jmg wrote: »
    David Betz wrote: »
    I understand that "jmp foo" has a meaning. That meaning is typically coded as "jmp @foo" in other assemblers. Of course, Chip used @ to mean relative addressing so something would have to be done about that if we were to move to this new model.

    Other Assemblers just use simple labels (no prefix) and relative is a tool-choice.
    Users need not worry about is a relative jump, or absolute jump is encoded.
    Simple and clean. ( @Rn is used by MSP430, 8051...)
    And the PDP-11. Oops, now you know how old I am! :-)

    Edit: Sorry. I'm wrong. The PDP-11 used (R1) to indicate indirect through R1. Maybe it was the PDP-10....

  • David Betz wrote: »
    I just thought of something else. What happens of you use an AUGS instruction with DJZ for example? Normally that instruction has a 9 bit S field and it indicates the destination of the jump as a long address not a byte address. Is the same true if you use AUGS? Is the 32 bit resulting address also a long address or is it a byte address? If it is a long address then there is no way to target a non-aligned instruction in hub memory. That doesn't bother me because I see little value in non-aligned instructions but it is a little odd if other instructions can target non-aligned addresses.

    DJZ (etc.) do not have an immediate form. On register or relative. I'm don't think you can use AUGx with relative addressing.
  • In any case, I really think we should just go with only long aligned execution across all types.

    I would even be fine with having hub access always be long oriented, and just have instructions for reading the proper bytes or words from a long address. So, for example, RDBYTE D,S,N where N is what byte to read from the hub address at S and place into D. This would be similar to the get/setbyte and get/setword instructions. In fact, we could even do the nibble versions if we wanted.

    The more I think about this, the more I think it's the way to go. I hope Chip likes it.
  • Seairth wrote: »
    David Betz wrote: »
    I just thought of something else. What happens of you use an AUGS instruction with DJZ for example? Normally that instruction has a 9 bit S field and it indicates the destination of the jump as a long address not a byte address. Is the same true if you use AUGS? Is the 32 bit resulting address also a long address or is it a byte address? If it is a long address then there is no way to target a non-aligned instruction in hub memory. That doesn't bother me because I see little value in non-aligned instructions but it is a little odd if other instructions can target non-aligned addresses.

    DJZ (etc.) do not have an immediate form. On register or relative. I'm don't think you can use AUGx with relative addressing.
    Ah, okay. Then is the relative address a byte or a long offset?

  • Roy Eltham wrote: »
    You can't use "jmp foo", it's already got a meaning.

    jmp foo puts the value of foo into the S portion of the instruction and leave the I flag off. This causes it to use the register at foo to get the address to jump to.
    jmp #foo puts the value of foo into the S portion of the instruction and sets the I flag on. This causes it to jump to the address where foo is at.


    I'm actually in favor of just having all execution be long aligned, so the PC doesn't need the lower 2 bits. We only need word and byte access for data to/from the hub.

    Slight correction. There are three forms for JMP:
    JMP foo     ' alias for CALLD INA, foo
    JMP #foo    ' 20-bit immediate value (in bytes)
    JMP @foo    ' 20-bit relative value (don't know if it's in bytes or longs)
    
  • David Betz wrote: »
    Seairth wrote: »
    David Betz wrote: »
    I just thought of something else. What happens of you use an AUGS instruction with DJZ for example? Normally that instruction has a 9 bit S field and it indicates the destination of the jump as a long address not a byte address. Is the same true if you use AUGS? Is the 32 bit resulting address also a long address or is it a byte address? If it is a long address then there is no way to target a non-aligned instruction in hub memory. That doesn't bother me because I see little value in non-aligned instructions but it is a little odd if other instructions can target non-aligned addresses.

    DJZ (etc.) do not have an immediate form. On register or relative. I'm don't think you can use AUGx with relative addressing.
    Ah, okay. Then is the relative address a byte or a long offset?

    In this case, it's long offset. I think. As I mentioned in the prior comment, I don't know if the 20-bit relative address is long or byte offsets.
  • jmgjmg Posts: 15,171
    Roy Eltham wrote: »
    I would even be fine with having hub access always be long oriented, and just have instructions for reading the proper bytes or words from a long address. So, for example, RDBYTE D,S,N ...

    but how do you scan byte arrays, with a 3 operand opcode ?
    Data access has always been the gotcha in all of this, it still needs to be byte-granular.
    To me, the Silicon is quite good as it is, it just needs a tool-clean-up pass.

  • cgraceycgracey Posts: 14,134
    edited 2015-09-30 22:10
    Roy Eltham wrote: »
    In any case, I really think we should just go with only long aligned execution across all types.

    I would even be fine with having hub access always be long oriented, and just have instructions for reading the proper bytes or words from a long address. So, for example, RDBYTE D,S,N where N is what byte to read from the hub address at S and place into D. This would be similar to the get/setbyte and get/setword instructions. In fact, we could even do the nibble versions if we wanted.

    The more I think about this, the more I think it's the way to go. I hope Chip likes it.

    Wouldn't this destroy linear byte and word addressing? We'd have to maintain separate counters to cycle through bytes and longs.

    I've been stalled out, trying to come to some resolution about how to reign this mess in, because moving forward on the current path is dismal.

    Here is what looks best to me:

    $00000..$001FF = cog exec (register addressing is 1:1, PC steps by 1)
    $00200..$003FF = LUT exec (register addressing is 1:1, PC steps by 1)
    $00400..$FFFFF = hub exec (PC steps by 4, relative D,@S (9-bit immediate) branches are shifted left twice)

    This keeps the cogs simple and fun, like they are on Prop1, which is a necessity. It also gets rid of any impetus to make overlapped cog/LUT/hub execution spaces.

    There's no way we ought to clutter up the assembly language with all kinds of operators to overcome the current 4:1 hub:cog/LUT addressing ratio. Making it 1:1 keeps us sane, happy, and free.

    This takes a few gates to implement and it doesn't slow the chip down.

    This would make the Prop2 just like the Prop1, but without any hub alignment requirements for longs and words, and with the pleasant addition of hub exec. It even gets rid of the notion that hub exec instructions ought to be long-aligned for any reason. Hub execution and data access all become dirt simple with no alignment caveats.
  • Roy ElthamRoy Eltham Posts: 3,000
    edited 2015-09-30 22:15
    (ignore this)
Sign In or Register to comment.