![]() |
Forum Index : Microcontroller and PC projects : CMM2: armcfgenv143 generating hex outside of the CSUB
Author | Message | ||||
thwill![]() Guru ![]() Joined: 16/09/2019 Location: United KingdomPosts: 4311 |
Hi folks, Hoping there is some kind soul who knows something about the lower levels of armcfgenv143, .elf, etc. When I run armcfgenv143 against the attached forth_cmm2.zip using the "merge" strategy it generates: 'File forth_cmm2.bas written 12-03-2021 10:45:26 E9D06A02 B410130C 1D143304 60116204 4B04F85D 47706303 CSUB forth_cmm2.bas 000018C8 'util_memset B2C9B342 1E54B510 D9242C02 0C00F04F 0E03F022 F3614603 44860C07 2C0FF361 4C17F361 6C1FF361 CB04F843 D1FB4573 0303F022 EBA4429A EB000403 D0080C03 1000F88C 2C01B12C 1001F88C F88CBF18 BD101002 46844770 BF00E7F2 'util_strcpy F8111E42 F8023B01 2B003F01 4770D1F9 etc ... Now that isn't going to work because there is "code" outside the CSUB. Not with much expectation I tried the naive approaches of commenting the offending lines out or moving it down to the start of the CSUB but as expected neither produced working code. Does anyone have any ideas ? If I have to "deep dive" on this myself then I may never resurface. Best wishes, Tom Edited 2021-03-12 20:53 by thwill MMBasic for Linux, Game*Mite, CMM2 Welcome Tape, Creaky old text adventures |
||||
jirsoft![]() Guru ![]() Joined: 18/09/2020 Location: Czech RepublicPosts: 533 |
Hi Tom, I'm generating CSUB from ELF with ELF2CSUB, so I can check it at evening... Jiri Napoleon Commander and SimplEd for CMM2 (GitHub), CMM2.fun |
||||
matherp Guru ![]() Joined: 11/12/2012 Location: United KingdomPosts: 10310 |
Looking at the BAS code I would suspect something like a symbol name > 31 chars There is a corruption in the header print - should be PRINT #2,"'File "+cname$+" "+DATE$+" "+Time$ Also, please post the map file Edited 2021-03-12 21:24 by matherp |
||||
epsilon![]() Senior Member ![]() Joined: 30/07/2020 Location: BelgiumPosts: 255 |
I think this happens when you have symbols such as globals outside of a function context. E.g. this: #include "ARMCFunctions.h" volatile int globalInt=0; //<-- the offenders volatile char globalc=' '; void p_int(int a,int base){ char b[64]; IntToStr(b,a,base); MMPrintString(b); } static void foo(void) { putConsole('*'); putConsole('\r'); putConsole('\n'); } void main(long long int *c, MMFLOAT *b){ ++globalInt; ++globalc; putConsole('a'); putConsole('\r'); putConsole('\n'); foo(); putConsole('b'); putConsole('\r'); putConsole('\n'); void (* volatile fptr)(void); putConsole('c'); putConsole('\r'); putConsole('\n'); fptr = (void (* volatile)(void)) &foo; // <--- hangs here, how is that even possible? fptr(); putConsole('d'); putConsole('\r'); putConsole('\n'); } produces: 'File tomstest.bas 0+DATE$++Time$ 4C06B510 6823202A 68234798 4798200D 200A6823 4010E8BD BF004718 080002A4 CSUB tomstest.bas 00000012 'p_int B094B510 46024C06 A80417C3 68219100 47889003 98034B03 4798681B BD10B014 080002C4 080002C0 'main 20614B23 447B4923 B5304A23 B083585D 68294C1E 60293101 7813589A B2DB3301 68237013 68234798 4798200D 200A6823 68234798 4798202A 200D6823 68234798 4798200A 20626823 68234798 4798200D 200A6823 68234798 47982063 200D6823 68234798 4798200A 447B4B0C 9B019301 68234798 47982064 200D6823 68234798 B003200A 4030E8BD BF004718 080002A4 17FFFFB2 00000000 00000004 FFFFFF4B End CSUB Epsilon CMM2 projects |
||||
matherp Guru ![]() Joined: 11/12/2012 Location: United KingdomPosts: 10310 |
That makes sense as they would go into a psect that isn't catered for and probably can't be. Probably .bss or .data Tom: if you need global variables then use CFuncRam - you have 128 bytes available that won't be changed by anything in MMbasic Edited 2021-03-12 22:03 by matherp |
||||
thwill![]() Guru ![]() Joined: 16/09/2019 Location: United KingdomPosts: 4311 |
I agree it makes sense, but I'm not explicitly using any globals, it's all pure functions. It's happening when I blindly flag all the functions as static so that the compiler will inline them. Will follow up later - sorry for sending fire & forget questions, just trying to use a day off to investigate the optimisation possibilities for spforth. Best wishes, Tom MMBasic for Linux, Game*Mite, CMM2 Welcome Tape, Creaky old text adventures |
||||
matherp Guru ![]() Joined: 11/12/2012 Location: United KingdomPosts: 10310 |
Static doesn't necessarily imply inline, merely that the scope of the function is local to the file. In general inline is a disaster, not sure why, but if I force inline the code often runs slower. The H series chips have very clever caching and trying to outguess both the chip and the compiler nearly always ends in failure. Likewise it is VERY difficult to beat the compiler by writing you own assembler Back to the problem: the map is the key - you need to see what has been put into a psect other than .text or .rodata. Those are the only two that are supported Edited 2021-03-12 22:15 by matherp |
||||
thwill![]() Guru ![]() Joined: 16/09/2019 Location: United KingdomPosts: 4311 |
Thanks Peter, I'm aware of the broader meaning of "static", but I believe if you don't mark a function as static then gcc won't inline it (or will also compile a non-inlined copy) because it believes it might need to be called from elsewhere. > Likewise it is VERY difficult to beat the compiler by writing you own assembler I understand that is the conventional wisdom, I don't have the experience to gainsay it, but that doesn't mean I may not experiment in the future. At the moment after the early gains I reported I'm finding spforth very stubborn to optimise- the Forth words I believed I could inline all turn out to be compile time words so don't impact execution speed. I'm sure a Forth should be able to do better than x1.5 a BASIC, but perhaps that belief is based on old non-tokenised BASICs that weren't doing things like hash-table variable lookups. > Back to the problem: the map is the key ... How do I generate "the map"? Best wishes, Tom Edited 2021-03-12 22:30 by thwill MMBasic for Linux, Game*Mite, CMM2 Welcome Tape, Creaky old text adventures |
||||
matherp Guru ![]() Joined: 11/12/2012 Location: United KingdomPosts: 10310 |
Are you using any STATIC variables? - they will go into .bss for a map file add "-Map output.map " or similar to the link command Edited 2021-03-12 22:37 by matherp |
||||
thwill![]() Guru ![]() Joined: 16/09/2019 Location: United KingdomPosts: 4311 |
Not explicitly, though I can't speak for what the compiler is doing ![]() Thanks, is it helpful ? Memory Configuration Name Origin Length Attributes rom 0x08000000 0x00100000 xr ram 0x20000000 0x00020000 xrw ram1 0x10000000 0x00010000 xrw *default* 0x00000000 0xffffffff Linker script and memory map 0x20020000 _eram = 0x20020000 .text 0x08000000 0x72eb *(.isr_vector) *(.text*) .text 0x08000000 0x0 forth_cmm2.o .text.forth_docol 0x08000000 0x18 forth_cmm2.o .text.util_memset 0x08000018 0x5c forth_cmm2.o 0x08000018 util_memset .text.util_strcpy 0x08000074 0x10 forth_cmm2.o 0x08000074 util_strcpy .text.util_strncpy 0x08000084 0x70 forth_cmm2.o 0x08000084 util_strncpy .text.util_strlen 0x080000f4 0x18 forth_cmm2.o 0x080000f4 util_strlen .text.forth_word_internal 0x0800010c 0x1a0 forth_cmm2.o 0x0800010c forth_word_internal .text.forth_number_internal 0x080002ac 0x8c forth_cmm2.o 0x080002ac forth_number_internal .text.forth_find_internal 0x08000338 0x74 forth_cmm2.o 0x08000338 forth_find_internal .text.forth_tcfa_internal 0x080003ac 0x8 forth_cmm2.o 0x080003ac forth_tcfa_internal .text.forth_create_internal 0x080003b4 0x15c forth_cmm2.o 0x080003b4 forth_create_internal .text.forth_comma_internal 0x08000510 0xc forth_cmm2.o 0x08000510 forth_comma_internal .text.forth_tell_internal 0x0800051c 0x2c forth_cmm2.o 0x0800051c forth_tell_internal .text.forth_parse_error 0x08000548 0x8c forth_cmm2.o 0x08000548 forth_parse_error .text.forth_udot_internal 0x080005d4 0x78 forth_cmm2.o 0x080005d4 forth_udot_internal .text.forth_execute_internal 0x0800064c 0x90c forth_cmm2.o 0x0800064c forth_execute_internal .text.forth_add_builtin 0x08000f58 0x48 forth_cmm2.o 0x08000f58 forth_add_builtin .text.forth_add_codeword 0x08000fa0 0x1c forth_cmm2.o 0x08000fa0 forth_add_codeword .text.forth_add_builtins 0x08000fbc 0xca8 forth_cmm2.o .text.forth_init 0x08001c64 0x48 forth_cmm2.o 0x08001c64 forth_init .text.forth_init_run 0x08001cac 0x38 forth_cmm2.o 0x08001cac forth_init_run .text.forth_run_internal 0x08001ce4 0xe8 forth_cmm2.o 0x08001ce4 forth_run_internal .text.forth_run 0x08001dcc 0x8 forth_cmm2.o 0x08001dcc forth_run .text.forth_run_string 0x08001dd4 0x3c forth_cmm2.o 0x08001dd4 forth_run_string .text.forth_add_extended_words 0x08001e10 0x4510 forth_cmm2.o 0x08001e10 forth_add_extended_words .text.startup.main 0x08006320 0x30 forth_cmm2.o 0x08006320 main *(.init) *(.fini) *crtbegin.o(.ctors) *crtbegin?.o(.ctors) *(EXCLUDE_FILE(*crtend.o *crtend?.o) .ctors) *(SORT_BY_NAME(.ctors.*)) *(.ctors) *crtbegin.o(.dtors) *crtbegin?.o(.dtors) *(EXCLUDE_FILE(*crtend.o *crtend?.o) .dtors) *(SORT_BY_NAME(.dtors.*)) *(.dtors) *(.rodata*) .rodata.str1.4 0x08006350 0xf9b forth_cmm2.o 0xff3 (size before relaxing) *(.eh_fram e*) .glue_7 0x080072ec 0x0 .glue_7 0x080072ec 0x0 linker stubs .glue_7t 0x080072ec 0x0 .glue_7t 0x080072ec 0x0 linker stubs .vfp11_veneer 0x080072ec 0x0 .vfp11_veneer 0x080072ec 0x0 linker stubs .v4_bx 0x080072ec 0x0 .v4_bx 0x080072ec 0x0 linker stubs .iplt 0x080072ec 0x0 .iplt 0x080072ec 0x0 forth_cmm2.o .rel.dyn 0x080072ec 0x0 .rel.iplt 0x080072ec 0x0 forth_cmm2.o .ARM.extab *(.ARM.extab* .gnu.linkonce.armextab.*) 0x080072eb __exidx_start = . .ARM.exidx *(.ARM.exidx* .gnu.linkonce.armexidx.*) 0x080072eb __exidx_end = . 0x080072eb __etext = . 0x080072eb _sidata = __etext .data 0x20000000 0x0 load address 0x080072eb 0x20000000 __data_start__ = . 0x20000000 _sdata = __data_start__ *(vtable) *(.data*) .data 0x20000000 0x0 forth_cmm2.o 0x20000000 . = ALIGN (0x4) [!provide] PROVIDE (__preinit_array_start = .) *(.preinit_array) [!provide] PROVIDE (__preinit_array_end = .) 0x20000000 . = ALIGN (0x4) [!provide] PROVIDE (__init_array_start = .) *(SORT_BY_NAME(.init_array.*)) *(.init_array) [!provide] PROVIDE (__init_array_end = .) 0x20000000 . = ALIGN (0x4) [!provide] PROVIDE (__fini_array_start = .) *(SORT_BY_NAME(.fini_array.*)) *(.fini_array) [!provide] PROVIDE (__fini_array_end = .) *(.jcr*) 0x20000000 . = ALIGN (0x4) 0x20000000 __data_end__ = . 0x20000000 _edata = __data_end__ .igot.plt 0x20000000 0x0 load address 0x080072ec .igot.plt 0x20000000 0x0 forth_cmm2.o .bss 0x20000000 0x40 load address 0x080072f0 0x20000000 . = ALIGN (0x4) 0x20000000 __bss_start__ = . 0x20000000 _sbss = __bss_start__ *(.bss*) .bss 0x20000000 0x40 forth_cmm2.o 0x20000000 val *(COMMON) 0x20000040 . = ALIGN (0x4) 0x20000040 __bss_end__ = . 0x20000040 _ebss = __bss_end__ .heap 0x20000040 0x0 0x20000040 __end__ = . 0x20000040 _end = __end__ 0x20000040 end = __end__ *(.heap*) 0x20000040 __HeapLimit = . .co_stack 0x20000040 0x0 0x20000040 . = ALIGN (0x8) *(.co_stack .co_stack.*) 0x20020000 __StackTop = (ORIGIN (ram) + LENGTH (ram)) 0x20020000 __StackLimit = (__StackTop - SIZEOF (.co_stack)) [!provide] PROVIDE (__stack = __StackTop) 0x00000001 ASSERT ((__StackLimit >= __HeapLimit), region ram overflowed with stack) LOAD forth_cmm2.o OUTPUT(forth_cmm2.elf elf32-littlearm) LOAD linker stubs .comment 0x00000000 0x4d .comment 0x00000000 0x4d forth_cmm2.o 0x4e (size before relaxing) .ARM.attributes 0x00000000 0x32 .ARM.attributes 0x00000000 0x32 forth_cmm2.o Best wishes, Tom MMBasic for Linux, Game*Mite, CMM2 Welcome Tape, Creaky old text adventures |
||||
matherp Guru ![]() Joined: 11/12/2012 Location: United KingdomPosts: 10310 |
There appears to be a variable val in .bss that is 64 bytes long. Are you doing something like: char val[64]={something}; |
||||
thwill![]() Guru ![]() Joined: 16/09/2019 Location: United KingdomPosts: 4311 |
The only 'val' in the codebase is the name of a function parameter and that's a 4 byte value. Could the compiler/optimiser be adding it for some reason? the garbage isn't present at -O0 but starts to appear at -O1 -O2 and -O3. Aside: I think I have a suspicion about my performance problems, the main instruction dispatch loop is a huge case statement: switch (x) { case 1 : drop(); break; case 2 : dup(); break; case 3 : save(); break; case 4 : over(); break; ... } though the numbers are #defined. I don't think the optimiser is doing anything special with this. Switching to an enum should cause the optimiser to use a branch table or binary search. I think the former, because I suspect it is storing function pointers in such a table, which of course aren't working ![]() ![]() ![]() Anyway that's me done until this evening, thanks for your help, Tom MMBasic for Linux, Game*Mite, CMM2 Welcome Tape, Creaky old text adventures |
||||
matherp Guru ![]() Joined: 11/12/2012 Location: United KingdomPosts: 10310 |
Is val related to a switch statement? Could be a jump table that is being created in .bss? Can I assume there is nothing in .bss when you use O0? i.e.bss is zero length .bss 0x20000000 0x40 load address 0x080072f0 0x20000000 . = ALIGN (0x4) 0x20000000 __bss_start__ = . 0x20000000 _sbss = __bss_start__ *(.bss*) .bss 0x20000000 0x40 forth_cmm2.o 0x20000000 val *(COMMON) 0x20000040 . = ALIGN (0x4) 0x20000040 __bss_end__ = . 0x20000040 _ebss = __bss_end__ In any event you need to play with the code until .bss is zero length Edited 2021-03-13 03:55 by matherp |
||||
GerryL Newbie ![]() Joined: 24/01/2019 Location: AustraliaPosts: 39 |
Hi Tom, just as an aside is your function "forth_add_codeword" pretty small (about 26 bytes long) or really large (approx 3200 bytes)? Gerry |
||||
thwill![]() Guru ![]() Joined: 16/09/2019 Location: United KingdomPosts: 4311 |
Pretty small: void forth_add_codeword(forth_t *self, char *name) { dictionary_entry_t *pentry = forth_find_internal(self, name, -1); forth_comma_internal(self, (cell_t) &pentry->codeword); } Best wishes, Tom MMBasic for Linux, Game*Mite, CMM2 Welcome Tape, Creaky old text adventures |
||||
GerryL Newbie ![]() Joined: 24/01/2019 Location: AustraliaPosts: 39 |
I note that even with the following code the .bss size in the ELF file is 0x40 so just wonder if it defaults to that, in fact with a number of my C functions its 0x40. #include "ARMCFunctions.h" void main(long long int *c, MMFLOAT *b){ *c = 20; *b = 20.0; } Gerry |
||||
![]() |
![]() |
The Back Shed's forum code is written, and hosted, in Australia. | © JAQ Software 2025 |