Skip to content

Commit

Permalink
Merge pull request #29 from Sonic-Amiga/cpu-fixes-from-phire
Browse files Browse the repository at this point in the history
Cpu fixes from phire
  • Loading branch information
EtchedPixels authored Jul 13, 2022
2 parents 138d5d4 + 229b143 commit f3e9541
Showing 1 changed file with 96 additions and 4 deletions.
100 changes: 96 additions & 4 deletions cpu6.c
Original file line number Diff line number Diff line change
Expand Up @@ -530,7 +530,7 @@ static int block_op(int inst)
return 0;
default:
fprintf(stderr, "%04X: Unknown block xfer %02X\n", cpu6_pc(), op);
return 0;
exit(1);
}
}

Expand Down Expand Up @@ -563,7 +563,6 @@ static int bignum_sub(int a_len, int b_len, uint64_t a_addr, uint16_t b_addr, in
fprintf(stderr, "unsupported SUBBIG at %04X\n", exec_pc);
exit(-1);
}
int a_idx = b_len - a_len; // might be negative

// For debugging
uint64_t result_big = 0;
Expand Down Expand Up @@ -1259,6 +1258,46 @@ static uint16_t rlc16(uint16_t a, uint16_t count)
return r;
}

static int mul16(unsigned dsta, unsigned a, unsigned b)
{
uint32_t r = (uint32_t)a * (uint32_t)b;
unsigned expected_sign = (a ^ b) & 0x8000;
unsigned sign = r & 0x8000;

mmu_mem_write16(dsta, r & 0xffff);

// These flags are a total guess
alu_out &= ~(ALU_F | ALU_M | ALU_V);
if (sign)
alu_out |= ALU_M;
if ((r & 0xffff) == 0)
alu_out |= ALU_V;
if (sign != expected_sign || r > 0xffff)
alu_out |= ALU_F;

return 0;
}

static int div16(unsigned dsta, unsigned a, unsigned b)
{
uint32_t r = (uint32_t)a / (uint32_t)b;
unsigned expected_sign = (a ^ b) & 0x8000;
unsigned sign = r & 0x8000;

mmu_mem_write16(dsta, r & 0xffff);

// These flags are a total guess
alu_out &= ~(ALU_F | ALU_M | ALU_V);
if (sign)
alu_out |= ALU_M;
if ((r & 0xffff) == 0)
alu_out |= ALU_V;
if (sign != expected_sign || r > 0xffff)
alu_out |= ALU_F;

return 0;
}

static int add16(unsigned dsta, unsigned a, unsigned b)
{
mmu_mem_write16(dsta, a + b);
Expand Down Expand Up @@ -1390,6 +1429,7 @@ static uint16_t decode_address(unsigned size, unsigned mode)
case 7:
fprintf(stderr, "unknown address indexing %X at %04X\n",
mode, exec_pc);
exit(1);
break;
default:
/* indexed off a register */
Expand Down Expand Up @@ -1594,7 +1634,9 @@ static int low_op(void)
new_pc = regpair_read(X);
{
uint8_t byte = popbyte();
alu_out = byte & (ALU_L | ALU_F | ALU_M | ALU_V);
// JSYS might have saved the flags, but RSYS doesn't restore them
// Syscalls sometimes return results as flags

/* We flip MMU context after all the POP cases */
cpu_mmu = byte & 0x07;
}
Expand Down Expand Up @@ -1670,6 +1712,7 @@ static int dma_op(void)
default:
fprintf(stderr, "Unknown DMA operations 2F%02X at %04X\n",
op, exec_pc);
exit(1);
break;
}
return 0;
Expand Down Expand Up @@ -2106,6 +2149,7 @@ static int alu4x_op(void)
case 0x4F: /* unused */
fprintf(stderr, "Unknown ALU4 op %02X at %04X\n", op,
exec_pc);
exit(1);
return 0;
default:
fprintf(stderr, "internal error alu4\n");
Expand Down Expand Up @@ -2182,6 +2226,7 @@ static int alu5x_op(void)
case 0x57: /* unused */
fprintf(stderr, "Unknown ALU5 op %02X at %04X\n", op,
exec_pc);
exit(1);
return 0;
case 0x58:
return add16(dsta, a, b);
Expand All @@ -2206,6 +2251,51 @@ static int alu5x_op(void)
}
}

static int muldiv_op() {

unsigned src, dst;
uint16_t addr;
uint16_t a; // First argument isn't always dst anymore.
uint16_t b;
uint16_t dsta;

// This is the same as alu5x

dst = fetch();
src = dst >> 4;
b = regpair_read(src & 0x0E);
dsta = regpair_addr(dst & 0x0E);
a = regpair_read(dst & 0XE);
switch(dst & 0x11) {
case 0x00: // dst_reg <- src_reg
break;
case 0x01: // dst_reg <- src_reg OP (direct)
// mov takes (direct)
addr = fetch16();
b = mmu_mem_read16(addr);
break;
case 0x10: // dst_reg <- src_reg OP literal
// mov takes literal
b = fetch16();
break;
case 0x11: // dst_reg <- (src_reg + disp16) OP dst_reg
// mov takes (src_reg + disp16)
addr = fetch16() + b;
b = a;
a = mmu_mem_read16(addr);
break;
}

switch (op) {
case 0x77: // 16bit Multiply
return mul16(dsta, a, b);
case 0x78: // 16bit Divide
return div16(dsta, a, b);
}
fprintf(stderr, "Unknown MULDIV op %02X at %04X\n", op, exec_pc);
exit(1);
}

/* It's not entirely clear what these instructions are for
* they set Level 1's AH to 0 and -1
*
Expand Down Expand Up @@ -2278,9 +2368,9 @@ void cpu_deassert_irq(unsigned ipl) {

unsigned cpu6_execute_one(unsigned trace)
{
cpu6_interrupt(trace);
exec_pc = pc;

cpu6_interrupt(trace);
if (trace)
fprintf(stderr, "CPU %04X: ", pc);
op = fetch();
Expand Down Expand Up @@ -2316,6 +2406,8 @@ unsigned cpu6_execute_one(unsigned trace)
return block_op(0x67);
if (op < 0x70)
return x_op();
if (op == 0x77 || op == 0x78)
return muldiv_op();
if (op < 0x80)
return jump_op();
if (op == 0xb6 || op == 0xc6)
Expand Down

0 comments on commit f3e9541

Please sign in to comment.