I also recently finished the Instruction set for my own flavor of 6502 RISC.
But i didn't want to use something like CustomASM to create the instructions from scratch using custom formats and such, i wanted this to be import-able into existing projects using a common assembler... and i choose ca65 (because i'm already using it for everything else).
so after reading through ca65's documentation about macros, i found out that they are somehow both more powerful and limit than i though. either way i did get it working and i also made a small bubble sort algorithm with it (though mine is 8-bit instead of 24-bit, maybe i'll do a rewrite)
the Instruction format and list is here:
Code: Select all
<<<Registers:
R0-R31 - 8-bit General Purpose Registers
W0-W15 - 16-bit General Purpose Registers
the W Registers are made out of pairs of R Registers, R0 and R1 form W0, R2 and R3 form W1, etc
<<<Instruction format:
Rs - Source Register
Rd - Destination Register
imm8 - 8-bit Immediate value
imm16 - 16-bit Immediate value
<<<Instruction List:
Load Immediate - LDI Rd, #imm8/16
Load Memory - LDM Rd, imm16
Load Register - LDR Rd, Rs (Rs can only be a W Register)
Store Memory - STM Rd, imm16
Store Register - STR Rd, Rs (Rd can only be a W Register)
Push Register - PSH Rs
Pull Register - PLL Rd
Add with Carry - ADR Rd, Rs1, Rs0
Subtract with Carry - SBR Rd, Rs1, Rs0
Logic AND - ANR Rd, Rs1, Rs0
Logic OR - ORR Rd, Rs1, Rs0
Logic XOR - XRR Rd, Rs1, Rs0
Compare - CPR Rs1, Rs0
Rotate Right - RRR Rd, Rs
Rotate Left - RLR Rd, Rs
Add with Carry Immediate - ADI Rd, Rs, #imm8/16
Sub. with Carry Immediate - SBI Rd, Rs, #imm8/16
Logic AND Immediate - ANI Rd, Rs, #imm8/16
Logic OR Immediate - ORI Rd, Rs, #imm8/16
Logic XOR Immediate - XRI Rd, Rs, #imm8/16
Compare Immediate - CPI Rs, #imm8/16
Something special about
LDM,
LDR,
STM, and
STR is that you can use either Index Registers with them. even though
LDR and
STR are basically just Indirect Addressing, the X Register will be added after the Indirect part, like with
(zp),Y. effectively creating the
(zp),X Addressing Mode.
Also, each instruction can either be 8 or 16-bit depending on the Registers used, but do note that mixing of Registers is not allowed.
So
ADR R6, R9, R10 is valid, but
ADR W2, R9, R5 is not. if i allow for register mixing there would be way too many possible register type arrangements for each instruction. and all of those would need their own chunk of code in the macro. and that's too insane for me!
going back to the Compare Instruction thing both of you mentioned, i originally thought about getting rid of Compare completely and just copying what RISC-V does with it's Branch instructions. but ultimately i just decided to go back and make the 16-bit Compare work exactly like the 8-bit one, where it sets the N, C, and Z flags like you'd expect from a single CMP Instruction.
and i did it kinda stupidly by using branches and hardwired
LDA # CMP # sequences to set the flags correctly:
Code: Select all
LDA src0 - (REG_OFFS - 1)
CMP src1 - (REG_OFFS - 1)
BCC @islower ; src0 < src1
BNE @ishigher ; src0 > src1
LDA src0 - REG_OFFS
CMP src1 - REG_OFFS
BCC @islower ; src0 < src1
BEQ @issame ; src0 = src1
@ishigher: ; src0 > src1
LDA #42
CMP #21
BRA @exit
@issame:
LDA #42
CMP #42
BRA @exit
@islower:
LDA #21
CMP #42
@exit:
anyways, here is my small Bubble Sort routine.
a_input is the Array containing the Bytes, and
a_count is the amount of Elements in the Array
Code: Select all
_main:
LDI W15, #a_input ; Get the Address of the Array
@outer_loop:
LDY #0
LDI R2, #0
@loop:
LDR R0, W15,Y
INY
LDR R1, W15,Y ; Get 2 consecutive bytes from the Input Array
CPR R0, R1 ; Compare them to eachother
BCS @noswap ; Branch if R0 >= R1
STR W15,Y, R0
DEY
STR W15,Y, R1 ; Otherwise swap the Values in the Array
INY
LDI R2, #1 ; And set R2 to >0 to show that the array wasn't sorted yet
@noswap:
CPY #a_count - 1 ; Repeat this loop until the last Element has been reached
BNE @loop
CPI R2, #0 ; If the previous loop didn't swap any values, exit the function
BNE @outer_loop ; As that means the Array is sorted
@exit:
_end:
I want to try and port this one to the 65816 next, since it should shrink down the 16-bit operations to basically the same exact size as the 8-bit ones. maybe i can use the smart mode in ca65 to only insert the REP/SEP instructions for the accumulator when they are actually needed instead of forcing them in each macro.
anyways, i attached the include file for ca65 below. the file extension doesn't matter but it's common for ca65 assembly includes to have the .inc extension (but i had to rename it to be able to upload it) there might also still be bugs...