# HG changeset patch # User Michael Pavone # Date 1472615454 25200 # Node ID 51672bd41cdd914b3a4f22443095829cec3895e1 # Parent 5338b9affd09231bef5731014a143d28c1643705 Rework data segment setup to allow a stack segment and to add space for push and pop instructions diff -r 5338b9affd09 -r 51672bd41cdd simple_console.txt --- a/simple_console.txt Mon Aug 29 21:17:41 2016 -0700 +++ b/simple_console.txt Tue Aug 30 20:50:54 2016 -0700 @@ -63,36 +63,44 @@ 0: reti - return from interrupt, D = register to restore from uer 1: trapi -2: getepc -3: setepc -4: getepch -5: setepch -6: getesr -7: setesr -8: getenum -9: setenum +2: push +3: pop +4: getpch +5: setpch +6: getepc +7: setepc +8: getesr +9: setesr A: getuer B: setuer -C: getvbr -D: setvbr -E: getdatabanks -F: setdatabanks +C: getenum +D: setenum +E: getvbr +F: setvbr Registers: -r0 - r12 : general purpose -r13 : technically general purpose, but canonically the stack register +r0 - r11 : general purpose +r12 : Data Banks - Holds the upper bytes used for data accesses (MSB = byte for lower half of memory space, LSB = byte for upper half of memory space) +r13 : stack register r14 : PC -r15 : status register +r15 : status register, Stack MSB + Layout: XSSS SSSS XXXN CZ10 + S = Stack most significant bits + N = Negaitve flag + C = Carry flag + Z = Zero flag + 1 = Interrupt 1 enable + 0 = Interrupt 0 enable Special Registers +pch - PC High - Low byte stores current PC High value, Upper byte stores saved PC High value when entering an exception handler epc - Exception PC - Stores PC value to resume to when entering an exception handler -epch - High 7-bits of PC esr - Exception SR - same as above, but for SR eur - Exceptuion User Reg - reg for temporary storage of a reg in a handler, intended to be used for the stack pointer enum - Exception Number - holds the number of the most recent exception -databanks - Holds the upper bytes used for data accesses (MSB = byte for upper half of memory space, LSB = byte for lower half of memory space) +vbr - Vector Base Register - Base address in page 0 of vector table IO: Ports @@ -151,8 +159,22 @@ $400000 - $4FFFFF - 128K RAM, mirrored every 128KB $500000 - $6FFFFF - Reserved $700000 - $7FFFFF - 64KB VRAM back buffer, mirrored every 64KB + +Banking/Segments: + Code Segment: 64KB, used for instruction fetch and PC-relative load/stores + Stack Segment: 64KB, used for push/pop and SP-relative load/stores + Upper Data Segment: 32KB, used for load/stores to addresses in the upper half of the 16-bit address space + Lower Data Segment: 32KB, used for load/stores to addresses in the lower half of the 16-bit address space - + 23-bit address generation details: + Code segment + r14 (aka PC) is used for the low 16 bits of the address and PCH is used for the upper 7 bits + Stack Segment + r13 (aka SP) is used for the low 16 bits of the address and the upper byte of SR is used for + the upper 7-bits. Note that for a load/store that uses both PC and SP, the code segment is used + Data segments + The low 15-bits of the computed 16-bit address are used directly. The most significant bit + selects a data segment and then the relevant byte of r12 is used for the upper 8 bits 26.112 MHZ Clock Dot Clock Divider 4 CPU Clock Divider 4 (assuming 1 cycle/instruction, 1 for 4 cycles/instruction) diff -r 5338b9affd09 -r 51672bd41cdd src/asm.c --- a/src/asm.c Mon Aug 29 21:17:41 2016 -0700 +++ b/src/asm.c Tue Aug 30 20:50:54 2016 -0700 @@ -120,8 +120,8 @@ } return ret; } - index = find_string_arr(mnemonics_single_reg, mnemonic, SETDATABANKS+1); - if (index > SETDATABANKS) { + index = find_string_arr(mnemonics_single_reg, mnemonic, SETVBR+1); + if (index > SETVBR) { ret.base = 0xFFFF; return ret; } @@ -308,6 +308,14 @@ return 1; } } + if (!strcmp(arg, "db")) { + *inst |= REG_DB << arg_shift; + return 1; + } + if (!strcmp(arg, "sp")) { + *inst |= REG_SP << arg_shift; + return 1; + } if (!strcmp(arg, "pc")) { *inst |= REG_PC << arg_shift; return 1; diff -r 5338b9affd09 -r 51672bd41cdd src/cpu.c --- a/src/cpu.c Mon Aug 29 21:17:41 2016 -0700 +++ b/src/cpu.c Tue Aug 30 20:50:54 2016 -0700 @@ -127,10 +127,10 @@ void vector_fetch(cpu *context) { context->exception_pc = context->regs[REG_PC] - 2; - context->exception_pch = context->pc_msb >> 16; + context->exception_pc_msb = context->pc_msb; context->exception_sr = context->regs[REG_SR]; context->regs[REG_SR] &= ~(STATUS_INT0_ENABLE | STATUS_INT1_ENABLE); - context->regs[REG_PC] = cpu_read_16(context, context->vector_base + context->exception * 2); + context->regs[REG_PC] = cpu_read_16(context, (context->vector_base + context->exception * 2) & 0xFFFF); context->pc_msb = 0; context->state = STATE_NEED_FETCH; } @@ -236,12 +236,25 @@ context->regs[dst] = context->exception_ur; context->regs[REG_PC] = context->exception_pc; context->regs[REG_SR] = context->exception_sr; + context->pc_msb = context->exception_pc_msb; context->state = STATE_NEED_FETCH; return; case TRAPI: context->state = STATE_EXCEPTION_START; context->exception = dst; - return; + return; + case PUSH: + break; + case POP: + break; + case GETPCH: + context->regs[dst] = context->exception_pc_msb >> 8 | context->pc_msb >> 16; + break; + case SETPCH: + context->exception_pc_msb = context->regs[dst] << 8 & 0x7F0000; + context->pc_msb = context->regs[dst] << 16 & 0x7F0000; + context->state = STATE_NEED_FETCH; + return; case GETEPC: context->regs[dst] = context->exception_pc; break; @@ -272,17 +285,6 @@ case SETVBR: context->vector_base = context->regs[dst]; break; - case GETDATABANKS: - context->regs[dst] = context->data_high_msb >> 7 | context->data_low_msb >> 15; - break; - case SETDATABANKS: - context->data_high_msb = (context->regs[dst] & 0xFF00) << 7; - context->data_low_msb = (context->regs[dst] & 0xFF) << 15; - break; - default: - context->state = STATE_EXCEPTION_START; - context->exception = EXCEPTION_INVALID_INSTRUCTION; - return; } if (dst == REG_PC) { context->state = STATE_NEED_FETCH; @@ -390,10 +392,12 @@ uint32_t address = context->regs[a] + context->regs[b]; if (a == REG_PC || b == REG_PC) { address |= context->pc_msb; + } else if (a == REG_SP || b == REG_SP) { + address |= context->regs[REG_SR] << 8 & 0x7F0000; } else if (address & 0x8000) { - address = (address & 0x7FFF) | context->data_high_msb; + address = (address & 0x7FFF) | (context->regs[REG_DB] << 15 & 0x7F8000); } else { - address |= context->data_low_msb; + address |= context->regs[REG_DB] << 7 & 0x7F8000; } return address; } diff -r 5338b9affd09 -r 51672bd41cdd src/cpu.h --- a/src/cpu.h Mon Aug 29 21:17:41 2016 -0700 +++ b/src/cpu.h Tue Aug 30 20:50:54 2016 -0700 @@ -34,13 +34,11 @@ uint16_t regs[16]; uint16_t exception; uint16_t exception_pc; - uint16_t exception_pch; uint16_t exception_sr; uint16_t exception_ur; uint16_t vector_base; uint32_t pc_msb; - uint32_t data_low_msb; - uint32_t data_high_msb; + uint32_t exception_pc_msb; uint16_t prefetch; @@ -103,10 +101,12 @@ enum { RETI, TRAPI, + PUSH, + POP, + GETPCH, + SETPCH, GETEPC, SETEPC, - GETEPCH, - SETEPCH, GETESR, SETESR, GETEUR, @@ -115,8 +115,6 @@ SETENUM, GETVBR, SETVBR, - GETDATABANKS, - SETDATABANKS, }; enum { @@ -132,6 +130,8 @@ COND_LEQ }; +#define REG_DB 12 +#define REG_SP 13 #define REG_PC 14 #define REG_SR 15 diff -r 5338b9affd09 -r 51672bd41cdd src/mnemonics.c --- a/src/mnemonics.c Mon Aug 29 21:17:41 2016 -0700 +++ b/src/mnemonics.c Tue Aug 30 20:50:54 2016 -0700 @@ -8,5 +8,5 @@ }; char * mnemonics_single_reg[] = { - "reti", "trapi", "getepc", "setepc", "getepch", "setepch", "getesr", "setesr", "getenum", "setenum", "getuer", "setuer", "getvbr", "setvbr", "getdatabanks", "setdatabanks" + "reti", "trapi", "push", "pop", "getpch", "setpch", "getepc", "setepc", "getesr", "setesr", "getuer", "setuer", "getenum", "setenum", "getvbr", "setvbr" };