diff --git a/6502.S b/6502.S new file mode 100644 index 0000000..e70b107 --- /dev/null +++ b/6502.S @@ -0,0 +1,1027 @@ + .syntax unified + .cpu cortex-m0 + .align 2 + .thumb + .thumb_func + .text + + .extern cpu6502_dump + .extern cpu6502_load + .extern cpu6502_store + +#define T0 r4 +#define T1 r5 +#define PC r6 +#define SR r7 +#define RA r8 +#define RX r9 +#define RY r10 +#define SP r11 + +#define FLAG_N (1 << 7) +#define FLAG_V (1 << 6) +#define FLAG_D (1 << 3) +#define FLAG_I (1 << 2) +#define FLAG_Z (1 << 1) +#define FLAG_C (1 << 0) + +.macro _ldb + bl cpu6502_load +.endm + +.macro _ldw + mov T0, r0 + bl cpu6502_load + mov T1, r0 + adds r0, T0, #1 + bl cpu6502_load + lsls r0, r0, #8 + adds r0, r0, T1 +.endm + +.macro _stb + bl cpu6502_store +.endm + +.macro _stw + mov T0, r0 + mov T1, r1 + bl cpu6502_store + adds r0, T0, #1 + lsrs r1, T1, #8 + bl cpu6502_store +.endm + +.macro _push16 reg + mov r0, SP + mov r1, \reg + lsrs r1, r1, #8 + _stb + mov r0, SP + subs r0, r0, #1 + mov r1, \reg + _stb + mov r0, SP + subs r0, r0, #2 + mov SP, r0 +.endm + +.macro _decode + b decode +.endm + +.macro _fromImm8 + adds PC, PC, #1 + mov r0, PC + _ldb +.endm + +.macro _clx flag + movs T0, #\flag + bics SR, SR, T0 + adds PC, PC, #1 +.endm + +.macro _sex flag + movs T0, #\flag + orrs SR, SR, T0 + adds PC, PC, #1 +.endm + +.macro _ld reg + _clx (FLAG_N | FLAG_Z) + mov \reg, r0 + beq 1f + _sex FLAG_Z +1: + movs r1, #0x80 + tst r0, r1 + beq 1f + _sex FLAG_N +1: + adds PC, PC, #1 +.endm + +.macro _resume + ldr r0, =#r_pc + ldr PC, [r0] + ldr r0, =#r_sr + ldr SR, [r0] + ldr r0, =#r_a + ldr T0, [r0] + mov RA, T0 + ldr r0, =#r_x + ldr T0, [r0] + mov RX, T0 + ldr r0, =#r_y + ldr T0, [r0] + mov RY, T0 + ldr r0, =#r_sp + ldr T0, [r0] + mov SP, T0 + ldr T0, =#op_table +.endm + +.macro _suspend + ldr r0, =#r_pc + str PC, [r0] + ldr r0, =#r_sr + str SR, [r0] + ldr r0, =#r_a + mov T0, RA + str T0, [r0] + ldr r0, =#r_x + mov T0, RX + str T0, [r0] + ldr r0, =#r_y + mov T0, RY + str T0, [r0] + ldr r0, =#r_sp + mov T0, SP + str T0, [r0] +.endm + +op00: + b quit +op01: + b quit +op02: + b quit +op03: + b quit +op04: + b quit +op05: + b quit +op06: + b quit +op07: + b quit +op08: + b quit +op09: + b quit +op0a: + b quit +op0b: + b quit +op0c: + b quit +op0d: + b quit +op0e: + b quit +op0f: + b quit +op10: + b quit +op11: + b quit +op12: + b quit +op13: + b quit +op14: + b quit +op15: + b quit +op16: + b quit +op17: + b quit +op18: // CLC + _clx FLAG_C + _decode +op19: + b quit +op1a: + b quit +op1b: + b quit +op1c: + b quit +op1d: + b quit +op1e: + b quit +op1f: + b quit +op20: // JSR + adds T0, PC, #2 + _push16 T0 + adds r0, PC, #1 + _ldw + mov PC, r0 + _decode +op21: + b quit +op22: + b quit +op23: + b quit +op24: + b quit +op25: + b quit +op26: + b quit +op27: + b quit +op28: + b quit +op29: + b quit +op2a: + b quit +op2b: + b quit +op2c: + b quit +op2d: + b quit +op2e: + b quit +op2f: + b quit +op30: + b quit +op31: + b quit +op32: + b quit +op33: + b quit +op34: + b quit +op35: + b quit +op36: + b quit +op37: + b quit +op38: // SEC + _sex FLAG_C + _decode +op39: + b quit +op3a: + b quit +op3b: + b quit +op3c: + b quit +op3d: + b quit +op3e: + b quit +op3f: + b quit +op40: + b quit +op41: + b quit +op42: + b quit +op43: + b quit +op44: + b quit +op45: + b quit +op46: + b quit +op47: + b quit +op48: + b quit +op49: + b quit +op4a: + b quit +op4b: + b quit +op4c: + b quit +op4d: + b quit +op4e: + b quit +op4f: + b quit +op50: + b quit +op51: + b quit +op52: + b quit +op53: + b quit +op54: + b quit +op55: + b quit +op56: + b quit +op57: + b quit +op58: // CLI + _clx FLAG_I + _decode +op59: + b quit +op5a: + b quit +op5b: + b quit +op5c: + b quit +op5d: + b quit +op5e: + b quit +op5f: + b quit +op60: + b quit +op61: + b quit +op62: + b quit +op63: + b quit +op64: + b quit +op65: + b quit +op66: + b quit +op67: + b quit +op68: + b quit +op69: + b quit +op6a: + b quit +op6b: + b quit +op6c: + b quit +op6d: + b quit +op6e: + b quit +op6f: + b quit +op70: + b quit +op71: + b quit +op72: + b quit +op73: + b quit +op74: + b quit +op75: + b quit +op76: + b quit +op77: + b quit +op78: // SEI + _sex FLAG_I + _decode +op79: + b quit +op7a: + b quit +op7b: + b quit +op7c: + b quit +op7d: + b quit +op7e: + b quit +op7f: + b quit +op80: + b quit +op81: + b quit +op82: + b quit +op83: + b quit +op84: + b quit +op85: + b quit +op86: + b quit +op87: + b quit +op88: + b quit +op89: + b quit +op8a: + b quit +op8b: + b quit +op8c: + b quit +op8d: + b quit +op8e: + b quit +op8f: + b quit +op90: + b quit +op91: + b quit +op92: + b quit +op93: + b quit +op94: + b quit +op95: + b quit +op96: + b quit +op97: + b quit +op98: + b quit +op99: + b quit +op9a: + b quit +op9b: + b quit +op9c: + b quit +op9d: + b quit +op9e: + b quit +op9f: + b quit +opa0: // LDY - Immediate + _fromImm8 + _ld RY + _decode +opa1: + b quit +opa2: // LDX - Immediate + _fromImm8 + _ld RX + _decode +opa3: + b quit +opa4: + b quit +opa5: + b quit +opa6: + b quit +opa7: + b quit +opa8: + b quit +opa9: // LDA - Immediate + _fromImm8 + _ld RA + _decode +opaa: + b quit +opab: + b quit +opac: + b quit +opad: + b quit +opae: + b quit +opaf: + b quit +opb0: + b quit +opb1: + b quit +opb2: + b quit +opb3: + b quit +opb4: + b quit +opb5: + b quit +opb6: + b quit +opb7: + b quit +opb8: // CLV + _clx FLAG_V + _decode +opb9: + b quit +opba: + b quit +opbb: + b quit +opbc: + b quit +opbd: + b quit +opbe: + b quit +opbf: + b quit +opc0: + b quit +opc1: + b quit +opc2: + b quit +opc3: + b quit +opc4: + b quit +opc5: + b quit +opc6: + b quit +opc7: + b quit +opc8: + b quit +opc9: + b quit +opca: + b quit +opcb: + b quit +opcc: + b quit +opcd: + b quit +opce: + b quit +opcf: + b quit +opd0: + b quit +opd1: + b quit +opd2: + b quit +opd3: + b quit +opd4: + b quit +opd5: + b quit +opd6: + b quit +opd7: + b quit +opd8: // CLD + _clx FLAG_D + _decode +opd9: + b quit +opda: + b quit +opdb: + b quit +opdc: + b quit +opdd: + b quit +opde: + b quit +opdf: + b quit +ope0: + b quit +ope1: + b quit +ope2: + b quit +ope3: + b quit +ope4: + b quit +ope5: + b quit +ope6: + b quit +ope7: + b quit +ope8: + b quit +ope9: + b quit +opea: + b quit +opeb: + b quit +opec: + b quit +oped: + b quit +opee: + b quit +opef: + b quit +opf0: + b quit +opf1: + b quit +opf2: + b quit +opf3: + b quit +opf4: + b quit +opf5: + b quit +opf6: + b quit +opf7: + b quit +opf8: // SED + _sex FLAG_D + _decode +opf9: + b quit +opfa: + b quit +opfb: + b quit +opfc: + b quit +opfd: + b quit +opfe: + b quit +opff: + b quit + + .global cpu6502_reset + .type cpu6502_reset, %function +cpu6502_reset: + push {r4-r7,lr} + movs r4, #0x00 + movs r5, #0x01 + lsls r5, r5, #8 + adds r5, r5, #0xff + movs r6, #0x30 + ldr r7, =#r_a + str r4, [r7] + ldr r7, =#r_x + str r4, [r7] + ldr r7, =#r_y + str r4, [r7] + ldr r7, =#r_sp + str r5, [r7] + ldr r7, =#r_sr + str r6, [r7] + ldr r0, =#0xfffc + _ldw + ldr r7, =#r_pc + str r0, [r7] + pop {r4-r7,pc} + + .global cpu6502_run + .type cpu6502_run, %function +cpu6502_run: + push {r4-r7,lr} + mov r0, r8 + mov r1, r9 + mov r2, r10 + mov r3, r11 + mov r4, r12 + push {r0-r4} + _resume + _decode +quit: + mov r12, r0 + _suspend + pop {r0-r4} + mov r8, r0 + mov r9, r1 + mov r10, r2 + mov r11, r3 + mov r0, r12 + mov r12, r4 + pop {r4-r7,pc} + +// void dump(uint16_t pc); + .type dump, %function +dump: + push {lr} + _suspend + ldr r0, =#r_sp + ldr r1, [r0] + ldr r0, =#r_sr + ldr r2, [r0] + push {r1,r2} + ldr r3, =#r_pc + ldr r0, [r3] + ldr r3, =#r_a + ldr r1, [r3] + ldr r3, =#r_x + ldr r2, [r3] + ldr r3, =#r_y + ldr r3, [r3] + // r0=pc, r1=a, r2=x, r3=y, [sp]=sp, [sp+4]=sr + bl cpu6502_dump + mov r0, sp + adds r0, r0, #8 + mov sp, r0 + pop {pc} + +// void decode(); + .type decode, %function +decode: + bl dump + mov r0, PC + _ldb + lsls r1, r0, #2 + ldr r2, =#op_table + adds r3, r2, r1 + ldr r1, [r3] + mov pc, r1 + + .section .rodata +op_table: + .long op00 + .long op01 + .long op02 + .long op03 + .long op04 + .long op05 + .long op06 + .long op07 + .long op08 + .long op09 + .long op0a + .long op0b + .long op0c + .long op0d + .long op0e + .long op0f + .long op10 + .long op11 + .long op12 + .long op13 + .long op14 + .long op15 + .long op16 + .long op17 + .long op18 + .long op19 + .long op1a + .long op1b + .long op1c + .long op1d + .long op1e + .long op1f + .long op20 + .long op21 + .long op22 + .long op23 + .long op24 + .long op25 + .long op26 + .long op27 + .long op28 + .long op29 + .long op2a + .long op2b + .long op2c + .long op2d + .long op2e + .long op2f + .long op30 + .long op31 + .long op32 + .long op33 + .long op34 + .long op35 + .long op36 + .long op37 + .long op38 + .long op39 + .long op3a + .long op3b + .long op3c + .long op3d + .long op3e + .long op3f + .long op40 + .long op41 + .long op42 + .long op43 + .long op44 + .long op45 + .long op46 + .long op47 + .long op48 + .long op49 + .long op4a + .long op4b + .long op4c + .long op4d + .long op4e + .long op4f + .long op50 + .long op51 + .long op52 + .long op53 + .long op54 + .long op55 + .long op56 + .long op57 + .long op58 + .long op59 + .long op5a + .long op5b + .long op5c + .long op5d + .long op5e + .long op5f + .long op60 + .long op61 + .long op62 + .long op63 + .long op64 + .long op65 + .long op66 + .long op67 + .long op68 + .long op69 + .long op6a + .long op6b + .long op6c + .long op6d + .long op6e + .long op6f + .long op70 + .long op71 + .long op72 + .long op73 + .long op74 + .long op75 + .long op76 + .long op77 + .long op78 + .long op79 + .long op7a + .long op7b + .long op7c + .long op7d + .long op7e + .long op7f + .long op80 + .long op81 + .long op82 + .long op83 + .long op84 + .long op85 + .long op86 + .long op87 + .long op88 + .long op89 + .long op8a + .long op8b + .long op8c + .long op8d + .long op8e + .long op8f + .long op90 + .long op91 + .long op92 + .long op93 + .long op94 + .long op95 + .long op96 + .long op97 + .long op98 + .long op99 + .long op9a + .long op9b + .long op9c + .long op9d + .long op9e + .long op9f + .long opa0 + .long opa1 + .long opa2 + .long opa3 + .long opa4 + .long opa5 + .long opa6 + .long opa7 + .long opa8 + .long opa9 + .long opaa + .long opab + .long opac + .long opad + .long opae + .long opaf + .long opb0 + .long opb1 + .long opb2 + .long opb3 + .long opb4 + .long opb5 + .long opb6 + .long opb7 + .long opb8 + .long opb9 + .long opba + .long opbb + .long opbc + .long opbd + .long opbe + .long opbf + .long opc0 + .long opc1 + .long opc2 + .long opc3 + .long opc4 + .long opc5 + .long opc6 + .long opc7 + .long opc8 + .long opc9 + .long opca + .long opcb + .long opcc + .long opcd + .long opce + .long opcf + .long opd0 + .long opd1 + .long opd2 + .long opd3 + .long opd4 + .long opd5 + .long opd6 + .long opd7 + .long opd8 + .long opd9 + .long opda + .long opdb + .long opdc + .long opdd + .long opde + .long opdf + .long ope0 + .long ope1 + .long ope2 + .long ope3 + .long ope4 + .long ope5 + .long ope6 + .long ope7 + .long ope8 + .long ope9 + .long opea + .long opeb + .long opec + .long oped + .long opee + .long opef + .long opf0 + .long opf1 + .long opf2 + .long opf3 + .long opf4 + .long opf5 + .long opf6 + .long opf7 + .long opf8 + .long opf9 + .long opfa + .long opfb + .long opfc + .long opfd + .long opfe + .long opff + + .bss +r_pc: .long 0 +r_a: .long 0 +r_x: .long 0 +r_y: .long 0 +r_sp: .long 0 +r_sr: .long 0 + diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..6a40d07 --- /dev/null +++ b/Makefile @@ -0,0 +1,52 @@ +APP = lpc1114app +CC = arm-linux-gnueabi-gcc +AS = arm-none-eabi-gcc -c +LD = arm-none-eabi-ld +OBJCOPY = arm-none-eabi-objcopy +LDSCRIPT= lpc1114.ld +LPC21ISP= lpc21isp +SERIAL = /dev/ttyUSB0 +#SERIAL = /dev/ttyACM0 +SPEED = 115200 +#SPEED = 9600 +CLOCK = 12000 +ROM = applebasic +ROMOBJ = $(ROM).o +ROMFLAG = -I binary -O elf32-littlearm -B arm --rename-section .data=.rodata +OBJS = vectors.o reset.o 6502.o apple2.o uart.o $(ROMOBJ) + +$(APP).bin: $(APP) + $(OBJCOPY) -O binary $< $@ + +$(APP): $(LDSCRIPT) $(OBJS) + $(LD) -T $(LDSCRIPT) -o $@ $(OBJS) + +$(ROM).rom: + @echo "*********************************************" + @echo "* $(ROM).rom is needed to build the app *" + @echo "*********************************************" + @exit 1 + +%.o: %.S + $(AS) -o $@ $< + +%.o: %.rom + $(OBJCOPY) $(ROMFLAG) $< $@ \ + --redefine-sym _binary_$(ROM)_rom_start=basic_rom \ + --strip-symbol _binary_$(ROM)_rom_end \ + --strip-symbol _binary_$(ROM)_rom_size + +# Test binary that runs on qemu user mode emulation for testing +test: 6502.o test.c + $(CC) -mthumb -static test.c 6502.o -o test && qemu-arm test + +# Assume a CQ Mary comaptible board. +run: $(APP).bin + $(LPC21ISP) -control -term -bin $(APP).bin $(SERIAL) $(SPEED) $(CLOCK) + +clean: + rm -rf $(APP).bin $(APP) $(OBJS) test + +# Use this build target to install required packages if you are on Ubuntu14.04. +install-deps: + sudo apt-get install binutils-arm-none-eabi gcc-arm-none-eabi gcc-arm-linux-gnueabi lpc21isp diff --git a/apple2.S b/apple2.S new file mode 100644 index 0000000..3eaf8c9 --- /dev/null +++ b/apple2.S @@ -0,0 +1,115 @@ + .syntax unified + .cpu cortex-m0 + .align 2 + .thumb + .thumb_func + + .extern basic_rom + + .section .rodata +dump0: + .ascii "*** dump *** PC=$\000" +dump1: + .ascii " A=$\000" +dump2: + .ascii " X=$\000" +dump3: + .ascii " Y=$\000" +dump4: + .ascii " SP=$\000" +dump5: + .ascii " NV-B_DIZC=\000" + + .text + .global cpu6502_dump + .type cpu6502_dump, %function +cpu6502_dump: + push {r4-r7, lr} + mov r4, r0 + mov r5, r1 + mov r6, r2 + mov r7, r3 + ldr r0, =#dump0 + bl uart_putstr + mov r0, r4 + bl uart_puthex16 + ldr r0, =#dump1 + bl uart_putstr + mov r0, r5 + bl uart_puthex + ldr r0, =#dump2 + bl uart_putstr + mov r0, r6 + bl uart_puthex + ldr r0, =#dump3 + bl uart_putstr + mov r0, r7 + bl uart_puthex + ldr r0, =#dump4 + bl uart_putstr + ldr r0, [sp, #20] + bl uart_puthex + ldr r0, =#dump5 + bl uart_putstr + ldr r4, [sp, #24] + mov r0, r4 + lsrs r0, #7 + bl uart_putx + mov r0, r4 + movs r5, #1 + lsrs r0, #6 + ands r0, r5 + bl uart_putx + movs r0, #'-' + bl uart_putc + mov r0, r4 + lsrs r0, #4 + ands r0, r5 + bl uart_putx + movs r0, #'_' + bl uart_putc + mov r0, r4 + lsrs r0, #3 + ands r0, r5 + bl uart_putx + mov r0, r4 + lsrs r0, #2 + ands r0, r5 + bl uart_putx + mov r0, r4 + lsrs r0, #1 + ands r0, r5 + bl uart_putx + mov r0, r4 + ands r0, r5 + bl uart_putx + movs r0, #'\n' + bl uart_putc + pop {r4-r7, pc} + + .global cpu6502_load + .type cpu6502_load, %function +cpu6502_load: + movs r1, r0 + lsrs r0, #8 + movs r2, #0xd0 + cmps r0, r2 + bhs 1f + // TODO: Load from RAM + movs r0, #0 + mov pc, lr +1: + // Load from ROM (0xd000-0xffff) + lsls r2, #8 + subs r1, r1, r2 + ldr r0, =#basic_rom + adds r0, r0, r1 + ldrb r0, [r0] + mov pc, lr + + .global cpu6502_store + .type cpu6502_store, %function +cpu6502_store: + // TODO + mov pc, lr + diff --git a/lpc1114.ld b/lpc1114.ld new file mode 100644 index 0000000..8bce077 --- /dev/null +++ b/lpc1114.ld @@ -0,0 +1,37 @@ +MEMORY +{ + flash (rx) : ORIGIN = 0x00000000, LENGTH = 32K + sram (rwx) : ORIGIN = 0x10000000, LENGTH = 4K +} + +SECTIONS +{ + .text : ALIGN(4) { + _vector_start = .; + KEEP(*(.isr_vector)) + _vector_end = .; + + _text_start = .; + KEEP(*(.text)) + _text_end = .; + + _rodata_start = .; + KEEP(*(.rodata)) + _rodata_end = .; + } > flash + + .data : ALIGN(4) { + _data_start = .; + KEEP(*(.data)) + _data_end = .; + } > sram AT > flash + + .bss : ALIGN(4) { + _bss_start = .; + KEEP(*(.bss)) + _bss_end = .; + } > sram + + _stack_top = 0x10001000; +} + diff --git a/registers.inc b/registers.inc new file mode 100644 index 0000000..fa4705a --- /dev/null +++ b/registers.inc @@ -0,0 +1,94 @@ + .equ U0RBR, 0x40008000 + .equ U0THR, 0x40008000 + .equ U0DLL, 0x40008000 + .equ U0DLM, 0x40008004 + .equ U0IER, 0x40008004 + .equ U0IIR, 0x40008008 + .equ U0FCR, 0x40008008 + .equ FIFO_ENABLE, (1 << 0) + .equ RX_RESET, (1 << 1) + .equ TX_RESET, (1 << 2) + .equ U0LCR, 0x4000800c + .equ WORD_LEN_5, 0 + .equ WORD_LEN_6, 1 + .equ WORD_LEN_7, 2 + .equ WORD_LEN_8, 3 + .equ STOP_BIT_1, (0 << 2) + .equ STOP_BIT_2, (1 << 2) + .equ PARITY_DISABLE,(0 << 3) + .equ PARITY_ENABLE, (1 << 3) + .equ PARITY_EVEN, (0 << 4) + .equ PARITY_ODD, (1 << 4) + .equ PARITY_1, (2 << 4) + .equ PARITY_0, (3 << 4) + .equ BREAK_DISABLE, (0 << 6) + .equ BREAK_ENABLE, (1 << 6) + .equ DLAB_DISABLE, (0 << 7) + .equ DLAB_ENABLE, (1 << 7) + .equ U0MCR, 0x40008010 + .equ U0LSR, 0x40008014 + .equ LSR_THRE, (1 << 5) + .equ U0MSR, 0x40008018 + .equ U0SCR, 0x4000801c + .equ U0ACR, 0x40008020 + .equ U0FDR, 0x40008028 + .equ MULVAL_SHIFT, 4 + .equ U0TER, 0x40008030 + .equ TXEN, (1 << 7) + .equ U0RS485CTRL, 0x4000804c + .equ U0ADRMATCH, 0x40008050 + .equ U0RS485DLY, 0x40008054 + + .equ IOCON_PIO2_0, 0x40044008 + .equ FUNC_PIO, 0 + .equ FUNC_DTR, 1 + .equ FUNC_SSEL, 2 + .equ MODE_DOWN, (1 << 3) + .equ MODE_UP, (2 << 3) + .equ MODE_REP, (3 << 3) + .equ HYS_EN, (1 << 5) + .equ PIO_BASE, (3 << 6) + .equ PIO_MASK, 0x3f + .equ IOCON_PIO1_5, 0x400440a0 + .equ FUNC_RTS, 1 + .equ FUNC_CT32, 2 + .equ IOCON_PIO1_6, 0x400440a4 + .equ FUNC_RXD, 1 + .equ IOCON_PIO1_7, 0x400440a8 + .equ FUNC_TXD, 1 + + .equ SYSAHBCLKCTRL, 0x40048080 + .equ CLK_IOCON, (1 << 16) + .equ CLK_UART, (1 << 12) + + .equ UARTCLKDIV, 0x40048098 + + .equ GPIO0DATA, 0x50003ffc + .equ GPIO0DIR, 0x50008000 + .equ GPIO0IS, 0x50008004 + .equ GPIO0IBE, 0x50008008 + .equ GPIO0IEV, 0x5000800c + .equ GPIO0IE, 0x50008010 + .equ GPIO0RIS, 0x50008014 + .equ GPIO0MIS, 0x50008018 + .equ GPIO0IC, 0x5000801c + + .equ GPIO1DATA, 0x50013ffc + .equ GPIO1DIR, 0x50018000 + .equ GPIO1IS, 0x50018004 + .equ GPIO1IBE, 0x50018008 + .equ GPIO1IEV, 0x5001800c + .equ GPIO1IE, 0x50018010 + .equ GPIO1RIS, 0x50018014 + .equ GPIO1MIS, 0x50018018 + .equ GPIO1IC, 0x5001801c + + .equ GPIO2DATA, 0x50023ffc + .equ GPIO2DIR, 0x50028000 + .equ GPIO2IS, 0x50028004 + .equ GPIO2IBE, 0x50028008 + .equ GPIO2IEV, 0x5002800c + .equ GPIO2IE, 0x50028010 + .equ GPIO2RIS, 0x50028014 + .equ GPIO2MIS, 0x50028018 + .equ GPIO2IC, 0x5002801c diff --git a/reset.S b/reset.S new file mode 100644 index 0000000..a30551f --- /dev/null +++ b/reset.S @@ -0,0 +1,32 @@ + .syntax unified + .cpu cortex-m0 + .align 2 + .thumb + .thumb_func + + .include "registers.inc" + + .extern cpu6502_reset + .extern cpu6502_run + .extern uart_init + .extern uart_putc + + .section .rodata +hello: + .ascii "Applerm II\n\000" + + .text + .global _reset + .type _reset, %function +_reset: + ldr r0, =#(_stack_top - 32) + mov sp, r0 + bl uart_init + ldr r0, =#hello + bl uart_putstr + + bl cpu6502_reset + bl cpu6502_run +1: + b 1b + .size _reset, .-_reset diff --git a/test.c b/test.c new file mode 100644 index 0000000..a88e64b --- /dev/null +++ b/test.c @@ -0,0 +1,34 @@ +#include +#include +#include + +uint8_t mem[0x10000]; + +void cpu6502_dump( + uint16_t pc, uint8_t a, uint8_t x, uint8_t y, uint8_t sp, uint8_t sr) { + printf("*** dump *** PC=$%04x A=$%02x X=$%02x Y=$%02x SP=$%02x " + "NV-B_DIZC=%d%d-%d_%d%d%d%d\n", + pc, a, x, y, sp, (sr >> 7) & 1, (sr >> 6) & 1, (sr >> 4) & 1, + (sr >> 3) & 1, (sr >> 2) & 1, (sr >> 1) & 1, sr & 1); +} + +uint8_t cpu6502_load(uint16_t addr) { + printf("load $%04x => $%02x\n", addr, mem[addr]); + return mem[addr]; +} + +void cpu6502_store(uint16_t addr, uint8_t data) { + printf("store $%04x <= $%02x\n", addr, data); + mem[addr] = data; +} + +int main(int argc, char** argv) { + FILE* fp = fopen("applebasic.rom", "rb"); + memset(mem, 0, 0x10000); + fread(&mem[0xd000], 1, 0x3000, fp); + fclose(fp); + cpu6502_reset(); + printf("quit: $%04x\n", cpu6502_run()); + return 0; +} + diff --git a/uart.S b/uart.S new file mode 100644 index 0000000..0b73465 --- /dev/null +++ b/uart.S @@ -0,0 +1,153 @@ + .syntax unified + .cpu cortex-m0 + .align 2 + .thumb + .thumb_func + + .include "registers.inc" + + .text + + // void uart_init() + .global uart_init + .type uart_init, %function +uart_init: + // 0) Set to provide I/O clock + ldr r0, =#SYSAHBCLKCTRL + ldr r1, [r0] + ldr r2, =#CLK_IOCON + orrs r1, r1, r2 + str r1, [r0] + // 1) IO port configuration to use UART + ldr r0, =#IOCON_PIO1_6 + movs r1, #(PIO_BASE | FUNC_RXD) + str r1, [r0] + ldr r0, =#IOCON_PIO1_7 + movs r1, #(PIO_BASE | FUNC_TXD) + str r1, [r0] + // 2) Set to provide UART clock + ldr r0, =#SYSAHBCLKCTRL + ldr r1, [r0] + ldr r2, =#CLK_UART + orrs r1, r1, r2 + str r1, [r0] + // 3) Set clock divider to enable UART clock + ldr r0, =#UARTCLKDIV + movs r1, #1 + str r1, [r0] + + // UART_PCLK = 12MHz, BR = 115200 + // DLM=0, DLL=4, DIVADDVAL = 5, MULVAL = 8 + ldr r0, =#U0LCR + movs r1, #DLAB_ENABLE + str r1, [r0] + ldr r0, =#U0DLM + movs r1, #0 + str r1, [r0] + ldr r0, =#U0DLL + movs r1, #4 + str r1, [r0] + ldr r0, =#U0FDR + movs r1, #((8 << MULVAL_SHIFT) | 5) + str r1, [r0] + + // Configure as 8-bit, 1 stop bit, no parity mode + ldr r0, =#U0LCR + movs r1, #(WORD_LEN_8 | STOP_BIT_1) + str r1, [r0] + + // Enable TX + ldr r0, =#U0TER + movs r1, #TXEN + str r1, [r0] + + // Reset FIFO + ldr r0, =#U0FCR + movs r1, #(FIFO_ENABLE | RX_RESET | TX_RESET) + str r1, [r0] + + mov pc, lr + .size uart_init, .-uart_init + + // void uart_putc(char c); + .global uart_putc + .type uart_putc, %function +uart_putc: + ldr r1, =#U0LSR + movs r2, #LSR_THRE +1: + ldr r3, [r1] + ands r3, r2, r3 + beq 1b + ldr r1, =#U0THR + str r0, [r1] + mov pc, lr + .size uart_putc, .-uart_putc + + // void uart_putstr(const char* str); + .global uart_putstr + .type uart_putstr, %function +uart_putstr: + push {r4, lr} + mov r4, r0 +1: + ldrb r0, [r4] + movs r0, r0 + beq 1f + bl uart_putc + movs r0, #1 + adds r4, r4, r0 + b 1b +1: + pop {r4, pc} + .size uart_putstr, .-uart_putstr + + // void uart_putx(char x); + .global uart_putx + .type uart_putx, %function +uart_putx: + push {lr} + movs r1, #10 + cmp r0, r1 + bhs 1f + movs r1, #'0' + adds r0, r0, r1 + bl uart_putc + pop {pc} +1: + movs r1, #('a' - 10) + adds r0, r0, r1 + bl uart_putc + pop {pc} + .size uart_putx, .-uart_putx + + // void uart_puthex(char n); + .global uart_puthex + .type uart_puthex, %function +uart_puthex: + push {lr} + push {r0} + lsrs r0, r0, #4 + bl uart_putx + pop {r0} + movs r1, #0xf + ands r0, r0, r1 + bl uart_putx + pop {pc} + .size uart_puthex, .-uart_puthex + + // void uart_puthex16(short n); + .global uart_puthex16 + .type uart_puthex16, %function +uart_puthex16: + push {lr} + push {r0} + lsrs r0, r0, #8 + bl uart_puthex + pop {r0} + movs r1, #0xff + ands r0, r0, r1 + bl uart_puthex + pop {pc} + .size uart_puthex16, .-uart_puthex16 + diff --git a/vectors.S b/vectors.S new file mode 100644 index 0000000..0658e7b --- /dev/null +++ b/vectors.S @@ -0,0 +1,97 @@ + .syntax unified + .cpu cortex-m0 + .align 2 + .thumb + .thumb_func + + .section .isr_vector + + .long _stack_top // 0x0000 + .long _reset // 0x0004 + .long _nmi // 0x0008 + .long _hard_fault // 0x000c + .long _reserved // 0x0010 + .long _reserved // 0x0014 + .long _reserved // 0x0018 + .long _reserved // 0x001c + .long _reserved // 0x0020 + .long _reserved // 0x0024 + .long _reserved // 0x0028 + .long _svc // 0x002c + .long _reserved // 0x0030 + .long _reserved // 0x0034 + .long _pend_sv // 0x0038 + .long _sys_tick // 0x003c + .long _pio0_0_wakeup // 0x0040 + .long _pio0_1_wakeup // 0x0044 + .long _pio0_2_wakeup // 0x0048 + .long _pio0_3_wakeup // 0x004c + .long _pio0_4_wakeup // 0x0050 + .long _pio0_5_wakeup // 0x0054 + .long _pio0_6_wakeup // 0x0058 + .long _pio0_7_wakeup // 0x005c + .long _pio0_8_wakeup // 0x0060 + .long _pio0_9_wakeup // 0x0064 + .long _pio0_10_wakeup // 0x0068 + .long _pio0_11_wakeup // 0x006c + .long _pio1_0_wakeup // 0x0070 + .long _c_can // 0x0074 + .long _ssp1 // 0x0078 + .long _i2c // 0x007c + .long _ct16b0 // 0x0080 + .long _ct16b1 // 0x0084 + .long _ct32b0 // 0x0088 + .long _ct32b1 // 0x008c + .long _ssp0 // 0x0090 + .long _uart // 0x0094 + .long _reserved // 0x0098 + .long _reserved // 0x009c + .long _adc // 0x00a0 + .long _wdt // 0x00a4 + .long _bod // 0x00a8 + .long _reserved // 0x00ac + .long _int3 // 0x00b0 + .long _int2 // 0x00b4 + .long _int1 // 0x00b8 + .long _int0 // 0x00bc + + .text + +_adc: +_bod: +_c_can: +_ct16b0: +_ct16b1: +_ct32b0: +_ct32b1: +_hard_fault: +_i2c: +_int0: +_int1: +_int2: +_int3: +_nmi: +_pend_sv: +_pio0_0_wakeup: +_pio0_1_wakeup: +_pio0_2_wakeup: +_pio0_3_wakeup: +_pio0_4_wakeup: +_pio0_5_wakeup: +_pio0_6_wakeup: +_pio0_7_wakeup: +_pio0_8_wakeup: +_pio0_9_wakeup: +_pio0_10_wakeup: +_pio0_11_wakeup: +_pio1_0_wakeup: +_reserved: +//_reset: +_ssp0: +_ssp1: +_svc: +_sys_tick: +_uart: +_wdt: +loop: + b loop