Shop OBEX P1 Docs P2 Docs Learn Events
".cog_ram" directive in inline assembly — Parallax Forums

".cog_ram" directive in inline assembly

jac_goudsmitjac_goudsmit Posts: 418
edited 2013-03-03 19:22 in Propeller 1
I've been dabbling around in Binutils and I don't understand why the ".cog_ram" directive exists.

As far as I can tell, the assembler generates labels that have a flag set when ".cog_ram" was active at the point where the label was generated. Then in any instruction that uses that label, it calculates the source/target field depending on the flag in the label.

This doesn't make much sense to me: In my mind, all assembler instructions that refer to a location should use the cog memory address of that location, except RDBYTE/RDWORD/RDLONG and WRBYTE/WRWORD/WRLONG, which are the only instructions that should use the hub address.

In an assembler program in Spin, the only way to express the hub address of an instruction is to use a Spin sequence to initialize a LONG in the assembler program with a value that's a spin pointer. Example:
pub...
   ...
  video_pointer = @video_buffer
  cognew(...)
   ...
dat
  ...
  video_pointer LONG 0
  ...
  rdlong r8, video_pointer

So I propose that in GCC Assembler, a new prefix @ should be introduced to generate a hub memory address in an instruction or in a BYTE/WORD/LONG directive. Example:
  video_buffer  RES 1024

  ...
  video_pointer LONG @video_buffer
  ...
  rdlong r8, video_pointer ' non-immediate
  ...
  rdlong r8, @video_buffer ' immediate, using hub address; obviously should give an error if > #0x1ff

Using the @ directive, the way that addresses are translated to machine language is always clear right away, without the need to know whether a ".cog_ram" or ".hub_ram" is active. I think this should be the default mode of working but if it breaks GCC, we can add a directive to change the AS behavior back to the old way for compatibility reasons. GCC can generate that directive at the beginning of all assembler output.

I've been working on Binutils to see if it's possible to do it this way, and I'm not close enough to being code-complete to post a Diff. I have commit access but I'm too scared to break something so I won't check anything in without ample review by Eric and Dave.

I hope what I'm saying makes sense. If not, let me know.

===Jac

Comments

  • ersmithersmith Posts: 6,092
    edited 2013-03-02 09:04
    What happens in this case:

    foo.s:
       .global x
       .set x,100   '' set our constant up
    

    bar.s:
       mov r0, #x
    

    Should we put 25 or 100 into r0? Clearly the answer is 100; but if we always divide symbols by 4 before use, we'll get 25.

    .cog_ram sets a flag on symbols to indicate that they really are COG addresses, and should be divided by 4 before use. It's not the default, because the default mode of operation for gcc (and the tools) is LMM mode, where addresses are normally HUB addresses.

    Eric
  • jac_goudsmitjac_goudsmit Posts: 418
    edited 2013-03-03 19:22
    ersmith wrote: »
    .cog_ram sets a flag on symbols to indicate that they really are COG addresses, and should be divided by 4 before use. It's not the default, because the default mode of operation for gcc (and the tools) is LMM mode, where addresses are normally HUB addresses.

    I understand what the directive does, but my argument is that it's the wrong way to solve the problem of the ambiguity between the two address spaces (which really only exists when storing pointers as data, not when storing pointers as part of instructions, see my post here) by declaring the symbol as either a hub symbol or a cog symbol when the symbol is defined.

    A better way to handle the ambiguity would be to just let the tools keep track of the hub address of everything, all the way until linking (or maybe even loading), i.e. the assembler shouldn't divide any addresses by 4; the linker or loader should do it (obviously the source and target value has to be stored separately but I think the assembly already does that). It should be possible to insert a special "ORG" record in the elf file that tells the linker/loader that cog addresses start from 0 (or any other value up to 511) at the current hub address. Then at link or load time, the instructions get their final encoding by calculating the cog offset from the last-seen ORG record. The linker will have to know whether to encode hub or cog addresses, but the decision should be based ON THE INSTRUCTION, NOT ON THE REFERRED LOCATION. For all instructions there is no ambiguity whether cog addresses or hub addresses need to be used. Only in the case of a stored pointer there may be ambiguity, and there is no way to override one way or another, hence the @ operator proposal.

    ===Jac
Sign In or Register to comment.