So I am writing a 6502 emulator, and now wants to test out some programs. I decided to generate the 6502 assembly from C using https://godbolt.org/. I wrote a simple program declaring two variables and then adding them and storing the result on a third variable. The generated assembly output using cc65 2.19 while makes sense, also includes several instructions which (I think) are not part of the original 6502 assembly, for example instructions like 'pushax', 'ldaxysp', 'tosaddax', 'incsp6', etc. I searched a bit, and I understood that since the memory supported by a 6502 processor is extremely small, the cc65 compiler maintains a software stack and these instructions I talked about are used to manipulate them.
Is my understanding correct? Secondly, is there a way to generate 'pure' 6502 assembly from C code, which I can just assemble to into opcodes and run in my emulator?
cc65 equivalent instructions?
Re: cc65 equivalent instructions?
I'd suggest you start by writing assembly from scratch and not try C - it's harder to write code, but easier to get the toolchain going.
Just start, one instruction at a time and (say) arrange your emulator to return after e.g. a BRK instruction.
When you think it's good enough you can run the Klauss tests on it for 6502 and 65C02.
https://github.com/Klaus2m5/6502_65C02_functional_tests
Although this site has the same tests, but edited for the ca65 assembler which you are (will be) using:
https://github.com/amb5l/6502_65C02_functional_tests
Hope it goes well.
-Gordon
Just start, one instruction at a time and (say) arrange your emulator to return after e.g. a BRK instruction.
When you think it's good enough you can run the Klauss tests on it for 6502 and 65C02.
https://github.com/Klaus2m5/6502_65C02_functional_tests
Although this site has the same tests, but edited for the ca65 assembler which you are (will be) using:
https://github.com/amb5l/6502_65C02_functional_tests
Hope it goes well.
-Gordon
--
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/
Re: cc65 equivalent instructions?
Agreed that C isn't a great place to start. For a beginner, I recommend the easy6502 tutorial. (Don't get hung up on syntax differences between assemblers - that's of no importance. The important thing is the mental model you need to build.
Having said that...
Are you sure you're seeing instructions like that? I suspect you're seeing subroutine calls, to helper routines which cc65 makes use of.
I tried adding some compiler options (-Oi -Os --codesize 999 --static-locals), with this result
https://godbolt.org/z/sds77vzcT
where
is transformed to
which still has a couple of helpers, but hopefully clear enough from context as to what they are doing. If in further doubt, consult the cc65 documentation.
Having said that...
Are you sure you're seeing instructions like that? I suspect you're seeing subroutine calls, to helper routines which cc65 makes use of.
I tried adding some compiler options (-Oi -Os --codesize 999 --static-locals), with this result
https://godbolt.org/z/sds77vzcT
where
Code: Select all
char sum(char a, b) {
char z;
z=a+b;
return z;
}
Code: Select all
.proc _sum: near
L0002:
jsr pushax
ldy #$00
lda (sp),y
clc
ldy #$02
adc (sp),y
sta L0002
ldx #$00
lda L0002
jmp incsp3Re: cc65 equivalent instructions?
randomkiwi wrote:
for example instructions like 'pushax', 'ldaxysp', 'tosaddax', 'incsp6', etc. I searched a bit, and I understood that since the memory supported by a 6502 processor is extremely small, the cc65 compiler maintains a software stack and these instructions I talked about are used to manipulate them.
if you have a custom target without a runtime library then the linker will complain about those functions being missing.
as the other's suggested, maybe getting started with assembly would be a better idea. but if your end goal is getting C running then maybe start directly with ca65 (the assembler included with the cc65 utilities). it's a bit more complicated than other assemblers because it generates object files which need to be linked, but once you understand it and are comfortable with it, going from there to C will be a lot easier (plus you don't have to learn a different assembler syntax when writing assembly functions for cc65).
Re: cc65 equivalent instructions?
If you wanted to make it "pure" assembly you can look up the assembly for these routines in the CC65 source.
Re: cc65 equivalent instructions?
BTW, to test out an emulator, one typical tactic is to try to run a Basic interpreter - any one of the usual ones. Another very useful tactic is to run Klaus Dormann's test suite, which is very thorough and has found errors in the great majority of emulators (since corrected, of course.)
To just get started, I would probably just take examples from anywhere - perhaps the easy6502 tutorial. Or example code from the reference section of this forum: http://6502.org/source/
To just get started, I would probably just take examples from anywhere - perhaps the easy6502 tutorial. Or example code from the reference section of this forum: http://6502.org/source/
Re: cc65 equivalent instructions?
Since I have the time I'll write bit more...
To generate executable code from cc65 it needs a few more things than just the compiler. It's a more or less complete set of tools that work in the same way as "the big boys" tools do on a desktop or server system - compiler, assembler and linker. Additionally you need a target platform which specifies the code (& data) load and execution addresses.
The target lets you pick the machine you're running it on - there are many pre-defined such as Apple II, BBC Micro, Commodore PET, OSI and so on. These affect the libraries, load addresses and so on.
The godbolt site is as it says; a compiler explorer. It's designed to let you see and compare the output ff various compilers and not to generate actual runnable code.
So the first thing you need to do is get the cc65 suite installed locally.
Then just write a simple assembly program (and I'm assuming that as you've written an emulator you're familiar with 6502 assembler)
You can then assemble with
ca65 -g myfile.s -o myfile.o -l myfile.l
That generates a relocatable object file called myfile.o with a listing file of myfile.l
To turn this into an executable binary file then:
ld65 -t none -S 0x8000 -vm -m myfile.m -o myfile myfile.o
That takes your relocatable object file, converts it into a standalone binary with a starting address of $8000 and a map file of myfile.m.
Here is a small example: Add numbers in locations 0 and 1 and store the result in 2:
myfile.s:
the assemble command and list the output:
The 'r' in the address field means it's a relocatable value as is the 'rr' in the JMP instruction.
Linking and displaying the object file:
Note the % symbol is my prompt and the odx command is a hex dump command I use. Also note the address after the 4C in the dump - 00 80 which the linker has translated into an absolute value based on the start address given on the command line.
There are many, many more ways to drive the cc65 suite but this is about the simplest.
Hope that helps....
Gordon
(Also writing an emulator after many years using real CPUs!)
To generate executable code from cc65 it needs a few more things than just the compiler. It's a more or less complete set of tools that work in the same way as "the big boys" tools do on a desktop or server system - compiler, assembler and linker. Additionally you need a target platform which specifies the code (& data) load and execution addresses.
The target lets you pick the machine you're running it on - there are many pre-defined such as Apple II, BBC Micro, Commodore PET, OSI and so on. These affect the libraries, load addresses and so on.
The godbolt site is as it says; a compiler explorer. It's designed to let you see and compare the output ff various compilers and not to generate actual runnable code.
So the first thing you need to do is get the cc65 suite installed locally.
Then just write a simple assembly program (and I'm assuming that as you've written an emulator you're familiar with 6502 assembler)
You can then assemble with
ca65 -g myfile.s -o myfile.o -l myfile.l
That generates a relocatable object file called myfile.o with a listing file of myfile.l
To turn this into an executable binary file then:
ld65 -t none -S 0x8000 -vm -m myfile.m -o myfile myfile.o
That takes your relocatable object file, converts it into a standalone binary with a starting address of $8000 and a map file of myfile.m.
Here is a small example: Add numbers in locations 0 and 1 and store the result in 2:
myfile.s:
Code: Select all
; Example
loop:
clc
lda $0
adc $1
sta $2
jmp loopCode: Select all
% ca65 -g myfile.s -o myfile.o -l myfile.l
% cat myfile.l
ca65 V2.17 - Git cd72f816
Main file : myfile.s
Current file: myfile.s
000000r 1 ; Example
000000r 1 18 clc
000001r 1 A5 00 lda $0
000003r 1 65 01 adc $1
000005r 1 85 02 sta $2
000007r 1 4C rr rr jmp loopLinking and displaying the object file:
Code: Select all
% ld65 -t none -S 0x8000 -vm -m myfile.m -o myfile myfile.o
% odx myfile
000000 18 a5 00 65 01 85 02 4c 00 80 >...e...L..<There are many, many more ways to drive the cc65 suite but this is about the simplest.
Hope that helps....
Gordon
(Also writing an emulator after many years using real CPUs!)
--
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/
Re: cc65 equivalent instructions?
BigEd wrote:
I tried adding some compiler options (-Oi -Os --codesize 999 --static-locals), with this result
https://godbolt.org/z/sds77vzcT
where
is transformed to
which still has a couple of helpers [..]
https://godbolt.org/z/sds77vzcT
where
Code: Select all
char sum(char a, b) {
char z;
z=a+b;
return z;
}
Code: Select all
.proc _sum: near
L0002:
jsr pushax
ldy #$00
lda (sp),y
clc
ldy #$02
adc (sp),y
sta L0002
ldx #$00
lda L0002
jmp incsp3Code: Select all
sum: ; @sum
stx __rc2
clc
adc __rc2
rts
LLVM-MOS does not, in general, generate code that calls inline stack helper functions. There are no "pushax" or "incsp3" functions and the like inlined... it's all just generated assembly. Those called functions are not exactly cheap on cc65.