Jump to content
IGNORED

C compilers?


zezba9000

Recommended Posts

Now, I won't pretend I remember all the things we tried when we were working on browncc/brownout, but I'm sure we tried a few things with linker scripts. The results we got was that ld would crash or ignore our scripts with the back then current binutils. So instead of trying to report our issues or hope they magically fix them we just went ahead with-Ttext-segment=0 and then wrote brownout to do the rest of the work. But hey, if that linker script above works, then it's good news!

Link to comment
Share on other sites

Also, small reminder/updater: http://brownbot.mooo.comis based on Compiler Explorer and lets you see the assembly output as you type your C code immediately! Also, under the "C" section there is now the option to use a couple of ST compilers using a thin emulation layer. It's fun to sometimes see gcc producing worse code than a 90s compiler :).

Link to comment
Share on other sites

Also, small reminder/updater: http://brownbot.mooo.comis based on Compiler Explorer and lets you see the assembly output as you type your C code immediately! Also, under the "C" section there is now the option to use a couple of ST compilers using a thin emulation layer. It's fun to sometimes see gcc producing worse code than a 90s compiler :).

 

It is shocking, what horrible code gcc produces sometimes. Esp. Duff's device is a good example where C compilers reach their limit ;-)

Or where careful chosen types (unsigned instead of signed) produce much better code.

Edited by 42bs
Link to comment
Share on other sites

Here a small framework (Note: only tested for compilation, not run!):

# Makefile (make sure to replace SPACES with TABs!!)
ALL: jaggy.bin

CC=m68k-atarist-elf-gcc -mcpu=68000
LD=m68k-atarist-elf-gcc -mcpu=68000
AS=m68k-atarist-elf-gcc -mcpu=68000

OBJCOPY=m68k-atarist-elf-objcopy

CFLAGS=-g
ASFLAGS=-g -Wa,--bitwise-or,--register-prefix-optional,--gdwarf2
LDFLAGS=-nostartfiles -nostdlib -Wl,-T,jaggy.ld,-Map,jaggy.map

OBJECTS=jaggy.o cstartup.o _start.o

jaggy.bin: jaggy.elf
        $(OBJCOPY) -Obinary $< $@

jaggy.elf: $(OBJECTS)
        $(LD) $(LDFLAGS) -o $@ $(OBJECTS)


.ONESHELL:
%.o     : %.c
        @echo "CC $<"
        $(CC) -c $(CFLAGS) $<

.ONESHELL:
%.o     : %.S
        @echo "AS $<"
        $(AS) -c $(ASFLAGS) $<

Linker script:

/* jaggy.ld */
/* mimimal linker script */

ENTRY(_start)

MEMORY {
       rom (rx) : org = 0x802000, len = 2M-0x2000
       ram (rx) : org = 0x4000, len = 2M-0x4000
}

stack_top = ORIGIN(ram)-4;

SECTIONS {
   .text : {
      KEEP(*(.init))
      *.o(.text)
      . = ALIGN(4);

      /* needed for cstartup */
      __section_init = .;
      LONG(0);
      LONG(0);
      LONG(0); /* dummy, needed for later ROM => RAM copy of code */

      LONG(0);
      LONG(0);
      LONG(0); /* dummy, needed for later ROM => RAM copy of data */

      LONG(ADDR(.bss));
      LONG(SIZEOF(.bss))
   } > ram

   .data ALIGN( : {
      *(.data)
      . = ALIGN(;
   } > ram

   .bss ALIGN( : {
      *(.bss)
      . = ALIGN(;
   } > ram

}

Entry point:

/* _start.S */
        .section ".init","ax"
        .extern stack_top
        .globl _start
        .type   _start,@function
_start:
        lea     stack_top,sp
        /* add jaguar setup here */
        jmp     cstartup

cstartup:

/* cstartup.S */
        .extern main

        .extern __section_init

        .text
        .globl cstartup
        .type   cstartup,@function
cstartup:
        lea     __section_init,a0
        move.l  (a0)+,a1        // text_romstart
        move.l  (a0)+,a2        // text_start
        move.l  (a0)+,d1        // text_size
        beq.s   crt2
        cmp.l   a1,a2           // src == dst => no copy
        beq.s   crt2
crt1:
        move.l  (a1)+,(a2)+
        subq.l  #4,d1
        bne.s   crt1

crt2:
        move.l  (a0)+,a1        // data_romstart
        move.l  (a0)+,a2        // data_start
        move.l  (a0)+,d1        // data_size
        beq.s   crt4
        cmp.l   a1,a2
        beq.s   crt4
crt3:
        move.l  (a1)+,(a2)+
        subq.l  #4,d1
        bne.s   crt3
crt4:
        move.l  (a0)+,a1        // bss_start
        move.l  (a0)+,d1        // bss_size
        beq.s   crt6
crt5:
        clr.l   (a1)+
        subq.l  #4,d1
        bne.s   crt5
crt6:
        jmp main

And last but not least the main function:

/* jaggy.c */
char test1[12];

__attribute((aligned()) short fb[320*240];

const char hello[] = "jaggy rulez";

void main(void)
{
  for(;;
}

When you check jaggy.map, you'll see, that the fb array is really aligned on 8 bytes.

The linker script now places everything in RAM. It can be expanded to link for ROM and have code linked for RAM.

HTH

 

Edit: Fix stack_top.

Edited by 42bs
  • Like 2
Link to comment
Share on other sites

It works with my sprite test, I've changed my makefile and used the linker script, etc and looks ok, even I've changed a few things into my code and still runs.

 

Now I'm gonna try with the st-niccc demo...

 

Thanks a lot.

 

Great.

 

The next step are overlays ;-) => Different code in ROM linked to the same address in RAM ......

Link to comment
Share on other sites

 

Nice. Because? Now gcc before vbcc?

 

vbcc generates code as a 32bits processor, it doesn't matter if you use int16_t types, it will read the value, expand to 32bits and do the operation.

 

The speed up it's quite huge, much better than I thought.

 

Edit:

https://twitter.com/swapd0/status/1095996493603979264

 

Edited by swapd0
  • Like 3
Link to comment
Share on other sites

It's weird.

 

I've in classic kong an assembly file with some incbin, I forgot to use .data directive in the file and the makefile puts that data file at the start, it doesn't use the ENTRY(_start).

 

You mean the linker not the Makefile, I guess.

 

Did you check the map file, if _start.o was included?

 

BTW: If you use sub-directories, you have to add a "*" in front of the files. LD is kinda stupid. If you write "_start.o(.init)" _start.o must be in the same place as the linker script.

If you write "*_start.o(.init)", it can be anywhere.

 

Maybe PM your linker-script and map-file.

  • Like 2
Link to comment
Share on other sites

There's a way to avoid to put __attribute__((aligned (4))) at the C data that I've to access from the GPU to avoid alignment issues?

 

Not sure if it would work but define your own types with that included? Or a way that should certainly work, create your own macro's for types you wish to be 4 byte aligned? I know a lot of people view macro's as dirty, but that should work if you can stop yourself from using the actual real types by mistake.

 

There is probably a cleaner way, just my 2p

  • Like 1
Link to comment
Share on other sites

The C++ adicts thing macros are bad and prefer templates. But you can do so much fun stuff with macros .... :-)

Defining own types is a valid option. stdint.h has already something like int_fast_t etc. So why not int_aligned_t or phrase_aligned_t.
Nice idea.

Link to comment
Share on other sites

It should align data on the natural boundary, that is char on byte, short on two and int on four bytes.

 

From gnu.org:

-malign-int

-mstrict-align

With -malign-int I got a nice internal compiler error: Segmentation fault: 11, lol.

 

 

Not sure if it would work but define your own types with that included? Or a way that should certainly work, create your own macro's for types you wish to be 4 byte aligned? I know a lot of people view macro's as dirty, but that should work if you can stop yourself from using the actual real types by mistake.

 

There is probably a cleaner way, just my 2p

Yes I've some struct with that defined, I'm gonna try the macro solution.

Link to comment
Share on other sites

  • 1 month later...

WTF!!!!!!!!1!!

 

With the skunk_print line commented it doesn't works, when I draw a string I get the first char of the string with garbage(actually I think that it draws the last character from the last string), but with the line uncommented it works...

 

I got a lot of issues like these with Classic Kong compiled with gcc, but with vbcc compiler it worked.

void draw_char(char ch, uint8_t *dst)
{
	const char *font = _font + (((uint16_t)ch - ' ') << 6);
//	skunk_print("char %d\n", ch);
	for ( int i = 0; i < 8; ++i )
	{
		*dst++ = *font++;
		*dst++ = *font++;
		*dst++ = *font++;
		*dst++ = *font++;
		*dst++ = *font++;
		*dst++ = *font++;
		*dst++ = *font++;
		*dst++ = *font++;

		// next line
		dst += 256 - 8;
	}
}

void draw_text(const char *text, uint8_t *dst)
{
    int16_t col = 0;
    while ( *text )
    {
        draw_char(*text, dst);
        ++text;
        ++col;
        dst += 8;

        if ( col == 32 )
        {
            col = 0;
            dst += 7*256;
        }
    }
}
Link to comment
Share on other sites

Rather than dropping a char directly into a decimal, perhaps convert it 1st?

skunk_print("char %d\n", ord(ch));

Might be down to how the different compilers are treating the translation between char and numerical value?

 

When you say it works with it commented out, do you mean the string appears as you intend or is the graphical string being displayed incorrect?

Link to comment
Share on other sites

Sorry, the bug it's what I get on the screen(Jaguar), not on the PC through the skunk.

 

That routine it's called to draw the score, bonus and lives in Classic Kong, the lives are drawn as two string of 10 chars, but the first char of each string gets garbage so I included the skunk_print for test purposes but then it worked. WTF!?!?

 

Also I've tested to send the string to the skunk board and it's ok, but if I remove some code (like the skunk_print) the first char it's wrong (on the screen) although the string it's ok (at the PC).

 

I'm getting a lot of weird issues like these.

 

I wish I could use gdb...

Edited by swapd0
Link to comment
Share on other sites

I get the feeling this *might* be an alignment issue, where the code is moving a data structure further down in the code out of long alignment, or even word alignment.

 

I am not sure how you could add 1 or 2 bytes via C however.

 

I have had things mysteriously stop working when I added a nop once, and then add another nop and it worked again in sections of code that were not being called even. It was an alignment issue.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...