Shop OBEX P1 Docs P2 Docs Learn Events
Making PropGCC programs more OS friendly - Page 3 — Parallax Forums

Making PropGCC programs more OS friendly

13»

Comments

  • ctwardellctwardell Posts: 1,716
    edited 2012-05-03 14:57
    OK...

    I made the changes based on Dave's explaination of the ldwa instruction. It works as expected and the DBASE value is getting passed as PAR. This is good.

    However, I'm thinking that using __hub_end to drive DBASE in this case may not be correct. I think this is an issue because while the SPIN stack grows upward, the C stack grows downward.

    So it seems the DBASE should be __hub_end + the desired stack size, or some parameter indicating the highest hub address to be used by the stack.

    C.W.
  • Dave HeinDave Hein Posts: 6,347
    edited 2012-05-03 15:37
    It seems to me that VBASE, DBASE and DCURR should just point to the the area of memory just after the end of the C program. In a normal Spin program, VBASE is equal to the size of the file. If there are no VAR variables then DBASE is VBASE+8 to account for the 8-byte stack frame. DCURR is then DBASE + 4*N, where N is the number of local stack variables. In our case, we don't use any local stack variables, and we don't even need the RESULT variable or a stack frame, so we could set VBASE = DBASE = DCURR = filesize.

    We could put a pointer to __hub_end somewhere else, such as absolute locaton $10 since we don't need a method table.
  • ctwardellctwardell Posts: 1,716
    edited 2012-05-03 17:24
    I was only thinking of DBASE in the context of what I want to happen to the value passed to PAR in the COGINIT. So the current value of DBASE is OK, it is just using that as the value passed to PAR that is an issue.

    I'm thinking it may be the most pragmatic to use a linker symbol to pass in the desired top of stack address to be passed in PAR.

    I'm going to do a test to see if I can easily set it up so that if the symbol is provided the value will be used, otherwise 0x8000 will be used.

    C.W.
  • David BetzDavid Betz Posts: 14,516
    edited 2012-05-03 18:03
    ctwardell wrote: »
    I was only thinking of DBASE in the context of what I want to happen to the value passed to PAR in the COGINIT. So the current value of DBASE is OK, it is just using that as the value passed to PAR that is an issue.

    I'm thinking it may be the most pragmatic to use a linker symbol to pass in the desired top of stack address to be passed in PAR.

    I'm going to do a test to see if I can easily set it up so that if the symbol is provided the value will be used, otherwise 0x8000 will be used.

    C.W.
    Okay, this is probably a dumb question but does the Spin stack grow up in memory or down?
  • jazzedjazzed Posts: 11,803
    edited 2012-05-03 18:34
    David Betz wrote: »
    Okay, this is probably a dumb question but does the Spin stack grow up in memory or down?

    It starts at the end of the VAR section and grows up. That is, the stack index increases for push and decreases for pop.
  • ctwardellctwardell Posts: 1,716
    edited 2012-05-03 18:36
    David Betz wrote: »
    Okay, this is probably a dumb question but does the Spin stack grow up in memory or down?

    AFAIK Spin grows up, while the LMM C programs grow down.

    That is why __hub_end = ADDR(.hub) + SIZEOF(.hub) which keeps any use of the Spin stack during load from clobbering the tail end of the LMM code.

    While the stack used by LMM must grow down, otherwise we couldn't normally put it at the top of the HUB.

    C.W.
  • ctwardellctwardell Posts: 1,716
    edited 2012-05-03 18:39
    Does anyone know if the .ifdef .else .endif construct works for the PropGCC version of GAS?

    I'm not getting any exceptions, but I'm also not having much luck getting the end results I'm looking for.

    Thanks,

    C.W.
  • Dave HeinDave Hein Posts: 6,347
    edited 2012-05-03 19:10
    I was confused about the value of __hub_end. It does represent the end of the C code, and it matches the file size. So the values in the Spin header look fine.

    C.W., your ideas about using a linker symbol to override the stack value sounds good. I recall seeing other symbols with default values that can be overridden by the linker.
  • ctwardellctwardell Posts: 1,716
    edited 2012-05-03 19:24
    Dave Hein wrote: »
    I was confused about the value of __hub_end. It does represent the end of the C code, and it matches the file size. So the values in the Spin header look fine.

    C.W., your ideas about using a linker symbol to override the stack value sounds good. I recall seeing other symbols with default values that can be overridden by the linker.

    I was hoping I could test for a linker symbol using .ifdef, but it looks like linker symbols aren't testable that way.

    I was trying something like this, but it always used the 0x8000 value for the stack even when I added -Xlinker --defsym -Xlinker __stack_end=0x7f00 to the command line.
    	.byte 0x3F		' Register op $1E9 Read - cogid
    	.byte 0x89
    	.byte 0xc7		' memory op: push PBASE + next byte
    	.byte 0x10
    	.byte 0x39		' load PAR with Stack address
    	.ifdef __stack_end
    		.word __stack_end
    	.else	
    		.byte 0x80
    		.byte 0x00
    	.endif
    		.byte 0x2C		' CogInit(Id, Addr, Ptr)
    
    



    It looks to me like we would need to define a symbol, say __stack_end, set to 0x8000 in all the loader scripts, and then override it with the command line when a different value is needed, that way no testing would be required.

    C.W.
  • jazzedjazzed Posts: 11,803
    edited 2012-05-03 20:10
    ctwardell wrote: »
    Does anyone know if the .ifdef .else .endif construct works for the PropGCC version of GAS?I'm not getting any exceptions, but I'm also not having much luck getting the end results I'm looking for.Thanks,C.W.

    Here is a GAS pdf that may help. The Propeller section 9.30 is incomplete though.

    Dave would you be able to help fill in the TODOs there ?
    Bill knows this stuff but he's vacationing again.

    Thanks,
    --Steve
  • ersmithersmith Posts: 6,097
    edited 2012-05-04 10:06
    gas can't test linker symbols in a .ifdef (the linker and gas are separate programs).

    I think you can use a weak symbol definition for __stack_end; something like:
        .weak __stack_end
    __stack_end = 0x8000
    
    That way __stack_end can be redefined on the command line (or in a library), but if no definition is provided elsewhere the definition in the file is used.

    Eric
  • Dave HeinDave Hein Posts: 6,347
    edited 2012-05-04 10:53
    C.W., you should use the opcode 0x3A instead of 0x39. 0x39 just loads the next byte. 0x3A will load a word from the next two bytes. The Spin boot code will look like this:
    	.byte 0x3F		' Register op $1E9 Read - cogid
    	.byte 0x89
    	.byte 0xc7		' memory op: push PBASE + next byte
    	.byte 0x10
    	.byte 0x3A		' load PAR with Stack address
    	.word __stack_end
    	.byte 0x2C		' CogInit(Id, Addr, Ptr)
    
    Spin doesn't require the 2 bytes after 0x3A to be word aligned, but the GAS does, so you will need to start the spin boot code at address 0x17 instead of 0x18. This is OK since we don't need the method table. Change PCURR in the header from 0x0018 to 0x0017, and change the .word at 0x16 to .byte.
  • ctwardellctwardell Posts: 1,716
    edited 2012-05-04 11:19
    Dave Hein wrote: »
    C.W., you should use the opcode 0x3A instead of 0x39. 0x39 just loads the next byte. 0x3A will load a word from the next two bytes. The Spin boot code will look like this:
    	.byte 0x3F		' Register op $1E9 Read - cogid
    	.byte 0x89
    	.byte 0xc7		' memory op: push PBASE + next byte
    	.byte 0x10
    	.byte 0x3A		' load PAR with Stack address
    	.word __stack_end
    	.byte 0x2C		' CogInit(Id, Addr, Ptr)
    
    Spin doesn't require the 2 bytes after 0x3A to be word aligned, but the GAS does, so you will need to start the spin boot code at address 0x17 instead of 0x18. This is OK since we don't need the method table. Change PCURR in the header from 0x0018 to 0x0017, and change the .word at 0x16 to .byte.

    I think 0x39 is actually the correct opcode, your spasm document shows 0x3A as reading the next 3 bytes.

    One thing I have noticed is the order seems to be an issue. If I set __stack_end to 0x8000, the LMM app fails, if I set it to 0x0080 it runs and reports the proper value in PAR.

    Just for grins I tried:

    .byte 0x39
    .byte 0x00
    .byte 0x80

    This runs and reports the proper stack end value.

    I appreciate everyones help and patience.

    C.W.

    UPDATE: I've made a work around, but until I solve the next issue of being able to externally change the value of __stack_end there isn't much point in showing it, unless someone thinks it would be helpful.
  • ctwardellctwardell Posts: 1,716
    edited 2012-05-04 12:05
    ersmith wrote: »
    gas can't test linker symbols in a .ifdef (the linker and gas are separate programs).

    I think you can use a weak symbol definition for __stack_end; something like:
        .weak __stack_end
    __stack_end = 0x8000
    
    That way __stack_end can be redefined on the command line (or in a library), but if no definition is provided elsewhere the definition in the file is used.

    Eric

    Thanks Eric.

    I've got it declared this way now in spinboot.s and whatever value I set it to directly is being properly used, but I have not had any success overriding it from the command line.

    I've tried:

    -D__stack_end=0x7F00 as part of the command line

    and

    DEFINE __stack_end 0x7F00 in my C source file

    I tried removing one and both of the leading underscores as well, just for fun...

    C.W.
  • David BetzDavid Betz Posts: 14,516
    edited 2012-05-04 12:28
    The propeller-elf-ld help text gives this way of defining a symbol on the linker command line:

    --defsym SYMBOL=EXPRESSION Define a symbol

    However, because you're probably invoking the linker indirectly from propeller-elf-gcc, you'll need to use this syntax:

    -Wl,--defsym SYMBOL=EXPRESSION Define a symbol

    The -Wl, prefix says to pass the option on to the linker.
  • ctwardellctwardell Posts: 1,716
    edited 2012-05-04 12:41
    David Betz wrote: »
    The propeller-elf-ld help text gives this way of defining a symbol on the linker command line:

    --defsym SYMBOL=EXPRESSION Define a symbol

    However, because you're probably invoking the linker indirectly from propeller-elf-gcc, you'll need to use this syntax:

    -Wl,--defsym SYMBOL=EXPRESSION Define a symbol

    The -Wl, prefix says to pass the option on to the linker.

    I couldn't get that syntax to work, I did get this one to work:

    -Xlinker --defsym -Xlinker __stack_end=0x6F00

    I've found that I can pass in the stack end value this way, but I always have to pass it.

    Putting

    .weak __stack_end
    __stack_end=0x8000

    in spinboot.s prevents it from being overridden, but without it, there is no default value.

    So I think that

    .weak __stack_end
    __stack_end=0x8000

    needs to be placed in a different file than spinboot.s.

    The saga continues...

    Thanks,

    C.W.
  • David BetzDavid Betz Posts: 14,516
    edited 2012-05-04 12:47
    ctwardell wrote: »
    I couldn't get that syntax to work, I did get this one to work:

    -Xlinker --defsym -Xlinker __stack_end=0x6F00

    I've found that I can pass in the stack end value this way, but I always have to pass it.

    Putting

    .weak __stack_end
    __stack_end=0x8000

    in spinboot.s prevents it from being overridden, but without it, there is no default value.

    So I think that

    .weak __stack_end
    __stack_end=0x8000

    needs to be placed in a different file than spinboot.s.

    The saga continues...

    Thanks,

    C.W.
    Ah yes, I forgot that -Wl, won't work with options that have spaces in them like this one. Glad you found something that worked for defining symbols. Let us know if it works to move that weak definition to another file.
  • ctwardellctwardell Posts: 1,716
    edited 2012-05-04 13:02
    I have it working the way it should as far as I can tell, I'll let you gurus determine if it is a reasonable solution.

    What I have:

    In crt0_lmm.s I added the __stack_end default right after the line .global __LMM_entry:
    	.global __LMM_entry
    
    	.weak __stack_end
    	__stack_end=0x8000
    	
    __LMM_entry
    

    I made the changes noted below to spinboot.s

    Comments are ADDED and CHANGED
    	''
    	'' code to set up the Propeller chip to run C
    	''
    	'' the checksum byte should be chosen so that the sum
    	'' of all the bytes in the file is 0x14 ; this actually
    	'' means all the bytes in RAM add to 0, since the
    	'' loader automatically puts the bytes
    	'' 0xFF, 0xFF, 0xF9, 0xFF, 0xFF, 0xFF, 0xF9, 0xFF
    	'' on the stack at startup (this is a spin jump to 0xFFF9,
    	'' which in the ROM has a stop routine)
    	''
    	.section .boot, "ax", @progbits
    	.global __clkfreq
    	.global __clkmode
    	.extern __hub_end
    	.extern __stack_end  'ADDED 
    	
    start
    __clkfreq
    	.long __clkfreqval	' clock frequency
    __clkmode
    	.byte __clkmodeval	' clock mode
    chksum	.byte 0x00		' checksum: see above
    
    	.word 0x0010		' PBASE
    	.global __sys_mbox	' added 20/09/11 for debugger/system support (WH)
    __sys_mbox
    '	.word 0x7fe8		' VBASE - start of variables
    	.word __hub_end		' VBASE - start of variables
    '	.word 0x7ff0		' DBASE - start of stack 
    	.word __hub_end+8	' DBASE - start of stack 
    	.word 0x0018		' PCURR - initial program counter
    '	.word 0x7ff8		' DCURR - initial stack pointer
    	.word __hub_end+12	' DCURR - initial stack pointer
    pbase
    	'' 8 byte header
    	.word 0x0008		' length of object ?
    	.byte 0x02		' number of methods ?
    	.byte 0x00		' number of objects ?
    	.word 0x0008		' pcurr - 0x10?
    	.word __stack_end    ' CHANGED, a few of you said this spot wasn't being used, so I used it to store __stack_end
    
    	'' here is the spin code to switch to pasm mode
    	'' removed a load of the constant 0 and replaced it with cogid
    	.byte 0x3F		' Register op $1E9 Read - cogid
    	.byte 0x89
    	.byte 0xc7		' memory op: push PBASE + next byte
    	.byte 0x10
    	.byte 0xA4		' CHANGED, push the word at OBJ offset
    	.byte 6			' CHANGED, offset = 6, the __stack_end value
    	.byte 0x2C		' CogInit(Id, Addr, Ptr)
    	.byte 0x32		' Return (unused)
    
    '' here is where the pasm code actually goes
    
    

    I used the storage spot for __stack_end because when I tried a direct push using the 0x39 opcode the byte order was being reversed.

    This has worked in my tests so far.

    If I don't override __stack_end it uses the 0x8000 default value, otherwise it uses the value of the override.

    I use the following to override:

    -Xlinker --defsym -Xlinker __stack_end=0x7F00

    I'm entering it as a Compile Option in SimpleIDE.

    Thanks for all the help.

    Chris Wardell

    Edit: Here is my update source:

    stack_end.zip
  • ctwardellctwardell Posts: 1,716
    edited 2012-05-04 13:31
    I've been thinking that crt0_lmm.s probably isn't the most appropriate place to define the default __stack_end, because if anyone ever wanted to make a change to crt0_lmm that actually used the value it would never any override value.

    Do any of you guys know of a file that is always loaded, that might be more appropriate?

    Thanks,

    C.W.
  • Dave HeinDave Hein Posts: 6,347
    edited 2012-05-04 20:00
    C.W., You were right about the 0x39 opcode. I was using a C version of my Spasm assembler to assemble snippets of code, and it was generating the wrong bytecode. I tried it on the Spin version of the Spasm assembler that runs under Spinix, and it produced the correct bytecode. The problem with using the LDWI instruction is that the value that follows is in big-endian order. Of course, ".word __stack_end" will be stored in little-endian order. Your solution that uses LDWO (bytecode $A4) is a better solution.
  • David BetzDavid Betz Posts: 14,516
    edited 2012-05-05 05:29
    ctwardell wrote: »
    I have it working the way it should as far as I can tell, I'll let you gurus determine if it is a reasonable solution.

    What I have:

    In crt0_lmm.s I added the __stack_end default right after the line .global __LMM_entry:
    	.global __LMM_entry
    
    	.weak __stack_end
    	__stack_end=0x8000
    	
    __LMM_entry
    

    I made the changes noted below to spinboot.s

    Comments are ADDED and CHANGED
    	''
    	'' code to set up the Propeller chip to run C
    	''
    	'' the checksum byte should be chosen so that the sum
    	'' of all the bytes in the file is 0x14 ; this actually
    	'' means all the bytes in RAM add to 0, since the
    	'' loader automatically puts the bytes
    	'' 0xFF, 0xFF, 0xF9, 0xFF, 0xFF, 0xFF, 0xF9, 0xFF
    	'' on the stack at startup (this is a spin jump to 0xFFF9,
    	'' which in the ROM has a stop routine)
    	''
    	.section .boot, "ax", @progbits
    	.global __clkfreq
    	.global __clkmode
    	.extern __hub_end
    	.extern __stack_end  'ADDED 
    	
    start
    __clkfreq
    	.long __clkfreqval	' clock frequency
    __clkmode
    	.byte __clkmodeval	' clock mode
    chksum	.byte 0x00		' checksum: see above
    
    	.word 0x0010		' PBASE
    	.global __sys_mbox	' added 20/09/11 for debugger/system support (WH)
    __sys_mbox
    '	.word 0x7fe8		' VBASE - start of variables
    	.word __hub_end		' VBASE - start of variables
    '	.word 0x7ff0		' DBASE - start of stack 
    	.word __hub_end+8	' DBASE - start of stack 
    	.word 0x0018		' PCURR - initial program counter
    '	.word 0x7ff8		' DCURR - initial stack pointer
    	.word __hub_end+12	' DCURR - initial stack pointer
    pbase
    	'' 8 byte header
    	.word 0x0008		' length of object ?
    	.byte 0x02		' number of methods ?
    	.byte 0x00		' number of objects ?
    	.word 0x0008		' pcurr - 0x10?
    	.word __stack_end    ' CHANGED, a few of you said this spot wasn't being used, so I used it to store __stack_end
    
    	'' here is the spin code to switch to pasm mode
    	'' removed a load of the constant 0 and replaced it with cogid
    	.byte 0x3F		' Register op $1E9 Read - cogid
    	.byte 0x89
    	.byte 0xc7		' memory op: push PBASE + next byte
    	.byte 0x10
    	.byte 0xA4		' CHANGED, push the word at OBJ offset
    	.byte 6			' CHANGED, offset = 6, the __stack_end value
    	.byte 0x2C		' CogInit(Id, Addr, Ptr)
    	.byte 0x32		' Return (unused)
    
    '' here is where the pasm code actually goes
    
    

    I used the storage spot for __stack_end because when I tried a direct push using the 0x39 opcode the byte order was being reversed.

    This has worked in my tests so far.

    If I don't override __stack_end it uses the 0x8000 default value, otherwise it uses the value of the override.

    I use the following to override:

    -Xlinker --defsym -Xlinker __stack_end=0x7F00

    I'm entering it as a Compile Option in SimpleIDE.

    Thanks for all the help.

    Chris Wardell

    Edit: Here is my update source:

    stack_end.zip

    Hi Chris,

    I made your proposed changes to spinboot.s and it seems to work. The only thing I changed was to put the weak definition of __stack_end in the default linker script rather than in crt0_lmm.s. I got the following results to my test. I'll make this an official change to propgcc once I get permission to check in another set of changes I've been working on to improve malloc heap handling in xmm mode. Oh, and I'll also have to do something similar for xmm and xmmc modes.

    Thanks for your work on this and to everyone else who contributed!

    David

    Test program:
    #include <stdio.h>
    int main(void)
    {
        int foo;
        printf("foo %08x\n", (int)&foo);
        return 0;
    }
    

    Results without overriding __stack_end:
    david-betzs-macbook-pro:malloc_test dbetz$ propeller-elf-gcc -Os -o stack.elf stack.c
    david-betzs-macbook-pro:malloc_test dbetz$ propeller-load stack.elf -r -t
    Propeller Version 1 on /dev/cu.usbserial-A8004ILf
    Loading stack.elf to hub memory
    13564 bytes sent                  
    Verifying RAM ... OK
    [ Entering terminal mode. Type ESC or Control-C to exit. ]
    foo 00007ff8
    

    Results overriding __stack_end on the command line:
    david-betzs-macbook-pro:malloc_test dbetz$ propeller-elf-gcc -Os -Wl,--defsym,__stack_end=0x7000 -o stack.elf stack.c
    david-betzs-macbook-pro:malloc_test dbetz$ propeller-load stack.elf -r -t
    Propeller Version 1 on /dev/cu.usbserial-A8004ILf
    Loading stack.elf to hub memory
    13564 bytes sent                  
    Verifying RAM ... OK
    [ Entering terminal mode. Type ESC or Control-C to exit. ]
    foo 00006ff8
    
  • ctwardellctwardell Posts: 1,716
    edited 2012-05-05 08:27
    Thanks David, having the definition in the linker script sounds much better than having it in any of the object files.

    Thanks again to everyone for there help and patience.

    Chris Wardell
  • jazzedjazzed Posts: 11,803
    edited 2012-05-08 11:25
    ctwardell wrote: »
    Thanks David, having the definition in the linker script sounds much better than having it in any of the object files.

    Thanks again to everyone for there help and patience.

    Chris Wardell

    C.W. The latest SimpleIDE v0-6-10 package includes the propeller-gcc toolchain that supports __stack_end.

    Thanks for your effort!
    --Steve
  • ctwardellctwardell Posts: 1,716
    edited 2012-05-08 12:11
    jazzed wrote: »
    C.W. The latest SimpleIDE v0-6-10 package includes the propeller-gcc toolchain that supports __stack_end.

    Thanks for your effort!
    --Steve

    Thanks Steve, I just tried it out and it is working well.

    Hopefully I can use SimpleIDE and PropGCC to build some success stories.

    C.W.
Sign In or Register to comment.