6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Sat Apr 27, 2024 7:40 am

All times are UTC




Post new topic Reply to topic  [ 46 posts ]  Go to page 1, 2, 3, 4  Next
Author Message
 Post subject: SDCC for 6502
PostPosted: Sat Mar 12, 2022 5:44 am 
Offline

Joined: Thu Mar 12, 2020 10:04 pm
Posts: 690
Location: North Tejas
http://sdcc.sourceforge.net/index.php#News

They just announced work in progress to support the 6502.


Top
 Profile  
Reply with quote  
 Post subject: Re: SDCC for 6502
PostPosted: Sat Mar 12, 2022 7:00 am 
Offline
User avatar

Joined: Fri Aug 03, 2018 8:52 am
Posts: 745
Location: Germany
it says "mos6502" so i assume they don't mean the W65C02, which is a shame.


Top
 Profile  
Reply with quote  
 Post subject: Re: SDCC for 6502
PostPosted: Sat Mar 12, 2022 8:03 am 
Offline
User avatar

Joined: Wed Feb 14, 2018 2:33 pm
Posts: 1398
Location: Scotland
Nice to have another C compiler on the block. I used SDCC on an 8-bit PIC project a number of years back and found it to be very good there. It managed to cover the data banking almost transparently, so maybe there is hope for it on the '816 too in the future?

-Gordon

_________________
--
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/


Top
 Profile  
Reply with quote  
 Post subject: Re: SDCC for 6502
PostPosted: Sat Mar 12, 2022 5:35 pm 
Offline

Joined: Sat Dec 12, 2015 7:48 pm
Posts: 122
Location: Lake Tahoe
Great news. I also used SDCC for an embedded 8051 project many years ago and found it very capable. It looks to also have support for the 65C02.


Top
 Profile  
Reply with quote  
 Post subject: Re: SDCC for 6502
PostPosted: Wed Feb 15, 2023 6:33 am 
Offline

Joined: Mon Jan 19, 2004 12:49 pm
Posts: 660
Location: Potsdam, DE
I played a little last night with SDCC-4.2.0 (the latest version) in a Linux Mint environment.

First thoughts:
- There is apparently no documentation regarding the 6502, other than a couple of mentions in the sdccman.pdf. Grepping doesn't find anything useful.

- Obviously, putchar() has to be defined if you want to use text input. The error message if you don't complains about a missing '_putchar' but it does not want that leading underscore.

- You're also going to have to include any necessary initialisation of the input mechanism (in my case, it will be a 68B50 uart).

- The mystic incantation (discovered after some trial and error) to build for 6502 is 'sdcc -mmos6502 hello.c' which rather implies that it's assembling base NMOS code (which I'm old-school enough to be happy about; it might not be optimal on a WDC part but it'll run on anything). It didn't like -65c02 or -wdc65c02.

- It seems to be assuming a flat memory model with 64k ram. The hex file starts with a single line:
Code:
:06FFFA00000200020002FB
which points the reset, nmi, and irq vectors to $0200.

- The simple test file (as yet unrun, and note it doesn't have the uart initialisation!)
Code:
#include <stdio.h>

char * ACIAStatus   = 0xa000;
char * ACIAData      = 0xa001;

int putchar(int ch);

int putchar(int ch)
{
   while (((*ACIAStatus) & 0x02) == 0x02) {}
   *ACIAData = (char)ch;
   return ch;
}

void main (void)
{
   printf ("hello world");
}

produces a hex file with code from $0200 to $0d30 or thereabouts. I assume that's because it's dragging in the stdio library - printf is always a code hog even without floating point.

Neil


Top
 Profile  
Reply with quote  
 Post subject: Re: SDCC for 6502
PostPosted: Wed Feb 15, 2023 8:21 am 
Offline

Joined: Thu Mar 12, 2020 10:04 pm
Posts: 690
Location: North Tejas
Try puts instead of printf and see how much baggage you omit...


Top
 Profile  
Reply with quote  
 Post subject: Re: SDCC for 6502
PostPosted: Wed Feb 15, 2023 4:35 pm 
Offline

Joined: Mon Jan 19, 2004 12:49 pm
Posts: 660
Location: Potsdam, DE
As expected: it's a lot smaller. As I said, printf is a memory hog on every small microcontroller; it drags in too much baggage with it even without floating point.

Code:
:06FFFA00000200020002FB
:20020000A2FF9AA9388D0680A9038D0780A9048D0880A9008D0980A900A280207902A9005F
:1A0220008D0A80A90B8D0B80A9008D0C80A904A28020B7022072024C37025E
:20023A008D04808E0580AD00808520AD01808521A000B120A20029024868C902D004E0006D
:1F025A00F0E4AD02808534AD03808535AD04809134AE0580AD048060A203A92C4C02035A
:10032C0068656C6C6F20776F726C640000A001A024
:20027900852C862D852E862FAD06808530AD07808531A000AE0980F013B130912EC8B130A4
:1E029900912EC8D0F4E631E62FCAD0EDAE0880F008B130912EC8CAD0F8A52CA62D601D
:2002B7008D0D808E0E80AE0B80AC0C80AD0C800D0B80F030AD0D808535AD0E808536AD0AEE
:2002D7008085348420A534A0009135A420E635D002E6368A38E901AA98E900A8C000D0020D
:0B02F700E000D0DFAE0E80AD0D806097
:20030200852A862BA000B12AC900F017E62AD002E62BA200203A02C9FFD0E9E0FFD0E5A981
:0A032200FFAA60A200A90A4C3A02EB
:00000001FF


Neil


Top
 Profile  
Reply with quote  
 Post subject: Re: SDCC for 6502
PostPosted: Wed Feb 22, 2023 7:53 am 
Offline

Joined: Mon Jan 19, 2004 12:49 pm
Posts: 660
Location: Potsdam, DE
I've been playing a little with the sdcc compiler; it's not bad at first glance but it's missing some obvious optimisations:

Code:
// pointers to the ACIA registers
volatile char * const ACIAStatus   = 0xa000;
volatile char * const ACIAData   = 0xa001;

int putchar(int ch)
{
   // blocking write to the serial port
   while ((*ACIAStatus) & 0x02) {}
   *ACIAData = (char)ch;
   return ch;
}


Those ACIA pointers should be constant pointers to a volatile char - the register content. However, it produces the following assembly:
Code:
_putchar:
   sta   _putchar_ch_65536_38
   stx   (_putchar_ch_65536_38 + 1)
;   monitor.c: 35: while ((*ACIAStatus) & 0x02) {}
00101$:
   lda   _ACIAStatus
   sta   *(__TEMP+0)
   lda   (_ACIAStatus + 1)
   sta   *(__TEMP+1)
   ldy   #0x00
   lda   [__TEMP+0],y
   and   #0x02
   bne   00101$
;   monitor.c: 36: *ACIAData = (char)ch;
   lda   _ACIAData
   sta   *_putchar_sloc0_1_0
   lda   (_ACIAData + 1)
   sta   *(_putchar_sloc0_1_0 + 1)
   lda   _putchar_ch_65536_38
   sta   [*_putchar_sloc0_1_0],y
;   monitor.c: 37: return ch;
   ldx   (_putchar_ch_65536_38 + 1)
   lda   _putchar_ch_65536_38
;   monitor.c: 38: }
   rts

where it has obviously defined the pointer as a word in memory; it copies it to a temporary word, and reads the byte using (abs),y. It also loops back and loads the pointer address every time. This is obviously generic so a pointer can change between calls - but one might have hoped that the const keyword would have allowed it to avoid the indirect load and the repeated load. Indeed, the ideal optimisation is perhaps a simple lda abs to the register... oh well, the whole point of C is that you don't have to worry about these things :)

Another bit which is somewhat confusing this early in the morning is if one replaces the
Code:
   while ((*ACIAStatus) & 0x02) {}

with the hopefully more self-documenting but theoretically identical operation
Code:
   while (0x02 == (*ACIAStatus) & 0x02) {}

which changes the generated assembly to
Code:
00101$:
   lda   _ACIAStatus
   sta   *(__TEMP+0)
   lda   (_ACIAStatus + 1)
   sta   *(__TEMP+1)
   ldy   #0x00
   lda   [__TEMP+0],y
   ldx   #0x00
   and   #0x02
   pha
   pla
   cmp   #0x02
   bne   00115$
   cpx   #0x00
   beq   00101$

Which includes the requested test but leaves an unnecessary pha/pla hanging around.

All very interesting, but this is the first release. At present there is zero documentation either in the installed codebase or on the wiki page associated; I may have to join their forum so at least I can ask some questions.

I think I'll knock up a quick monitor and see how that works. I've got lots of eeprom space :)

Neil


Top
 Profile  
Reply with quote  
 Post subject: Re: SDCC for 6502
PostPosted: Thu Feb 23, 2023 9:44 pm 
Offline

Joined: Mon Jan 19, 2004 12:49 pm
Posts: 660
Location: Potsdam, DE
Another observation: as far as I recall no flags are set by simply loading a variable on the 6502, but require a cmp, cpx, or cpy operation (or playing games with the flag register via the stack).

In which case, this generated code looks suspicious:
Code:
_get_line:
;   monitor.c: 61: unsigned char inptr = 0;   // eight bits are enough
   ldx   #0x00
   stx   _get_line_inptr_65536_46
;   monitor.c: 62: char done         = 0;   // not done yet
   stx   _get_line_done_65536_46
;   monitor.c: 65: while (0 == done)
00113$:
   lda   _get_line_done_65536_46
   beq   00154$
   rts
00154$:
;   monitor.c: 67: inbuffer[inptr] = '\0';
   ldx   _get_line_inptr_65536_46
   ldy   #0x00
   tya
   sta   (_inbuffer+0+0x0000),x
...

It seems to me that the beq after 00113$ is dependent on the flags on entry to get_line, and not on an actual test. There is a jump to 0113$ later based on a comparison (buffer full) but also one later still which is just a jump.

Am I missing something obvious?

(I have not yet been able to get the code onto a real 6502; my development machine doesn't have the same GLIBC as this one and I'm a bit leery of updating it; there's too much on it. Hopefully over the weekend.)

Neil


Top
 Profile  
Reply with quote  
 Post subject: Re: SDCC for 6502
PostPosted: Thu Feb 23, 2023 9:48 pm 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10793
Location: England
Hmm, no, you have that wrong unfortunately: loading a register does set N and Z. (Not so on all other micros, but true on 6502. If in doubt run a few instructions in an emulator: easy6502 is right there in your browser, for example.)


Top
 Profile  
Reply with quote  
 Post subject: Re: SDCC for 6502
PostPosted: Thu Feb 23, 2023 10:04 pm 
Online
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8428
Location: Southern California
As stated in the "programming tips" section of the 6502 primer at http://wilsonminesco.com/6502primer/PgmTips.html, an automatic compare-to-zero instruction is built into the following 65c02 instructions: LDA, LDX, LDY, INC, INX, INY, DEC, DEX, DEY, INA, DEA, AND, ORA, EOR, ASL, LSR, ROL, ROR, PLA, PLX, PLY, SBC, ADC, TAX, TXA, TAY, TYA, and TSX. This means that, for example, a CMP #0 after an LDA is redundant, a wasted instruction. A kitten somewhere dies every time you do that! :lol:  The only time a 65c02 (CMOS) needs a compare-to-zero instruction after one of these is if you want to compare a register that was not involved in the previous instruction.  Store instructions (STA, STX, STY) however do not affect status.

_________________
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?


Top
 Profile  
Reply with quote  
 Post subject: Re: SDCC for 6502
PostPosted: Fri Feb 24, 2023 6:31 am 
Offline

Joined: Mon Jan 19, 2004 12:49 pm
Posts: 660
Location: Potsdam, DE
Thank you gents! I thought I knew this processor - it's only been forty years since I used one in anger :D

So I looked in the Zaks that's been open on my desktop for the last month and there it is, plain as day... doh!

I think I got confused with the 8080 which I've been recreating at logic level; that one does require an ALU operation to set the flags and the register move and load instructions don't set flags. https://www.pastraiser.com/cpu/i8080/i8080_opcodes.html

Thanks again; I'll keep on plugging on at understanding this compiler.


Top
 Profile  
Reply with quote  
 Post subject: Re: SDCC for 6502
PostPosted: Fri Feb 24, 2023 8:14 pm 
Offline

Joined: Mon Jan 19, 2004 12:49 pm
Posts: 660
Location: Potsdam, DE
Getting a little further with the secret incantations:
Code:
sdcc -mmos6502 monitor.c --code-loc 0xe000 --xram-loc 0x0200

tells the linker to put the assembled code at 0xe000 (in my eeprom space) and to use from 0x0200 for constants and variables. Default values without --code-loc is to build at 0x0200 and it puts the bss at 0x8000 (where I have an empty hole in the memory map) without the --xram-loc. A --data-loc looked like the obvious switch for the bss but instead it moves the zero page variables...

That done, the code
Code:
   *ACIAStatus = 0x95;
   *ACIAData = '#';

produces
Code:
;   monitor.c: 140: *ACIAStatus = 0x95;
   ldx   _ACIAStatus
   ldy   (_ACIAStatus + 1)
   stx   *(__TEMP+0)
   sty   *(__TEMP+1)
   lda   #0x95
   ldy   #0x00
   sta   [__TEMP+0],y
;   monitor.c: 142: *ACIAData = '#';
   ldx   _ACIAData
   ldy   (_ACIAData + 1)
   stx   *(__TEMP+0)
   sty   *(__TEMP+1)
   lda   #0x23
   ldy   #0x00
   sta   [__TEMP+0],y

which outputs the expected '#' from the 68B50.

Neil


Top
 Profile  
Reply with quote  
 Post subject: Re: SDCC for 6502
PostPosted: Fri Feb 24, 2023 9:09 pm 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10793
Location: England
> secret incantations
That's good to know, thanks!


Top
 Profile  
Reply with quote  
 Post subject: Re: SDCC for 6502
PostPosted: Sat Feb 25, 2023 6:33 am 
Offline

Joined: Mon Jan 19, 2004 12:49 pm
Posts: 660
Location: Potsdam, DE
When I get to a more complete state of knowledge, I'll knock up a quick how-to. The main things I need to know are
  • How to compile anything! (done)
  • How to compile code to a given memory map (done)
  • How to handle interrupts and the BRK instruction
  • How to include assembly code directly

Neil


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 46 posts ]  Go to page 1, 2, 3, 4  Next

All times are UTC


Who is online

Users browsing this forum: No registered users and 17 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: