diff options
author | mrb0nk500 <b0nk@b0nk.xyz> | 2019-12-01 17:40:41 -0500 |
---|---|---|
committer | mrb0nk500 <b0nk@b0nk.xyz> | 2019-12-02 18:10:41 -0500 |
commit | cbad8aabbc82efbe7a49572a2da74224ae9c9f85 (patch) | |
tree | e97b1ab35208bc3e4d633f235d875fd4c69d039f | |
parent | ca89989d057a19b647514656d96d00ff23be9640 (diff) |
Added the ability to disable the prefix byte.
Any instructions that either have a register size of
8 bits, use implied addressing, or branch can save a
byte by disabling the prefix byte.
It does this by checking if the first three bits are
all set to 1.
If true, then it will treat it as a prefix
byte, otherwise, it will treat it as an opcode.
-rw-r--r-- | asmmon.c | 89 | ||||
-rw-r--r-- | opcode.c | 22 | ||||
-rw-r--r-- | opcode.h | 1 | ||||
-rw-r--r-- | sux.c | 26 | ||||
-rw-r--r-- | test/test-no-prefix.s | 8 | ||||
-rw-r--r-- | test/test.s | 2 |
6 files changed, 118 insertions, 30 deletions
@@ -103,7 +103,7 @@ int asmmon() { char *cmd; char *tmp = malloc(sizeof(char *)*128); size_t size; - done &= ~6; + done &= ~14; getline(&buf, &size, stdin); cmd = strtok_r(buf, "\n", &tmp); if (cmd != NULL) { @@ -213,28 +213,79 @@ int asmmon() { } } } - if (postfix != NULL && !(done & 6)) { - if (strcasecmp(postfix, "w") == 0) { - addr[address++] = 1; - } else if (strcasecmp(postfix, "d") == 0) { - addr[address++] = 2; - } else if (strcasecmp(postfix, "q") == 0) { - addr[address++] = 3; - } else { - addr[address++] = 0; - } - } else if (postfix == NULL && !(done & 6)) { - addr[address++] = 0; - } if (ins != NULL && !(done & 6)) { uint8_t i; for (i = 0; i < 77; i++) { if (strcasecmp(opcodes[i].mnemonic, ins) == 0) { + if (addrmode == 0 && (opcodes[i].impl || opcodes[i].impl == CPS)) { + done |= 8; + } else if (addrmode == 1) { + switch (opcodes[i].imm) { + case PHP: + case PHA: + case PHY: + case PHX: + case PLP: + case PLA: + case PLY: + case PLX: + case STT: + case LSL: + case LSR: + case ROL: + case ROR: + case ENT: + done |= 8; + break; + } + } else { + if (strcasecmp(ins, "JMP") == 0) + done |=8; + if (strcasecmp(ins, "JSR") == 0) + done |=8; + if (strcasecmp(ins, "JSL") == 0) + done |=8; + if (strcasecmp(ins, "INC") == 0) + done |=8; + if (strcasecmp(ins, "BPO") == 0) + done |=8; + if (strcasecmp(ins, "BNG") == 0) + done |=8; + if (strcasecmp(ins, "BCS") == 0) + done |=8; + if (strcasecmp(ins, "BCC") == 0) + done |=8; + if (strcasecmp(ins, "BEQ") == 0) + done |=8; + if (strcasecmp(ins, "BNE") == 0) + done |=8; + if (strcasecmp(ins, "BVS") == 0) + done |=8; + if (strcasecmp(ins, "BVC") == 0) + done |=8; + } op = opcodes[i]; break; } } - uint8_t r = addr[address-1] & 3; + if (postfix != NULL && !(done & 8)) { + if (strcasecmp(postfix, "w") == 0) { + addr[address++] = 0x17; + } else if (strcasecmp(postfix, "d") == 0) { + addr[address++] = 0x27; + } else if (strcasecmp(postfix, "q") == 0) { + addr[address++] = 0x37; + } else { + done |=8; + } + } else if (postfix == NULL && !(done & 8)) { + done |=8; + } + uint8_t r; + if (!(done & 8)) + r = addr[address-1]; + else + r = 0; switch (addrmode) { case 0: if (op.impl || op.impl == CPS) { @@ -266,18 +317,18 @@ int asmmon() { break; default: addr[address] = value & 0xFF; - if (r & 1) + if (r & 0x10) addr[address+1] = value >> 8; - if (r & 2) + if (r & 0x20) addr[address+2] = value >> 16; addr[address+3] = value >> 24; - if (r & 3) + if (r & 0x30) addr[address+4] = value >> 32; addr[address+5] = value >> 40; addr[address+6] = value >> 48; addr[address+7] = value >> 56; - address+=(1 << (r & 3)); + address+=(1 << ((r & 0x30) >> 4)); break; } @@ -12,8 +12,9 @@ void setps(struct sux *cpu, uint8_t thread) { void adc(struct sux *cpu, uint64_t adr, uint8_t thread, uint8_t regsize) { uint64_t value; value = (uint64_t)addr[adr]; - if (regsize >= 2) + if (regsize >= 2) { value += (uint64_t)addr[adr+1] << 8; + } if (regsize >= 4) { value += (uint64_t)addr[adr+2] << 16; value += (uint64_t)addr[adr+3] << 24; @@ -385,6 +386,7 @@ uint64_t absaddr(struct sux *cpu, uint8_t thread) { | (uint64_t)addr[cpu->pc[thread]+6] << 48 | (uint64_t)addr[cpu->pc[thread]+7] << 56; cpu->pc[thread]+=8; + ibcount+=8; clk++; return adr; } @@ -395,7 +397,11 @@ uint32_t zeromtx(struct sux *cpu, uint8_t thread) { | (uint32_t)addr[cpu->pc[thread]+2] << 16 | (uint32_t)addr[cpu->pc[thread]+3] << 24; cpu->pc[thread]+=4; - clk++; + ibcount+=4; + if (ibcount > 8) { + clk++; + ibcount = 0; + } return adr; } @@ -406,7 +412,11 @@ uint32_t zeromx(struct sux *cpu, uint8_t thread) { | (uint32_t)addr[cpu->pc[thread]+3] << 24; adr += cpu->x[thread]; cpu->pc[thread]+=4; - clk++; + ibcount+=4; + if (ibcount > 8) { + clk++; + ibcount = 0; + } return adr; } @@ -417,6 +427,10 @@ uint32_t zeromy(struct sux *cpu, uint8_t thread) { | (uint32_t)addr[cpu->pc[thread]+3] << 24; adr += cpu->y[thread]; cpu->pc[thread]+=4; - clk++; + ibcount+=4; + if (ibcount > 8) { + clk++; + ibcount = 0; + } return adr; } @@ -97,6 +97,7 @@ struct sux; uint8_t *addr; /* Address Space. */ uint64_t clk; /* Clock cycles. */ +uint8_t ibcount; /* Number of bytes taken up by instruction. */ struct sux { uint64_t ps; /* The processor status register. */ @@ -6,7 +6,8 @@ int run(struct sux *cpu, uint8_t prefix, uint8_t opcode, uint8_t thread) { uint64_t address; - uint8_t regsize = (1 << (prefix & 3)); + uint8_t rs = (prefix & 0x30) >> 4; + uint8_t regsize = (1 << rs); uint8_t tmp; address = cpu->pc[thread]; #if !bench @@ -17,7 +18,10 @@ int run(struct sux *cpu, uint8_t prefix, uint8_t opcode, uint8_t thread) { fflush(stdout); #endif cpu->pc[thread]++; - clk++; + if (ibcount > 8) { + clk++; + ibcount = 0; + } switch(opcode) { case CPS: /* Clear Processor Status. */ for (uint8_t i = 0; i < 8; i++) { @@ -366,6 +370,7 @@ int main(int argc, char **argv) { cpu.x[0] = 0; cpu.y[0] = 0; cpu.sp = 0xFFFF; + ibcount = 0; addr = malloc(8*0x04000000); int v = 0; if (asmmon() == 2) @@ -416,13 +421,21 @@ int main(int argc, char **argv) { st = clock(); #endif while (!end) { - prefix = addr[cpu.pc[0]++]; + prefix = addr[cpu.pc[0]]; + if ((prefix & 0x07) == 0x07) { + cpu.pc[0]++; + ibcount++; + } opcode = addr[cpu.pc[0]]; + ibcount++; #if !bench printf("\033[%uH\033[2K", lines); lines++; #endif - run(&cpu, prefix, opcode, 0); + if ((prefix & 0x07) == 0x07) + run(&cpu, prefix-7, opcode, 0); + else + run(&cpu, 0, opcode, 0); #if !bench if (lines > 24) lines = 2; @@ -431,9 +444,8 @@ int main(int argc, char **argv) { t0 = ((double)clock() - (double)st)/(double)CLOCKS_PER_SEC; #endif inst++; - #if !bench - printf("\033[HInstructions executed: %llu, Clock cycles: %llu\n", inst, clk); + printf("\033[HInstruction bytes: %x, Instructions executed: %llu, Clock cycles: %llu\n", ibcount, inst, clk); fflush(stdout); #endif #if bench @@ -441,6 +453,8 @@ int main(int argc, char **argv) { end = 1; } #endif + if (ibcount >= 7) + ibcount = 0; } #if bench en = (double)clock(); diff --git a/test/test-no-prefix.s b/test/test-no-prefix.s new file mode 100644 index 0000000..3c9c6a9 --- /dev/null +++ b/test/test-no-prefix.s @@ -0,0 +1,8 @@ +cps +lda #$10 +rol #$1 +jmp $3 +;viewmem +;q +done + diff --git a/test/test.s b/test/test.s index 3e8a7f2..7c36579 100644 --- a/test/test.s +++ b/test/test.s @@ -5,7 +5,7 @@ cps ; Clear the processor status register. lda.w #$1000 ; Load 0x1000 into the accumulator. rol #$1 ; Then rotate the accumulator left by 1 bit. -jmp $8006 ; And then loop. +jmp $8005 ; And then loop. .org $FFC0 ; Reset vector. .qword $8000 |