Page 1 of 1
High level macros
Posted: Sat Sep 14, 2013 3:33 pm
by Movax12
Hi,
I'd like to let everyone here know about the macros I have been working on for high-level like coding with the 6502. My target is NES, so no 65c02 or better features are targeted. Maybe in the future they will be.
I've been working on and using these macros for some time. I use them often and they have been somewhat tested by others. Anyone who already uses
ca65 will have no trouble giving them a try as only two files are needed and only one file needs to be included in your source module:
There is no library code and no memory used. The syntax is quite flexible, and logical structures can of course be nested as much as you would like. You can also create your own custom macros to work with the logical conditions, which act like boolean functions. The resulting code can look very high-level, but still maintains an almost 1:1 relationship to the underlying assembly in almost every case.
The only possible downside is that for very large projects it can be slow to build, but if you are utilizing that fact that ca65 has a linker, your code can (in my opinion, should) be separated into modules, which will eliminate this issue.
I am currently working on some sample code, and updating the wiki:
https://www.assembla.com/spaces/ca65hl/wiki
Thanks!
Re: High level macros
Posted: Sat Sep 14, 2013 6:49 pm
by GARTHWILSON
I'm glad to see the interest in this growing! You're the fourth one here so far (that I know of) to be doing this-- or maybe third, since BitWise's aren't macros. He built the capability into his assembler so in that respect it's partly a compiler, not just an assembler; but the end result is the same. It also chooses which instructions to use based on whether a branch distance is outside the -128 to +127 range (which would be a really big program structure, but it can happen, especially with a CASE statement).
Re: High level macros
Posted: Sat Sep 14, 2013 8:17 pm
by enso
assemblia.com link is not working!
Re: High level macros
Posted: Sat Sep 14, 2013 8:21 pm
by GARTHWILSON
It works for me. Maybe it was down briefly?
Re: High level macros
Posted: Sat Sep 14, 2013 8:45 pm
by Movax12
I'm glad to see the interest in this growing!
It also chooses which instructions to use based on whether a branch distance is outside the -128 to +127 range (which would be a really big program structure, but it can happen, especially with a CASE statement).
ca65 will stop with an error if a branch is too far, at which time the user can add the macro directive
setLongBranch + before the offending statement to invert all branch logic and use absolute jmp instructions. I plan to finish implementing a warning when you have a long branch where it is not needed, but that is not properly implemented at the moment.
Unfortunately (in this case), ca65 is a one pass assembler, and can't figure out if a branch is too far until it is too late to fix automatically with macro code.
I haven't really looked at adding a CASE, but I've looked at adding FOR, but am hesitant due to wanting to stick to a C like syntax, and the C FOR loop being more like a while <> do, meaning an inefficient jmp back to the top of the while to test the condition on the last iteration. I guess a FOR loop doesn't have to stick to that structure though.
Re: High level macros
Posted: Sat Sep 14, 2013 10:20 pm
by GARTHWILSON
I haven't really looked at adding a CASE, but I've looked at adding FOR, but am hesitant due to wanting to stick to a C like syntax, and the C FOR loop being more like a while <> do, meaning an inefficient jmp back to the top of the while to test the condition on the last iteration. I guess a FOR loop doesn't have to stick to that structure though.
I modeled my structures mosly after Forth's standard ones (I say "standard" because Forth lets you make your own, in fact you can even define your own operators in Forth) but I figured BASIC's FOR...NEXT kind of syntax would be more readily accepted than Forth's simple but unusual DO...LOOP sytax (if you can even call it syntax, as Forth hardly has any syntax) by non-Forth-speaking people. In DO...LOOP, the internal compiled by DO only runs once, at the beginning of the loop, to prepare the stack, and then the internal compiled by LOOP (at the end of the loop) is what determines whether to go back to the top or not, similar to assembly language. The FOR...NEXT macros assemble the same thing you would do by hand, with for example:
Code: Select all
FOR_X 8, DOWN_TO, 0
<loop contents>
<actions, actions>
<yada yada>
NEXT_X
which assembles:
Code: Select all
LDX #8
TOP: <loop contents>
<actions, actions>
<yada yada>
DEX
BNE TOP
The loop does not get run for the counter value equal to 0 like it would in BASIC, but it's a better transfer to/from assembly where we're subconsciously thinking of the DEX BNE here.
There are so many possible ways to do a FOR...LOOP in assembly thought that I originally thought it would not be feasible, so FOR...NEXT was added a long time after I did the others, and the FOR...NEXT macros are very long for the little code they lay down (which is usually only two or three bytes), because of the many options the macros have to sort out to decide what code to lay down.
I consider the CASE statement to be very valuable, but I have never run into a situation where I've had to nest CASE statements. CASE and my 16-bit FOR...NEXT (which is separate from FOR_X|FOR_Y...NEXT_X|NEXT_Y which are always 8-bit for 6502) are the only ones I have not made nestable.
Re: High level macros
Posted: Mon Oct 14, 2013 4:03 pm
by Movax12
My macros now feature support for parentheses in expressions! Although I am confident everything is working I would consider this untested, beta code.
https://www.assembla.com/code/ca65hl/git/nodes/devel
Following the same rules as the previous version, you can test 'expressions' that represent or result in a CPU flag being set/clear and branch appropriately. The latest code allows parentheses to create more complex logical conditions, as well as a negate operator that can distribute across parenthesis. The code generated aims to be efficient and will short circuit as soon as the outcome can be determined.
The only limitation is that all OR logic must be before all AND logic in the same parentheses set. ( Add parentheses to work around this.)
Some poor nonsensical examples:
Code: Select all
; branch to label:
* = 8000
foo = $00
bar = $01
baz = $03
myLabel = * + $50
if ( ( foo >= #$03 && ! bar ) || ((zero && negative) || baz = #1)) goto myLabel
; code output:
8000 A5 00 LDA $00
8002 C9 03 CMP #$03
8004 90 04 BCC $800A
8006 A5 01 LDA $01
8008 F0 46 BEQ $8050
800A D0 02 BNE $800E
800C 30 42 BMI $8050
800E A5 03 LDA $03
8010 C9 01 CMP #$01
8012 F0 3C BEQ $8050
; if-endif ( else supported )
* = 8000
foo = $00
bar = $01
baz = $03
if ( !( bar & #$03 && baz == N set ) || (( V set || baz < #$10 ) || foo = #1) )
nop
endif
; code output:
8000 A5 01 LDA $01
8002 29 03 AND #$03
8004 F0 12 BEQ $8018
8006 A5 03 LDA $03
8008 10 0E BPL $8018
800A 70 0C BVS $8018
800C A5 03 LDA $03
800E C9 10 CMP #$10
8010 90 06 BCC $8018
8012 A5 00 LDA $00
8014 C9 01 CMP #$01
8016 D0 01 BNE $8019
8018 EA NOP
8019
Re: High level macros
Posted: Wed Oct 16, 2013 4:51 pm
by Movax12
Implemented FOR; devel branch on assembla will be updated in the next few days.
http://i.imgur.com/KkUbyEA.png
Re: High level macros
Posted: Wed Oct 16, 2013 6:44 pm
by GARTHWILSON
with step size too. I didn't get that far on mine.
Re: High level macros
Posted: Wed Oct 23, 2013 2:20 am
by Movax12
FOR added to the devel branch:
https://www.assembla.com/code/ca65hl/git/nodes/devel
I changed how it works from the first example I posted.
1)C-style of loop:
for ( <thing to do 1st>, <Flag to test - continue while true >, <stuff to do at end of loop> )
Example:
Code: Select all
for ( x := #$3, not negative, dex )
; code
next
; more complex:
for ( x := foo, (x > #10) && (foo <> #1), dex:dex)
; some code
next
2) BASIC-style syntax:
This actually tries to optimize some, and will break if you mess with your counter register or variable without thinking:
Code: Select all
for x := #$AA to #$10 step -3
;some code
next
It will loop until your counter hits the first invalid (for the loop) value. If possible it will skip CMP and use BPL/BMI or a lone BNE. 'step' can be omitted and a step of -1 or 1 decided on if possible. You can use variables rather than immediate values, but no optimizations are possible.
Re: High level macros
Posted: Mon Nov 04, 2013 5:18 pm
by Movax12
Hi,
It may need some polish, but I updated the documentation on the wiki for ca65hl:
https://www.assembla.com/spaces/ca65hl/wiki