You had "loc ptrb, #message", which gets the code address of message into ptrb. You wanted "mov ptrb, ##message", which puts the data address of message into ptrb. Code and data addresses are the same for addresses greater than or equal to $400, which is why it worked with "orgh $400".
Hmm, me needs to do some reading too ... some PNUT specific detail there I'd guess.
LOC is useful for getting the address of anything in hub RAM. Doesn't matter if it's code or data.
There should be no trouble reading and writing below $400 in hub. The only caveat is that if you jump to any of those locations, you are executing from the cog/lut. Remember that reads and writes to anywhere in hub must use RDxxxx/WRxxxx. If you do 'MOV 0,#100' you are moving 100 into cog register $000, not into hub RAM $00000.
LOC is useful for getting the address of anything in hub RAM. Doesn't matter if it's code or data.
There should be no trouble reading and writing below $400 in hub. The only caveat is that if you jump to any of those locations, you are executing from the cog/lut. Remember that reads and writes to anywhere in hub must use RDxxxx/WRxxxx. If you do 'MOV 0,#100' you are moving 100 into cog register $000, not into hub RAM $00000.
I think my code is the problem, not your image! I have used
loc adrb, #@symbol
in my Hub Exec code for symbols in Hub RAM.
It looks like I should have been using
loc adrb, #\symbol
in order to get its' absolute address.
Therefore, it may explain the problem I've been experiencing. I will change my code and see if that resolves the matter.
I have drawn a diagram which I think may explain things a bit clearer than words, attached as file for comment.
LOC is useful for getting the address of anything in hub RAM. Doesn't matter if it's code or data.
There should be no trouble reading and writing below $400 in hub. The only caveat is that if you jump to any of those locations, you are executing from the cog/lut. Remember that reads and writes to anywhere in hub must use RDxxxx/WRxxxx. If you do 'MOV 0,#100' you are moving 100 into cog register $000, not into hub RAM $00000.
I think my code is the problem, not your image! I have used
loc adrb, #@symbol
in my Hub Exec code for symbols in Hub RAM.
It looks like I should have been using
loc adrb, #\symbol
in order to get its' absolute address.
Therefore, it may explain the problem I've been experiencing. I will change my code and see if that resolves the matter.
I have drawn a diagram which I think may explain things a bit clearer than words, attached as file for comment.
It's not nearly that complicated!
Lack of documentation is causing problems.
All cog register accesses are direct via instructions (MOV rega,regb).
All lut access is via RDLUT/WRLUT (cog registers <--> lut registers) or SETQ2+RDLONG (hub --> lut).
All hub accesses are via RDxxxx/WRxxxx/RFxxxx/WFxxxx, only.
"@", "#hublabel", "#\hublabel" refers to hub RAM, only.
"#@hublabel" is the same as "#hublabel".
"@", "#\", and "#@" cannot be used to point at anything in the cog or lut. They always denote hub memory.
I think we need to develop some syntax that inhibits all this confusion over addressing.
LOC is useful for getting the address of anything in hub RAM. Doesn't matter if it's code or data.
There should be no trouble reading and writing below $400 in hub. The only caveat is that if you jump to any of those locations, you are executing from the cog/lut. Remember that reads and writes to anywhere in hub must use RDxxxx/WRxxxx. If you do 'MOV 0,#100' you are moving 100 into cog register $000, not into hub RAM $00000.
I think my code is the problem, not your image! I have used
loc adrb, #@symbol
in my Hub Exec code for symbols in Hub RAM.
It looks like I should have been using
loc adrb, #\symbol
in order to get its' absolute address.
Therefore, it may explain the problem I've been experiencing. I will change my code and see if that resolves the matter.
I have drawn a diagram which I think may explain things a bit clearer than words, attached as file for comment.
It's not nearly that complicated!
Lack of documentation is causing problems.
All cog register accesses are direct via instructions (MOV rega,regb).
All lut access is via RDLUT/WRLUT (cog registers <--> lut registers) or SETQ2+RDLONG (hub --> lut).
All hub accesses are via RDxxxx/WRxxxx/RFxxxx/WFxxxx, only.
"@", "#hublabel", "#\hublabel" refers to hub RAM, only.
"#@hublabel" is the same as "#hublabel".
"@", "#\", and "#@" cannot be used to point at anything in the cog or lut. They always denote hub memory.
I think we need to develop some syntax that inhibits all this confusion over addressing.
I am very good at complicating things, me
What I am after is how to obtain the address of a location of a symbol in Cog, and also in Hub and Lut. The assembler knows them, I wish to know them, too.
org 0
mov my_addr, magic_address_of_long_in_cog_for my_reg
my_reg long 0
my_addr long 0
so my_reg is at address 1 in Cog long RAM, my_addr at 2, and in my example woud contain the value 1.
I am after the same in LUT and Hub RAM.
I await clarification, then hopefully my memory overwrites, I think we can all see why that is happening, even though I'm not sure, will logically resolve themselves.
All symbols defined under ORGH are hub addresses. Any reference to one of them returns a hub address.
All symbols defined under ORG are both cog and hub addresses, with a direct reference returning a cog address. Using @ before one of those symbols returns the hub address, instead.
All symbols defined under ORGH are hub addresses. Any reference to one of them returns a hub address.
All symbols defined under ORG are both cog and hub addresses, with a direct reference returning a cog address. Using @ before one of those symbols returns the hub address, instead.
That is so concise and elegant compared to my understanding Good job there's only us two mice here reading this!
Ah, so in your all_cogs_blink.spin example in the FPGA download, you use the coginit cognum,#@blink because the binary is initially loaded into hub ram, however, they are really cog programs within cog space. Thus #@blink gives the source hub address from which to load the cog from that image.
So if I had a cog binary image loaded into hub ram at startup, and I wished to change some information in it, I would need to use the #@ for hub ram address, make any necessary changes, and then it could be loaded into a cog.
To setup address registers with loc, the simple loc ptrb, #symbol is all that is required?
I have changed and checked my code for the test harness. I am using a hub based stack with ptra as the stack pointer. All calls and rets are by calla #function and reta, all stack pushes and pops are pusha and popa. All locs use loc ptrb, #symbol.
However, at present I am still experiencing corruption of data as before. I will check through carefully on what happens to my registers, it sounds like I must be corrupting one for some reason, but thinking about it I think it has always happened in the decimal conversion process chain somewhere.
I think we need to develop some syntax that inhibits all this confusion over addressing.
I agree - the P2 has multiple memory areas now, combined with value and opcode rules for access.
It would be good (and not too difficult) to have the tools check and confirm correct indexing context, otherwise there will be a lot of slip-ups (as these posts show)
HLL's have this index context control more naturally handled, but there will be more ASM exposed to users on P2 than other MCUs, so good ASM support is important.
I think we need to develop some syntax that inhibits all this confusion over addressing.
I agree - the P2 has multiple memory areas now, combined with value and opcode rules for access.
It would be good (and not too difficult) to have the tools check and confirm correct indexing context, otherwise there will be a lot of slip-ups (as these posts show)
HLL's have this index context control more naturally handled, but there will be more ASM exposed to users on P2 than other MCUs, so good ASM support is important.
I agree about the tools checking and assisting as much as possible with these 'seperate yet combined' memory areas. Anything which makes the path easier.
HLLs have to be adapted / written first, then tested to ensure that they too are analysing and synthesising correctly. Obviously that takes time, so what we currently use needs to be supportive. In the mean time I will become quite proficient at PASM2 (sans macros) I hope!
Now, what we could do for macros is use have a preprocessor, obviuously the C preprocessor won't be suitable because of the liberal sprinkling of # characters in PASM2. What we need is:
openfile_for_read( PNut_editor_file_or_memory )
openfile_for_write( spin_file_for_PNut_editor )
while readlines() ' a token could be a multiline comment
while get_token_from_lines() ' this would include comment tokens
if token == "macro" )
make_a_macro_from_what_follows_on_lines() ' macros span lines
else
if token == a_macro_we_have_defined( )
expand_macro_for_tokens_from_what_follows_on_lines( token )
else
put_token_to_output_spin_file( token )
' hopefully it's real pasm, not the stuff 78rpm TRIES to write
endwhile
endwhile
closeallfiles( )
return_to_PNut()
Now something like that would help and work, especially if the macroed source can be edited within PNut, then launched for pre-processing and the output spin file then assembled by PNut. Life would be a far easier. Perhaps there is something already around like that, or could be tailored for use. Simply a case of deciding if the word "macro" defines the start of a macro definition and how parameters are passed and expanded and any other fancy stuff like looping.
I agree about the tools checking and assisting as much as possible with these 'seperate yet combined' memory areas. Anything which makes the path easier.
....
Now, what we could do for macros is use have a preprocessor, obviuously the C preprocessor won't be suitable because of the liberal sprinkling of # characters in PASM2. What we need is:
I was thinking of something easier to add to PNUT than macros (but macros would be nice, & they are in GAS)
Some checking could be done with a mnemonic expansion, that tags the register with memory area.
When used, that register is checked for correct memory area for that opcode.
This would also allow easier relocate of buffers/arrays.
The classic # immediate would still work, such as HLL's might generate.
I agree about the tools checking and assisting as much as possible with these 'seperate yet combined' memory areas. Anything which makes the path easier.
....
Now, what we could do for macros is use have a preprocessor, obviuously the C preprocessor won't be suitable because of the liberal sprinkling of # characters in PASM2. What we need is:
I was thinking of something easier to add to PNUT than macros (but macros would be nice, & they are in GAS)
Some checking could be done with a mnemonic expansion, that tags the register with memory area.
When used, that register is checked for correct memory area for that opcode.
This would also allow easier relocate of buffers/arrays.
The classic # immediate would still work, such as HLL's might generate.
The memory tagging I think I understand.
Relocating arrays and buffers. This is at assembly time for intended use at runtime? So are you suggesting this is for use with the memory area tag, such that at runtime you intend to move something, in hub space, or to a different memory space, cog or lut? And thus check that your pasm is checked such that a rdlong in hub space to memory in hub space, doesn't get moved to cog space with the associated hub buffer moved into say the lut?
I can see that would be a big boost. More of a directive to PNut than a macro, that this symbol may be declared here, but I intend to use it elsewhere, such as here? If was called "relocate", then "relocate destination, source", would follow in the Propeller and pasm spirit.
Relocating arrays and buffers. This is at assembly time for intended use at runtime? So are you suggesting this is for use with the memory area tag, such that at runtime you intend to move something, in hub space, or to a different memory space, cog or lut? And thus check that your pasm is checked such that a rdlong in hub space to memory in hub space, doesn't get moved to cog space with the associated hub buffer moved into say the lut?
I can see that would be a big boost. More of a directive to PNut than a macro, that this symbol may be declared here, but I intend to use it elsewhere, such as here? If was called "relocate", then "relocate destination, source", would follow in the Propeller and pasm spirit.
That's quite close.
Yes, it is a build time choice, as during a design you may not be sure if you want or need buffers in HUB or LUT for example.
Yes, you can declare variables in one area, and use them later in the code.
( If there is no checking, you tend to code differently in style )
The memory tag is another field in the symbol record, so is easy to add.
If you move the memory area, but forget to move one opcode, this would catch that.
Once you have that, you can even code generic items
( similar to CALL and JMP ) and have the tools know what you intend
an example of pointer loading with address of label, could be in generic form :
GADR_H Reg_or_Ptr,HUBLabel ' Loads Reg_or_Ptr with Hub Label addr, chk & tags as HUB
GADR_L Reg_or_Ptr,LUTLabel ' Loads Reg_or_Ptr with LUT Label addr, chk & tags as LUT
GADR_C Reg_or_Ptr,COGLabel ' Loads Reg_or_Ptr with COG Label addr, chk & tags as COG
GADR_T Reg_or_Ptr,ANYLabel ' Loads Reg_or_Ptr with ANY Label addr, tags as that Area
GADR_L Reg_or_Ptr,LUTLabel ' Loads Reg_or_Ptr with LUT Label address & tags as LUT
RDLUT D,[Reg_or_Ptr] ' Checks [S] field for LUT tagged
WRLUT [Reg_or_Ptr],S ' Checks [D] field for LUT tagged
GADR_T Reg_or_Ptr,HUBLabel ' Auto tags as HUB
RDLONG D,[Reg_or_Ptr] ' Checks [S] field for HUB tagged
WRLONG [Reg_or_Ptr],S ' Checks [D] field for HUB tagged
Relocating arrays and buffers. This is at assembly time for intended use at runtime? So are you suggesting this is for use with the memory area tag, such that at runtime you intend to move something, in hub space, or to a different memory space, cog or lut? And thus check that your pasm is checked such that a rdlong in hub space to memory in hub space, doesn't get moved to cog space with the associated hub buffer moved into say the lut?
I can see that would be a big boost. More of a directive to PNut than a macro, that this symbol may be declared here, but I intend to use it elsewhere, such as here? If was called "relocate", then "relocate destination, source", would follow in the Propeller and pasm spirit.
That's quite close.
Yes, it is a build time choice, as during a design you may not be sure if you want or need buffers in HUB or LUT for example.
Yes, you can declare variables in one area, and use them later in the code.
( If there is no checking, you tend to code differently in style )
The memory tag is another field in the symbol record, so is easy to add.
If you move the memory area, but forget to move one opcode, this would catch that.
Once you have that, you can even code generic items
( like CALL and JMP ) and have the tools know what you intend
an example of pointer loading with address of label, could be in generic form :
GADR_H Reg_or_Ptr,HUBLabel ' Loads Reg_or_Ptr with Hub Label addr, chk & tags as HUB
GADR_L Reg_or_Ptr,LUTLabel ' Loads Reg_or_Ptr with LUT Label addr, chk & tags as LUT
GADR_C Reg_or_Ptr,COGLabel ' Loads Reg_or_Ptr with COG Label addr, chk & tags as COG
GADR_T Reg_or_Ptr,ANYLabel ' Loads Reg_or_Ptr with ANY Label addr, tags as that Area
GADR_L Reg_or_Ptr,LUTLabel ' Loads Reg_or_Ptr with LUT Label address & tags as LUT
RDLUT D,[Reg_or_Ptr] ' Checks [S] field for LUT tagged
WRLUT [Reg_or_Ptr],S ' Checks [D] field for LUT tagged
GADR_T Reg_or_Ptr,HUBLabel ' Auto tags as HUB
RDLONG D,[Reg_or_Ptr] ' Checks [S] field for HUB tagged
WRLONG [Reg_or_Ptr],S ' Checks [D] field for HUB tagged
Ah, I see clearly there. That type of checking would be of great advantage. I wonder how easily that could be integrated and tested into PNut or a PNut clone. As far as documentation, it could generate reports of symbols and memory spaces marked for access and/or relocation.
I've kept the idea simple, & PNUT could add a single byte record field and check that.
Without seeing the source, in asm86?, I wouldn't like to say.
However, the idea is simple in practice.
Yes, MAP files would naturally show the memory-area of each variable, and LST files would show the actual binary opcode ASM chose for that operation.
Agreed, the traditional approach does work. Tha MAP file would be somewhat different from other processors due to these three memory areas and the fact you are able to relocate within them.
As an additional thought. The names I use may be wrong, I see a similarity to scoping at global and function level. Your ANY label would be the global case, and COG would be within COG function and not reference the global instance.
It would also need to support, could still be done in a single byte, that a data structure could exist in all three memory spaces, though each instance would be dealt with in the code. This to be is quite specific in that it could be anywhere because you perhaps haven't specified, but it could in fact exist everywhere.
Now, carrying on that thought, would you wish to annotate LST an MAP files with all known locations as indicated by your code. I would say yes.
As an additional thought. The names I use may be wrong, I see a similarity to scoping at global and function level. Your ANY label would be the global case, and COG would be within COG function and not reference the global instance.
To clarify, the ANY case is a slight elevation in IQ, whilst the earlier GADR_H, GADR_L, GADR_C explicitly define the memory area, and the Label is checked for correct match.
The GADR_T 'auto-typed' form, auto-extracts the memory area from the label (which is tagged by its ORG_C,ORG_H,ORG_L).
It still gives pointer use checking, but it can open the door to easier move between (supported) Arrays in LUT or HUB, for example.
GADR_T Reg_or_Ptr,HUBLabel ' Auto tags as HUB
..
RDLNG D,[Reg_or_Ptr] ' Reads Long from HUB
WRLNG [Reg_or_Ptr],S ' Writes Long to HUB
' -- or --
GADR_T Reg_or_Ptr,LUTLabel ' Auto tags as LUT
..
RDLNG D,[Reg_or_Ptr] ' Reads Long from LUT
WRLNG [Reg_or_Ptr],S ' Writes Long to LUT
ASM form chosen in those cases is either RDLONG or RDLUT, with the label declaration being the only item needing edit to move a buffer.
It would also need to support, could still be done in a single byte, that a data structure could exist in all three memory spaces, though each instance would be dealt with in the code. This to be is quite specific in that it could be anywhere because you perhaps haven't specified, but it could in fact exist everywhere.
Now, carrying on that thought, would you wish to annotate LST an MAP files with all known locations as indicated by your code. I would say yes.
That may be going beyond what PNUT can support - I'm trying to keep this simple .
What you describe sounds like it needs run-time support, and I've seen that for example in some 8051 HLL compilers, where a 3rd byte is added to pointers, that is run-time checked for the various memory areas in 8051.
In the 8051, DATA and CODE use different RdByte opcodes and IDATA and XDATA and PDATA also have different RdByte opcodes, so issues are similar to P2.
To clarify, the ANY case is a slight elevation in IQ, whilst the earlier GADR_H, GADR_L, GADR_C explicitly define the memory area, and the Label is checked for correct match.
The GADR_T 'auto-typed' form, auto-extracts the memory area from the label (which is tagged by its ORG_C,ORG_H,ORG_L).
It still gives pointer use checking, but it can open the door to easier move between (supported) Arrays in LUT or HUB, for example.
GADR_T Reg_or_Ptr,HUBLabel ' Auto tags as HUB
..
RDLNG D,[Reg_or_Ptr] ' Reads Long from HUB
WRLNG [Reg_or_Ptr],S ' Writes Long to HUB
' -- or --
GADR_T Reg_or_Ptr,LUTLabel ' Auto tags as LUT
..
RDLNG D,[Reg_or_Ptr] ' Reads Long from LUT
WRLNG [Reg_or_Ptr],S ' Writes Long to LUT
ASM form chosen in those cases is either RDLONG or RDLUT, with the label declaration being the only item needing edit to move a buffer.
Those look like rules for the access rights and permitted operations of the memory areas, we'll say an array,in this example.
So the macro in this case may be GET to read from the array, and PUT to write. In your code you may have GETBYTE my_reg,ptrb. The tagging for both code and data, and the rule check the access is permitted. If so, GETBYTE is replaced with the appropriate rdbyte, or rdlut, or mov, sequence. Reading a byte may involve a LONG operation, so the instruction is susbtituted and another is automatically inserted to give the byte access, my_reg,#$ff. Thus we have the code from the data space.
Or is that going a little too far. Is it slightly toward HLL in thinking? You can extend the idea with passing arguments on the stack, for if you require reentrant code in HUB. Issue a GETARG_1 my_reg and the register selected as the stack pointer can be substituted, along with the appropriate offsets for a rdlong my_reg,ptrb[ THIS_FUNCTIONS_ARG_1 ]. It could be a great aid, because coding would be more precise. If you defined your routine as FUNCTION a1, a2, a3, a4, the macro could generate the relevant constant index values for that function. They would only need to be local scope constants, similar to local .LABEL .
What you describe sounds like it needs run-time support, and I've seen that for example in some 8051 HLL compilers, where a 3rd byte is added to pointers, that is run-time checked for the various memory areas in 8051.
In the 8051, DATA and CODE use different RdByte opcodes and IDATA and XDATA and PDATA also have different RdByte opcodes, so issues are similar to P2.
It may need some runtime support, but if you're having the memory area and symbol checking done for you, it can also insert the necessary runtime support code for you. Akin to a source level linker
So the macro in this case may be GET to read from the array, and PUT to write. In your code you may have GETBYTE my_reg,ptrb. The tagging for both code and data, and the rule check the access is permitted. If so, GETBYTE is replaced with the appropriate rdbyte, or rdlut, or mov, sequence. Reading a byte may involve a LONG operation, so the instruction is susbtituted and another is automatically inserted to give the byte access, my_reg,#$ff. Thus we have the code from the data space.
Or is that going a little too far. Is it slightly toward HLL in thinking?
That's going somewhat further than I was thinking, but it is possible.
I limited the use to where direct equivalent opcodes existed, in this case LONG access on HUB and LUT.
That keeps things very simple (within the realms of PNIUT x86 ASM ) and there is always a predicable 'opcode outcome'.
GETBYTE into LUT needs more than one opcode, and PUT is even trickier, and how that is implemented may depend on what else is happening. So I'd call that a little out of scope, for now.
The intention is to keep 'Assembler level thinking', but add just enough IQ to remove the obtuse character tags used to denote address spaces (which also fail to check)
It may need some runtime support, but if you're having the memory area and symbol checking done for you, it can also insert the necessary runtime support code for you. Akin to a source level linker
I'm still on the fence over run-time, but that is only code & the user can do what they like.... *
Maybe not for PNUT, but a better Assembler could open some more build-time decisions.
eg a Library could use an Assembler Conditional build test of
.IF (GetSeg(SymbolName) = HUB)
..
.ELSIF (GetSeg(SymbolName) = COG)
..
.ENDIF
and the tools/linker stage could include just one, or both code expansions aka dead code removal.
Some label alias mechanism would be needed, but this could give smallest-possible memory footprints, and a general ASM library coding style.
* eg For those wanting run-time decisions, that Assembler directive GetSeg() could be used to load address upper bits, to be run-time checked.
So the macro in this case may be GET to read from the array, and PUT to write. In your code you may have GETBYTE my_reg,ptrb. The tagging for both code and data, and the rule check the access is permitted. If so, GETBYTE is replaced with the appropriate rdbyte, or rdlut, or mov, sequence. Reading a byte may involve a LONG operation, so the instruction is susbtituted and another is automatically inserted to give the byte access, my_reg,#$ff. Thus we have the code from the data space.
Or is that going a little too far. Is it slightly toward HLL in thinking?
That's going somewhat further than I was thinking, but it is possible.
I limited the use to where direct equivalent opcodes existed, in this case LONG access on HUB and LUT.
That keeps things very simple (within the realms of PNIUT x86 ASM ) and there is always a predicable 'opcode outcome'.
GETBYTE into LUT needs more than one opcode, and PUT is even trickier, and how that is implemented may depend on what else is happening. So I'd call that a little out of scope, for now.
The intention is to keep 'Assembler level thinking', but add just enough IQ to remove the obtuse character tags used to denote address spaces (which also fail to check)
Ok, so we're looking for a 1:1 on directives for checking and substitution. That is indeed simpler, and would provide less of path for instruction substitution and insertion which may by classified as 'interesting, WHAT!" One does indeed need to consider the task for x86 ASM coder, though if it were accomplished by another task which was launched, perhaps returning line numbers and the attribute tag in another file where the memory access checking directives were detected. Then PNut could read that file, apply the tags as it reads lines, etc. That way, it could be written in a HLL to tackle advantage of a more abstract code nature. It also makes integration easy. If the memory tagger failed to launch, PNut defaults to feeding itself internally your ANY tag on every line read, similar to the current arrangment. That would work, even if not quite what you had in mind.
I understand about the abstraction level at asm level. At least if PNut provided the appropriate memory access operators itself internally the approach would be consistant, especially for people new to the Propeller, and to the P2. I think that is the direction you're going in here.
Ok, so we're looking for a 1:1 on directives for checking and substitution. That is indeed simpler...
Yes, but if you want to be strictly correct on the 1:1 there can be one minor exception around address range : The tools can decide on whether to use a AUGS to extend to 32b immediate load , or if 9 bits will fit, use that smaller form.
COG and LOW-HUB vars, can use the smaller immediate load.
I understand about the abstraction level at asm level. At least if PNut provided the appropriate memory access operators itself internally the approach would be consistant, especially for people new to the Propeller, and to the P2. I think that is the direction you're going in here.
Yes, direction is keeping it 'very much assembler' in coding and thinking, but hiding some of the kludges so the code is easier to maintain and read.
Yes, but if you want to be strictly correct on the 1:1 there can be one minor exception around address range : The tools can decide on whether to use a AUGS to extend to 32b immediate load , or if 9 bits will fit, use that smaller form.
COG and LOW-HUB vars, can use the smaller immediate load.
That makes sense and is the optimal step. It may even be useful in hub ram on a Nano FPGA, like I use, limited to 32K.
Yes, direction is keeping it 'very much assembler' in coding and thinking, but hiding some of the kludges so the code is easier to maintain and read.
Readability is a big plus, it enables easier maintenance as it's more quickly understood.
Readability also plays in to an introduction to pasm by avoiding as many pitfalls as possible. That is something to be pursued. If the assembler is responsible for allocating memory locations for code and symbols, why does it insist on making the user play games when it has enough information to do the job. It knows when # or similar is required, it most cases it can supply it itself based on a little extra logic.
Now, can I interest you in saving pasm files in .RTF files for viewing in Windows WordPad with the correct syntax highlighting?
Now, can I interest you in saving pasm files in .RTF files for viewing in Windows WordPad with the correct syntax highlighting?
That's a different topic entirely, but syntax highlighting editors can often do this.
eg I see Notepad++ has plugins that export RTF and HTML, and you can add your own language highlighters to Notepad++
Well, I am in full agreement with you, but I'm sure you must find the idea entertaining that WordPad could show pasm colour highlighting as in the PST.
Well, I am in full agreement with you, but I'm sure you must find the idea entertaining that WordPad could show pasm colour highlighting as in the PST.
Um, NO!!!
I find little about using WordPad as a programming editor entertaining.
(Wait, should there be another smiley some place in there?)
Comments
This a Program-Counter only concern, ie: Affects instruction fetching. The general data manipulation instructions are all CogRAM only.
Hmm, me needs to do some reading too ... some PNUT specific detail there I'd guess.
So, in Hub Exec, where division_by_zero_error is a Hub label for a byte array of data, are you saying... ...is wrong?
Because the loc adrb is operating on a cog register and division_by_zero is in Hub space?
There should be no trouble reading and writing below $400 in hub. The only caveat is that if you jump to any of those locations, you are executing from the cog/lut. Remember that reads and writes to anywhere in hub must use RDxxxx/WRxxxx. If you do 'MOV 0,#100' you are moving 100 into cog register $000, not into hub RAM $00000.
loc adrb, #@symbol
in my Hub Exec code for symbols in Hub RAM.
It looks like I should have been using
loc adrb, #\symbol
in order to get its' absolute address.
Therefore, it may explain the problem I've been experiencing. I will change my code and see if that resolves the matter.
I have drawn a diagram which I think may explain things a bit clearer than words, attached as file for comment.
It's not nearly that complicated!
Lack of documentation is causing problems.
All cog register accesses are direct via instructions (MOV rega,regb).
All lut access is via RDLUT/WRLUT (cog registers <--> lut registers) or SETQ2+RDLONG (hub --> lut).
All hub accesses are via RDxxxx/WRxxxx/RFxxxx/WFxxxx, only.
"@", "#hublabel", "#\hublabel" refers to hub RAM, only.
"#@hublabel" is the same as "#hublabel".
"@", "#\", and "#@" cannot be used to point at anything in the cog or lut. They always denote hub memory.
I think we need to develop some syntax that inhibits all this confusion over addressing.
I am very good at complicating things, me
What I am after is how to obtain the address of a location of a symbol in Cog, and also in Hub and Lut. The assembler knows them, I wish to know them, too. so my_reg is at address 1 in Cog long RAM, my_addr at 2, and in my example woud contain the value 1.
I am after the same in LUT and Hub RAM.
I await clarification, then hopefully my memory overwrites, I think we can all see why that is happening, even though I'm not sure, will logically resolve themselves.
All symbols defined under ORG are both cog and hub addresses, with a direct reference returning a cog address. Using @ before one of those symbols returns the hub address, instead.
Ah, so in your all_cogs_blink.spin example in the FPGA download, you use the coginit cognum,#@blink because the binary is initially loaded into hub ram, however, they are really cog programs within cog space. Thus #@blink gives the source hub address from which to load the cog from that image.
So if I had a cog binary image loaded into hub ram at startup, and I wished to change some information in it, I would need to use the #@ for hub ram address, make any necessary changes, and then it could be loaded into a cog.
To setup address registers with loc, the simple loc ptrb, #symbol is all that is required?
I have changed and checked my code for the test harness. I am using a hub based stack with ptra as the stack pointer. All calls and rets are by calla #function and reta, all stack pushes and pops are pusha and popa. All locs use loc ptrb, #symbol.
However, at present I am still experiencing corruption of data as before. I will check through carefully on what happens to my registers, it sounds like I must be corrupting one for some reason, but thinking about it I think it has always happened in the decimal conversion process chain somewhere.
I'll get there eventually.
It would be good (and not too difficult) to have the tools check and confirm correct indexing context, otherwise there will be a lot of slip-ups (as these posts show)
HLL's have this index context control more naturally handled, but there will be more ASM exposed to users on P2 than other MCUs, so good ASM support is important.
I agree about the tools checking and assisting as much as possible with these 'seperate yet combined' memory areas. Anything which makes the path easier.
HLLs have to be adapted / written first, then tested to ensure that they too are analysing and synthesising correctly. Obviously that takes time, so what we currently use needs to be supportive. In the mean time I will become quite proficient at PASM2 (sans macros) I hope!
Now, what we could do for macros is use have a preprocessor, obviuously the C preprocessor won't be suitable because of the liberal sprinkling of # characters in PASM2. What we need is: Now something like that would help and work, especially if the macroed source can be edited within PNut, then launched for pre-processing and the output spin file then assembled by PNut. Life would be a far easier. Perhaps there is something already around like that, or could be tailored for use. Simply a case of deciding if the word "macro" defines the start of a macro definition and how parameters are passed and expanded and any other fancy stuff like looping.
I was thinking of something easier to add to PNUT than macros (but macros would be nice, & they are in GAS)
Some checking could be done with a mnemonic expansion, that tags the register with memory area.
When used, that register is checked for correct memory area for that opcode.
This would also allow easier relocate of buffers/arrays.
The classic # immediate would still work, such as HLL's might generate.
The memory tagging I think I understand.
Relocating arrays and buffers. This is at assembly time for intended use at runtime? So are you suggesting this is for use with the memory area tag, such that at runtime you intend to move something, in hub space, or to a different memory space, cog or lut? And thus check that your pasm is checked such that a rdlong in hub space to memory in hub space, doesn't get moved to cog space with the associated hub buffer moved into say the lut?
I can see that would be a big boost. More of a directive to PNut than a macro, that this symbol may be declared here, but I intend to use it elsewhere, such as here? If was called "relocate", then "relocate destination, source", would follow in the Propeller and pasm spirit.
That's quite close.
Yes, it is a build time choice, as during a design you may not be sure if you want or need buffers in HUB or LUT for example.
Yes, you can declare variables in one area, and use them later in the code.
( If there is no checking, you tend to code differently in style )
The memory tag is another field in the symbol record, so is easy to add.
If you move the memory area, but forget to move one opcode, this would catch that.
Once you have that, you can even code generic items
( similar to CALL and JMP ) and have the tools know what you intend
an example of pointer loading with address of label, could be in generic form :
Ah, I see clearly there. That type of checking would be of great advantage. I wonder how easily that could be integrated and tested into PNut or a PNut clone. As far as documentation, it could generate reports of symbols and memory spaces marked for access and/or relocation.
Yes, and notice the hieroglyphs have gone away...
I've kept the idea simple, & PNUT could add a single byte record field and check that.
Yes, MAP files would naturally show the memory-area of each variable, and LST files would show the actual binary opcode ASM chose for that operation.
You mean the full message quote?
Without seeing the source, in asm86?, I wouldn't like to say.
However, the idea is simple in practice.
Agreed, the traditional approach does work. Tha MAP file would be somewhat different from other processors due to these three memory areas and the fact you are able to relocate within them.
As an additional thought. The names I use may be wrong, I see a similarity to scoping at global and function level. Your ANY label would be the global case, and COG would be within COG function and not reference the global instance.
It would also need to support, could still be done in a single byte, that a data structure could exist in all three memory spaces, though each instance would be dealt with in the code. This to be is quite specific in that it could be anywhere because you perhaps haven't specified, but it could in fact exist everywhere.
Now, carrying on that thought, would you wish to annotate LST an MAP files with all known locations as indicated by your code. I would say yes.
The GADR_T 'auto-typed' form, auto-extracts the memory area from the label (which is tagged by its ORG_C,ORG_H,ORG_L).
It still gives pointer use checking, but it can open the door to easier move between (supported) Arrays in LUT or HUB, for example.
ASM form chosen in those cases is either RDLONG or RDLUT, with the label declaration being the only item needing edit to move a buffer.
That may be going beyond what PNUT can support - I'm trying to keep this simple .
What you describe sounds like it needs run-time support, and I've seen that for example in some 8051 HLL compilers, where a 3rd byte is added to pointers, that is run-time checked for the various memory areas in 8051.
In the 8051, DATA and CODE use different RdByte opcodes and IDATA and XDATA and PDATA also have different RdByte opcodes, so issues are similar to P2.
Those look like rules for the access rights and permitted operations of the memory areas, we'll say an array,in this example.
So the macro in this case may be GET to read from the array, and PUT to write. In your code you may have GETBYTE my_reg,ptrb. The tagging for both code and data, and the rule check the access is permitted. If so, GETBYTE is replaced with the appropriate rdbyte, or rdlut, or mov, sequence. Reading a byte may involve a LONG operation, so the instruction is susbtituted and another is automatically inserted to give the byte access, my_reg,#$ff. Thus we have the code from the data space.
Or is that going a little too far. Is it slightly toward HLL in thinking? You can extend the idea with passing arguments on the stack, for if you require reentrant code in HUB. Issue a GETARG_1 my_reg and the register selected as the stack pointer can be substituted, along with the appropriate offsets for a rdlong my_reg,ptrb[ THIS_FUNCTIONS_ARG_1 ]. It could be a great aid, because coding would be more precise. If you defined your routine as FUNCTION a1, a2, a3, a4, the macro could generate the relevant constant index values for that function. They would only need to be local scope constants, similar to local .LABEL .
It may need some runtime support, but if you're having the memory area and symbol checking done for you, it can also insert the necessary runtime support code for you. Akin to a source level linker
That's going somewhat further than I was thinking, but it is possible.
I limited the use to where direct equivalent opcodes existed, in this case LONG access on HUB and LUT.
That keeps things very simple (within the realms of PNIUT x86 ASM ) and there is always a predicable 'opcode outcome'.
GETBYTE into LUT needs more than one opcode, and PUT is even trickier, and how that is implemented may depend on what else is happening. So I'd call that a little out of scope, for now.
The intention is to keep 'Assembler level thinking', but add just enough IQ to remove the obtuse character tags used to denote address spaces (which also fail to check)
I'm still on the fence over run-time, but that is only code & the user can do what they like.... *
Maybe not for PNUT, but a better Assembler could open some more build-time decisions.
eg a Library could use an Assembler Conditional build test of
.IF (GetSeg(SymbolName) = HUB)
..
.ELSIF (GetSeg(SymbolName) = COG)
..
.ENDIF
and the tools/linker stage could include just one, or both code expansions aka dead code removal.
Some label alias mechanism would be needed, but this could give smallest-possible memory footprints, and a general ASM library coding style.
* eg For those wanting run-time decisions, that Assembler directive GetSeg() could be used to load address upper bits, to be run-time checked.
Ok, so we're looking for a 1:1 on directives for checking and substitution. That is indeed simpler, and would provide less of path for instruction substitution and insertion which may by classified as 'interesting, WHAT!" One does indeed need to consider the task for x86 ASM coder, though if it were accomplished by another task which was launched, perhaps returning line numbers and the attribute tag in another file where the memory access checking directives were detected. Then PNut could read that file, apply the tags as it reads lines, etc. That way, it could be written in a HLL to tackle advantage of a more abstract code nature. It also makes integration easy. If the memory tagger failed to launch, PNut defaults to feeding itself internally your ANY tag on every line read, similar to the current arrangment. That would work, even if not quite what you had in mind.
I understand about the abstraction level at asm level. At least if PNut provided the appropriate memory access operators itself internally the approach would be consistant, especially for people new to the Propeller, and to the P2. I think that is the direction you're going in here.
COG and LOW-HUB vars, can use the smaller immediate load.
Yes, direction is keeping it 'very much assembler' in coding and thinking, but hiding some of the kludges so the code is easier to maintain and read.
Readability is a big plus, it enables easier maintenance as it's more quickly understood.
Readability also plays in to an introduction to pasm by avoiding as many pitfalls as possible. That is something to be pursued. If the assembler is responsible for allocating memory locations for code and symbols, why does it insist on making the user play games when it has enough information to do the job. It knows when # or similar is required, it most cases it can supply it itself based on a little extra logic.
Now, can I interest you in saving pasm files in .RTF files for viewing in Windows WordPad with the correct syntax highlighting?
Um, NO!!
That's a different topic entirely, but syntax highlighting editors can often do this.
eg I see Notepad++ has plugins that export RTF and HTML, and you can add your own language highlighters to Notepad++
I find little about using WordPad as a programming editor entertaining.
(Wait, should there be another smiley some place in there?)