static void subx_w(struct cpu *cpu, WORD op) { WORD s,d,r; int rx,ry; rx = (op&0xe00)>>9; ry = op&0x7; if(op&0x8) { cpu->a[ry] -= 2; s = bus_read_word(cpu->a[ry]); cpu->a[rx] -= 2; d = bus_read_word(cpu->a[rx]); r = d-s; if(CHKX) r -= 1; bus_write_word(cpu->a[rx], r); ADD_CYCLE(18); } else { s = cpu->d[ry]&0xffff; d = cpu->d[rx]&0xffff; r = d-s; if(CHKX) r -= 1; cpu->d[rx] = (cpu->d[rx]&0xffff0000)|r; ADD_CYCLE(4); } cpu_set_flags_subx(cpu, s&0x8000, d&0x8000, r&0x8000, r); }
static struct cprint *movep_print(LONG addr, WORD op) { int ar,dr,o; struct cprint *ret; ret = cprint_alloc(addr); ar = op&0x7; dr = (op&0xe00)>>9; o = bus_read_word(addr+ret->size); if(o&0x8000) o |= 0xffff0000; ret->size += 2; switch((op&0xc0)>>6) { case 0: strcpy(ret->instr, "MOVEP.W"); sprintf(ret->data, "%d(A%d),D%d", o, ar, dr); break; case 1: strcpy(ret->instr, "MOVEP.L"); sprintf(ret->data, "%d(A%d),D%d", o, ar, dr); break; case 2: strcpy(ret->instr, "MOVEP.W"); sprintf(ret->data, "D%d,%d(A%d)", dr, o, ar); break; case 3: strcpy(ret->instr, "MOVEP.L"); sprintf(ret->data, "D%d,%d(A%d)", dr, o, ar); break; } return ret; }
static void cmpm_w(struct cpu *cpu, WORD op) { int rx,ry; WORD s,d,r; rx = (op&0xe00)>>9; ry = op&0x7; s = bus_read_word(cpu->a[ry]); cpu->a[ry] += 2; d = bus_read_word(cpu->a[rx]); cpu->a[rx] += 2; r = d-s; ADD_CYCLE(12); cpu_set_flags_cmp(cpu, s&0x8000, d&0x8000, r&0x8000, r); }
static void ori_to_ccr(struct cpu *cpu, WORD op) { WORD d; ENTER; ADD_CYCLE(20); d = bus_read_word(cpu->pc)&0x1f; cpu->pc += 2; cpu_set_sr(cpu->sr|d); cpu_prefetch(); }
static void andi_to_sr(struct cpu *cpu, WORD op) { WORD d; ENTER; if(cpu->sr&0x2000) { ADD_CYCLE(20); d = bus_read_word(cpu->pc); cpu->pc += 2; cpu_set_sr(cpu->sr&d); cpu->tracedelay = 1; } else { cpu_set_exception(8); /* Privilege violation */ } }
static void movep(struct cpu *cpu, WORD op) { LONG d,a; int dr,ar; ENTER; ar = op&0x7; dr = (op&0xe00)>>9; a = bus_read_word(cpu->pc); if(a&0x8000) a |= 0xffff0000; a += cpu->a[ar]; cpu->pc += 2; switch((op&0xc0)>>6) { case 0: d = (bus_read_byte(a)<<8)|bus_read_byte(a+2); cpu->d[dr] = (cpu->d[dr]&0xffff0000)|(d&0xffff); ADD_CYCLE(16); return; case 1: d = ((bus_read_byte(a)<<24)| (bus_read_byte(a+2)<<16)| (bus_read_byte(a+4)<<8)| (bus_read_byte(a+6))); cpu->d[dr] = d; ADD_CYCLE(24); return; case 2: d = cpu->d[dr]&0xffff; cpu_prefetch(); bus_write_byte(a, (BYTE)((d&0xff00)>>8)); bus_write_byte(a+2, (BYTE)((d&0xff))); ADD_CYCLE(16); return; case 3: d = cpu->d[dr]; cpu_prefetch(); bus_write_byte(a, (BYTE)((d&0xff000000)>>24)); bus_write_byte(a+2, (BYTE)((d&0xff0000)>>16)); bus_write_byte(a+4, (BYTE)((d&0xff00)>>8)); bus_write_byte(a+6, (BYTE)((d&0xff))); ADD_CYCLE(24); return; } }
static void subi_b(struct cpu *cpu, WORD op) { BYTE s,d,r; s = bus_read_word(cpu->pc)&0xff; cpu->pc += 2; if(op&0x38) { ADD_CYCLE(12); } else { ADD_CYCLE(8); } d = ea_read_byte(cpu, op&0x3f, 1); r = d-s; ea_set_prefetch_before_write(); ea_write_byte(cpu, op&0x3f, r); cpu_set_flags_sub(cpu, s&0x80, d&0x80, r&0x80, r); }
static void addi_w(struct cpu *cpu, WORD op) { WORD s,d,r; s = bus_read_word(cpu->pc); cpu->pc += 2; if(op&0x38) { ADD_CYCLE(12); } else { ADD_CYCLE(8); } d = ea_read_word(cpu, op&0x3f, 1); r = d+s; ea_set_prefetch_before_write(); ea_write_word(cpu, op&0x3f, r); cpu_set_flags_add(cpu, s&0x8000, d&0x8000, r&0x8000, r); }
// DMA into the RSP's memory space. void rsp_dma_read(struct rsp *rsp) { uint32_t length = (rsp->regs[RSP_CP0_REGISTER_DMA_READ_LENGTH] & 0xFFF) + 1; uint32_t skip = rsp->regs[RSP_CP0_REGISTER_DMA_READ_LENGTH] >> 20 & 0xFFF; unsigned count = rsp->regs[RSP_CP0_REGISTER_DMA_READ_LENGTH] >> 12 & 0xFF; unsigned j, i = 0; // Force alignment. length = (length + 0x7) & ~0x7; rsp->regs[RSP_CP0_REGISTER_DMA_CACHE] &= ~0x3; rsp->regs[RSP_CP0_REGISTER_DMA_DRAM] &= ~0x7; // Check length. if (((rsp->regs[RSP_CP0_REGISTER_DMA_CACHE] & 0xFFF) + length) > 0x1000) length = 0x1000 - (rsp->regs[RSP_CP0_REGISTER_DMA_CACHE] & 0xFFF); do { uint32_t source = rsp->regs[RSP_CP0_REGISTER_DMA_DRAM] & 0x7FFFFC; uint32_t dest = rsp->regs[RSP_CP0_REGISTER_DMA_CACHE] & 0x1FFC; j = 0; do { uint32_t source_addr = (source + j) & 0x7FFFFC; uint32_t dest_addr = (dest + j) & 0x1FFC; uint32_t word; bus_read_word(rsp, source_addr, &word); // Update opcode cache. if (dest_addr & 0x1000) { rsp->opcode_cache[(dest_addr - 0x1000) >> 2] = *rsp_decode_instruction(word); } else { word = byteswap_32(word); } memcpy(rsp->mem + dest_addr, &word, sizeof(word)); j += 4; } while (j < length); rsp->regs[RSP_CP0_REGISTER_DMA_DRAM] += length + skip; rsp->regs[RSP_CP0_REGISTER_DMA_CACHE] += length; } while(++i <= count);
static void bset_i(struct cpu *cpu, int mode) { BYTE b,d; b = (BYTE)bus_read_word(cpu->pc)&0xff; b &= 31; cpu->pc += 2; if(mode&0x38) { ADD_CYCLE(8); d = ea_read_byte(cpu, mode, 1); if(d & (1<<(b&7))) CLRZ; else SETZ; d |= (1<<(b&7)); ea_set_prefetch_before_write(); ea_write_byte(cpu, mode, d); } else { ADD_CYCLE(10); if(cpu->d[mode&7] & (1<<b)) CLRZ; else SETZ; cpu->d[mode&7] |= (1<<b); } }
static void link(struct cpu *cpu, WORD op) { int r; LONG d; ENTER; d = bus_read_word(cpu->pc); cpu->pc += 2; if(d&0x8000) d |= 0xffff0000; r = op&0x7; cpu->a[7] -= 4; cpu_prefetch(); bus_write_long(cpu->a[7], cpu->a[r]); cpu->a[r] = cpu->a[7]; cpu->a[7] += d; ADD_CYCLE(16); }
void bcc(struct cpu *cpu, WORD op) { SLONG o; int w; ENTER; w = 0; o = (SLONG)(SBYTE)(op&0xff); if(!o) { o = bus_read_word(cpu->pc); if(o&0x8000) o |= 0xffff0000; o -= 2; cpu->pc += 2; w = 1; } switch((op&0xf00)>>8) { case 0: /* BRA */ ADD_CYCLE(10); cpu->pc += o; break; case 1: /* BSR */ ADD_CYCLE(18); cpu->a[7] -= 4; bus_write_long(cpu->a[7], cpu->pc); cpu->pc += o; break; case 2: /* BHI */ if(!CHKC && !CHKZ) { ADD_CYCLE(10); cpu->pc += o; } else { ADD_CYCLE(8); if(w) ADD_CYCLE(4); } break; case 3: /* BLS */ if(CHKC || CHKZ) { ADD_CYCLE(10); cpu->pc += o; } else { ADD_CYCLE(8); if(w) ADD_CYCLE(4); } break; case 4: /* BCC */ if(!CHKC) { ADD_CYCLE(10); cpu->pc += o; } else { ADD_CYCLE(8); if(w) ADD_CYCLE(4); } break; case 5: /* BCS */ if(CHKC) { ADD_CYCLE(10); cpu->pc += o; } else { ADD_CYCLE(8); if(w) ADD_CYCLE(4); } break; case 6: /* BNE */ if(!CHKZ) { ADD_CYCLE(10); cpu->pc += o; } else { ADD_CYCLE(8); if(w) ADD_CYCLE(4); } break; case 7: /* BEQ */ if(CHKZ) { ADD_CYCLE(10); cpu->pc += o; } else { ADD_CYCLE(8); if(w) ADD_CYCLE(4); } break; case 8: /* BVC */ if(!CHKV) { ADD_CYCLE(10); cpu->pc += o; } else { ADD_CYCLE(8); if(w) ADD_CYCLE(4); } break; case 9: /* BVS */ if(CHKV) { ADD_CYCLE(10); cpu->pc += o; } else { ADD_CYCLE(8); if(w) ADD_CYCLE(4); } break; case 10: /* BPL */ if(!CHKN) { ADD_CYCLE(10); cpu->pc += o; } else { ADD_CYCLE(8); if(w) ADD_CYCLE(4); } break; case 11: /* BMI */ if(CHKN) { ADD_CYCLE(10); cpu->pc += o; } else { ADD_CYCLE(8); if(w) ADD_CYCLE(4); } break; case 12: /* BGE */ if((CHKN && CHKV) || (!CHKN && !CHKV)) { ADD_CYCLE(10); cpu->pc += o; } else { ADD_CYCLE(8); if(w) ADD_CYCLE(4); } break; case 13: /* BLT */ if((CHKN && !CHKV) || (!CHKN && CHKV)) { ADD_CYCLE(10); cpu->pc += o; } else { ADD_CYCLE(8); if(w) ADD_CYCLE(4); } break; case 14: /* BGT */ if((CHKN && CHKV && !CHKZ) || (!CHKN && !CHKV && !CHKZ)) { ADD_CYCLE(10); cpu->pc += o; } else { ADD_CYCLE(8); if(w) ADD_CYCLE(4); } break; case 15: /* BLE */ if(CHKZ || (CHKN && !CHKV) || (!CHKN && CHKV)) { ADD_CYCLE(10); cpu->pc += o; } else { ADD_CYCLE(8); if(w) ADD_CYCLE(4); } break; } cpu_prefetch(); }