summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormrb0nk500 <b0nk@b0nk.xyz>2019-12-01 17:40:41 -0500
committermrb0nk500 <b0nk@b0nk.xyz>2019-12-02 18:10:41 -0500
commitcbad8aabbc82efbe7a49572a2da74224ae9c9f85 (patch)
treee97b1ab35208bc3e4d633f235d875fd4c69d039f
parentca89989d057a19b647514656d96d00ff23be9640 (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.c89
-rw-r--r--opcode.c22
-rw-r--r--opcode.h1
-rw-r--r--sux.c26
-rw-r--r--test/test-no-prefix.s8
-rw-r--r--test/test.s2
6 files changed, 118 insertions, 30 deletions
diff --git a/asmmon.c b/asmmon.c
index fd7c636..1a41214 100644
--- a/asmmon.c
+++ b/asmmon.c
@@ -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;
}
diff --git a/opcode.c b/opcode.c
index 0bee207..4484466 100644
--- a/opcode.c
+++ b/opcode.c
@@ -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;
}
diff --git a/opcode.h b/opcode.h
index d83b74c..5203fa9 100644
--- a/opcode.h
+++ b/opcode.h
@@ -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. */
diff --git a/sux.c b/sux.c
index f42c0da..7bb8661 100644
--- a/sux.c
+++ b/sux.c
@@ -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