diff options
Diffstat (limited to 'opcode.c')
-rw-r--r-- | opcode.c | 358 |
1 files changed, 358 insertions, 0 deletions
diff --git a/opcode.c b/opcode.c new file mode 100644 index 0000000..ea3f726 --- /dev/null +++ b/opcode.c @@ -0,0 +1,358 @@ +#include "opcode.h" +void setps(struct sux *cpu, uint8_t thread) { + (cpu->c[thread]) ? (cpu->ps |= (C << 8*thread)) : (cpu->ps &= ~(C << 8*thread)); + (cpu->z[thread]) ? (cpu->ps |= (Z << 8*thread)) : (cpu->ps &= ~(Z << 8*thread)); + (cpu->i[thread]) ? (cpu->ps |= (I << 8*thread)) : (cpu->ps &= ~(I << 8*thread)); + (cpu->s[thread]) ? (cpu->ps |= (S << 8*thread)) : (cpu->ps &= ~(S << 8*thread)); + (cpu->v[thread]) ? (cpu->ps |= (V << 8*thread)) : (cpu->ps &= ~(V << 8*thread)); + (cpu->n[thread]) ? (cpu->ps |= (N << 8*thread)) : (cpu->ps &= ~(N << 8*thread)); +} + +void adc(struct sux *cpu, uint64_t adr, uint8_t thread) { + uint64_t value = (uint64_t)addr[adr] + | (uint64_t)addr[adr+1] << 8 + | (uint64_t)addr[adr+2] << 16 + | (uint64_t)addr[adr+3] << 24 + | (uint64_t)addr[adr+4] << 32 + | (uint64_t)addr[adr+5] << 40 + | (uint64_t)addr[adr+6] << 48 + | (uint64_t)addr[adr+7] << 56; + uint64_t sum = cpu->a[thread]+value+cpu->c[thread]; + cpu->z[thread] = (sum == 0); + cpu->n[thread] = (sum >> 63); + cpu->v[thread] = !((cpu->a[thread]^value) & 0x8000000000000000) && ((cpu->a[thread]^sum) & 0x8000000000000000); + cpu->c[thread] = (sum < value); + cpu->a[thread] = sum; + setps(cpu, thread); +} + +void sbc(struct sux *cpu, uint64_t adr, uint8_t thread) { + uint64_t value = (uint64_t)addr[adr] + | (uint64_t)addr[adr+1] << 8 + | (uint64_t)addr[adr+2] << 16 + | (uint64_t)addr[adr+3] << 24 + | (uint64_t)addr[adr+4] << 32 + | (uint64_t)addr[adr+5] << 40 + | (uint64_t)addr[adr+6] << 48 + | (uint64_t)addr[adr+7] << 56; + uint64_t sum = cpu->a[thread]-value-!cpu->c[thread]; + cpu->z[thread] = (sum == 0); + cpu->n[thread] = (sum >> 63); + cpu->v[thread] = ((cpu->a[thread]^value) & 0x8000000000000000) && ((cpu->a[thread]^sum) & 0x8000000000000000); + cpu->c[thread] = (sum > value); + cpu->a[thread] = sum; + setps(cpu, thread); +} + +void mul(struct sux *cpu, uint64_t adr, uint8_t thread) { + uint64_t value = (uint64_t)addr[adr] + | (uint64_t)addr[adr+1] << 8 + | (uint64_t)addr[adr+2] << 16 + | (uint64_t)addr[adr+3] << 24 + | (uint64_t)addr[adr+4] << 32 + | (uint64_t)addr[adr+5] << 40 + | (uint64_t)addr[adr+6] << 48 + | (uint64_t)addr[adr+7] << 56; + uint64_t sum = cpu->a[thread]*value+cpu->c[thread]; + cpu->z[thread] = (sum == 0); + cpu->n[thread] = (sum >> 63); + cpu->v[thread] = !((cpu->a[thread]^value) & 0x8000000000000000) && ((cpu->a[thread]^sum) & 0x8000000000000000); + cpu->c[thread] = (!((cpu->a[thread]^sum) && (cpu->a[thread]^value)) || (cpu->a[thread] >= ((uint64_t)1 << 32) && value >= ((uint64_t)1 << 32))); + cpu->a[thread] = sum; + setps(cpu, thread); +} + +void divd(struct sux *cpu, uint64_t adr, uint8_t thread) { + uint64_t value = (uint64_t)addr[adr] + | (uint64_t)addr[adr+1] << 8 + | (uint64_t)addr[adr+2] << 16 + | (uint64_t)addr[adr+3] << 24 + | (uint64_t)addr[adr+4] << 32 + | (uint64_t)addr[adr+5] << 40 + | (uint64_t)addr[adr+6] << 48 + | (uint64_t)addr[adr+7] << 56; + uint64_t sum = cpu->a[thread]/value; + cpu->z[thread] = (sum == 0); + cpu->v[thread] = !((cpu->a[thread]^value) & 0x8000000000000000) && ((cpu->a[thread]^sum) & 0x8000000000000000); + cpu->a[thread] = sum; + setps(cpu, thread); +} + +uint64_t and(struct sux *cpu, uint64_t value, uint8_t thread) { + uint64_t sum; + sum &= value; + cpu->z[thread] = (sum == 0); + cpu->n[thread] = (sum >> 63); + setps(cpu, thread); + return sum; +} + +void and_addr(struct sux *cpu, uint64_t* const reg, uint64_t adr, uint8_t thread) { + uint64_t value = (uint64_t)addr[adr] + | (uint64_t)addr[adr+1] << 8 + | (uint64_t)addr[adr+2] << 16 + | (uint64_t)addr[adr+3] << 24 + | (uint64_t)addr[adr+4] << 32 + | (uint64_t)addr[adr+5] << 40 + | (uint64_t)addr[adr+6] << 48 + | (uint64_t)addr[adr+7] << 56; + *reg &= value; + cpu->z[thread] = (*reg == 0); + cpu->n[thread] = (*reg >> 63); + setps(cpu, thread); +} + +uint64_t or(struct sux *cpu, uint64_t value, uint8_t thread) { + uint64_t sum; + sum |= value; + cpu->z[thread] = (sum == 0); + cpu->n[thread] = (sum >> 63); + setps(cpu, thread); + return sum; +} + +void or_addr(struct sux *cpu, uint64_t* const reg, uint64_t adr, uint8_t thread) { + uint64_t value = (uint64_t)addr[adr] + | (uint64_t)addr[adr+1] << 8 + | (uint64_t)addr[adr+2] << 16 + | (uint64_t)addr[adr+3] << 24 + | (uint64_t)addr[adr+4] << 32 + | (uint64_t)addr[adr+5] << 40 + | (uint64_t)addr[adr+6] << 48 + | (uint64_t)addr[adr+7] << 56; + *reg |= value; + cpu->z[thread] = (*reg == 0); + cpu->n[thread] = (*reg >> 63); + setps(cpu, thread); +} + +uint64_t xor(struct sux *cpu, uint64_t value, uint8_t thread) { + uint64_t sum; + sum ^= value; + cpu->z[thread] = (sum == 0); + cpu->n[thread] = (sum >> 63); + setps(cpu, thread); + return sum; +} + +void xor_addr(struct sux *cpu, uint64_t* const reg, uint64_t adr, uint8_t thread) { + uint64_t value = (uint64_t)addr[adr] + | (uint64_t)addr[adr+1] << 8 + | (uint64_t)addr[adr+2] << 16 + | (uint64_t)addr[adr+3] << 24 + | (uint64_t)addr[adr+4] << 32 + | (uint64_t)addr[adr+5] << 40 + | (uint64_t)addr[adr+6] << 48 + | (uint64_t)addr[adr+7] << 56; + *reg ^= value; + cpu->z[thread] = (*reg == 0); + cpu->n[thread] = (*reg >> 63); + setps(cpu, thread); +} + +void rol(struct sux *cpu, uint64_t adr, uint8_t thread) { + uint64_t value = addr[adr]; + uint64_t sum = cpu->a[thread] << value; + sum |= cpu->c[thread]; + cpu->z[thread] = (sum == 0); + cpu->n[thread] = (sum >> 63); + cpu->c[thread] = cpu->a[thread] >> (uint64_t)64-value; + cpu->a[thread] = sum; + setps(cpu, thread); +} + +void ror(struct sux *cpu, uint64_t adr, uint8_t thread) { + uint64_t value = addr[adr]; + uint64_t sum = cpu->a[thread] >> value; + sum |= (uint64_t)cpu->c[thread] << (uint64_t)64-value; + cpu->c[thread] = cpu->a[thread] & 1; + cpu->a[thread] = sum; + setps(cpu, thread); +} + +void lsl(struct sux *cpu, uint64_t adr, uint8_t thread) { + uint64_t value = addr[adr]; + uint64_t sum = (value < 64) ? cpu->a[thread] << value : 0; + cpu->c[thread] = cpu->a[thread] >> 64-value; + cpu->a[thread] = sum; + setps(cpu, thread); +} + +void lsr(struct sux *cpu, uint64_t adr, uint8_t thread) { + uint64_t value = addr[adr]; + uint64_t sum = (value < 64) ? cpu->a[thread] >> value : 0; + cpu->c[thread] = cpu->a[thread] & 1; + cpu->a[thread] = sum; + setps(cpu, thread); +} + +void inc(struct sux *cpu, uint64_t *reg, uint8_t thread) { + *reg += 1; + cpu->z[thread] = (*reg == 0); + cpu->n[thread] = (*reg >> 63); + setps(cpu, thread); +} + +void inc_addr(struct sux *cpu, uint64_t adr, uint8_t thread) { + addr[adr]++; +} + +void dec(struct sux *cpu, uint64_t *reg, uint8_t thread) { + *reg -= 1; + cpu->z[thread] = (*reg == 0); + cpu->n[thread] = (*reg >> 63); + setps(cpu, thread); +} + +void dec_addr(struct sux *cpu, uint64_t adr, uint8_t thread) { + addr[adr]--; +} + +void stt(struct sux* const cpu, uint8_t value) { + uint16_t tv = 0xFF50; /* Thread Vector. */ + uint8_t t = addr[value]; + cpu->crt |= t; + for (uint8_t i = 0; i < 7; i++) + if ((t >> i) & 1) { + uint64_t adr = (uint64_t)addr[tv+(8*i)] + | (uint64_t)addr[tv+1+(8*i)] << 8 + | (uint64_t)addr[tv+2+(8*i)] << 16 + | (uint64_t)addr[tv+3+(8*i)] << 24 + | (uint64_t)addr[tv+4+(8*i)] << 32 + | (uint64_t)addr[tv+5+(8*i)] << 40 + | (uint64_t)addr[tv+6+(8*i)] << 48 + | (uint64_t)addr[tv+7+(8*i)] << 56; + cpu->pc[i+1] = adr; + } +} + +void ent(struct sux *cpu, uint8_t value) { + uint8_t t = addr[value]; + cpu->crt &= ~t; + for (uint8_t i = 0; i < 7; i++) + if ((t >> i) & 1) + cpu->pc[i+1] = cpu->pc[0]+(i+1); +} + +void ld(struct sux *cpu, uint64_t *reg, uint64_t adr, uint8_t thread) { + *reg = (uint64_t)addr[adr] + | (uint64_t)addr[adr+1] << 8 + | (uint64_t)addr[adr+2] << 16 + | (uint64_t)addr[adr+3] << 24 + | (uint64_t)addr[adr+4] << 32 + | (uint64_t)addr[adr+5] << 40 + | (uint64_t)addr[adr+6] << 48 + | (uint64_t)addr[adr+7] << 56; + cpu->z[thread] = (*reg == 0); + cpu->n[thread] = (*reg >> 63); + setps(cpu, thread); +} + +void st(struct sux *cpu, uint64_t *reg, uint64_t adr, uint8_t thread) { + addr[adr] = *reg & 0xFF; + addr[adr+1] = *reg >> 8; + addr[adr+2] = *reg >> 16; + addr[adr+3] = *reg >> 24; + addr[adr+4] = *reg >> 32; + addr[adr+5] = *reg >> 40; + addr[adr+6] = *reg >> 48; + addr[adr+7] = *reg >> 56; +} + +void push(struct sux *cpu, uint8_t value) { + addr[STK_STADDR+cpu->sp] = value; + cpu->sp--; + addr[0xFF90] = cpu->sp & 0xFF; + addr[0xFF91] = cpu->sp >> 8; +} + +uint8_t pull(struct sux *cpu) { + cpu->sp++; + addr[0xFF90] = cpu->sp & 0xFF; + addr[0xFF91] = cpu->sp >> 8; + return addr[STK_STADDR+cpu->sp]; +} + +void cmp_addr(struct sux *cpu, uint64_t reg, uint64_t adr, uint8_t thread) { + uint64_t value = (uint64_t)addr[adr] + | (uint64_t)addr[adr+1] << 8 + | (uint64_t)addr[adr+2] << 16 + | (uint64_t)addr[adr+3] << 24 + | (uint64_t)addr[adr+4] << 32 + | (uint64_t)addr[adr+5] << 40 + | (uint64_t)addr[adr+6] << 48 + | (uint64_t)addr[adr+7] << 56; + uint64_t sum = reg-value; + cpu->n[thread] = (sum & 0x8000000000000000) ? 1 : 0; + cpu->z[thread] = (sum == 0) ? 1 : 0; + cpu->c[thread] = (sum > value) ? 1 : 0; + setps(cpu, thread); +} + +void cmp(struct sux *cpu, uint64_t reg1, uint64_t reg2, uint8_t thread) { + uint64_t sum = reg1-reg2; + cpu->n[thread] = (sum & 0x8000000000000000) ? 1 : 0; + cpu->z[thread] = (sum == 0) ? 1 : 0; + cpu->c[thread] = (sum > reg2) ? 1 : 0; + setps(cpu, thread); +} + +/* Branch if Flag Set. */ +void bfs(struct sux *cpu, uint8_t flag, uint64_t adr, uint8_t thread) { + if (flag) + cpu->pc[thread] = adr; +} + +/* Branch if Flag Clear. */ +void bfc(struct sux *cpu, uint8_t flag, uint64_t adr, uint8_t thread) { + if (!flag) + cpu->pc[thread] = adr; +} + +uint64_t immaddr(struct sux *cpu, uint8_t thread, uint8_t size) { + uint64_t adr = cpu->pc[thread]; + cpu->pc[thread]+=size; + return adr; +} + +uint64_t absaddr(struct sux *cpu, uint8_t thread) { + uint64_t adr = (uint64_t)addr[cpu->pc[thread]] + | (uint64_t)addr[cpu->pc[thread]+1] << 8 + | (uint64_t)addr[cpu->pc[thread]+2] << 16 + | (uint64_t)addr[cpu->pc[thread]+3] << 24 + | (uint64_t)addr[cpu->pc[thread]+4] << 32 + | (uint64_t)addr[cpu->pc[thread]+5] << 40 + | (uint64_t)addr[cpu->pc[thread]+6] << 48 + | (uint64_t)addr[cpu->pc[thread]+7] << 56; + cpu->pc[thread]+=8; + return adr; +} + +uint32_t zeromtx(struct sux *cpu, uint8_t thread) { + uint32_t adr = (uint32_t)addr[cpu->pc[thread]] + | (uint32_t)addr[cpu->pc[thread]+1] << 8 + | (uint32_t)addr[cpu->pc[thread]+2] << 16 + | (uint32_t)addr[cpu->pc[thread]+3] << 24; + cpu->pc[thread]+=4; + return adr; +} + +uint32_t zeromx(struct sux *cpu, uint8_t thread) { + uint32_t adr = (uint32_t)addr[cpu->pc[thread]] + | (uint32_t)addr[cpu->pc[thread]+1] << 8 + | (uint32_t)addr[cpu->pc[thread]+2] << 16 + | (uint32_t)addr[cpu->pc[thread]+3] << 24; + adr += cpu->x[thread]; + cpu->pc[thread]+=4; + return adr; +} + +uint32_t zeromy(struct sux *cpu, uint8_t thread) { + uint32_t adr = (uint32_t)addr[cpu->pc[thread]] + | (uint32_t)addr[cpu->pc[thread]+1] << 8 + | (uint32_t)addr[cpu->pc[thread]+2] << 16 + | (uint32_t)addr[cpu->pc[thread]+3] << 24; + adr += cpu->y[thread]; + cpu->pc[thread]+=4; + return adr; +} |