From 8eed63fa52d82d54e9bfc5c197e005473c34a4a7 Mon Sep 17 00:00:00 2001 From: Byron Lathi Date: Wed, 6 May 2026 09:52:32 -0700 Subject: [PATCH] First go at adding 65C032 --- src/ca65/instr.c | 217 ++++++++++++++++++++++- src/ca65/main.c | 1 + src/ca65/objcode.c | 6 + src/ca65/objcode.h | 3 + src/cc65/main.c | 1 + src/common/cpu.c | 3 + src/common/cpu.h | 6 +- test/asm/opcodes/65c032-opcodes.ref | 0 test/asm/opcodes/65c032-opcodes.s | 258 ++++++++++++++++++++++++++++ 9 files changed, 486 insertions(+), 9 deletions(-) create mode 100644 test/asm/opcodes/65c032-opcodes.ref create mode 100644 test/asm/opcodes/65c032-opcodes.s diff --git a/src/ca65/instr.c b/src/ca65/instr.c index f32a2b968..a154e928d 100644 --- a/src/ca65/instr.c +++ b/src/ca65/instr.c @@ -151,6 +151,9 @@ static void PutRTS (const InsDesc* Ins attribute ((unused))); static void PutAll (const InsDesc* Ins); /* Handle all other instructions */ +static void PutAll32 (const InsDesc* Ins); +/* Handle all other instructions for the 65C032 */ + static void Put4510 (const InsDesc* Ins); /* Handle instructions of 4510 not matching any EATab */ @@ -729,6 +732,119 @@ static const struct { } }; +/* Instruction table for the 65C032 (WDC CMOS with 32 bit addressing) */ +static const struct { + unsigned Count; + InsDesc Ins[100]; +} InsTab65C032 = { + /* CAUTION: table must be sorted for bsearch */ + sizeof (InsTab65C032.Ins) / sizeof (InsTab65C032.Ins[0]), + { +/* BEGIN SORTED.SH */ + { "ADC", 0x080A66C, 0x60, 0, PutAll32 }, + { "AND", 0x080A66C, 0x20, 0, PutAll32 }, + { "ASL", 0x000006e, 0x02, 1, PutAll32 }, + { "BBR0", 0x0000000, 0x0F, 0, PutBitBranch }, + { "BBR1", 0x0000000, 0x1F, 0, PutBitBranch }, + { "BBR2", 0x0000000, 0x2F, 0, PutBitBranch }, + { "BBR3", 0x0000000, 0x3F, 0, PutBitBranch }, + { "BBR4", 0x0000000, 0x4F, 0, PutBitBranch }, + { "BBR5", 0x0000000, 0x5F, 0, PutBitBranch }, + { "BBR6", 0x0000000, 0x6F, 0, PutBitBranch }, + { "BBR7", 0x0000000, 0x7F, 0, PutBitBranch }, + { "BBS0", 0x0000000, 0x8F, 0, PutBitBranch }, + { "BBS1", 0x0000000, 0x9F, 0, PutBitBranch }, + { "BBS2", 0x0000000, 0xAF, 0, PutBitBranch }, + { "BBS3", 0x0000000, 0xBF, 0, PutBitBranch }, + { "BBS4", 0x0000000, 0xCF, 0, PutBitBranch }, + { "BBS5", 0x0000000, 0xDF, 0, PutBitBranch }, + { "BBS6", 0x0000000, 0xEF, 0, PutBitBranch }, + { "BBS7", 0x0000000, 0xFF, 0, PutBitBranch }, + { "BCC", 0x0020000, 0x90, 0, PutPCRel8 }, + { "BCS", 0x0020000, 0xb0, 0, PutPCRel8 }, + { "BEQ", 0x0020000, 0xf0, 0, PutPCRel8 }, + { "BIT", 0x0A0006C, 0x00, 2, PutAll32 }, + { "BMI", 0x0020000, 0x30, 0, PutPCRel8 }, + { "BNE", 0x0020000, 0xd0, 0, PutPCRel8 }, + { "BPL", 0x0020000, 0x10, 0, PutPCRel8 }, + { "BRA", 0x0020000, 0x80, 0, PutPCRel8 }, + { "BRK", 0x0800005, 0x00, 6, PutAll32 }, + { "BVC", 0x0020000, 0x50, 0, PutPCRel8 }, + { "BVS", 0x0020000, 0x70, 0, PutPCRel8 }, + { "CLC", 0x0000001, 0x18, 0, PutAll32 }, + { "CLD", 0x0000001, 0xd8, 0, PutAll32 }, + { "CLI", 0x0000001, 0x58, 0, PutAll32 }, + { "CLV", 0x0000001, 0xb8, 0, PutAll32 }, + { "CMP", 0x080A66C, 0xc0, 0, PutAll32 }, + { "CPX", 0x080000C, 0xe0, 1, PutAll32 }, + { "CPY", 0x080000C, 0xc0, 1, PutAll32 }, + { "DEA", 0x0000001, 0x00, 3, PutAll32 }, /* == DEC */ + { "DEC", 0x000006F, 0x00, 3, PutAll32 }, + { "DEX", 0x0000001, 0xca, 0, PutAll32 }, + { "DEY", 0x0000001, 0x88, 0, PutAll32 }, + { "EOR", 0x080A66C, 0x40, 0, PutAll32 }, + { "INA", 0x0000001, 0x00, 4, PutAll32 }, /* == INC */ + { "INC", 0x000006f, 0x00, 4, PutAll32 }, + { "INX", 0x0000001, 0xe8, 0, PutAll32 }, + { "INY", 0x0000001, 0xc8, 0, PutAll32 }, + { "JMP", 0x0010808, 0x4c, 6, PutAll32 }, + { "JSR", 0x0000008, 0x20, 7, PutAll32 }, + { "LDA", 0x080A66C, 0xa0, 0, PutAll32 }, + { "LDX", 0x080030C, 0xa2, 1, PutAll32 }, + { "LDY", 0x080006C, 0xa0, 1, PutAll32 }, + { "LSR", 0x000006F, 0x42, 1, PutAll32 }, + { "NOP", 0x0000001, 0xea, 0, PutAll32 }, + { "ORA", 0x080A66C, 0x00, 0, PutAll32 }, + { "PHA", 0x0000001, 0x48, 0, PutAll32 }, + { "PHP", 0x0000001, 0x08, 0, PutAll32 }, + { "PHX", 0x0000001, 0xda, 0, PutAll32 }, + { "PHY", 0x0000001, 0x5a, 0, PutAll32 }, + { "PLA", 0x0000001, 0x68, 0, PutAll32 }, + { "PLP", 0x0000001, 0x28, 0, PutAll32 }, + { "PLX", 0x0000001, 0xfa, 0, PutAll32 }, + { "PLY", 0x0000001, 0x7a, 0, PutAll32 }, + { "RMB0", 0x0000004, 0x07, 1, PutAll32 }, + { "RMB1", 0x0000004, 0x17, 1, PutAll32 }, + { "RMB2", 0x0000004, 0x27, 1, PutAll32 }, + { "RMB3", 0x0000004, 0x37, 1, PutAll32 }, + { "RMB4", 0x0000004, 0x47, 1, PutAll32 }, + { "RMB5", 0x0000004, 0x57, 1, PutAll32 }, + { "RMB6", 0x0000004, 0x67, 1, PutAll32 }, + { "RMB7", 0x0000004, 0x77, 1, PutAll32 }, + { "ROL", 0x000006F, 0x22, 1, PutAll32 }, + { "ROR", 0x000006F, 0x62, 1, PutAll32 }, + { "RTI", 0x0000001, 0x40, 0, PutAll32 }, + { "RTS", 0x0000001, 0x60, 0, PutAll32 }, + { "SBC", 0x080A66C, 0xe0, 0, PutAll32 }, + { "SEC", 0x0000001, 0x38, 0, PutAll32 }, + { "SED", 0x0000001, 0xf8, 0, PutAll32 }, + { "SEI", 0x0000001, 0x78, 0, PutAll32 }, + { "SMB0", 0x0000004, 0x87, 1, PutAll32 }, + { "SMB1", 0x0000004, 0x97, 1, PutAll32 }, + { "SMB2", 0x0000004, 0xA7, 1, PutAll32 }, + { "SMB3", 0x0000004, 0xB7, 1, PutAll32 }, + { "SMB4", 0x0000004, 0xC7, 1, PutAll32 }, + { "SMB5", 0x0000004, 0xD7, 1, PutAll32 }, + { "SMB6", 0x0000004, 0xE7, 1, PutAll32 }, + { "SMB7", 0x0000004, 0xF7, 1, PutAll32 }, + { "STA", 0x000A66C, 0x80, 0, PutAll32 }, + { "STP", 0x0000001, 0xdb, 0, PutAll32 }, + { "STX", 0x000010c, 0x82, 1, PutAll32 }, + { "STY", 0x000002c, 0x80, 1, PutAll32 }, + { "STZ", 0x000006c, 0x04, 5, PutAll32 }, + { "TAX", 0x0000001, 0xaa, 0, PutAll32 }, + { "TAY", 0x0000001, 0xa8, 0, PutAll32 }, + { "TRB", 0x000000c, 0x10, 1, PutAll32 }, + { "TSB", 0x000000c, 0x00, 1, PutAll32 }, + { "TSX", 0x0000001, 0xba, 0, PutAll32 }, + { "TXA", 0x0000001, 0x8a, 0, PutAll32 }, + { "TXS", 0x0000001, 0x9a, 0, PutAll32 }, + { "TYA", 0x0000001, 0x98, 0, PutAll32 }, + { "WAI", 0x0000001, 0xcb, 0, PutAll32 } +/* END SORTED.SH */ + } +}; + /* Instruction table for the 65CE02 */ static const struct { unsigned Count; @@ -1622,6 +1738,7 @@ static const InsTable* InsTabs[CPU_COUNT] = { (const InsTable*) &InsTab45GS02, (const InsTable*) &InsTabW65C02, /* CMOS with WDC extensions */ (const InsTable*) &InsTab65CE02, /* CMOS with CSG extensions */ + (const InsTable*) &InsTab65C032, }; const InsTable* InsTab = (const InsTable*) &InsTab6502; @@ -1786,6 +1903,40 @@ static unsigned char Sweet16ExtBytes[AMSW16I_COUNT] = { 0, /* AMSW16_REG */ }; +unsigned char ExtBytes32[AM65I_COUNT] = { + 0, /* Implicit */ + 0, /* Accu */ + 1, /* Direct */ + 4, /* Absolute */ + 3, /* Absolute long */ + 1, /* Direct,X */ + 4, /* Absolute,X */ + 3, /* Absolute long,X */ + 1, /* Direct,Y */ + 4, /* Absolute,Y */ + 1, /* (Direct) */ + 4, /* (Absolute) */ + 1, /* [Direct] */ + 1, /* (Direct),Y */ + 1, /* [Direct],Y */ + 1, /* (Direct,X) */ + 4, /* (Absolute,X) */ + 1, /* Relative short */ + 2, /* Relative long */ + 1, /* r,s */ + 1, /* (r,s),y */ + 1, /* Immidiate accu */ + 1, /* Immidiate index */ + 1, /* Immidiate byte */ + 2, /* Blockmove (65816) */ + 7, /* Block transfer (HuC6280) */ + 4, /* Absolute Indirect long */ + 2, /* Immidiate word */ + 2, /* Direct, Relative short */ + 1, /* Special Page */ + 1, /* [Direct],z */ + 0, /* Q */ +}; /*****************************************************************************/ @@ -1849,15 +2000,23 @@ static int EvalEA (const InsDesc* Ins, EffAddr* A) } /* Check the size */ - switch (ED.AddrSize) { + if (CPU == CPU_65C032) { + switch (ED.AddrSize) { + case ADDR_SIZE_LONG: + A->AddrModeSet &= ~AM65_SET_ZP; + break; + } + } else { + switch (ED.AddrSize) { - case ADDR_SIZE_ABS: - A->AddrModeSet &= ~AM65_SET_ZP; - break; + case ADDR_SIZE_ABS: + A->AddrModeSet &= ~AM65_SET_ZP; + break; - case ADDR_SIZE_FAR: - A->AddrModeSet &= ~(AM65_SET_ZP | AM65_SET_ABS); - break; + case ADDR_SIZE_FAR: + A->AddrModeSet &= ~(AM65_SET_ZP | AM65_SET_ABS); + break; + } } /* Free any resource associated with the expression desc */ @@ -1950,6 +2109,39 @@ static void EmitCode (EffAddr* A) } } +static void EmitCode32 (EffAddr* A) +/* Output code for the data in A */ +{ + /* Check how many extension bytes are needed and output the instruction */ + switch (ExtBytes32[A->AddrMode]) { + + + case 0: + Emit0 (A->Opcode); + break; + + case 1: + Emit1 (A->Opcode, A->Expr); + break; + + case 2: + Internal ("65C032 has no 3 byte instructions!"); + break; + + case 3: + Internal ("65C032 has no 4 byte instructions!"); + break; + + case 4: + Emit4 (A->Opcode, A->Expr); + break; + + default: + Internal ("Invalid operand byte count: %u", ExtBytes[A->AddrMode]); + + } +} + static void PutLDM_m740 (const InsDesc* Ins) { @@ -2416,6 +2608,17 @@ static void PutAll (const InsDesc* Ins) } } +static void PutAll32 (const InsDesc* Ins) +/* Handle all other instructions for the 65C032 */ +{ + EffAddr A; + + /* Evaluate the Addressing Mode Used */ + if (EvalEA (Ins, &A)) { + /* No error, output code */ + EmitCode32 (&A); + } +} static void Emit4510 (EffAddr* A) { diff --git a/src/ca65/main.c b/src/ca65/main.c index 3e751109e..c9bb11eb9 100644 --- a/src/ca65/main.c +++ b/src/ca65/main.c @@ -219,6 +219,7 @@ static void DefineCpuSymbols (void) NewSymbol ("CPU_ISET_45GS02", CPU_ISET_45GS02); NewSymbol ("CPU_ISET_W65C02", CPU_ISET_W65C02); NewSymbol ("CPU_ISET_65CE02", CPU_ISET_65CE02); + NewSymbol ("CPU_ISET_65C032", CPU_ISET_65C032); /* Additional ones from cpu.mac. Not sure how useful they are after the ** changes from #2751. diff --git a/src/ca65/objcode.c b/src/ca65/objcode.c index d1ab4f6bd..38b9a27ba 100644 --- a/src/ca65/objcode.c +++ b/src/ca65/objcode.c @@ -131,6 +131,12 @@ void Emit3 (unsigned char OPC, ExprNode* Expr) EmitFarAddr (Expr); } +void Emit4 (unsigned char OPC, ExprNode* Expr) +/* Emit an instruction with a four byte argument */ +{ + Emit0 (OPC); + EmitDWord (Expr); +} void EmitSigned (ExprNode* Expr, unsigned Size) diff --git a/src/ca65/objcode.h b/src/ca65/objcode.h index 70a031164..a93d51ecf 100644 --- a/src/ca65/objcode.h +++ b/src/ca65/objcode.h @@ -62,6 +62,9 @@ void Emit2 (unsigned char OPC, ExprNode* Value); void Emit3 (unsigned char OPC, ExprNode* Expr); /* Emit an instruction with a three byte argument */ +void Emit4 (unsigned char OPC, ExprNode* Expr); +/* Emit an instruction with a four byte argument */ + void EmitSigned (ExprNode* Expr, unsigned Size); /* Emit a signed expression with the given size */ diff --git a/src/cc65/main.c b/src/cc65/main.c index b952667b0..5040f6e7f 100644 --- a/src/cc65/main.c +++ b/src/cc65/main.c @@ -413,6 +413,7 @@ static void DefineCpuMacros (void) DefineNumericMacro ("__CPU_ISET_65C02__", CPU_ISET_65C02); DefineNumericMacro ("__CPU_ISET_W65C02__", CPU_ISET_W65C02); DefineNumericMacro ("__CPU_ISET_65CE02__", CPU_ISET_65CE02); + DefineNumericMacro ("__CPU_ISET_65C032__", CPU_ISET_65C032); DefineNumericMacro ("__CPU_ISET_65816__", CPU_ISET_65816); DefineNumericMacro ("__CPU_ISET_HUC6280__", CPU_ISET_HUC6280); DefineNumericMacro ("__CPU_ISET_4510__", CPU_ISET_4510); diff --git a/src/common/cpu.c b/src/common/cpu.c index 6089b42c1..30d8e5787 100644 --- a/src/common/cpu.c +++ b/src/common/cpu.c @@ -68,6 +68,7 @@ const char* CPUNames[CPU_COUNT] = { "45GS02", "W65C02", /* CMOS with WDC extensions */ "65CE02", /* CMOS with CSG extensions */ + "65C032", /* CMOS with 32 bit addressing */ }; /* Tables with CPU instruction sets @@ -102,6 +103,8 @@ const unsigned CPUIsets[CPU_COUNT] = { CPU_ISET_W65C02 | CPU_ISET_6502 | CPU_ISET_65SC02 | CPU_ISET_65C02, /* CPU_65CE02 */ CPU_ISET_65CE02 | CPU_ISET_6502 | CPU_ISET_65C02, + /* CPU_65C032 */ + CPU_ISET_65C032, }; /* Defines for capabilities. Currently the entries are uint32_ts but the table diff --git a/src/common/cpu.h b/src/common/cpu.h index bc6260371..ec091319d 100644 --- a/src/common/cpu.h +++ b/src/common/cpu.h @@ -66,7 +66,8 @@ typedef enum { CPU_45GS02, /* CPU of MEGA65 */ CPU_W65C02, /* CMOS with WDC extensions */ CPU_65CE02, /* CMOS with CSG extensions */ - CPU_COUNT /* Number of different CPUs */ + CPU_65C032, /* CMOS with 32 bit addressing */ + CPU_COUNT, /* Number of different CPUs */ } cpu_t; /* CPU instruction sets */ @@ -84,7 +85,8 @@ enum { CPU_ISET_4510 = 1 << CPU_4510, CPU_ISET_45GS02 = 1 << CPU_45GS02, CPU_ISET_W65C02 = 1 << CPU_W65C02, - CPU_ISET_65CE02 = 1 << CPU_65CE02 + CPU_ISET_65CE02 = 1 << CPU_65CE02, + CPU_ISET_65C032 = 1 << CPU_65C032, }; /* CPU used */ diff --git a/test/asm/opcodes/65c032-opcodes.ref b/test/asm/opcodes/65c032-opcodes.ref new file mode 100644 index 000000000..e69de29bb diff --git a/test/asm/opcodes/65c032-opcodes.s b/test/asm/opcodes/65c032-opcodes.s new file mode 100644 index 000000000..4ff0a7537 --- /dev/null +++ b/test/asm/opcodes/65c032-opcodes.s @@ -0,0 +1,258 @@ +.setcpu "65C032" + + brk + ora ($12,x) + .byte $02 + .byte $03 + tsb $12 + ora $12 + asl $12 + rmb0 $12 + php + ora #$12 + asl a + .byte $0B + tsb $3456789a + ora $3456789a + asl $3456789a + bbr0 $12,*+122 + bpl *+122 + ora ($12),y + ora ($12) + .byte $13 + trb $12 + ora $12,x + asl $12,x + rmb1 $12 + clc + ora $3456789a,y + inc a + .byte $1B + trb $3456789a + ora $3456789a,x + asl $3456789a,x + bbr1 $12,*+122 + jsr $3456789a + and ($12,x) + .byte $22 + .byte $23 + bit $12 + and $12 + rol $12 + rmb2 $12 + plp + and #$12 + rol a + .byte $2B + bit $3456789a + and $3456789a + rol $3456789a + bbr2 $12,*+122 + bmi *+122 + and ($12),y + and ($12) + .byte $33 + bit $12,x + and $12,x + rol $12,x + rmb3 $12 + sec + and $3456789a,y + dec a + .byte $3B + bit $3456789a,x + and $3456789a,x + rol $3456789a,x + bbr3 $12,*+122 + rti + eor ($12,x) + .byte $42 + .byte $43 + .byte $44 + eor $12 + lsr $12 + rmb4 $12 + pha + eor #$12 + lsr a + .byte $4B + jmp $3456789a + eor $3456789a + lsr $3456789a + bbr4 $12,*+122 + bvc *+122 + eor ($12),y + eor ($12) + .byte $53 + .byte $54 + eor $12,x + lsr $12,x + rmb5 $12 + cli + eor $3456789a,y + phy + .byte $5B + .byte $5C + eor $3456789a,x + lsr $3456789a,x + bbr5 $12,*+122 + rts + adc ($12,x) + .byte $62 + .byte $63 + stz $12 + adc $12 + ror $12 + rmb6 $12 + pla + adc #$12 + ror a + .byte $6B + jmp ($3456789a) + adc $3456789a + ror $3456789a + bbr6 $12,*+122 + bvs *+122 + adc ($12),y + adc ($12) + .byte $73 + stz $12,x + adc $12,x + ror $12,x + rmb7 $12 + sei + adc $3456789a,y + ply + .byte $7B + jmp ($3456789a,x) + adc $3456789a,x + ror $3456789a,x + bbr7 $12,*+122 + bra *+122 + sta ($12,x) + .byte $82 + .byte $83 + sty $12 + sta $12 + stx $12 + smb0 $12 + dey + bit #$12 + txa + .byte $8B + sty $3456789a + sta $3456789a + stx $3456789a + bbs0 $12,*+122 + bcc *+122 + sta ($12),y + sta ($12) + .byte $93 + sty $12,x + sta $12,x + stx $12,y + smb1 $12 + tya + sta $3456789a,y + txs + .byte $9B + stz $3456789a + sta $3456789a,x + stz $3456789a,x + bbs1 $12,*+122 + ldy #$12 + lda ($12,x) + ldx #$12 + .byte $A3 + ldy $12 + lda $12 + ldx $12 + smb2 $12 + tay + lda #$12 + tax + .byte $AB + ldy $3456789a + lda $3456789a + ldx $3456789a + bbs2 $12,*+122 + bcs *+122 + lda ($12),y + lda ($12) + .byte $B3 + ldy $12,x + lda $12,x + ldx $12,y + smb3 $12 + clv + lda $3456789a,y + tsx + .byte $BB + ldy $3456789a,x + lda $3456789a,x + ldx $3456789a,y + bbs3 $12,*+122 + cpy #$12 + cmp ($12,x) + .byte $C2 + .byte $C3 + cpy $12 + cmp $12 + dec $12 + smb4 $12 + iny + cmp #$12 + dex + .byte $CB + cpy $3456789a + cmp $3456789a + dec $3456789a + bbs4 $12,*+122 + bne *+122 + cmp ($12),y + cmp ($12) + .byte $D3 + .byte $D4 + cmp $12,x + dec $12,x + smb5 $12 + cld + cmp $3456789a,y + phx + .byte $DB + .byte $DC + cmp $3456789a,x + dec $3456789a,x + bbs5 $12,*+122 + cpx #$12 + sbc ($12,x) + .byte $E2 + .byte $E3 + cpx $12 + sbc $12 + inc $12 + smb6 $12 + inx + sbc #$12 + nop + .byte $EB + cpx $3456789a + sbc $3456789a + inc $3456789a + bbs6 $12,*+122 + beq *+122 + sbc ($12),y + sbc ($12) + .byte $F3 + .byte $F4 + sbc $12,x + inc $12,x + smb7 $12 + sed + sbc $3456789a,y + plx + .byte $FB + .byte $FC + sbc $3456789a,x + inc $3456789a,x + bbs7 $12,*+122