--- trunk/src/cpus/cpu_sh_instr.c 2007/10/08 16:20:58 32 +++ trunk/src/cpus/cpu_sh_instr.c 2007/10/08 16:21:17 34 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2006 Anders Gavare. All rights reserved. + * Copyright (C) 2005-2007 Anders Gavare. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -25,7 +25,7 @@ * SUCH DAMAGE. * * - * $Id: cpu_sh_instr.c,v 1.44 2006/11/02 05:43:43 debug Exp $ + * $Id: cpu_sh_instr.c,v 1.49 2007/01/28 16:59:06 debug Exp $ * * SH instructions. * @@ -196,6 +196,84 @@ /* + * xor_b_imm_r0_gbr: mem[r0+gbr] |= imm + * or_b_imm_r0_gbr: mem[r0+gbr] ^= imm + * and_b_imm_r0_gbr: mem[r0+gbr] &= imm + * + * arg[0] = imm + */ +X(xor_b_imm_r0_gbr) +{ + uint32_t addr = cpu->cd.sh.gbr + cpu->cd.sh.r[0]; + uint8_t *p = (uint8_t *) cpu->cd.sh.host_store[addr >> 12]; + + if (p != NULL) { + p[addr & 0xfff] ^= ic->arg[0]; + } else { + uint8_t data; + SYNCH_PC; + if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data, + sizeof(data), MEM_READ, CACHE_DATA)) { + /* Exception. */ + return; + } + data ^= ic->arg[0]; + if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data, + sizeof(data), MEM_WRITE, CACHE_DATA)) { + /* Exception. */ + return; + } + } +} +X(or_b_imm_r0_gbr) +{ + uint32_t addr = cpu->cd.sh.gbr + cpu->cd.sh.r[0]; + uint8_t *p = (uint8_t *) cpu->cd.sh.host_store[addr >> 12]; + + if (p != NULL) { + p[addr & 0xfff] |= ic->arg[0]; + } else { + uint8_t data; + SYNCH_PC; + if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data, + sizeof(data), MEM_READ, CACHE_DATA)) { + /* Exception. */ + return; + } + data |= ic->arg[0]; + if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data, + sizeof(data), MEM_WRITE, CACHE_DATA)) { + /* Exception. */ + return; + } + } +} +X(and_b_imm_r0_gbr) +{ + uint32_t addr = cpu->cd.sh.gbr + cpu->cd.sh.r[0]; + uint8_t *p = (uint8_t *) cpu->cd.sh.host_store[addr >> 12]; + + if (p != NULL) { + p[addr & 0xfff] &= ic->arg[0]; + } else { + uint8_t data; + SYNCH_PC; + if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data, + sizeof(data), MEM_READ, CACHE_DATA)) { + /* Exception. */ + return; + } + data &= ic->arg[0]; + if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data, + sizeof(data), MEM_WRITE, CACHE_DATA)) { + /* Exception. */ + return; + } + } +} + + +/* * mov_imm_rn: Set rn to a signed 8-bit value * add_imm_rn: Add a signed 8-bit value to Rn * @@ -1954,12 +2032,16 @@ cpu->cd.sh.utlb_hi[urc] = cpu->cd.sh.pteh; cpu->cd.sh.utlb_lo[urc] = cpu->cd.sh.ptel; - if ((old_lo & SH4_PTEL_SZ_MASK) == SH4_PTEL_SZ_4K) - cpu->invalidate_translation_caches(cpu, - old_hi & 0xfffff000, INVALIDATE_VADDR); - else - cpu->invalidate_translation_caches(cpu, - old_hi & 0xfffff000, INVALIDATE_ALL); + /* Invalidate the old mapping, if it belonged to the same ASID: */ + if ((old_hi & SH4_PTEH_ASID_MASK) == + (cpu->cd.sh.pteh & SH4_PTEH_ASID_MASK)) { + if ((old_lo & SH4_PTEL_SZ_MASK) == SH4_PTEL_SZ_4K) + cpu->invalidate_translation_caches(cpu, + old_hi & 0xfffff000, INVALIDATE_VADDR); + else + cpu->invalidate_translation_caches(cpu, + old_hi & 0xfffff000, INVALIDATE_ALL); + } } @@ -2808,7 +2890,7 @@ /* STC Rm_BANK, Rn */ ic->f = instr(copy_privileged_register); ic->arg[0] = (size_t)&cpu->cd.sh.r_bank[(lo8 >> 4) & 7]; - } else if (iword == 0x00ff) { + } else if (iword == SH_INVALID_INSTR) { /* PROM emulation specifically for Dreamcast */ ic->f = instr(prom_emul_dreamcast); } else { @@ -3113,6 +3195,11 @@ case 0x1b: /* TAS.B @Rn */ ic->f = instr(tas_b_rn); break; + case 0x1e: /* LDC Rm,GBR */ + ic->f = instr(mov_rm_rn); + ic->arg[0] = (size_t)&cpu->cd.sh.r[r8]; /* m */ + ic->arg[1] = (size_t)&cpu->cd.sh.gbr; + break; case 0x20: /* SHAL Rn */ ic->f = instr(shll_rn); /* NOTE: shll */ break; @@ -3422,6 +3509,18 @@ ic->f = instr(or_imm_r0); ic->arg[0] = lo8; break; + case 0xd: /* AND.B #imm,@(R0,GBR) */ + ic->f = instr(and_b_imm_r0_gbr); + ic->arg[0] = lo8; + break; + case 0xe: /* XOR.B #imm,@(R0,GBR) */ + ic->f = instr(xor_b_imm_r0_gbr); + ic->arg[0] = lo8; + break; + case 0xf: /* OR.B #imm,@(R0,GBR) */ + ic->f = instr(or_b_imm_r0_gbr); + ic->arg[0] = lo8; + break; default:fatal("Unimplemented opcode 0x%x,0x%x\n", main_opcode, r8); goto bad;