alekmaul/pvsneslib

.data section broken when used for code

darkain opened this issue · 4 comments

I'll preface this by saying, yes, I'm doing something highly non-standard in the SNES area. I'm working with some highly specialized custom hardware, and this is a technique common on microcontrollers.

I need to be able to run a chunk of code from RAM instead of ROM because at a certain point in time, the ROM becomes unavailable.

A very basic example looks like as follows:

void test(void) __attribute__ ((section(".data")))
{
    bgSetDisable(2);
    consoleDrawText(1, 17, "Super Test");
}

Now, TCC understands this properly, and knows to load this chunk of data from ROM to RAM on code initialization, the same as it would for predefined string variables.

The problem is, is that it looks like the linker gets highly confused by this.

The actual contents put into the ROM and then copied into RAM is literally the ASM text, rather than the assembled text into machine code as follows. This is literally the contents in RAM after initialization at location $7F0022.

I think it goes without saying... this should be machine code here, not ASM text!

.SECTION ".text_0x0" SUPERFREE

test:
; sub sp,#__test_locals
.ifgr __test_locals 0
tsa
sec
sbc #__test_locals
tas
.endif
; push1 imm r 0xf0
sep #$20
lda #2
pha
rep #$20
; call r 0x2f0
jsr.l bgSetDisable
; add sp, #1
tsa
clc
adc #1
tas
; push4 imm r 0x2f0
pea.w :tccs_L.tmpxfilec7q7rz8
pea.w tccs_L.tmpxfilec7q7rz8 + 0
; push2 imm r 0xf0
pea.w 17
; push2 imm r 0xf0
pea.w 1
; call r 0x2f0
jsr.l consoleDrawText
; add sp, #8
tsa
clc
adc #8
tas
; gsym_addr t 0 a 476 ind 476
; ERROR no jump found to patch
; add sp, #__test_locals
.ifgr __test_locals 0
tsa
clc
adc #__test_locals
tas
.endif
rtl
.ENDS
0000af6c 07t of stuff
.SECTION ".text_0x0" SUPERFREE

test:
; sub sp,#__test_locals
.ifgr __test_locals 0
tsa
sec
sbc #__test_locals
tas
.endif
; push1 imm r 0xf0
sep #$20
lda #2
pha
rep #$20
; call r 0x2f0
jsr.l bgSetDisable
; add sp, #1
tsa
clc
adc #1
tas
; push4 imm r 0x2f0
pea.w :tccs_L.tmpxfilec7q7rz8
pea.w tccs_L.tmpxfilec7q7rz8 + 0
; push2 imm r 0xf0
pea.w 17
; push2 imm r 0xf0
pea.w 1
; call r 0x2f0
jsr.l consoleDrawText
; add sp, #8
tsa
clc
adc #8
tas
; gsym_addr t 0 a 476 ind 476
; ERROR no jump found to patch
; add sp, #__test_locals
.ifgr __test_locals 0
tsa
clc
adc #__test_locals
tas
.endif
rtl
.ENDS

Hello,
Thanks for this test, it's weird but a nice test
SO, if I understand well, the problem is that
"The actual contents put into the ROM and then copied into RAM is literally the ASM text, rather than the assembled text into machine code as follows. This is literally the contents in RAM after initialization at location $7F0022."
SO the ascii code of the asm characters like that:
".SECTION ".text_0x0" SUPERFREE
test:
; sub sp,#__test_locals
.ifgr __test_locals 0
tsa"

Is it correct ?
I will do a test, i'm curious to see that ^^

YES, that's exactly it! The ASCII representation of the assembly instructions is what is put into the ROM rather than the actual machine byte code instructions. That text above was direct copy-pasted from RAM after execution initialized that section and copied its contents from ROM to RAM as seen here:

image

For reference, to repro this:

I took the Hello World example, and just added this to the top:

void test(void) __attribute__ ((section(".data")))
{
    bgSetDisable(2);
    consoleDrawText(1, 17, "Super Test");
}

And then called the test() function from inside of main(), and that's it.

That's really fantastic! I test it now :D !
I took a look and I think I know why it is like that.
It is a tcc behavior
image
AS your code is put in data section, it is interpreted as data, not code, so transformed like that in data.
I really don't know what I can do to change this behavior, we can leave this issue open but I can't share you that we will fix it.
If you're skilled in C programming, you can try to check what is done in my tcc repository and where it is transformed in data (https://github.com/alekmaul/tcc/tree/develop),